
0ctf_2017_babyheap
分析题目
题目提供了libc 的版本,因为我使用的是archlinux系统,使用的musl的libc,没有适合的ld加载,所以去glibc-all-in-one中下载了合适的glibc并且进行编译,然后使用patchelf更换libc和ld。
丢进Ghidra中,看一下伪代码(没有加载出函数名,找到__libc_start_main找到main函数),发现在Fill选项调用的函数处,存在无限制任意写大小长度的问题,可以考虑溢出堆块。
使用Gdb进行调试的时候,我们发现了程序中存在alarm函数,所以我们打开hex编辑器,找到对应的位置,当然也可以搜索E8EBFEFFFF,更换为NOP(0x90),方便进行gdb的动态调试。
为了方便测试,我们先把调用函数写出来:
1 | def add(size): |
基本思路
首先建立两个fast chunk和一个small chunk,释放第三个chunk,写入第一个chunk溢出到第二个chunk后,修改第二个chunk的大小,使之能够泄露出第三个chunk指向的main_arena的地址(不是main_arena的初始地址,是main_arena+0x58的地址,对应small_bin的位置),然后根据已知libc中main_arena的相对偏移,获取程序的基址。
然后,通过建立fake_chunk,我们修改__malloc_hook的位置的值为one_gadget地址,然后我们再创建一个chunk,就可以获取shell。
出现的问题及解决方案
1、我使用的libc和提供的libc的main_arena的偏移量不同,需要修改。
2、程序使用的alloc,跟malloc存在一部分的区别,malloc创建chunk后不会清空chunk的内容,而alloc会,所以,第三个创建的small_chunk需要重新修复。
3、关于fake_chunk,我们可以理解为在要修改的位置,创建一个包含它的chunk。这里我们可以利用small_bin的双链表,修改fd和bk的值,伪造一个bin,然后我们再malloc一下,在chunk内实现任意写,成功修改目标地址。
最终EXP
1 | ##Author by: limu |