1. Hook的基本原理

Windows 钩子的本质是一段用以处理系统消息的程序,通过系统调用,将其挂入到系统。钩子的种类有很多,每一种钩子负责截获并处理相应的消息。钩子机制允许应用程序截获并处理发往指定窗口的消息或特定事件,其监视的窗口即可以是本进程内的也可以是由其他进程所创建的。在特定的消息发出,并在到达目的窗口之前,钩子程序先行截获此消息并得到对其的控制权。此时在钩子函数中就可以对截获的消息进行各种修改处理,甚至强行终止该消息的继续传递。
Detours库是Microsoft研究院的一个开发库,最新版本为3.0。它可以拦截任意的API调用,拦截代码是在动态运行时加载的,替换目标API最前面的几条指令,使其无条件的跳转到用户提供的拦截函数。

2. Hook神器Detours

2.1 Detours基本原理

2.1.1 Win32进程的内存管理

  1. 进程要执行的指令也放在虚存空间中
  2. 可以使用QueryProtectEx函数把存放指令的页面的权限更改为可读可写可执行,再改写其内容,从而修改正在运行的程序
  3. 可以使用VirtualAllocEx从一个进程为另一正运行的进程分配虚存,再使用 QueryProtectEx函数把页面的权限更改为可读可写可执行,并把要执行的指令以二进制机器码的形式写入,从而为一个正在运行的进程注入任意的代码

2.1.2 拦截WIN32 API的原理

  1. Target函数:要拦截的函数,通常为WindowsAPI
  2. Trampoline函数:Target函数的复制品。因为Detours将会改写Target函数,所以先把Target函数复制保存好,一方面仍然保存Target函数的过程调用语义,另一方面便于以后的恢复。
  3. Detour函数:用来替代Target函数的函数

2.1.3 为进程注入DLL

  1. 创建一个ThreadFuction,内容仅是调用LoadLibrary
  2. VirtualAllocEx为一个已在运行的进程分配一片虚存,并把权限更改为可读可写可执行。
  3. ThreadFuction的二进制机器码写入这片虚存。
  4. CreateRemoteThread在该进程上创建一个线程,传入前面分配的虚存的起始地址作为线程函数的地址,即可为一个已在运行的进程装入一个DLL。通过DllMain 即可在一个已在运行的进程中运行自己的代码

2.2 下载地址

  1. https://github.com/microsoft/detours

下载解压之后:
image.png

3. Hook实验

3.1 基本配置

x64 Native Tools Command Prompt for VS 2019 和 x86 Native Tools Command Prompt for VS 2019,这两个可以分别用来编译64位和32位的Detours
image.png
进入到/Detours-4.0.1/src目录:
image.png
然后使用nmake命令进行编辑:

  1. nmake /f Makefile

image.png
编译之后生成下面的文件:
image.png
创建项目之后,设置项目属性,其中:

  1. include添加包含目录
  2. lib.X64添加到库目录

包含目录:
image.png
库目录:
image.png
image.png

3.2 Hook代码

  1. 完整的C++代码如下所示:
  1. #include <iostream>
  2. #include "windows.h"
  3. #include "detours.h"
  4. #pragma comment(lib,"detours.lib")
  5. int (WINAPI* Old_MessageBoxA)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) = MessageBoxA;
  6. int WINAPI New_MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
  7. {
  8. return Old_MessageBoxA(NULL, "Hooked MessageBoxA", "Hooked MessageBoxA", NULL);
  9. }
  10. void Hook()
  11. {
  12. DetourTransactionBegin();
  13. DetourUpdateThread(GetCurrentThread());
  14. DetourAttach(&(PVOID&)Old_MessageBoxA, New_MessageBoxA);//Hook 相关函数
  15. DetourTransactionCommit();
  16. }
  17. void DeHook()
  18. {
  19. DetourTransactionBegin();
  20. DetourUpdateThread(GetCurrentThread());
  21. DetourDetach(&(PVOID&)Old_MessageBoxA, New_MessageBoxA);//Hook 相关函数
  22. DetourTransactionCommit();
  23. }
  24. int main()
  25. {
  26. std::cout << "Hello World!\n";
  27. MessageBoxA(NULL, "Hello World!", "MessageBoxA", NULL);
  28. Hook();
  29. MessageBoxA(NULL, "Hello World!", "MessageBoxA", NULL);
  30. DeHook();
  31. MessageBoxA(NULL, "Hello World!", "MessageBoxA", NULL);
  32. }

3.3 代码拆解

首先先声明要hook的两个函数的函数指针,这里是MessageBoxA和MessageBoxW:

  1. int (WINAPI* Old_MessageBoxA)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) = MessageBoxA;

然后创建Hook后要对上述两个函数进行的操作

  1. int WINAPI New_MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
  2. {
  3. return Old_MessageBoxA(NULL, "Hooked MessageBoxA", "Hooked MessageBoxA", NULL);
  4. }

编写相应的Hook操作:

  1. void Hook()
  2. {
  3. DetourTransactionBegin(); //开始Hook拦截
  4. DetourUpdateThread(GetCurrentThread()); //刷新当前线程
  5. DetourAttach(&(PVOID&)Old_MessageBoxA, New_MessageBoxA); //Hook 相关函数
  6. DetourTransactionCommit(); //拦截生效
  7. }

编写相应的Hook取消操作:

  1. void DeHook()
  2. {
  3. DetourTransactionBegin();
  4. DetourUpdateThread(GetCurrentThread());
  5. DetourDetach(&(PVOID&)Old_MessageBoxA, New_MessageBoxA);//取消Hook 相关函数
  6. DetourTransactionCommit();
  7. }

最后,在main函数中进行测试:

  1. int main()
  2. {
  3. std::cout << "Hello World!\n";
  4. MessageBoxA(NULL, "Hello World!", "MessageBoxA", NULL); //未Hook输出
  5. Hook();//开始Hook
  6. MessageBoxA(NULL, "Hello World!", "MessageBoxA", NULL);
  7. DeHook();//解除Hook
  8. MessageBoxA(NULL, "Hello World!", "MessageBoxA", NULL);
  9. }

为Hook弹出的弹窗分别为:
image.png
Hook后的弹窗分别为:
image.png
取消Hook的弹窗分别为:
image.png

4. referers

  1. https://blog.csdn.net/allenq/article/details/8363363
  2. https://blog.csdn.net/z971130192/article/details/100565010
  3. https://www.bilibili.com/s/video/BV1ZA411t7Hy
  4. https://www.cxyzjd.com/article/z971130192/100565398
  5. https://blog.csdn.net/tutucoo/article/details/85235478