ROP练习中给定的剥离二进制程序存在哪些可利用漏洞?
ROP练习漏洞分析与利用思路
核心漏洞点
- io函数中,
local_9是栈上仅1字节的字符变量,但fgets(&local_9, 0x3c, stdin)允许读取最多60字节输入,完全超出栈上分配的空间,栈溢出漏洞是明确的可利用点,溢出后可覆盖返回地址劫持执行流。
利用步骤
- 计算溢出偏移
- 通过Ghidra查看io函数的栈帧结构,或用调试器(如gdb)发送不同长度的测试输入,观察程序崩溃时的寄存器状态,确定从
local_9到io函数返回地址的字节数,即需要填充的垃圾数据长度。
- 通过Ghidra查看io函数的栈帧结构,或用调试器(如gdb)发送不同长度的测试输入,观察程序崩溃时的寄存器状态,确定从
- 构造ROP链
- 先填充对应偏移量的垃圾数据,直到覆盖返回地址的位置。
- 将返回地址替换为
secret函数的实际内存地址(程序无符号,需在Ghidra中定位该函数的起始地址)。 - 根据目标架构的调用约定传递参数:
- x86架构(cdecl调用约定):在secret函数地址后,依次填充一个合法的返回地址(如程序的exit函数地址)、参数
num=1、参数str(指向栈中存储的"Hewhewbrew"字符串地址,需把密码放在payload的垃圾数据区域中)。 - x86_64架构(System V调用约定):先查找
pop rdi; ret和pop rsi; ret的gadget,先调用pop rdi; ret将rdi寄存器设为1,再调用pop rsi; ret将rsi寄存器设为栈中密码字符串的地址,最后跳转到secret函数地址。
- x86架构(cdecl调用约定):在secret函数地址后,依次填充一个合法的返回地址(如程序的exit函数地址)、参数
- 生成payload并触发
- 拼接垃圾数据、ROP链、密码字符串为完整输入,发送给程序,触发栈溢出后即可调用secret函数并满足验证条件,输出"you win!"。
关键注意事项
- 程序无符号,所有函数地址、ROP gadget都需要在Ghidra中通过反编译代码或汇编指令定位。
- 确认栈区域为可写权限(默认情况下栈是可写的),确保密码字符串能被正常读取。
内容的提问来源于stack exchange,提问作者Cheesewaffle
相关产品推荐
相关产品推荐

