#hook #redirect #detour #function #api

detour3

用Rust编写的跨平台绕行库

2个不稳定版本

0.1.0 2022年12月29日
0.0.0 2022年12月29日

#1710Rust模式

Download history 102/week @ 2024-03-13 105/week @ 2024-03-20 154/week @ 2024-03-27 226/week @ 2024-04-03 138/week @ 2024-04-10 157/week @ 2024-04-17 99/week @ 2024-04-24 77/week @ 2024-05-01 73/week @ 2024-05-08 97/week @ 2024-05-15 80/week @ 2024-05-22 76/week @ 2024-05-29 75/week @ 2024-06-05 53/week @ 2024-06-12 53/week @ 2024-06-19 31/week @ 2024-06-26

每月229次下载

BSD-2-Clause

80KB
1.5K SLoC

detour-rs

Github Actions 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]
detour3 = "0.1.0"

示例

  • 静态绕行(三种不同绕行方式之一)
use std::error::Error;
use detour3::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来返回到函数来完成的。这几乎从未成为一个问题,在单线程环境中从未发生过,但YMMV。

  • NOP填充

    int function() { return 0; }
    // xor eax, eax
    // ret
    // nop
    // nop
    // ...
    

    这种缺少热修复区域的函数,且太小无法用5字节 jmp 钩子挂钩,得益于代码填充(NOP/INT3 指令)的检测而得到支持。因此,需要替换尾部 NOP 指令的数量,以腾出空间进行跳转。

依赖项

~0.8–8.5MB
~65K SLoC