fastbin 利用小结之fastbin double free, house of spirit
1、fastbin chunk 结构
未分配的chunk
| | size |
| fd | |
已分配chunk
| | size |
| content |
……
malloc返回的指针指向content位置
2、Fastbin Double Free
Fastbin Double Free 是指 fastbin 的 chunk 可以被多次释放,伪造一个假的fastbin链表,根据malloc规则,再次申请同样大小的内存时会从fastbin中获取。而该链表是被伪造过的,可申请得到任意地址,实现任意地址写。
以以下例子为例
typedef struct _chunk
{
long long pre_size;
long long size;
long long fd;
long long bk;
} CHUNK,*PCHUNK;
CHUNK bss_chunk;//一个全局的伪造的chunk
int main(void)
{
void *chunk1,*chunk2,*chunk3;
void *chunk_a,*chunk_b;
bss_chunk.size=0x21;
chunk1=malloc(0x10);
chunk2=malloc(0x10);
//a
free(chunk1);
free(chunk2);
free(chunk1);
//b
chunk_a=malloc(0x10);
//c
*(long long *)chunk_a=&bss_chunk;
//d
malloc(0x10);
malloc(0x10);
chunk_b=malloc(0x10);
//e
printf("%p",chunk_b);
return 0;
}
a 此句执行完后,chunk1,chunk2会在连续的区域内,在内存里的表现
|chunk1||chunk2|
low addr----->high addr
b 如果直接连续free(chunk1),会被libc检查出double free(检查方式为free时看放入链表的指针与链表现在的指针是否同一个。如fastbin->a,free(a)则检查出double free。如果fastbin->b->a。free(a)则bypass)
此时fastbin链表为:
main_arena.fastbin--->chunk1--->chunk2--->chunk1(注意chunk1的fd也是指向chunk2,即chunk1和chunk2是一个环形链表)
在内存中表现如下:
chunk1_addr:
|
0
|
0x11
|
|
chunk2_addr
|
|
chunk2_addr:
|
0
|
0x11
|
|
chunk1_addr
|
|
c 分配时从fastbin的首部取出,即chunk_a获得的是chunk1的地址
d 修改chunk_a即修改chunk1的fd位置,把此处修改为全局变量bss_chunk的地址
此时fastbin链表为fastbin--->chunk2--->chunk1--->bss_chunk
e 经过3次malloc(0x11),依次从fastbin中取出,此次取出的地址就是我们写入的地址
3、house of spirit 有一个可以随意free的指针,伪造长度绕过检查,再次malloc即可得到伪造的地址 以how2heap的例子说明(已略去说明2部分) int main() { malloc(1);//初始化堆空间 unsigned long long *a; unsigned long long fake_chunks[10]; //a fake_chunks[1] = 0x40; // b fake_chunks[9] = 0x1234; // c a = &fake_chunks[2]; free(a); //d fprintf(stderr, "malloc(0x30): %p\n", malloc(0x30)); //e } a 需要一个控制一个伪造的chunk以及相邻chunk的头部(相邻chunk头部有一个长度检查,需要修改来绕过)。 这里想伪造的chunk大小为0x40。该伪造chunk大小为0x40+0x10(chunk头部大小)=0x50 相邻的chunk头部大小为0x10。即总的空间为0x50+0x10=0x60=80。刚好是10个long long的大小(long long在64位系统上是8个字节)。 b 伪造free的chunk的大小。 c 相邻chunk的大小有检查,该长度需要大于chunk头部大小(在64位系统上为16字节)小于128kb。 fake_chunks[1]+0x40是相邻chunk地址(fake_chunks[8]),长度在该地址偏移8位移处,即fake_chunks[9] d free该伪造chunk,放入fastbin中 e malloc同样大小的内存,得到该地址
|