【小课堂】ret2syscall 的学习

最近在学习Pwn-stack-ROP基础。在ctf-wiki上面有讲解到:bamboofox中的ret2syscall这道题。不过我没有明白原文中的一些操作,很迷茫,所以就仔细去分析一下。首先file…

我目前正在研究Pwn-stack-ROP基础。在ctf-wiki上,bamboofox中有ret2syscall的描述。但是,我对原文中的一些操作并不了解,非常困惑,所以我会仔细分析。第一个文件和checksec

有用信息:0x0:ELF 32位LSB可执行文件//32位ELF文件0x1:NX: NX启用//打开NX保护,不能使用跳板执行代码,因为它无法执行,堆栈溢出我们使用ROP技术。然后我执行了程序功能分析:

输入点,与上一个问题相同,然后使用IDA32分析分析:

像之前的ctf-wiki一样,gets()堆栈溢出,但是这次我们不能像以前那样使用我们在堆栈上编写的代码来获取shell,因为我们已经提到了NX保护措施,那么我们使用ROP。所以我们处理这个程序并使用系统调用来获取shell。在正常情况下,它是这样的:execve('/bin/sh',NULL,NULL)根据ctf-wiki中的详细描述:这个程序是32位,所以我们需要:0x0:系统调用号即eax应该是0xb0x1:第一个参数,ebx应该指向/bin/sh的地址,实际上,执行sh的地址也可以是0x2:第二个参数ecx应该是00x3:第三个参数edx应该是0。我不太明白为什么我必须像这样编写exp,这很令人困惑,所以:我打开了我之前绘制的堆栈更改图和我之前编写的小程序片段(Win7 /vc6.0环境):

当调用C程序的函数时,堆栈有一个平衡的概念,我称之为:堆栈平衡。 vc6.0中使用的默认__cdcel是典型的外部平面堆栈。如果程序在调用完成后将esp,数字 添加到堆栈余额,则为__cdcel调用模式。

但是,在我反汇编IDA和gdb后,我发现main函数中没有类似的加载:添加esp,数字来平衡堆栈汇编指令,然后我只能想到使用__stdcall,这就是我所说的“内部扁平堆栈” “,那么我们必须确认一下,我们需要去gdb找到证据:

宾果,在这里我也完全理解内部和外部平面堆栈和函数调用之间的小关系。然后gets()函数在ret之后,esp应该指向原始的esp +0x4,我们可以控制ret地址指向其他地址继续执行。等等..我刚刚研究了内部和外部扁平堆栈。我退后,我与他们无关! (不要惊呆了,继续。这里引用一句名言“在Pwn中,你的大脑将执行以下代码,如CPU和内存并预测结果——鲁迅”,然后查看我们需要的目标0x0:系统调用号即eax应该是0xb0x1:ebx应该指向/bin/sh地址的第一个参数,实际上,执行sh的地址也可以是0x2:第二个参数ecx应该是00x3:第三个参数edx应该是0,那么我们去寻找需要控制eax的小工具:

0x080bb196是gadget_pop_eax_ret,将此地址放入ret_addr,跳过,然后pop的值为ret +0x4,我们写入0xb,执行pop_eax_ret后,它将返回当前esp中存储的值(解析为地址Go) ,所以我们将下一个小工具的地址直接放在ret +0x8。我们需要改变ebx,ecx,edx,并做同样的事情:

幸运的是,0x0806eb90: pop edx; pop ecx; pop ebx; ret可以直接操作三个pop,这正是我们需要的,但是我们必须注意我们放置参数的顺序。 Edx,ecx,ebx应该是这样的。相应的参数是:0,0,/bin/sh地址,那么我们当前的Payload是这样的:

我们需要找到带有字符串/bin/sh的小工具

然后我们需要在Linux中跟随系统调用的结束:

让结尾为int0x80:

好的,0x08049421: int0x80有。然后程序在我们的脑海中是这样的:

这应该有一个shell,我的exp学到了ctf-wiki:

然后: