最近一段时间由于使用MinHook的API挂钩不稳定,经常因为挂钩地址错误而导致宿主进程崩溃。听同事介绍了一款智能强大的挂钩引擎EasyHook。它比微软的detours好的一点是它的x64注入支持是免费开源的。不想微软的detours,想搞x64还得购买。
好了,闲话不多说,先下载EasyHook的开发库,当然有兴趣的同学可以下载源码进行学习。下载地址:http://easyhook.codeplex.com/releases/view/24401。我给的这个是2.6版本的。
EasyHook提供了两种模式的注入管理。一种是托管代码的注入,另一种是非托管代码的注入。我是学习C++的,所以直接学习了例子中的非托管项目UnmanagedHook。里面给了一个简单的挂钩MessageBeep API的示例。我需要将其改造成支持远程注入的。下面先给出钩子DLL代码:
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include "HookApi.h"
#include "easyhook.h"
#include "ntstatus.h"
ptrCreateFileW realCreateFileW = NULL;
ptrCreateFileA realCreateFileA = NULL;
HMODULE hKernel32 = NULL;
TRACED_HOOK_HANDLE hHookCreateFileW = new HOOK_TRACE_INFO();
TRACED_HOOK_HANDLE hHookCreateFileA = new HOOK_TRACE_INFO();
NTSTATUS statue;
ULONG HookCreateFileW_ACLEntries[1] = {0};
ULONG HookCreateFileA_ACLEntries[1] = {0};
int PrepareRealApiEntry()
{
OutputDebugString(L"PrepareRealApiEntry()\n");
// 获取真实函数地址
HMODULE hKernel32 = LoadLibrary(L"Kernel32.dll");
if (hKernel32 == NULL)
{
OutputDebugString(L"LoadLibrary(L\"Kernel32.dll\") Error\n");
return -6002;
}
OutputDebugString(L"LoadLibrary(L\"Kernel32.dll\") OK\n");
realCreateFileW = (ptrCreateFileW)GetProcAddress(hKernel32, "CreateFileW");
if (realCreateFileW == NULL)
{
OutputDebugString(L"(ptrCreateFileW)GetProcAddress(hKernel32, \"CreateFileW\") Error\n");
return -6007;
}
OutputDebugString(L"(ptrCreateFileW)GetProcAddress(hKernel32, \"CreateFileW\") OK\n");
realCreateFileA = (ptrCreateFileA)GetProcAddress(hKernel32, "CreateFileA");
if (realCreateFileA == NULL)
{
OutputDebugString(L"(ptrCreateFileA)GetProcAddress(hKernel32, \"CreateFileA\") Error\n");
return -6007;
}
OutputDebugString(L"(ptrCreateFileA)GetProcAddress(hKernel32, \"CreateFileA\") OK\n");
return 0;
}
void DoHook()
{
OutputDebugString(L"DoHook()\n");
statue = LhInstallHook(realCreateFileW,
MyCreateFileW,
/*(PVOID)0x12345678*/NULL,
hHookCreateFileW);
if(!SUCCEEDED(statue))
{
switch (statue)
{
case STATUS_NO_MEMORY:
OutputDebugString(L"STATUS_NO_MEMORY\n");
break;
case STATUS_NOT_SUPPORTED:
OutputDebugString(L"STATUS_NOT_SUPPORTED\n");
break;
case STATUS_INSUFFICIENT_RESOURCES:
OutputDebugString(L"STATUS_INSUFFICIENT_RESOURCES\n");
break;
default:
WCHAR dbgstr[512] = {0};
wsprintf(dbgstr, L"%d\n&