BUUCTF-babyheap_0ctf_2017(巨细)
可能这道题是很多人在堆这一块初窥门径的一道题目。我第一次见堆是在4月份,中间各种杂事,现在来把这道题的wp补一补
- 首先说一些前置知识。
-
小白(我)眼里的堆{做题没啥关系,但是可以丰富你的认知}

在程序运行过程中,堆可以提供动态分配的内存,允许程序申请大小未知的内存。堆其实就是程序虚拟地址空间的一块连续的线性区域,它由低地址向高地址方向增长。我们一般称管理堆的那部分程序为堆管理器。
堆管理器处于用户程序与内核中间,主要做以下工作:
1.响应用户的申请内存请求,向操作系统申请内存,然后将其返回给用户程序。同时,为了保持内存管理的高效性,内核一般都会预先分配很大的一块连续的内存,然后让堆管理器通过某种算法管理这块内存。只有当出现了堆 空间不足的情况,堆管理器才会再次与操作系统进行交互。
2.管理用户所释放的内存。一般来说,用户释放的内存并不是直接返还给操作系统的,而是由堆管理器进行管理。这些释放的内存可以来响应用户新申请的内存的请求。 -
做题需要知道的堆的相关内容
https://blog.csdn.net/m0_64195960/article/details/124376966?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-1-124376966-blog-121664510.pc_relevant_paycolumn_v3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-1-124376966-blog-121664510.pc_relevant_paycolumn_v3&utm_relevant_index=2
补充:alloc的大小只是date的大小,不包括表头(0x10);堆的size位指的是包括表头包括date的数据大小。
这位师傅总结了,我这里就不赘述 -
堆该如何getshell?
首先介绍一下unsortedbin,当一个chunk被free后归入unsortedbin中时,unsortedbin的表头指向这个被free的chunk,然后这个chunk的fd指向下一个被free的chunk,当没有的时候就会指回来(nsortedbin的表头),而且这个链表是双向的。
其次,说一下__malloc_hook这个函数,这玩意也在lib里面可以找到(也就暗示了我们可以通过这个找偏移),这个里面存了一个地址,当我们用malloc创建新的chunk的时候,就会调用hook,导致的结果就是call 那个地址,如果这个地址是system函数,那就相当于getshell了再次,如果想通过上面的方法,要知道__malloc_hook这个函数的地址。它有一个固定的偏移(以2.23也就是ubuntu16为例),main_arena-0x10=__malloc_hook,unsorted的表头=main_arena+0x58,换算下来就是unsorted的 表头-0x58-0x10=__malloc_hook。
好滴,经过我们的一系列简化,getshell只需要得到unsorted的表头的地址
- 我们回到这个题目
先说第一个思路
我们创建4个0x80的堆块(算上表头九十0x90),记作0,1,2,3。我们填第0个堆块,让他一直填到第一个堆块的size位,修改大小为两个堆块的大小

free掉chunk1
再alloc一个0x80,那之前那一个被free掉的堆块就会被分割一个0x90的大小出来,这个时候那个空闲的unsortedbin 的fd就会指向unsorted的表头,unsorted的表头会指向这个堆块的bk
我们从两个视角来看
使用者的视角

堆管理器的视角

也就是说,那个堆块既在unsortedbin里,同时也是chunk2,我们就可以dump chunk2来得到unsorted的表头的地址。
前一个是空闲堆块的表示,后一个是chunk2的表示


浙公网安备 33010602011771号