ctfshow pwn72
本题主要考察的ret2syscall 此前已经接触到了ret2text 、ret2shellcode、ret2libc
简单说一下这几个的区别:
ret2text,将返回地址覆盖为程序已有的函数地址
ret2shellcode,构造一段shellcode,然后让返回地址能指向这段shellcode
ret2libc ,泄露libc地址,来构造函数和对应参数,从而getshell
ret2syscall ,预先构造好特殊寄存器的值,然后跳到int 0x80 中断号,来实现系统调用。
以CTFshow pwn72题为例:
附件check一下发现是32位,没开保护。file看一下发现是静态链接。拖到IDA去分析:
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
存在栈溢出,这题考点已经提示了是ret2syscall。所以我们想办法去构造。ctrl + s 查找不到 /bin/sh 字符串。但是发现了bss段,且有写权限,可以考虑往里面写/bin/sh 。注意这里写的首地址,以000结尾。 之前有个题目是mprotect函数,要求首地址是页的开始(4K),所以就以000的结尾,这里其实不用。那么我们如何去实现往BSS段写数据?显然还是可以用ret2syscall 去实现read函数的系统调用。然后再去实现execv函数的系统调用。所以这里是两层。所以思路就很清晰了。不过有个点需要注意下。因为涉及到两层。所以第一次调用int 0x80 后面一定要有ret 。一开始我用ROPgadget --binary pwn72 --only "int"只能搜到 int 0x80 。这里换一种方式去搜索:ropper --file pwn72 --search "int 0x80" ,对比如下:

最终的脚本如下:
1 | from pwn import * |
注意寄存器里对应的这些参数的值。