rp-bf:一款Windows下辅助进行ROP gadgets搜索的Rust库

2024-02-01 11:12

本文主要是介绍rp-bf:一款Windows下辅助进行ROP gadgets搜索的Rust库,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

关于rp-bf

rp-bf是一款Windows下辅助进行ROP gadgets搜索的Rust库,该工具可以通过模拟Windows用户模式下的崩溃转储来爆破枚举ROP gadgets。

在很多系统安全测试场景中,研究人员成功劫持控制流后,通常需要将堆栈数据转移到他们所能够控制的内存区域中,以便执行ROP链。但是在劫持控制流时,找到合适的部分很大程度取决于研究人员对CPU上下文场景的控制。那么为了劫持具备任意值的控制流,我们需要找到合适的地址,但这个地址的寻找过程又非常的麻烦,需要涉及到各种地址值、代码指针、堆栈和汇编指令。

为了解决上述问题,rp-bf便应运而生,该工具能够有效地解决上述问题,并通过ROP gadgets搜索来辅助广大研究人员完成ROP链的执行。

依赖组件配置

在使用该工具之前,我们首先需要手动配置好bochscpu模拟器,它也是rp-bf的主要依赖组件。具体的配置方法如下:

1、点击【这里】下载对应操作系统平台的bochscpu组件版本;

2、使用下列命令克隆bochscpu项目代码:

git clone https://github.com/yrp604/bochscpu.git

3、将项目中的lib和bochs目录提取到解压后的bochscpu根目录;

4、使用下列命令验证bochscpu是否构建成功:

cargo build --release

工具下载

广大研究人员可以直接使用下列命令将rp-bf项目源码克隆至本地:

git clone https://github.com/0vercl0k/rp-bf.rs.git

然后切换到项目目录下,并使用cargo build命令完成代码构建:

cargo build --release

工具运行机制

rp-bf能够从根据一个进程快照来模拟目标代码,并能够迭代快照中找到的每一个内存区域,然后将其传递给用户模块。接下来,研究人员就可以用这个地址来执行其他的安全测试了:

pub trait Finder {fn pre(&mut self, emu: &mut Emu, candidate: u64) -> Result<()>;fn post(&mut self, emu: &Emu) -> Result<bool>;}

工具使用

获取一个快照

该工具的使用方法适用于所有的操作系统和体系架构,但我们的使用样例会以Windows/Intel为例。

我们可以直接使用Windows调试器生成快照,在Windbg中运行你的目标,然后在所需状态下的所需位置生成崩溃转储(.dump/ma)即可。

搜索算法

rp-bf能够遍历崩溃转储中找到的所有内存区域,然后在模拟器中重新创建相同的执行环境。接下来,它会调用用户的pre条件,并持续执行,直到模拟器退出。此时,工具会调用post条件来让用户决定目标区域是否合适,模拟器的状态(即内存和CPU上下文)将被不断恢复和刷新。

