【小课堂】ret2syscall 的学习

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

640 (1).jpg

0x03.png


有用的信息:0x0:ELF 32-bit LSB executable //32位的ELF文件0x1:NX: NX enabled //开启了NX保护,不能采用跳板入栈执行代码了,因为不可执行,所以栈溢出我们采用ROP技术。然后我进行程序功能分析:

640 (1).jpg

一个输入点,和之前的题一样,然后使用IDA32来分析分析:

image.png

和前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环境):

image.png

image.png

在C语言的程序的函数调用的时候,栈会有一个平衡的概念,我称之为:堆栈平衡。而在vc6.0中默认使用的__cdcel就是典型的外平栈。如果这个程序在call完了之后add esp,number 来进行堆栈平衡的话,就是__cdcel调用方式。

image.png

但是我在IDA和gdb进行反汇编之后在main函数中并没有发现类似于:add esp,number这样去平衡堆栈的汇编指令,那我只能认为这里使用的是__stdcall,也就是我称之为“内平栈”,那我们要证实这一点,需要去gdb里面找到证据:

image.png

Bingo,这里我也彻底明白了内外平栈和函数调用的一个小关系。那么这个gets()函数在ret之后,esp指向的就应该是原esp+0x4,而我们控制ret地址也能将其指向其他的地址去继续执行。等等…我刚才研究了那么久的内外平栈,我ret了之后和他们没有关系了啊!(震惊没事,继续。这里引用一句名言“在Pwn的时候,你的脑子就要像CPU和内存一样执行下面的代码并预知结果 ——鲁迅”再看一遍我们需要的目标0x0:系统调用号即eax应该为0xb0x1:第一个参数即ebx应该指向/bin/sh的地址,其实执行sh的地址也可以0x2:第二个参数即ecx应该为00x3:第三个参数edx应该为0那我们去找需要控制eax的gadgets:

0x03.png

0x080bb196是pop_eax_ret的gadgets,将这个地址放到ret_addr中,跳过去,那么pop的值就是ret+0x4,我们写上0xb,而pop_eax_ret执行完之后,会ret到当前esp中存放的值(解析为地址)去,所以我们直接在ret+0x8放入下个gadgets的地址。我们需要改变ebx,ecx,edx,如法炮制:

0x03.png

幸运的是,0x0806eb90 : pop edx ; pop ecx ; pop ebx ; ret可以直接操作三个pop,都正好是我们需要的,但是我们一定要注意我们放参数的顺序。edx,ecx,ebx应该这样。对应的参数是:0,0,/bin/sh的地址那么我们现在的Payload是这样了:

0x03.png


我们需要找到字符串为/bin/sh的gadgets

0x03.png

然后我们需要遵从linux中系统调用的结束中断:

image.png

让最后是int 0x80:

0x03.png

刚刚好,0x08049421 : int 0x80有了。那么程序在我们脑子里面就是这样:

image.png


应该这就能有shell了,我的exp学习了ctf-wiki中的写法:

image.png


然后:

image.png


本文作者:白帽100安全攻防实验室

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/95391.html

Tags:
评论  (0)
快来写下你的想法吧!

白帽100安全攻防实验室

文章数:22 积分: 52

安全问答社区

安全问答社区

脉搏官方公众号

脉搏公众号