本帖最后由 MicroBlock 于 2024-7-30 20:47 编辑
https://github.com/MicroCBer/blook
# 介绍
这段时间主要是在搓这个 blook (https://github.com/MicroCBer/blook),一个自己的 hook/hack 框架
为什么已经有这么多好的 Hook 框架了(比如 MinHook, Dobby, frida, subhook, detours.....)还要自己造轮子呢?其实还是对它们的 API 都不满意;
个个都声称有 C++ 兼容,但是个个的 API 都长得像 hook(void* target, void* hook) 这种东西;
用的时候东 cast 一下、西 cast 一下,南边还写一堆全局变量,也不支持 lambda 作为 hook 函数等...
同时,它们对逆向工程利用的周边建筑(infrastructure?)都不完善甚至没有,比如 xref, aob scan, CRT injection 等;
对某些特殊需求(如需要在函数中间 hook)支持也无法令人满意;
这些以前都是我手搓的,组合起来很别扭,一点都不优雅
于是出于解决这些种种问题的目的,我又造了个这个轮子。
现在,B* 已经完全切换至该框架运行,足见其完备性。将来 chronocat-native/crychiccat 也会切换至该框架~
不过目前还是项目初期,可能会有一些 bug 之类的,也还只支持 Windows x64,大伙看看就好~
Fun Facts
在重构至 blook 后:
> 20 changed files with 385 additions and 2,177 deletions.
> 初始化时间加速了约 80%
> 非常方便地实现了 Failing gracefully
# 示例代码
Inline hook a function? Easy!
auto process = blook::Process::self();
auto hook = process->module("user32.dll").value()
->exports("MessageBoxA")
->inline_hook();
hook->install([=](int64_t a, char *text, char *title, int64_t b) -> int64_t {
return hook->trampoline_t<int64_t(int64_t, char *, char *, int64_t)>()(
a, "oh yes", text, b);
});
MessageBoxA(nullptr, "hi", "hi", 0);
...hook more? Sure!
auto process = blook::Process::self();
auto mod = process->module("user32.dll").value();
for (auto& func: mod.obtain_exports()) {
auto hook = mod
->exports(func)
->inline_hook();
hook->install([=](int64_t a) -> int64_t {
// Yes, capture anything you want!
std::cout << "Someone called: " << std::hex << func << "\n";
return hook->trampoline_t<int64_t(int64_t)>()(a);
});
}
How about hooking a method that's not exported?
auto process = blook::Process::self();
auto mod = process->module().value();
// Let's find the specific function in .text (Code Segment) with blook's AOB shortcut!.
auto text_segment = mod->section(".text").value();
using ANYp = blook::memory_scanner::ANYPattern;
auto hook = text_segment.find_one({
0x55, 0x56, 0x57, 0x48, 0x83, 0xec, 0x70, 0x48, 0x8d, 0x6c, 0x24, 0x70,
0x48, 0xc7, 0x45, 0xf8, 0xfe, 0xff, 0xff, 0xff, 0x48, 0x89, 0xce, 0x48,
0x8d, 0x7d, 0xd0, 0x48, 0x89, 0xfa, 0xe8, 0x44, ANYp, ANYp, ANYp
})->sub(-0x28).as_function().inline_hook();
// And now it's easy to hook it.
hook->install([=](int64_t a) -> int64_t {
std::cout << "Someone called some internal function!\n";
return hook->trampoline_t<int64_t(int64_t)>()(a);
});
# 技术细节
我使用的反编译库是 https://github.com/zyantific/zydis,同时支持 assemble(有近似于asmjit的API,比较好使)和 disassemble,在易用性,二进制体积方面都挺不错的;另外,它还是无 allocation 的,意味着在 kernel module 之类的地方用变简单了一点
其他没什么好说的,就是一个比较方便的 inline_hook & trampoline;还对内存访问,xref等做了一些抽象 |