hctf2016-fheap Writeup
TOC
题目地址:https://github.com/zh-explorer/hctf2016-fheap。
测试环境为笔者自行编译的glibc-2.23,加上-g参数(baby heap),并按照要求开启pie保护。
感谢来自大佬 钞sir 的指点。部分思路借鉴自 钞sir 的博客: https://cc-sir.github.io/2019/03/28/pwnf/ 。
题目介绍
源码:main.c
|
主要功能
void showMenu(void) |
两个结构体
typedef struct String |
create string
void creatStr() |
create string 有两种不同方式来储存字符串,当字符串小于16时,直接储存在string->o.array,否则申请新的内存空间来储存,而且释放的方法也不同。完成操作后生产的String结构体会储存在全局变量Strings中。
deleteStr
void deleteStr() |
给出要删除的id进行删除。
漏洞利用
typedef struct String |
看到这里第一个想到的就是double free,而且在deleteStr函数中并没有对double free有什么限制的操作。本难题的难点是绕过pie保护,可以用部分覆盖来绕过pie。
ex@ubuntu:~/test/hctf2016-fheap$ readelf -a pwn | grep -E "puts|free" |
如上所示,将freeShort部分覆盖为上面的值时,即可相当于将freeShort改成puts函数。
利用思路
- UAF漏洞将freeShort改成puts函数
- 泄露程序基地址
- 格式化字符串漏洞泄露libc基地址
- getshell
用UAF漏洞将freeShort改成puts函数
d18: e8 63 fc ff ff call 980 <puts@plt> |
就改成上面的地址即可。
call_puts_addr = 0xd18 |
泄露程序基地址
# 泄露程序的基地址 |
由于string->free函数指针储存的信息就包括了程序基地址。
格式化字符串漏洞泄露libc基地址
在Linux,*BSD和Mac OS X里也使用同一种方式来传递函数参数。前6个参数使用 RDI,RSI,RDX,RCX,R8,R9 来传递的,剩下的用栈。所以第七个参数才是栈上的一个偏移,即用$6来偏移。
这里我用了一个最近的偏移,具体计算方法如下:
───────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────── |
准备好所有值后就可以直接进行泄露了
# 泄露libc基地址 |
getshell
# 设置string->free为system函数,getshell |
完整脚本
#!/usr/bin/python2 |
运行结果
ex@ubuntu:~/test/hctf2016-fheap$ ./exp.py |
总结
不管你有多么聪明,总有人比你更聪明。如果你想变得更强,那就必须得到能得到的一切帮助。