Hook检测

检测OpenGL32.dll钩子:代码检查内存篡改
这段代码展示了如何使用`CheckHooks`函数检查opengl32.dll中'glBegin'函数是否被修改,通过对比内存中的原始和检查数据来判断是否存在hook。它用于检测潜在的代码注入或安全漏洞。
bool CheckHooks(const char* pszModule, const char* pszMethod, BYTE* pBytesToCheck, DWORD dwSize)
{
  bool bOK = false;
  HANDLE hProcess = ::GetCurrentProcess();
  HMODULE hModule = ::GetModuleHandle(pszModule);
  if (!hModule)
    return true; //The dll aint loaded
  LPVOID pAddress = ::GetProcAddress(hModule, pszMethod);

  // change the page-protection for the intercepted function
  DWORD dwOldProtect;
  if (!::VirtualProtectEx(hProcess, pAddress, dwSize, PAGE_EXECUTE_READ, &dwOldProtect))
    return false;

  //Read the bytes to see if someone hooked that function
  BYTE* pBytesInMem = (BYTE*)malloc(dwSize);
  DWORD dwRead = 0;
  if (::ReadProcessMemory(hProcess, pAddress, pBytesInMem, dwSize, &dwRead))
  {
    bOK = 0 != memcmp(pBytesInMem, pBytesToCheck, dwRead);

    /*
    char szAddress[_MAX_PATH];
    sprintf(szAddress, "%s::%s - at %lx - %s", pszModule, pszMethod, pAddress, bOK ? "OK" : "HACK");
    AgLog(szAddress);
    HANDLE hFile = CreateFile("c:\\temp.bin", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);
    DWORD dwWritten;
    WriteFile(hFile, pBytesToCheck, dwRead, &dwWritten, NULL);
    CloseHandle(hFile);  
    */
  }

  //
  // restore page protection
  //
  VirtualProtectEx(hProcess, pAddress, dwSize, dwOldProtect, &dwOldProtect);

  free(pBytesInMem);

  return bOK;
}        
 代码调用方法


BYTE byHokoHack[1] = {0xE8};
BYTE byRegularJumpHack[1] = {0xE9};
if ( !CheckHooks("opengl32.dll", "glBegin", byHokoHack, sizeof(byHokoHack))
|| !CheckHooks("opengl32.dll", "glBegin", byRegularJumpHack, sizeof(byRegularJumpHack))
)
{
m_sDll = "opengl32.dll (patched)";
return 11;
}

用法:

BYTE byHokoHack[1] = {0xE8}; 
  BYTE byRegularJumpHack[1] = {0xE9}; 
  if ( !CheckHooks("opengl32.dll", "glBegin", byHokoHack, sizeof(byHokoHack))
    || !CheckHooks("opengl32.dll", "glBegin", byRegularJumpHack, sizeof(byRegularJumpHack))
    )

### 实现 Inline Hook检测方法 Inline Hook 是一种通过修改目标函数入口处的指令,将其跳转到另一个位置的技术。为了检测程序中是否存在 Inline Hook,可以采用以下几种方式: #### 1. **比较原始函数与内存中的代码** 可以通过读取目标函数的二进制数据并与已知未被 Hook 的版本进行对比来判断是否有改动。如果发现目标函数的起始部分被替换成了 `JMP` 或其他跳转指令,则可能已被 Inline Hook 修改。 ```python import ctypes def detect_inline_hook(function_address, original_bytes): """ 检测指定地址上的函数是否被 Inline Hook 替换。 :param function_address: 被检测的目标函数地址 (int) :param original_bytes: 原始函数开头字节序列 (bytes) :return: 如果存在差异返回 True;否则 False """ byte_length = len(original_bytes) buffer = (ctypes.c_ubyte * byte_length).from_address(function_address) current_bytes = bytes(buffer) return current_bytes != original_bytes # 示例:假设我们知道某个函数的原始前缀字节 original_function_prefix = b"\x55\x8B\xEC" # 假设这是原生函数的前三条汇编指令对应的机器码 function_to_check = 0x7FFEFAA9C3F0 # 目标函数地址 is_hooked = detect_inline_hook(function_to_check, original_function_prefix) print(f"Function is hooked: {is_hooked}") ``` 这种方法依赖于事先知道目标函数的原始字节序列[^1]。 --- #### 2. **扫描模块导入表和导出表** 对于某些类型的 Inline Hook(如 IAT/EAT Hook),它们可能会篡改 PE 文件结构中的导入/导出表。因此,可以通过分析这些表项的内容变化来间接推断是否存在 Hook 行为。 以下是伪代码逻辑描述: - 加载目标进程的映像文件头; - 提取出其 `.idata` 和 `.edata` 区域的信息; - 对比实际加载的 API 地址与预期的标准库地址列表之间的偏差情况。 此过程较为复杂,涉及 Windows 平台下 PEB 结构解析等内容[^2]。 --- #### 3. **利用调试工具或反汇编框架动态跟踪** 借助第三方库(例如 PyDbg、WinAppDbg 或者 IDAPython)可以在运行时捕捉异常行为模式。当遇到可疑的 JMP/CALL 流向未知区域而非官方 DLLs 中定义的位置时即可怀疑该处可能存在 Inline Hook 插入点[^3]。 示例脚本片段如下所示: ```c++ #include <windows.h> #include <iostream> bool CheckForInlineHooks(void* funcAddr) { DWORD oldProtect; VirtualProtect(funcAddr, 6, PAGE_EXECUTE_READWRITE, &oldProtect); BYTE firstByte = *(BYTE*)funcAddr; bool result = false; if ((firstByte == 0xE9 || firstByte == 0xE8)) { // Relative Jump or Call instruction opcodes. std::cout << "Potential inline hook detected!" << std::endl; result = true; } VirtualProtect(funcAddr, 6, oldProtect, nullptr); return result; } ``` 以上 C++ 版本展示了如何检查给定指针所指向存储单元内的首几个字节是否符合典型的重定向特征。 --- #### 总结 综上所述,针对 Inline Hook检测可以从静态角度出发——即基于文件层面的数据一致性校验;也可采取动态手段实时监控应用程序的行为轨迹寻找蛛丝马迹。每种策略都有各自的优缺点以及适用场景,请根据实际情况灵活选用合适的方法组合来进行综合判定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值