游戏注⼊教程(⼆)--HOOK注⼊
⼀、我们新建⼀个win32的dll,⽤来注⼊到游戏进程当中,注⼊成功的时候,会提⽰“注⼊成功”,⽽且提⽰注⼊到哪个窗⼝。
代码如下:
// dllmain.cpp : 定义 DLL 应⽤程序的⼊⼝点。
#include "stdafx.h"
// 枚举窗⼝进程ID是否为主进程
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) {
DWORD dwCurrentProcessId = *((DWORD*)lParam);
DWORD dwProcessId = 0;
GetWindowThreadProcessId(hWnd, &dwProcessId);
if (dwProcessId == dwCurrentProcessId && GetParent(hWnd) == NULL) {
*((HWND*)lParam) = hWnd;
return FALSE;
}
return TRUE;
}
// 获取主窗⼝的句柄
HWND GetMainHwnd()
{
DWORD dwCurrentProcessId = GetCurrentProcessId();
if (!EnumWindows(EnumWindowsProc, (LPARAM)&dwCurrentProcessId))
{
return (HWND)dwCurrentProcessId;
}
return NULL;
}
BOOL APIENTRY DllMain(HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBox(GetMainHwnd(), TEXT("注⼊成功"), TEXT("⽬标程序"), MB_OK);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
MessageBox(GetMainHwnd(), TEXT("卸载注⼊"), TEXT("⽬标程序"), MB_OK);
break;
}
return TRUE;
}
⼆、新建⼀个的injectDll.dll,这个dll是⽤来hook⽬标进程的,就是给⽬标进程中添加⼀个消息钩⼦。上⾯的dll是要注⼊到⽬标的dll,不要搞混了
// dllmain.cpp : 定义 DLL 应⽤程序的⼊⼝点。
#include "stdafx.h"
#include <TlHelp32.h>
#pragma data_seg("Shared")
HHOOK g_hHook = NULL;    // 钩⼦句柄
HHOOK g_hHook = NULL;    // 钩⼦句柄
TCHAR g_dllPath[MAX_PATH] = {0}; // 第三⽅dll的路径
BOOL  g_status = FALSE;    // 回调函数是否调⽤
#pragma data_seg()
#pragma comment(linker,"/section:Shared,RWS")
HINSTANCE g_hInst = NULL;
extern "C" BOOL _declspec(dllexport) InjectLib(DWORD dwThreadId, PCWSTR szDllPath);
extern "C" BOOL _declspec(dllexport) EjectLib(DWORD dwThreadId, PCWSTR szDllPath);
BOOL APIENTRY DllMain( HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_hInst = hModule;
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// 钩⼦处理函数,⽤来注⼊第三⽅dll,此函数会进⼊游戏进程空间
LRESULT CALLBACK InjectLibProc(int code, WPARAM wParam, LPARAM lParam) {
static BOOL bFirstTime = TRUE;
if (bFirstTime){
bFirstTime = FALSE;
LoadLibrary(g_dllPath); // 加载第三⽅待注⼊的dll
g_status = TRUE;
}
return CallNextHookEx(g_hHook, code, wParam, lParam);
}
// 钩⼦处理函数,⽤来卸载第三⽅dll,此函数会进⼊游戏进程空间
LRESULT CALLBACK EjectLibProc(int code, WPARAM wParam, LPARAM lParam) {
static BOOL bFirstTime = TRUE;
if (bFirstTime) {
bFirstTime = FALSE;
// 获取⼀个进程快照
HANDLE hthSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());  // 获取模块的结构信息
MODULEENTRY32W me = { sizeof(me) };
BOOL bFound = FALSE;
BOOL bMoreMods = Module32FirstW(hthSnapshot, &me);
for (; bMoreMods; bMoreMods = Module32NextW(hthSnapshot, &me))
{
bFound = (_wcsicmp(me.szModule, g_dllPath) == 0) || (_wcsicmp(me.szExePath, g_dllPath) == 0);
if (bFound) break;
}
if(bFound) FreeLibrary((dBaseAddr); // 卸载第三⽅待注⼊的dll
g_status = TRUE;
}
return CallNextHookEx(g_hHook, code, wParam, lParam);
}
// 注⼊DLL函数
BOOL InjectLib(DWORD dwThreadId,PCWSTR szDllPath) {
BOOL bOk = FALSE;
if (dwThreadId != 0) {
wcscpy_s(g_dllPath, MAX_PATH, szDllPath); // 拷贝路径字符串到共享区
g_hHook = SetWindowsHookEx(WH_GETMESSAGE, InjectLibProc, g_hInst, dwThreadId);
if (g_hHook == NULL) return bOk;
if (!PostThreadMessage(dwThreadId, WM_NULL, 0, 0)) return bOk;
// 判断游戏进程是否已经注⼊了第三⽅dll
// 判断游戏进程是否已经注⼊了第三⽅dll
while (!g_status) { Sleep(100); }
postthreadmessageif (!UnhookWindowsHookEx(g_hHook)) return bOk;
g_hHook = NULL;
bOk = TRUE;
}
return bOk;
}
// 卸载注⼊函数
BOOL EjectLib(DWORD dwThreadId, PCWSTR szDllPath) {
BOOL bOk = FALSE;
if (dwThreadId != 0) {
wcscpy_s(g_dllPath, MAX_PATH, szDllPath); // 拷贝路径字符串到共享区
g_hHook = SetWindowsHookEx(WH_GETMESSAGE, EjectLibProc, g_hInst, dwThreadId);  if (g_hHook == NULL) return bOk;
if (!PostThreadMessage(dwThreadId, WM_NULL, 0, 0)) return bOk;
// 判断游戏进程是否已经卸载了第三⽅dll
while (!g_status) { Sleep(100); }
if (!UnhookWindowsHookEx(g_hHook)) return bOk;
g_hHook = NULL;
bOk = TRUE;
}
return bOk;
}
三、 创建⼀个exe程序,⽤来把dll注⼊到⽬标进程中
// 注⼊dll
void CInjectToolDlg::OnBnClickedInject()
{
BOOL bOk = FALSE;
DWORD dwProcessId = 0, dwThreadId = 0;
HWND hWnd = ::FindWindow(NULL, _T("demo1"));
if (hWnd == NULL) {
AfxMessageBox(_T("demo1 Window not found.")); return;
}
dwThreadId = ::GetWindowThreadProcessId(hWnd, &dwProcessId);
if (dwThreadId == NULL) {
AfxMessageBox(_T("demo1 thread id not fetch.")); return;
}
HMODULE hModule = NULL;
__try {
hModule = ::LoadLibrary(_T("InjectDll.dll"));
if (hModule == NULL) __leave;
typedef BOOL(*InjectLib)(DWORD, PCWSTR);
InjectLib InjectLibFunc = (InjectLib)GetProcAddress(hModule, "InjectLib");
if (InjectLibFunc == NULL) __leave;
if (!InjectLibFunc(dwThreadId, TEXT("F:\\CPP\\pro\\inject\\Release\\inject.dll"))) __leave;  bOk = TRUE;
}
__finally {
if(hModule != NULL)
::FreeLibrary(hModule);
}
}
// 卸载dll
void CInjectToolDlg::OnBnClickedEject()
{
BOOL bOk = FALSE;
DWORD dwProcessId = 0, dwThreadId = 0;
HWND hWnd = ::FindWindow(NULL, _T("demo1"));
if (hWnd == NULL) {
AfxMessageBox(_T("demo1 Window not found.")); return;
}
dwThreadId = ::GetWindowThreadProcessId(hWnd, &dwProcessId);
if (dwThreadId == NULL) {
AfxMessageBox(_T("demo1 thread id not fetch.")); return;
}
HMODULE hModule = NULL;
__try {
hModule = ::LoadLibrary(_T("InjectDll.dll"));
if (hModule == NULL) __leave;
typedef BOOL(*EjectLib)(DWORD, PCWSTR);
EjectLib EjectLibFunc = (EjectLib)GetProcAddress(hModule, "EjectLib");
if (EjectLibFunc == NULL) __leave;
if (!EjectLibFunc(dwThreadId, TEXT("F:\\CPP\\pro\\inject\\Release\\inject.dll"))) __leave;  bOk = TRUE;
}
__finally {
if (hModule != NULL)
::FreeLibrary(hModule);
}
}