stevemk14ebr / PolyHook_2_0使用介绍

744 阅读5分钟

聚合钩2.0

C++17, x86/x64 钩子库 v2.0

第1条:https://www.codeproject.com/articles/1100579/polyhook-the-cplusplus-x-x-hooking-library

第2条:www.codeproject.com/Articles/12…

第三条:https://www.fireeye.com/blog/threat-research/2020/11/wow64-subsystem-internals-and-hooking-techniques.html

Dynamic Re-Writing:twitter.com/stevemk14eb…

======================================================================================================================

社区

寻求帮助,与他人聊天,在这里与我交谈

包装

PolyHook2在vcpkg上是可用的。如果你喜欢的话,可以考虑尝试这种安装方法。只要按照microsofts的指示安装vcpkg即可。

命令:

λ git clone https://github.com/Microsoft/vcpkg.git
λ cd vcpkg
λ .\bootstrap-vcpkg.bat -disableMetrics
λ (as admin) .\vcpkg integrate install

适用于x86

λ vcpkg.exe install polyhook2 --triplet x86-windows

对于x64

λ vcpkg.exe install polyhook2 --triplet x64-windows

然后你只需包括polyhook头文件,确保链接生成的.lib。

手动构建

见。#59(评论)

λ git clone --recursive https://github.com/stevemk14ebr/PolyHook_2_0.git
λ cd PolyHook_2_0
λ git submodule update --init --recursive
λ cmake -B"./_build" -DCMAKE_INSTALL_PREFIX="./_install/" -DPOLYHOOK_BUILD_SHARED_LIB=ON
λ cmake --build "./_build" --config Release --target INSTALL

我在下面提供了关于如何设置visual studio cmake环境的指导。如果你不想使用visual studio,也没关系,这是一个标准的cmake项目,可以通过命令行构建。

Visual Studio 2022

克隆该项目,并按上面的方法执行子模块初始化。不要运行cmake命令,而是。

打开VS 2022,进入file->open->cmake...这将加载项目并开始cmake生成。接下来进入cmake->build all或cmake->build,你也可以设置一个启动项和发布模式,使用播放按钮(不要使用安装目标)。Capstone、Zydis和asmjit被设置为自动构建和链接,你不需要单独构建它们。

文档

stevemk14ebr.github.io/PolyHook_2_…并阅读测试!

我设置了一个实例项目来展示如何将其作为一个静态库使用。你应该在改变这些选项时清除你的cmake缓存。该dll是用cmake选项导出所有符号构建的。这与典型的windows DLL不同,windows DLL是通过declspec(dllexport)手动导出的,相反,它的行为方式与linux dll一样,默认导出所有符号。这种风格应该使代码更容易维护,缺点是有很多导出,但我并不在乎。

特点

  1. 支持capstone和zydis作为反汇编后端,并且是完全抽象的。

  2. 内联钩子(x86/x64 迂回)

    • 在序言处放置一个jmp到回调,然后分配一个蹦床来继续执行原始函数
    • 完全在一个中间指令对象上操作,反汇编引擎是可交换的,默认包含capstone
    • 可以在编译时调用conv未知时进行JIT回调(见ILCallback.cpp)。
    • 跟随已经上钩的函数
    • 解决间接调用,如通过iat和hooks底层函数的调用
    • 重新定位序幕并解决所有位置相关的代码
      • 进入被覆盖部分的分支被解析到新的移动位置
      • 从被移动的序章回到原始部分的Jmp是通过jmp表解决的。
      • 在被移动的部分内的重定位被解决(不使用重定位表,使用引擎进行反汇编)
      • 非可重定位的指令通过动态二进制重写来重写,并用语义上等同的指令来替换。
    • x64蹦床不限于+-2GB,可以在任何地方,避免影子空间+没有寄存器被破坏(取决于迂回方案)。
      • 覆盖代码洞和填充字节可以被设置为主要策略,而不是作为一个后备方案
    • 如果内联钩子在中间步骤中失败,原始函数将不会被畸形化。所有的写入都是分批进行的,直到我们知道后面的步骤成功之后。
    • 完全支持跨架构的钩子。包括覆盖内存访问例程,以允许从32位进程读写64位内存。如果你足够聪明,可以编写回调所需的shellcode,你可以从32位进程中钩住64位。
    • 实现了有效的重钩逻辑。这可以用来对抗第三方将序言覆盖回原始字节。这被优化为几个简单的memcpy,而不是在hook()中重新执行整个逻辑。
  3. 运行时内联钩子

    • 具有普通内联钩子的所有优点,但JIT的翻译存根与给定的类型定义和ABI兼容。翻译存根将参数移到一个小结构中,作为指针传递给回调,并允许欺骗返回值。这允许工具在运行时生成钩子翻译存根,允许在运行时才知道类型定义的情况下完全内联钩住函数。
  4. 虚拟函数互换(VFuncSwap)

    • 交换C++ VTable中给定索引的指针,使其指向一个回调。
  5. 虚拟表交换(VTableSwap)

    • 在一个C++ VTable上执行深度拷贝,用新分配的拷贝替换指向该表的指针。然后交换副本中的指针条目,使其指向回调。
  6. 软件断点钩 (BreakpointHook)

    • 用0xCC覆盖一个函数的第一个字节并调用异常处理程序中的回调。为用户提供一个自动的方法来恢复被覆盖的原始字节。
  7. 硬件断点钩(HWBreakpointHook)

    • 设置CPU的调试寄存器,为调用线程添加一个HW执行BP。该回调在异常处理程序中被调用。记住HW BP是按线程来的,调用hook()的线程必须与被钩住的线程相同。你可能会发现快速迂回,然后在迂回的回调中设置HWBP,然后解除钩子是一个有用的结构。
  8. 导入地址表钩子(IatHook)

    • 通过PEB对加载的模块进行解析,找到IAT,然后将thunk指针交换到回调。
  9. 输出地址表钩子(EatHook)

    • 通过PEB对加载的模块进行解析,找到EAT,然后将指向出口的指针交换到回调。由于这是一个32位的偏移量,我们可以选择分配一个trampoline stub来完成向回调的全部转移,如果它超过了32位。

额外内容

  • 严格的单元测试,数以百计的测试,使用奇妙的库Catch
  • 与Unix兼容

注意事项

  • 断点测试不能在调试器下运行。它们现在被默认为注释了。

未来

支持Linux。有一个部分的unix实现,但它没有得到很好的测试。请做出贡献或报告错误。

许可证

MIT - 请考虑捐献

资源&/|参考文献

evolution536, DarthTon, IChooseYou on Unknowncheats.me

@Ochii &www.unknowncheats.me/forum/c-and…for EAT implementation

github.com/DarthTon/Bl…

www.codeproject.com/Articles/44…

wiki.osdev.org/CPU_Registe…

reverseengineering.stackexchange.com/questions/1…

web.archive.org/web/2017012…

github.com/odzhan/shel…