pub fn explore(opts: &Opts, finder: &mut dyn Finder, ui: &mut dyn ui::Ui) -> Result<Vec<Candidate>> {// ...for (mem_address, mem_block) in dump.mem_blocks() {// ...'outer: for candidate in mem_block.range.start..mem_block.range.end {// ...// Invoke the `pre` callback to set-up state.trace!("Trying out {candidate:#x}");finder.pre(&mut emu, candidate)?;// Run the emulation with the candidate.let (res, stats) = emu.run()?;how_many_total += 1;// We found a candidate if it lead to a crash & the `post` condition// returned `true`.let crashed = matches!(res, TestcaseResult::Crash);let found_candidate = crashed && finder.post(&emu)?;// ...emu.restore()?;// ...}}}

从用户模式Windows崩溃转储模拟代码

该工具所使用的模拟器都使用了bochscpu库的Bochs CPU模拟器。为了在Bochs中重新创建执行环境,rp-bf将构建页面表以重新创建用户模式转储中可用的相同虚拟环境。

编写一个Finder模块

Finder模块需要提供一个pre方法和一个post方法:

pub trait Finder {fn pre(&mut self, emu: &mut Emu, candidate: u64) -> anyhow::Result<()>;fn post(&mut self, emu: &Emu) -> anyhow::Result<bool>;}

pre方法接收一个指向模拟器的可变引用,以及候选内存区域,我们可以在运行时环境中的某个位置“注入”候选区域。它能够将寄存器设置为候选值,或者将其写入内存中的某个位置:

impl Finder for Pwn2OwnMiami2022_2 {fn pre(&mut self, emu: &mut Emu, candidate: u64) -> Result<()> {// Here, we continue where we left off after the gadget found in |miami1|,// where we went from constrained arbitrary call, to unconstrained arbitrary// call. At this point, we want to pivot the stack to our heap chunk.//// ```// (1de8.1f6c): Access violation - code c0000005 (first/second chance not available)// For analysis of this file, run !analyze -v// mfc140u!_guard_dispatch_icall_nop:// 00007ffd`57427190 ffe0            jmp     rax {deadbeef`baadc0de}//// 0:011> dqs @rcx// 00000000`1970bf00  00000001`400aed08 GenBroker64+0xaed08// 00000000`1970bf08  bbbbbbbb`bbbbbbbb// 00000000`1970bf10  deadbeef`baadc0de <-- this is where @rax comes from// 00000000`1970bf18  61616161`61616161// ```self.rcx_before = emu.rcx();// Fix-up @rax with the candidate address.emu.set_rax(candidate);// Fix-up the buffer, where the address of the candidate would be if we were// executing it after |miami1|.let size_of_u64 = std::mem::size_of::<u64>() as u64;let second_qword = size_of_u64 * 2;emu.virt_write(Gva::from(self.rcx_before + second_qword), &candidate)?;// Overwrite the buffer we control with the `MARKER_PAGE_ADDR`. Skip the first 3// qwords, because the first and third ones are already used to hijack flow// and the second we skip it as it makes things easier.for qword_idx in 3..18 {let byte_idx = qword_idx * size_of_u64;emu.virt_write(Gva::from(self.rcx_before + byte_idx),&MARKER_PAGE_ADDR.u64(),)?;}Ok(())}// ...}

模拟完成后便会调用post方法,我们可以在这里找到你想要的内容,即堆栈数据和可控制的@rip值等数据,这里还允许我们指定需要实现的特定需求:

impl Finder for Pwn2OwnMiami2022_2 {// ...fn post(&mut self, emu: &Emu) -> Result<bool> {// Let's check if we pivoted into our buffer AND that we also are able to// start a ROP chain.let wanted_landing_start = self.rcx_before + 0x18;let wanted_landing_end = self.rcx_before + 0x90;let pivoted = has_stack_pivoted_in_range(emu, wanted_landing_start..=wanted_landing_end);let mask = 0xffffffff_ffff0000;let rip = emu.rip();let rip_has_marker = (rip & mask) == (MARKER_PAGE_ADDR.u64() & mask);let is_interesting = pivoted && rip_has_marker;Ok(is_interesting)}}

post方法返回值之后,模拟器会恢复内存和CPU寄存器,并继续寻找下一个候选区域。

工具运行演示

许可证协议

本项目的开发与发布遵循MIT开源许可证协议。

项目地址

rp-bf:【GitHub传送门】

参考资料

Competing in Pwn2Own ICS 2022 Miami: Exploiting a zero click remote memory corruption in ICONICS Genesis64

GitHub - yrp604/bochscpu

这篇关于rp-bf:一款Windows下辅助进行ROP gadgets搜索的Rust库的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/667095

相关文章

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

hdu1240、hdu1253(三维搜索题)

1、从后往前输入,(x,y,z); 2、从下往上输入,(y , z, x); 3、从左往右输入,(z,x,y); hdu1240代码如下: #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#inc

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测

hdu 4517 floyd+记忆化搜索

题意: 有n(100)个景点,m(1000)条路,时间限制为t(300),起点s,终点e。 访问每个景点需要时间cost_i,每个景点的访问价值为value_i。 点与点之间行走需要花费的时间为g[ i ] [ j ] 。注意点间可能有多条边。 走到一个点时可以选择访问或者不访问,并且当前点的访问价值应该严格大于前一个访问的点。 现在求,从起点出发,到达终点,在时间限制内,能得到的最大

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

hdu4277搜索

给你n个有长度的线段,问如果用上所有的线段来拼1个三角形,最多能拼出多少种不同的? import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;

在 Windows 上部署 gitblit

在 Windows 上部署 gitblit 在 Windows 上部署 gitblit 缘起gitblit 是什么安装JDK部署 gitblit 下载 gitblit 并解压配置登录注册为 windows 服务 修改 installService.cmd 文件运行 installService.cmd运行 gitblitw.exe查看 services.msc 缘起

Windows如何添加右键新建菜单

Windows如何添加右键新建菜单 文章目录 Windows如何添加右键新建菜单实验环境缘起以新建`.md`文件为例第一步第二步第三步 总结 实验环境 Windows7 缘起 因为我习惯用 Markdown 格式写文本,每次新建一个.txt后都要手动修改为.md,真的麻烦。如何在右键新建菜单中添加.md选项呢? 网上有很多方法,这些方法我都尝试了,要么太麻烦,要么不凑效

【Rust练习】12.枚举

练习题来自:https://practice-zh.course.rs/compound-types/enum.html 1 // 修复错误enum Number {Zero,One,Two,}enum Number1 {Zero = 0,One,Two,}// C语言风格的枚举定义enum Number2 {Zero = 0.0,One = 1.0,Two = 2.0,}fn m