全局API钩子的设置方法

本文将介绍一种简便的方法来设置系统范围内的全局API钩子。将使用AppInit_DLLs注册表键进行DLL注入,并使用Mhook库进行API钩子设置。为了说明这种技术,将展示如何轻松地从运行中的进程列表中隐藏calc.exe。

1. API钩子简介

API钩子意味着拦截某些API函数调用。通过它,可以改变任何软件的行为。钩子被广泛用于防病毒软件、安全应用程序、系统实用程序、编程工具等。

2. 本地和全局钩子

有两种类型的钩子:本地和全局。本地钩子仅应用于特定应用程序。全局钩子应用于系统中的所有进程。本文展示的钩子技术是全局的,影响所有进程的所有会话(与特定桌面绑定的SetWindowsHooks方式不同)。

3. AppInit_DLLs基础设施

AppInit_DLLs基础设施是一种机制,用于在所有用户模式进程中加载任意列表的DLL,这些进程与User32.dll相关联(实际上,很少有可执行文件不与它相关联)。这些DLL由User32.dll在其初始化时加载。

AppInit_DLLs基础设施的行为由存储在注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows键下的一组值配置。这些注册表值如表1所示:

描述 示例值
LoadAppInit_DLLs 全局启用或禁用AppInit_DLLs的值。 0x0 – AppInit_DLLs禁用。0x1 – AppInit_DLLs启用。
AppInit_DLLs 空格或逗号分隔的要加载的DLL列表。应使用短文件名指定DLL的完整路径。 C:\PROGRA~1\Test\Test.dll
RequireSignedAppInit_DLLs 要求代码签名的DLL。 0x0 – 加载任何DLL。0x1 – 仅加载代码签名的DLL。

4. Mhook库

有几种库用于API钩子。它们通常做的事情包括:

  • 用自定义代码(所谓的“蹦床”)覆盖目标函数的开头。当函数执行时,它将跳转到钩子处理程序。
  • 将目标函数的覆盖原始代码存储在某个地方。这对于目标函数的正确功能是必需的。
  • 恢复目标函数的覆盖部分。

Mhook是一个免费的开源库,用于API钩子。它支持x86和x64平台,使用起来非常简单。Mhook接口简单且相当自描述:

BOOL Mhook_SetHook(PVOID *ppSystemFunction, PVOID pHookFunction); BOOL Mhook_Unhook(PVOID *ppHookedFunction);

有关库使用的更多信息,请参见下一段中显示的代码示例或访问Mhook主页。

5. 编写代码

将编写一个用户模式DLL。首先,应该下载最新的Mhook源代码并将其添加到项目中。如果使用预编译头文件,请为Mhook文件关闭它。

如上所述,示例将隐藏calc.exe从运行中的进程列表中。

通过调用NTAPI函数NtQuerySystemInformation查询运行中的进程列表。因此,需要向项目中添加一些NTAPI内容。不幸的是,winternl.h头文件不包含完整的信息,不得不自己定义所需的数据类型:

#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) typedef struct _MY_SYSTEM_PROCESS_INFORMATION { ULONG NextEntryOffset; ULONG NumberOfThreads; LARGE_INTEGER Reserved[3]; LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; LARGE_INTEGER KernelTime; UNICODE_STRING ImageName; ULONG BasePriority; HANDLE ProcessId; HANDLE InheritedFromProcessId; } MY_SYSTEM_PROCESS_INFORMATION, *PMY_SYSTEM_PROCESS_INFORMATION; typedef NTSTATUS (WINAPI *PNT_QUERY_SYSTEM_INFORMATION)( __in SYSTEM_INFORMATION_CLASS SystemInformationClass, __inout PVOID SystemInformation, __in ULONG SystemInformationLength, __out_opt PULONG ReturnLength );

创建一个全局变量并初始化它以存储原始函数地址:

PNT_QUERY_SYSTEM_INFORMATION OriginalNtQuerySystemInformation = (PNT_QUERY_SYSTEM_INFORMATION)::GetProcAddress(::GetModuleHandle(L"ntdll"), "NtQuerySystemInformation");

在钩子函数中,首先调用原始函数。然后检查SystemInformationClass。如果是SystemProcessInformation,遍历运行中的进程列表,找到所有calc.exe的条目,将它们从列表中删除。就是这样!

注意:此函数必须具有与原始函数相同的签名。

NTSTATUS WINAPI HookedNtQuerySystemInformation( __in SYSTEM_INFORMATION_CLASS SystemInformationClass, __inout PVOID SystemInformation, __in ULONG SystemInformationLength, __out_opt PULONG ReturnLength ) { NTSTATUS status = OriginalNtQuerySystemInformation(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength); if (SystemProcessInformation == SystemInformationClass && STATUS_SUCCESS == status) { PMY_SYSTEM_PROCESS_INFORMATION pCurrent = NULL; PMY_SYSTEM_PROCESS_INFORMATION pNext = (PMY_SYSTEM_PROCESS_INFORMATION)SystemInformation; do { pCurrent = pNext; pNext = (PMY_SYSTEM_PROCESS_INFORMATION)((PUCHAR)pCurrent + pCurrent->NextEntryOffset); if (!wcsncmp(pNext->ImageName.Buffer, L"calc.exe", pNext->ImageName.Length)) { if (0 == pNext->NextEntryOffset) { pCurrent->NextEntryOffset = 0; } else { pCurrent->NextEntryOffset += pNext->NextEntryOffset; } pNext = pCurrent; } } while (pCurrent->NextEntryOffset != 0); } return status; }

设置钩子非常简单:在DLL加载到新进程时,从DllMain调用Mhook_SetHook:

BOOL WINAPI DllMain( __in HINSTANCE hInstance, __in DWORD Reason, __in LPVOID Reserved ) { switch (Reason) { case DLL_PROCESS_ATTACH: Mhook_SetHook((PVOID*)&OriginalNtQuerySystemInformation, HookedNtQuerySystemInformation); break; } }

取消钩子是通过在DLL从进程卸载时,从DllMain调用Mhook_Unhook来执行的:

BOOL WINAPI DllMain( __in HINSTANCE hInstance, __in DWORD Reason, __in LPVOID Reserved ) { switch (Reason) { case DLL_PROCESS_DETACH: Mhook_Unhook((PVOID*)&OriginalNtQuerySystemInformation); break; } }

6. 运行示例

现在是时候展示所描述的钩子在行动中了。构建项目并将生成的AppInitHook.dll放到C盘的根目录。

打开注册表编辑器并定位AppInit_DLLs注册表键(键是HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows)。然后指定钩子DLL的路径(在例子中是C:\AppInitHook.dll)。

修改注册表后,钩子开始工作。让运行几个calc.exe实例。然后打开Windows任务管理器并查看进程选项卡。根本没有calc.exe!

让看看由Mark Russinovich编写的另一个流行工具 - Process Explorer。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485