ret2syscall

checksec

ret2syscall

查找溢出点

ret2syscall

计算偏移量

1 手动计算

ret2syscall
0x8048e8f和0x8048e93这两行明显是为调用函数准备参数,把参数的地址给压栈。这个地址就是gets函数写入地址的起始地址,也就是eax,此时距基址的距离是EBP-EAX,由于是32位,所以返回地址在EBP-EAX+4的距离。

2 脚本

我们可以直接输入一个有序的长输出,然后观察EBP的基址是被哪一个下标的值所代替,之后根据该值返回去寻找下标来得到偏移量。
下断点
ret2syscall
远程调试,输入一个长输入:
ret2syscall
根据EBP的值反推偏移
ret2syscall

3 其实peda可以直接填充

ret2syscall

systemcall

1 自动化脚本

ret2syscall
ret2syscall
exp
ret2syscall

2 手动构造

Syscall的函数调用规范为: execve(“/bin/sh”, 0,0);
它对应的汇编代码为:

pop eax, # 系统调用号载入, execve为0xb
pop ebx, # 第一个参数, /bin/sh的string
pop ecx, # 第二个参数,0
pop edx, # 第三个参数,0
int 0x80, # 执行系统调用

接下来通过ROPgadget来构造:
查找汇编指令,其中—binary 表示目标二进制的路径,—only 表示只显示指定的汇编语句, grep可以展示想要的寄存器:
先查找pop eax:
ret2syscall
ret2syscall
ret2syscall
ret2syscall
ret2syscall
这里选择的每一个gadgets都含有ret是为了能够使得程序自动持续的选择堆栈中的指令依次执行。在构造这些gadgets之前,我们通过下面的堆栈指针移动图,来分析一下eip指针的移动,以及对应获取的数据内容。ret指令可以理解成去栈顶的数据作为下次跳转的位置。即,

eip = [esp];
esp = esp+4;
或者简单理解成: pop eip;

ret2syscall
上图中,左边显示的堆栈的内容,右边是对应的代码。数字表示的是,运行到特定的汇编指令的时候,esp指针的位置。总结下来,我们通过pop指令来移动esp指针获取数据,比如字符串/bin/sh,我们通过ret指令来同样移动esp指针来获取下一条执行的命令。这样,我们就能够在不需要与堆栈中执行程序的情况下,顺利的控制程序控制流的执行。

构造exp:
ret2syscall

还可以用0x0806eb90 : pop edx ; pop ecx ; pop ebx ; ret来构造
ret2syscall