以前做过realloc相关的利用,不过这题让我学到了realloc利用的新姿势
题目描述
题目提供了四个功能
1  | 1. alloc  | 
其中alloc功能相当于malloc一个指定大小的块,不过大小限定在了0x78以内,realloc功能就是使用realloc函数重新分配空间,如果成功返回了一个地址,那么就把这个地址复制到bss段上。这里存在一个off by null,如果这个题没有两个堆块这个数量限制的话还可以搞堆重叠,但是只有两个chunk的话就很难利用。
realloc功能为更改chunk的size以及更新content内容,这里末尾不会自动补0.值得注意的是,当size为0时,相当于触发free但是对应的bss上的数组中的指针不会清0,于是这里有一个uaf可以利用。
free功能就是同时free掉chunk以及将heap数组中的指针清0
相关知识点
libc2.29 相关
1  | typedef struct tcache_entry  | 
libc2.29中多出了一个结构叫做key,它会把tcache结构的头部保存在key中,然后在空闲chunk加入tcache链后从key开始遍历tcache中的chunk,看看有没有重复的,有则会出现double free的报错
检测代码如下
1  | if (__glibc_unlikely (e->key == tcache)) // 检查是否为tcache_perthread_struct地址  | 
简单总结一下,2.29下tcache触发double free报错的条件为:
1  | e-key == &tcache_perthread_struct && chunk in tcachebin[chunk_idx]  | 
realloc(ptr, size)函数
总的来说,realloc函数在size不同的情况下,可以达到malloc,edit,free三种功能:
ptr == 0: malloc(size)ptr != 0 && size == 0: free(ptr)ptr != 0 && size == old_size: edit(ptr)ptr != 0 && size < old_size: edit(ptr) and free(remainder)ptr != 0 && size > old_size: new_ptr = malloc(size); strcpy(new_ptr, ptr); free(ptr); return new_ptr;
利用思路
- 利用uaf在不同的tcache链上放置atoll_got的chunk
 - 利用其中一个指向atoll_got的chunk,把atoll_got改为printf,利用格式化字符串漏洞泄露libc
 - 最后再利用另一个指向atoll_got的chunk,将其改为system,最后调用system(‘/bin/sh’)拿到shell
 
1  | from pwn import *  | 
小结
- 被free掉的chunk再用realloc进行相同size的操作居然可以达到uaf的效果,本以为会malloc出来的
 - 把atoll函数改为printf真的强,这也提供了一个思路就是可以通过一个漏洞来构造另外的漏洞来达成利用的目的