需要用到minhook
先编译DLL
#include <Windows.h>
#include <string>
#include <TlHelp32.h>
#include <Shlwapi.h>#include "MinHook.h"
// 自动选择正确的MinHook库
#pragma comment(lib, "Shlwapi.lib")
#if defined(_M_X64)
#pragma comment(lib, "libMinHook.x64.lib")
#else
#pragma comment(lib, "libMinHook.x86.lib")
#endif// 定义缺失的NTAPI类型
typedef struct _UNICODE_STRING {USHORT Length;USHORT MaximumLength;PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;typedef struct _OBJECT_ATTRIBUTES {ULONG Length;HANDLE RootDirectory;PUNICODE_STRING ObjectName;ULONG Attributes;PVOID SecurityDescriptor;PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;typedef struct _IO_STATUS_BLOCK {union {NTSTATUS Status;PVOID Pointer;};ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;// 定义NTSTATUS类型
typedef LONG NTSTATUS;// NTAPI常量
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L)
#define FILE_CREATE 0x00000002
#define FILE_OVERWRITE_IF 0x00000005
#define FILE_OPEN_IF 0x00000003// 原始函数指针
typedef HANDLE(WINAPI* CreateFileW_t)(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);typedef NTSTATUS(WINAPI* NtCreateFile_t)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, PLARGE_INTEGER,ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);// 全局变量
CreateFileW_t OriginalCreateFileW = nullptr;
NtCreateFile_t OriginalNtCreateFile = nullptr;
volatile LONG g_hookInitialized = 0;// 调试输出宏
#ifdef _DEBUG
#define DEBUG_OUTPUT(msg) OutputDebugStringW(msg)
#else
#define DEBUG_OUTPUT(msg)
#endif// 精确判断资源管理器进程
bool IsExplorerProcess()
{static bool isExplorer = false;static bool checked = false;if (checked)return isExplorer;WCHAR exePath[MAX_PATH] = { 0 };if (GetModuleFileNameW(nullptr, exePath, MAX_PATH) > 0){// 提取文件名WCHAR* fileName = PathFindFileNameW(exePath);// 不区分大小写比较if (_wcsicmp(fileName, L"explorer.exe") == 0){DEBUG_OUTPUT(L"Detected explorer.exe process");isExplorer = true;}}checked = true;return isExplorer;
}// 判断是否创建新文件的操作
bool IsFileCreation(DWORD creationDisposition)
{return (creationDisposition == CREATE_ALWAYS ||creationDisposition == CREATE_NEW ||creationDisposition == OPEN_ALWAYS);
}// CreateFileW 钩子
HANDLE WINAPI HookedCreateFileW(LPCWSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile)
{if (IsExplorerProcess() && IsFileCreation(dwCreationDisposition)){DEBUG_OUTPUT(L"Blocking CreateFileW: ");DEBUG_OUTPUT(lpFileName);SetLastError(ERROR_ACCESS_DENIED);return INVALID_HANDLE_VALUE;}return OriginalCreateFileW(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes,dwCreationDisposition,dwFlagsAndAttributes,hTemplateFile);
}// NtCreateFile 钩子
NTSTATUS WINAPI HookedNtCreateFile(PHANDLE FileHandle,ACCESS_MASK DesiredAccess,POBJECT_ATTRIBUTES ObjectAttributes,PIO_STATUS_BLOCK IoStatusBlock,PLARGE_INTEGER AllocationSize,ULONG FileAttributes,ULONG ShareAccess,ULONG CreateDisposition,ULONG CreateOptions,PVOID EaBuffer,ULONG EaLength)
{if (IsExplorerProcess() &&(CreateDisposition == FILE_CREATE ||CreateDisposition == FILE_OVERWRITE_IF ||CreateDisposition == FILE_OPEN_IF)){// 获取文件名WCHAR fileName[MAX_PATH] = { 0 };if (ObjectAttributes && ObjectAttributes->ObjectName && ObjectAttributes->ObjectName->Buffer){// 安全复制文件名size_t maxLen = min(ObjectAttributes->ObjectName->Length / sizeof(WCHAR), MAX_PATH - 1);wcsncpy_s(fileName, MAX_PATH, ObjectAttributes->ObjectName->Buffer, maxLen);}DEBUG_OUTPUT(L"Blocking NtCreateFile: ");DEBUG_OUTPUT(fileName);return STATUS_ACCESS_DENIED;}return OriginalNtCreateFile(FileHandle,DesiredAccess,ObjectAttributes,IoStatusBlock,AllocationSize,FileAttributes,ShareAccess,CreateDisposition,CreateOptions,EaBuffer,EaLength);
}// 初始化钩子
void InitializeHook()
{if (InterlockedCompareExchange(&g_hookInitialized, 1, 0) != 0)return;if (MH_Initialize() != MH_OK){DEBUG_OUTPUT(L"MH_Initialize failed");return;}// 挂钩 CreateFileWauto pCreateFileW = reinterpret_cast<LPVOID>(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateFileW"));if (pCreateFileW &&MH_CreateHook(pCreateFileW, &HookedCreateFileW,reinterpret_cast<LPVOID*>(&OriginalCreateFileW)) == MH_OK){if (MH_EnableHook(pCreateFileW) == MH_OK){DEBUG_OUTPUT(L"CreateFileW hook installed");}else{DEBUG_OUTPUT(L"MH_EnableHook for CreateFileW failed");}}else{DEBUG_OUTPUT(L"CreateFileW hook creation failed");}// 挂钩更底层的 NtCreateFileauto pNtCreateFile = reinterpret_cast<LPVOID>(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateFile"));if (pNtCreateFile &&MH_CreateHook(pNtCreateFile, &HookedNtCreateFile,reinterpret_cast<LPVOID*>(&OriginalNtCreateFile)) == MH_OK){if (MH_EnableHook(pNtCreateFile) == MH_OK){DEBUG_OUTPUT(L"NtCreateFile hook installed");}else{DEBUG_OUTPUT(L"MH_EnableHook for NtCreateFile failed");}}else{DEBUG_OUTPUT(L"NtCreateFile hook creation failed");}
}// DLL入口点
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved)
{switch (reason){case DLL_PROCESS_ATTACH:DisableThreadLibraryCalls(hModule);InitializeHook();break;case DLL_PROCESS_DETACH:if (g_hookInitialized){MH_DisableHook(MH_ALL_HOOKS);MH_Uninitialize();DEBUG_OUTPUT(L"MinHook uninitialized");}break;}return TRUE;
}
再编译注入程序
// 简易注入工具示例
#include <Windows.h>
#include <TlHelp32.h>DWORD GetExplorerPID()
{PROCESSENTRY32W pe32 = { sizeof(pe32) };HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (Process32FirstW(snapshot, &pe32)) {do {if (_wcsicmp(pe32.szExeFile, L"explorer.exe") == 0) {CloseHandle(snapshot);return pe32.th32ProcessID;}} while (Process32NextW(snapshot, &pe32));}CloseHandle(snapshot);return 0;
}int main()
{DWORD pid = GetExplorerPID();if (pid == 0) return 1;HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);if (!hProcess) return 2;LPCWSTR dllPath = L"C:\\Visual Studio 2015\\Projects\\Hook测试\\x64\\Release\\Hook测试.dll";SIZE_T pathSize = (wcslen(dllPath) + 1) * sizeof(WCHAR);LPVOID pRemoteMem = VirtualAllocEx(hProcess, NULL, pathSize,MEM_COMMIT, PAGE_READWRITE);if (!pRemoteMem) {CloseHandle(hProcess);return 3;}if (!WriteProcessMemory(hProcess, pRemoteMem, dllPath, pathSize, NULL)) {VirtualFreeEx(hProcess, pRemoteMem, 0, MEM_RELEASE);CloseHandle(hProcess);return 4;}HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0,(LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "LoadLibraryW"),pRemoteMem, 0, NULL);if (!hThread) {VirtualFreeEx(hProcess, pRemoteMem, 0, MEM_RELEASE);CloseHandle(hProcess);return 5;}WaitForSingleObject(hThread, INFINITE);CloseHandle(hThread);VirtualFreeEx(hProcess, pRemoteMem, 0, MEM_RELEASE);CloseHandle(hProcess);return 0;
}