百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术流 > 正文

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

citgpt 2024-09-07 13:31 6 浏览 0 评论

关于rp-bf

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

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

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

为了解决上述问题,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:https://github.com/0vercl0k/rp-bf.rs

参考资料

https://doar-e.github.io/blog/2023/05/05/competing-in-pwn2own-ics-2022-miami-exploiting-a-zero-click-remote-memory-corruption-in-iconics-genesis64/#hijacking-control-flow-roping-to-get-arbitrary-native-code-execution

https://github.com/yrp604/bochscpu

相关推荐

js中arguments详解

一、简介了解arguments这个对象之前先来认识一下javascript的一些功能:其实Javascript并没有重载函数的功能,但是Arguments对象能够模拟重载。Javascrip中每个函数...

firewall-cmd 常用命令

目录firewalldzone说明firewallzone内容说明firewall-cmd常用参数firewall-cmd常用命令常用命令 回到顶部firewalldzone...

epel-release 是什么

EPEL-release(ExtraPackagesforEnterpriseLinux)是一个软件仓库,它为企业级Linux发行版(如CentOS、RHEL等)提供额外的软件包。以下是关于E...

FullGC详解  什么是 JVM 的 GC
FullGC详解 什么是 JVM 的 GC

前言:背景:一、什么是JVM的GC?JVM(JavaVirtualMachine)。JVM是Java程序的虚拟机,是一种实现Java语言的解...

2024-10-26 08:50 citgpt

使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
跨域(CrossOrigin)

1.介绍  1)跨域问题:跨域问题是在网络中,当一个网络的运行脚本(通常时JavaScript)试图访问另一个网络的资源时,如果这两个网络的端口、协议和域名不一致时就会出现跨域问题。    通俗讲...

微服务架构和分布式架构的区别

1、含义不同微服务架构:微服务架构风格是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制(通常用HTTP资源API)。这些服务围绕业务能力构建并...

深入理解与应用CSS clip-path 属性
深入理解与应用CSS clip-path 属性

clip-pathclip-path是什么clip-path 是一个CSS属性,允许开发者创建一个剪切区域,从而决定元素的哪些部分可见,哪些部分会被隐...

2024-10-25 11:51 citgpt

HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
Request.ServerVariables 大全

Request.ServerVariables("Url")返回服务器地址Request.ServerVariables("Path_Info")客户端提供的路...

python操作Kafka

目录一、python操作kafka1.python使用kafka生产者2.python使用kafka消费者3.使用docker中的kafka二、python操作kafka细...

Runtime.getRuntime().exec详解

Runtime.getRuntime().exec详解概述Runtime.getRuntime().exec用于调用外部可执行程序或系统命令,并重定向外部程序的标准输入、标准输出和标准错误到缓冲池。...

promise.all详解 promise.all是干什么的
promise.all详解 promise.all是干什么的

promise.all详解promise.all中所有的请求成功了,走.then(),在.then()中能得到一个数组,数组中是每个请求resolve抛出的结果...

2024-10-24 16:21 citgpt

Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解

取消回复欢迎 发表评论: