12 个版本 (7 个重大更新)
0.8.1 | 2021年7月27日 |
---|---|
0.7.1 | 2019年8月25日 |
0.7.0 | 2019年6月10日 |
0.6.0 | 2019年1月3日 |
0.1.1 | 2017年6月22日 |
#671 在 开发工具
每月 1,192 次下载
用于 4 个crate(直接使用3个)
77KB
1.5K SLoC
这是一个使用 Rust 开发的跨平台绕行库。除了基本功能外,这个库还处理分支重定向、RIP 相对指令、热补丁、NOP 填充函数,并在挂钩的同时允许通过跳板调用原始函数。
这是为数不多的几个 跨平台 绕行库之一,为了保持这一特性,由于缺少跨平台 API,无法支持所有期望的功能。因此,不支持 EIP 重定位。
注意:目前需要 Nightly 才能使用 static_detour!
,并且默认启用。
平台
此库为以下目标提供 CI
- Linux
i686-unknown-linux-gnu
x86_64-unknown-linux-gnu
x86_64-unknown-linux-musl
- Windows
i686-pc-windows-gnu
i686-pc-windows-msvc
x86_64-pc-windows-gnu
x86_64-pc-windows-msvc
- macOS
i686-apple-darwin
x86_64-apple-darwin
安装
将以下内容添加到您的 Cargo.toml
[dependencies]
detour = "0.8.0"
示例
- 静态绕行(三种不同绕行方式之一)
use std::error::Error;
use detour::static_detour;
static_detour! {
static Test: /* extern "X" */ fn(i32) -> i32;
}
fn add5(val: i32) -> i32 {
val + 5
}
fn add10(val: i32) -> i32 {
val + 10
}
fn main() -> Result<(), Box<dyn Error>> {
// Reroute the 'add5' function to 'add10' (can also be a closure)
unsafe { Test.initialize(add5, add10)? };
assert_eq!(add5(1), 6);
assert_eq!(Test.call(1), 6);
// Hooks must be enabled to take effect
unsafe { Test.enable()? };
// The original function is detoured to 'add10'
assert_eq!(add5(1), 11);
// The original function can still be invoked using 'call'
assert_eq!(Test.call(1), 6);
// It is also possible to change the detour whilst hooked
Test.set_detour(|val| val - 5);
assert_eq!(add5(5), 0);
unsafe { Test.disable()? };
assert_eq!(add5(1), 6);
Ok(())
}
- 一个 Windows API 绕行示例可在 此处 获得;通过运行以下命令进行构建:
$ cargo build --example messageboxw_detour
提及
库的外部用户界面部分受到了 minhook-rs 的启发,该库由 Jascha-N 创建,并包含了他工作的派生代码。
附录
-
EIP 重定位
应在执行函数的前置指令时执行,同时函数本身正在绕行。这通过挂起所有受影响的线程,复制受影响的指令并追加一个
JMP
来返回函数实现。这几乎永远不会是一个问题,并且在单线程环境中永远不会是问题,但具体情况可能有所不同。 -
NOP 填充
int function() { return 0; } // xor eax, eax // ret // nop // nop // ...
由于检测到代码填充(
NOP/INT3
指令),因此支持此类函数,这些函数没有热补丁区域,并且太小而无法用5字节jmp
钩子。因此,需要替换尾部的NOP
指令的数量,以腾出空间进行绕行。
依赖项
~0.8–1.3MB
~25K SLoC