消息钩子
- 我们创建DLL
- 我们在DLLmain函数中劫持了我们指定线程的窗口消息
- 我们利用另一个程序,在原程序中注入我们自定义的DLL
- DLL加载后就完成了劫持
实例
- 注意窗口句柄分为 宽字节 窄字节
- 通过
IsWindowUnicode
来判断 宽字节 窄字节 - 区别使用
SetWindowsHookExA
与SetWindowsHookExW
- 释放DLL的时候 要把回掉函数恢复
释放DLL的时候 别再DLL主线程中
FreeLibrary
FreeLibrary
会返回调用他的地址,但是这时候DLL已经被释放了所以会崩溃- 最好的做法是在第三方线程中施放 DLL
我们可以在DLL主线程中创建一个子线程
FreeLibrary
- 巧合编程
创建消息劫持DLL
//全局变量保存我们创建的钩子
HHOOK myhook_COMMAND;
//自定义我们的消息函数
LRESULT CALLBACK COMMANDProc(int nCode, WPARAM wParam, LPARAM lParam)
{
const CWPSTRUCT& cwps = *(CWPSTRUCT*)lParam;
int wmId = LOWORD(cwps.wParam);
char msg[128] = { 0 };
switch (cwps.message) {
case WM_COMMAND: {
if (HIWORD(cwps.wParam) == BN_CLICKED) {
char sz[128] = { 0 };
sprintf_s(sz, "触发 COMMAND nCode=%d id= %d lParam=%d", nCode , LOWORD(cwps.wParam), lParam);
OutputDebugStringA(sz);
}
}
}
return CallNextHookEx(myhook_COMMAND, nCode, wParam, lParam);
}
//劫持 原程序的消息
void dll_accach() {
//锁定劫持的线程id
DWORD dw_hack = 0;
HWND hCalc = FindWindowW(NULL, L"计算器");
dw_hack = GetWindowThreadProcessId(hCalc, NULL);
//劫持
myhook_COMMAND = SetWindowsHookEx(
WH_CALLWNDPROC, // 监听类型
COMMANDProc, // 处理函数
NULL, // 当前实例句柄
dw_hack // 监听窗口句柄
);
if (myhook_COMMAND == NULL)
{
char text[128] = { 0 };
sprintf_s(text, "COMMAND监听失败!error : %d n", GetLastError());
MessageBoxA(NULL, text, "错误", MB_OK);
}
//MessageBoxA(NULL, "绑定成功", "ok", MB_OK);
OutputDebugStringA("dll_accach");
}
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved) // reserved
{
// Perform actions based on the reason for calling.
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
OutputDebugStringA("DLL_PROCESS_ATTACH");
dll_accach();//注入
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
OutputDebugStringA("DLL_THREAD_ATTACH");
dll_accach();//注入
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
OutputDebugStringA("DLL_THREAD_DETACH");
break;
case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
OutputDebugStringA("DLL_PROCESS_DETACH");
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
创建DLL注入程序
void Inject() {
//1. 获取目标进程句柄
DWORD dwPID = 0;
HWND hGame = FindWindowA(NULL, "计算器");
if (hGame == NULL) {
return;
}
GetWindowThreadProcessId(hGame, &dwPID);
HANDLE hGameProcess = OpenProcess(PROCESS_ALL_ACCESS,
TRUE,
dwPID);
if (hGameProcess == NULL || hGameProcess == INVALID_HANDLE_VALUE) {
return;
}
//2 在目标进程空间中,开辟一块内存,存放待注入的dll路径
LPVOID lpAddr = VirtualAllocEx(hGameProcess,
NULL,
0x1000,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if (lpAddr == NULL) {
return;
}
SIZE_T dwWritedBytes = 0;
//3 向目标进程的写入注入dll路径
BOOL bRet = WriteProcessMemory(hGameProcess,
lpAddr,
"劫持窗口消息.dll",
sizeof("劫持窗口消息.dll"),
&dwWritedBytes);
//4 调用远程线程,使用LoadLibraryA,加载目标dll.
HANDLE hRemoteThread = CreateRemoteThread(hGameProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)LoadLibraryA,
lpAddr,
0,
NULL);
//5 等待DLL 结束运行
WaitForSingleObject(hRemoteThread, INFINITE);
DWORD dwExitCode = 0;
//6 获取DLL句柄
GetExitCodeThread(hRemoteThread, &dwExitCode);
//释放目标进程的注入dll FreeLibrary
CreateRemoteThread(hGameProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)FreeLibrary,
(LPVOID)dwExitCode,
0,
NULL);
}