House of Force

原理

Glibc的很多版本中(2.23和2.27),并没有对Top Chunk的Size字段进行完整性检查.

利用

1.先通过溢出到top chunk的size字段,伪造top chunk的大小。
2.然后malloc申请堆块并写入数据,实现任意地址任意写

详述

tip:
1.详述示例参考hacking everyday
2.用抽象的思维看此示例,不用过度纠结细节,着重看如何实现House of Heap

分析程序

1.程序运行前输出了puts地址和heap开始的地址
2.给出菜单
示例
3.选择malloc,申请一个0x18大小的堆块
(实际上分配了0x20大小)
malloc
在pwndbg里,用vis命令查看现在的堆
可以看到由于溢出了7个字节的b和1个字节的\x0a,可以覆盖top chunk的size
heap
4.选择第二个选项,会输出变量target的值
target
x/gx &target指令(或者dp &target等其他指令)查看变量target地址附近的值
可以看到target变量地址比堆的起始地址要小。
而malloc函数只能继续向高地址申请空间,没办法向target变量靠拢。
check

漏洞利用

前置知识

程序执行malloc函数,先从bins中寻找满足需求的堆块.如果没有,再从top chunk中切下一块内存返回给malloc
malloc源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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;
}

1.首先申请0x18的空间,并输入b’a’*24 + b’\xff’*8,由此可以把top chunk覆盖为’ffffffffffffffff’

源码中有如下代码:

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

2.然后,申请chunk,正好到target前面一点点的位置,需要分配的是(0xffffffff-0x603000)+0x602010-0x20-0x20这么大的内容

计算分配大小的原理

源码中有如下代码:

1
2
remainder = chunk_at_offset (victim, nb)
//victim(切割前top_chunk的地址) + nb (要申请的内存大小) = top_chunk (切割后top_chunk的地址)

如果我们改变nb的值,就可以让切割后top chunk的地址变为目标地址
其中:

1
2
3
1.nb = request_size + chunk_header    
2.top_chunk + chunk_header = target_addr
(因为是通过往top_chunk的usr data区里输入数据,来达到修改target_addr的效果)

整合得:

request_size = target_addr - 2 * chunk_header-victim         
(request_size为负数) 

tip

1.House of Force可以在tcache存在的libc中使用
2.