This is a cross-platform detour library developed in Rust. Beyond the basic functionality, this library handles branch redirects, RIP-relative instructions, hot-patching, NOP-padded functions, and allows the original function to be called using a trampoline whilst hooked.
This is one of few cross-platform detour libraries that exists, and to maintain this feature, not all desired functionality can be supported due to lack of cross-platform APIs. Therefore EIP relocation is not supported.
NOTE: Nightly is currently required, mostly due to untagged_union.
x86
: Windows, Linux, macOSx64
: Windows, Linux, macOSARM
: Not implemented, but foundation exists.Add this to your Cargo.toml
:
toml
[dependencies]
detour = "0.1.0"
... and this to your crate root:
```rust
extern crate detour; ```
```rust
extern "C" fn add(x: i32, y: i32) -> i32 { x + y }
static_detours! { struct DetourAdd: extern "C" fn(i32, i32) -> i32; }
fn main() { // Replaces the 'add' function with a closure that subtracts let mut hook = unsafe { DetourAdd.initialize(add, |x, y| x - y).unwrap() };
assert_eq!(add(1, 5), 6);
assert_eq!(hook.is_enabled(), false);
unsafe { hook.enable().unwrap(); }
assert_eq!(add(1, 5), -4);
assert_eq!(hook.call(1, 5), 6);
// Change the detour whilst hooked
hook.set_detour(|x, y| x * y);
assert_eq!(add(5, 5), 25);
unsafe { hook.disable().unwrap(); }
assert_eq!(hook.is_enabled(), false);
assert_eq!(hook.call(1, 5), 6);
assert_eq!(add(1, 5), 6);
} ```
Parh of the library's external user interface was inspired by minhook-rs, created by Jascha-N, and it contains derivative code of his work.
EIP relocation
Should be performed whenever a function's prolog instructions
are being executed, simultaneously as the function itself is being
detoured. This is done by halting all affected threads, copying the related
instructions and appending a JMP
to return to the function. This is
barely ever an issue, and never in single-threaded environments, but YMMV.
NOP-padding
c
int function() { return 0; }
// xor eax, eax
// ret
// nop
// nop
// ...
Functions such as this one, lacking a hot-patching area, and too small to
be hooked with a 5-byte jmp
, are supported thanks to the detection of
code padding (NOP/INT3
instructions). Therefore the required amount of
trailing NOP
instructions will be replaced, to make room for the detour.