13个版本 (7个稳定版)
2.1.1 | 2024年7月2日 |
---|---|
2.1.0 | 2023年9月6日 |
2.0.0 | 2023年4月5日 |
1.4.0 | 2023年1月3日 |
0.1.2 | 2019年12月14日 |
#75 在 硬件支持
每月155次下载
86KB
2K SLoC
ilhook
此包提供内联hook x86
和 x64
指令集二进制代码的方法。
HOOK 是一种拦截函数调用并通过用户定义的代码处理它们的机制。
安装
此包与Cargo兼容,位于 crates.io 上。将其添加到您的 Cargo.toml
中,如下所示
[dependencies]
ilhook = "2"
hook类型
Ilhook支持4种hook类型。
跳回hook
此类型用于您希望在指定时间获取一些信息或修改某些值(参数、栈变量、堆变量等)时。
假设我们有一个C++函数
void check_serial_number(std::string& sn){
uint32_t machine_hash = get_machine_hash();
uint32_t sn_hash = calc_hash(sn);
// we want to modify the result of this comparison.
if (sn_hash == machine_hash) {
// success
}
// fail
}
并且它编译成汇编代码
0x401054 call get_machine_hash ;get_machine_hash()
0x401059 mov ebx, eax
; ...
0x401070 lea eax, sn
0x401076 push eax
0x401077 call calc_hash ;calc_hash(sn)
0x40107C add esp, 4
0x40107F cmp eax, ebx ;we want to modify the eax here!
0x401081 jnz _check_fail
; check_success
现在我们开始
use ilhook::x86::{Hooker, HookType, Registers, CallbackOption, HookFlags};
unsafe extern "C" fn on_check_sn(
reg: *mut Registers,
_: usize
) {
println!("m_hash: {}, sn_hash: {}", (*reg).ebx, (*reg).eax);
(*reg).eax = (*reg).ebx; //we modify the sn_hash!
}
let hooker = Hooker::new(
0x40107F,
HookType::JmpBack(on_check_sn),
CallbackOption::None,
0,
HookFlags::empty(),
);
hooker.hook().unwrap();
然后 check_serial_number
将始终走成功路径。
函数hook
此类型用于您想用您自定义的函数替换函数时。请注意,您应该只在函数的开始处hook。
假设我们有一个函数
fn foo(x: u64) -> u64 {
x * x
}
assert_eq!(foo(5), 25);
并且您想让它返回 x*x+3
,这意味着 foo(5)==28。
现在让我们hook
use ilhook::x64::{Hooker, HookType, Registers, CallbackOption, HookFlags};
unsafe extern "win64" fn new_foo(
reg: *mut Registers,
_ :usize,
_ :usize
) -> usize {
let x = (&*reg).rdi as usize;
x * x + 3
}
let hooker = Hooker::new(
foo as usize,
HookType::Retn(new_foo),
CallbackOption::None,
0,
HookFlags::empty(),
);
unsafe { hooker.hook().unwrap() };
assert_eq!(foo(5), 28);
跳转地址hook
此类型用于您想更改原始运行路径到您想要的任何路径时。
枚举 HookType::JmpToAddr
的第一个元素表示在回调例程返回后,EIP希望跳转到何处。
跳转返回hook
此类型用于您想更改原始运行路径到您想要的任何路径,并且目标地址可能由输入参数更改。
EIP将跳转到回调例程返回的值。
注意
如果您没有指定 HookFlags::NOT_MODIFY_MEMORY_PROTECT
,则此包不是线程安全的。当然,如果您指定了,您需要自己修改目标地址的内存保护。
由于Rust的测试并行运行,如果不指定 --test-threads=1
,它可能会崩溃。
依赖关系
~16–30MB
~440K SLoC