#hook #function #redirect #api

detour

使用 Rust 编写的跨平台绕行库

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开发工具

Download history 382/week @ 2024-03-13 611/week @ 2024-03-20 383/week @ 2024-03-27 267/week @ 2024-04-03 443/week @ 2024-04-10 308/week @ 2024-04-17 387/week @ 2024-04-24 555/week @ 2024-05-01 260/week @ 2024-05-08 286/week @ 2024-05-15 199/week @ 2024-05-22 190/week @ 2024-05-29 151/week @ 2024-06-05 115/week @ 2024-06-12 155/week @ 2024-06-19 719/week @ 2024-06-26

每月 1,192 次下载
用于 4 个crate(直接使用3个)

BSD-2-Clause

77KB
1.5K SLoC

detour-rs

Azure build Status crates.io version Documentation Language (Rust)

这是一个使用 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