Fastbin-attack之house-of-spirit

house of spirit是一种组合型漏洞利用,目标位置处伪造fastbin chunk,并将其释放,从而达到分配指定地址的chunk的目的

绕过检测

以libc-2.23.so为例子,直接看一下malloc.c的源码吧。

fake chunk的ismmap不能是1,因为是1的话会拿出来单独处理,并且写入的fake_chunk要对齐

要满足fastbin,要对齐

next_chunk大小不能小于2 * SIZE_SZ同时也不能大于av->system_men

fastbin 链表头部不能是该 fake chunk,即不能构成 double free 的情况

例子

来自how2heap上的例子进行说明(删除了一些,不影响代码

https://github.com/shellphish/how2heap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//gcc -g z1r01.c -o z1r01
#include <stdio.h>
#include <stdlib.h>
int main()
{
fprintf(stderr, "This file demonstrates the house of spirit attack.\n");
fprintf(stderr, "Calling malloc() once so that it sets up its memory.\n");
malloc(1);
fprintf(stderr, "We will now overwrite a pointer to point to a fake 'fastbin' region.\n");
unsigned long long *a;
unsigned long long fake_chunks[10] __attribute__ ((aligned (16)));
fprintf(stderr, "This region (memory of length: %lu) contains two chunks. The first starts at %p and the second at %p.\n", sizeof(fake_chunks), &fake_chunks[1], &fake_chunks[9]);
fake_chunks[1] = 0x40; // this is the size
fprintf(stderr, "The chunk.size of the *next* fake region has to be sane. That is > 2*SIZE_SZ (> 16 on x64) && < av->system_mem (< 128kb by default for the main arena) to pass the nextsize integrity checks. No need for fastbin size.\n");
// fake_chunks[9] because 0x40 / sizeof(unsigned long long) = 8
fake_chunks[9] = 0x1234; // nextsize
fprintf(stderr, "Now we will overwrite our pointer with the address of the fake region inside the fake first chunk, %p.\n", &fake_chunks[1]);
fprintf(stderr, "... note that the memory address of the *region* associated with this chunk must be 16-byte aligned.\n");
a = &fake_chunks[2];
fprintf(stderr, "Freeing the overwritten pointer.\n");
free(a);
fprintf(stderr, "Now the next malloc will return the region of our fake chunk at %p, which will be %p!\n", &fake_chunks[1], &fake_chunks[2]);
fprintf(stderr, "malloc(0x30): %p\n", malloc(0x30));
}

首先,malloc(1)创建了一个chunk,接着定义了long long的指针a,和fake_chunks[10]的数组,接着让fake_chunks[1]的数据变成0x40,也就是fake的size,将[9]改为0x1234,将[2]的地址给了指针a,释放a指针,最后创建了0x30大小的chunk。

gdb 一下吧,在第13行下个断点吧。b 13

0x7fffffffdd88 - 0x8为fake_chunk的起始地址

第17行下个断点

红色框内已经被改变了,fake_chunk的size变成了0x40,上面的绕过检测已经符合了

  • fake chunk 的 ISMMAP 位不能为 1
  • fake chunk 地址需要对齐
  • fake chunk 的 size 大小需要满足对应的 fastbin 的需求,同时也得对齐

0x1234也满足了一个条件 ,做为next_chunk的size位,next_chunk大小不能小于2 * SIZE_SZ同时也不能大于av->system_men

下个22行的断点

因为a=&fake_chunk[2],a也就是指向了fake_chunk的data部分,此时释放a,也就是释放了fake_chunk,又因为fake_chunk的size为0x40所以在fastbins中0x40里出现了fake_chunk的地址,下一次申请malloc时,就会将fake_chunk的地址拿出来使用,也就是任意写地址

运行到最后可以看到fastbin已经被取出,使用hose-of-spirit这种漏洞利用,可以先伪造chunk,写好free,再利用释放,重启,覆盖free写入system从而getshell