ctfshowpwn69
CTFshow pwn69的题解,网上有很多类似的WP,这里把当时看的时候几个疑惑的地方解释下:
题目提示我们用ORW去拿flag。checksec看一下,开了Partial RELRO ,其他保护没开,拖到IDA分析,有几个重点函数分析下:
mmap((void *)0x123000, 0x1000uLL, 6, 34, -1, 0LL); ,这函数作用就是从0x123000这个地址开始的0x1000个字节,给上写和执行权限权限。注意这里和linux操作系统文件权限有区别。mmap这里的4代表执行,2代表写,1代表读。
然后就是sub_400949这个函数,是一个沙箱函数,我们可以借助工具来分析还有哪些可以用。工具用法:seccomp-tools dump ./pwn69
1 | __int64 sub_400949() |
通过分析可以知道只有open 、read、write可以用。再来看看sub_400A16函数,发现存在栈溢出
1 | int sub_400A16() |
到这里,攻击思路就比较清晰了,我们想办法往mmap给的这个地址段里面写shellcode(ORW),然后跳转到这里执行,就OK了。
最终利用脚本 pwn69.py:
1 | from pwn import * |
这里的payload解释下,用我个人的话来说就是套娃的存在。这个payload就是先把返回地址覆盖成了jmp rsp ,然后通过改变rsp指针的值,让它指向buf,然后程序就会去执行我们一开始在payload里面写好的asm(shellcraft.read(0,mmap,0x100)) 以及 asm("mov rax,0x123000;jmp rax") 。
到这里有几个地方需要解释下:jmp rsp 之后改变了程序的执行流程,后面也都会被当作程序指令去执行,所以我们sub rsp,0x30;jmp rsp才会被当作指令去执行。另外一点就是sub rsp,0x30起到了一个什么作用,可能一开始是有点懵的,其实画个图就很清楚了。

执行到返回地址时,此时rsp指向返回地址,pop弹出到ip,然后此时rsp指向为红色rsp,然后ip执行jmp rsp,相当于跳转到了红色rsp那里的执向,然后就会执行asm(sub rsp xxx) ,至于buf和此时的rsp为啥是0x30,这个可以通过gdb调试去看。然后jmp rsp,再一次改变程序执行流程,就会来到蓝色rsp这里执行了。就套了一层读入的操作(此时我们就可以往mmap读shellcode),然后跳转到mmap那边执行。就成功了。
这里的调试也要注意,断点打在read函数调用完之后,(打到之前发现程序每次都是把read走完了的,并没有停下来。这里感谢肖总帮我看了很久。。。)