方法介绍:把你的代码放到一个DLL中;然后用 windows 钩子把它映射到其它进程。
Q: 为什么Windows钩子可以把一个DLL映射到其它进程?
A: 首先要看下 SetWindowsHookEx() 这个创建钩子函数的说明
Remarks
SetWindowsHookEx can be used to inject a DLL into another process. A 32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL cannot be
injected into a 32-bit process. If an application requires the use of hooks in other processes, it is required that a 32-bit application call
SetWindowsHookEx to inject a 32-bit DLL into 32-bit processes, and a 64-bit application call
SetWindowsHookEx to inject a 64-bit DLL into 64-bit processes. The 32-bit and
64-bit DLLs must have different names.
一个进程需要在其它进程里使用 hooks, 那么需要先调用 SetWindowsHookEx 注入一个DLL到另一个进程里; 需要注意的是 32-bit 的DLL只
能注入到32-bit的进程, 64-bit的DLL只能注入到64-bit 的进程.
注意:
1. 因为所有的Windows钩子都是基于消息的,也就是说,想注入的进程必须有窗口,如果它没有窗体,那么就不能使用这种方法了。
DLL代码:
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
g_hModDll = (HMODULE)hModule;
return TRUE;
}
LRESULT CallWndProc(int code, WPARAM wParam, LPARAM lParam)
{
CWPSTRUCT* pMsg = ((CWPSTRUCT*)lParam);
if( pMsg->message == g_nHOOKMsg )
{
MessageBox(NULL, "Successed to inject DLL", "Success", MB_OK);
UnInstallHook();
}
return CallNextHookEx(g_hHook, code, wParam, lParam);
}
HOOKDLL_API BOOL WINAPI InstallHook(HWND hWnd)
{
g_hHook = ::SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWndProc, g_hModDll, ::GetWindowThreadProcessId(hWnd, NULL));
if( g_hHook == NULL )
return FALSE;
if( g_nHOOKMsg == 0 )
g_nHOOKMsg = ::RegisterWindowMessage("WM_HOOK_MSG");
::SendMessage(hWnd, g_nHOOKMsg, 0, 0);
return ( g_hHook != NULL );
}
HOOKDLL_API int WINAPI UnInstallHook(void)
{
return UnhookWindowsHookEx( g_hHook );
}
#ifdef HOOKDLL_EXPORTS
#define HOOKDLL_API __declspec(dllexport)
#else
#define HOOKDLL_API __declspec(dllimport)
#endif
#pragma data_seg("Shared")
HMODULE g_hModDll = NULL;
HHOOK g_hHook = NULL;
UINT g_nHOOKMsg = 0;
#pragma data_seg()
#pragma comment(linker,"/Section:Shared, rws")
HOOKDLL_API BOOL WINAPI InstallHook(HWND hWnd);
HOOKDLL_API int WINAPI UnInstallHook(void);
DLL导出接口
EXPORTS
; Explicit exports can go here
InstallHook @1
UnInstallHook @2
界面的调用:
HMODULE hMoudle = ::LoadLibrary("E:\\dllhook\\Debug\\HookDLL.dll");
if ( hMoudle == NULL )
return ;
typedef BOOL (WINAPI *InstallHook)(HWND hWnd);
InstallHook fnInstallHook = (InstallHook)::GetProcAddress(hMoudle, "InstallHook");
if ( fnInstallHook == NULL )
return ;
fnInstallHook(fnInstallHook(::FindWindow(NULL, "testHooked")););
结果调用后,总有很多“怪事”发生,使用工具查看,目标进程模块确实已经加载了 Hook 的DLL,
但它总是走不到这个逻辑,
if( pMsg->message == g_nHOOKMsg )
{
MessageBox(NULL, "Successed to inject DLL", "Success", MB_OK);
UnInstallHook();
}
而且调试期间,testHooked.exe(即目标程序)会挂掉!
查看程序堆崩
0:000> .reload
Reloading current modules
.
0:000> g
ModLoad: 76390000 763ad000 C:\WINDOWS\system32\IMM32.DLL
ModLoad: 77dd0000 77e6b000 C:\WINDOWS\system32\ADVAPI32.dll
ModLoad: 77e70000 77f01000 C:\WINDOWS\system32\RPCRT4.dll
ModLoad: 629c0000 629c9000 C:\WINDOWS\system32\LPK.DLL
ModLoad: 74d90000 74dfb000 C:\WINDOWS\system32\USP10.dll
ModLoad: 5fd00000 5fd0d000 C:\WINDOWS\system32\MFC42LOC.DLL
ModLoad: 5d090000 5d127000 C:\WINDOWS\system32\COMCTL32.DLL
ModLoad: 5ad70000 5ada8000 C:\WINDOWS\system32\uxtheme.dll
ModLoad: 74720000 7476b000 C:\WINDOWS\system32\MSCTF.dll
ModLoad: 77c00000 77c08000 C:\WINDOWS\system32\version.dll
ModLoad: 755c0000 755ee000 C:\WINDOWS\system32\msctfime.ime
ModLoad: 774e0000 7761c000 C:\WINDOWS\system32\ole32.dll
ModLoad: 77fe0000 77ff1000 C:\WINDOWS\system32\Secur32.dll
ModLoad: 76fd0000 7704f000 C:\WINDOWS\system32\CLBCATQ.DLL
ModLoad: 77120000 771ac000 C:\WINDOWS\system32\OLEAUT32.dll
ModLoad: 77050000 77115000 C:\WINDOWS\system32\COMRes.dll
ModLoad: 77c00000 77c08000 C:\WINDOWS\system32\VERSION.dll
ModLoad: 10000000 10012000 c:\Desktop\test\HookDLL.dll
(ba4.13f0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=0012f1c4 ecx=7ffdf000 edx=00000000 esi=00000000 edi=00000000
eip=77d4e63b esp=0012f1f0 ebp=0012f204 iopl=0 nv up ei ng nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010293
USER32!__fnNCDESTROY+0x28:
77d4e63b 8b06 mov eax,dword ptr [esi] ds:0023:00000000=????????
0:000> kb100
ChildEBP RetAddr Args to Child
0012f204 7c90eae3 0012f214 00000018 00812d38 USER32!__fnNCDESTROY+0x28
0012f228 77d494e3 77d866fc 00480c94 000001ef ntdll!KiUserCallbackDispatcher+0x13
0012f254 77d86760 00480c94 000001ef 00000000 USER32!NtUserMessageCall+0xc
0012f270 77d48709 00480c94 000001ef 00000000 USER32!MenuWndProcA+0x18
0012f29c 77d487eb 77d86748 00480c94 000001ef USER32!InternalCallWinProc+0x28
0012f304 77d4c00e 00000000 77d86748 00480c94 USER32!UserCallWinProcCheckWow+0x150
0012f334 77d4e366 77d86748 00480c94 000001ef USER32!CallWindowProcAorW+0x98
0012f354 73dd720d 77d86748 00480c94 000001ef USER32!CallWindowProcA+0x1b
0012f3c8 77d48709 00480c94 000001ef 00000000 MFC42!_AfxActivationWndProc+0x11b
0012f3f4 77d487eb 73dd70f2 00480c94 000001ef USER32!InternalCallWinProc+0x28
0012f45c 77d4b368 00000000 73dd70f2 00480c94 USER32!UserCallWinProcCheckWow+0x150
0012f4b0 77d4b3b4 00812d38 000001ef 00000000 USER32!DispatchClientMessage+0xa3
0012f4d8 7c90eae3 0012f4e8 00000018 00812d38 USER32!__fnDWORD+0x24
0012f4fc 77d494e3 77d4b2d5 00330cb0 0000007b ntdll!KiUserCallbackDispatcher+0x13
0012f550 77d4e010 00330cb0 0000007b 00330cb0 USER32!NtUserMessageCall+0xc
0012f56c 5ad73c20 00330cb0 0000007b 00330cb0 USER32!RealDefWindowProcA+0x47
0012f584 5ad98ab9 0012f5c0 00330cb0 003789f0 uxtheme!DoMsgDefault+0x2d
0012f5a4 5ad71ac7 003789f0 00378a14 0000007b uxtheme!OnDwpContextMenu+0x98
0012f5f4 5ad7367a 5ad98a21 00000000 00330cb0 uxtheme!_ThemeDefWindowProc+0x13a
0012f610 77d4e02b 00330cb0 0000007b 00330cb0 uxtheme!ThemeDefWindowProcA+0x18
0012f658 77d57593 00330cb0 0000007b 00330cb0 USER32!DefWindowProcA+0x6b
0012f670 77d54bcc 0076eb90 0000007b 00330cb0 USER32!DefWindowProcWorker+0x27
0012f6ac 77d575bf 00000000 0000007b 00330cb0 USER32!DefDlgProcWorker+0x6cf
0012f6c8 77d48709 00330cb0 0000007b 00330cb0 USER32!DefDlgProcA+0x22
0012f6f4 77d487eb 77d5759d 00330cb0 0000007b USER32!InternalCallWinProc+0x28
0012f75c 77d4c00e 00000000 77d5759d 00330cb0 USER32!UserCallWinProcCheckWow+0x150
0012f78c 77d4e366 77d5759d 00330cb0 0000007b USER32!CallWindowProcAorW+0x98
0012f7ac 73dd216b 77d5759d 00330cb0 0000007b USER32!CallWindowProcA+0x1b
0012f7cc 73dd1bb2 0000007b 00330cb0 00f0011e MFC42!CWnd::DefWindowProcA+0x44
0012f7e8 73dd1b05 0000007b 00330cb0 00f0011e MFC42!CWnd::WindowProc+0x3b
0012f848 73dd1a58 0012fe8c 00000000 0000007b MFC42!AfxCallWndProc+0x91
0012f868 73e6847d 00330cb0 0000007b 00330cb0 MFC42!AfxWndProc+0x36
0012f894 77d48709 00330cb0 0000007b 00330cb0 MFC42!AfxWndProcBase+0x39
0012f8c0 77d487eb 73e68444 00330cb0 0000007b USER32!InternalCallWinProc+0x28
0012f928 77d4b368 00000000 73e68444 00330cb0 USER32!UserCallWinProcCheckWow+0x150
0012f97c 77d4b3b4 0076eb90 0000007b 00330cb0 USER32!DispatchClientMessage+0xa3
0012f9a4 7c90eae3 0012f9b4 00000018 0076eb90 USER32!__fnDWORD+0x24
0012f9c8 77d494e3 77d4b2d5 00330cb0 000000a4 ntdll!KiUserCallbackDispatcher+0x13
0012fa1c 77d4e010 00330cb0 000000a4 00000002 USER32!NtUserMessageCall+0xc
0012fa38 77d4dfbe 00330cb0 000000a4 00000002 USER32!RealDefWindowProcA+0x47
0012fa80 77d57593 00330cb0 000000a4 00000002 USER32!DefWindowProcA+0x72
0012fa98 77d54bcc 0076eb90 000000a4 00000002 USER32!DefWindowProcWorker+0x27
0012fad4 77d575bf 00000000 000000a4 00000002 USER32!DefDlgProcWorker+0x6cf
0012faf0 77d48709 00330cb0 000000a4 00000002 USER32!DefDlgProcA+0x22
0012fb1c 77d487eb 77d5759d 00330cb0 000000a4 USER32!InternalCallWinProc+0x28
0012fb84 77d4c00e 00000000 77d5759d 00330cb0 USER32!UserCallWinProcCheckWow+0x150
0012fbb4 77d4e366 77d5759d 00330cb0 000000a4 USER32!CallWindowProcAorW+0x98
0012fbd4 73dd216b 77d5759d 00330cb0 000000a4 USER32!CallWindowProcA+0x1b
0012fbf4 73dd1bb2 000000a4 00000002 00f0011e MFC42!CWnd::DefWindowProcA+0x44
0012fc10 73dd1b05 000000a4 00000002 00f0011e MFC42!CWnd::WindowProc+0x3b
0012fc70 73dd1a58 0012fe8c 00000000 000000a4 MFC42!AfxCallWndProc+0x91
0012fc90 73e6847d 00330cb0 000000a4 00000002 MFC42!AfxWndProc+0x36
0012fcbc 77d48709 00330cb0 000000a4 00000002 MFC42!AfxWndProcBase+0x39
0012fce8 77d487eb 73e68444 00330cb0 000000a4 USER32!InternalCallWinProc+0x28
0012fd50 77d489a5 00000000 73e68444 00330cb0 USER32!UserCallWinProcCheckWow+0x150
0012fdb0 77d4bccc 0040306c 00000001 0040306c USER32!DispatchMessageWorker+0x306
0012fdc0 73dd125a 0040306c 00000000 0012fe8c USER32!DispatchMessageA+0xf
0012fdd0 73de6b99 00000004 0012fe8c 0012fe30 MFC42!CWinThread::PumpMessage+0x3c
0012fdf4 73de6a2e 00000004 00403038 00403038 MFC42!CWnd::RunModalLoop+0xd9
*** WARNING: Unable to verify checksum for testHooked.exe
0012fe30 004011a8 00403038 00403038 ffffffff MFC42!CDialog::DoModal+0xe8
0012ff00 73ddcf74 0131f6f2 00141f06 00000000 testHooked!CTestHookedApp::InitInstance+0x58 [D:\testHooked\testHooked.cpp @ 59]
0012ff10 00401ed3 00400000 00000000 00141f06 MFC42!AfxWinMain+0x49
0012ff24 00401df4 00400000 00000000 00141f06 testHooked!WinMain+0x15 [appmodul.cpp @ 30]
0012ffc0 7c816d4f 0131f6f2 0131f75a 7ffdd000 testHooked!WinMainCRTStartup+0x134
0012fff0 00000000 00401cc0 00000000 78746341 kernel32!BaseProcessStart+0x23 没看出问题,下了网上其它人写的DEMO然后进行比较,结果发现是
LRESULT CallWndProc(int code, WPARAM wParam, LPARAM lParam) 这里出问题,少了个 CALLBACK
LRESULT CALLBACK CallWndProc(int code, WPARAM wParam, LPARAM lParam)
因为函数参数的堆栈顺序不同导致程序挂掉!!
将DLL的代码进行修改:
// HookDLL.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include "HookDLL.h"
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
g_hModDll = (HMODULE)hModule;
return TRUE;
}
LRESULT CALLBACK CallWndProc(int code, WPARAM wParam, LPARAM lParam)
{
CWPSTRUCT* pStruct = (CWPSTRUCT*)lParam;
if( code == HC_ACTION)
{
if( pStruct->message == g_nHOOKMsg )
{
::UnhookWindowsHookEx(g_hHook);
MessageBox(NULL, "Successed to inject DLL", "Success", MB_OK);
}
}
return CallNextHookEx (g_hHook, code, wParam, lParam);
}
//---------------------------------------------------------------------------
// ModuleFromAddress
//
// Returns the HMODULE that contains the specified memory address
//---------------------------------------------------------------------------
static HMODULE ModuleFromAddress(PVOID pv)
{
MEMORY_BASIC_INFORMATION mbi;
return ((::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0) ? (HMODULE) mbi.AllocationBase : NULL);
}
HOOKDLL_API BOOL WINAPI InstallHook(HWND hWnd)
{
g_hHook = ::SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)(CallWndProc), ModuleFromAddress(CallWndProc), 0);
if( g_hHook == NULL )
return FALSE;
if( g_nHOOKMsg == 0 )
g_nHOOKMsg = ::RegisterWindowMessage("WM_HOOK_MSG");
::SendMessage(hWnd, g_nHOOKMsg, 0, 0);
return ( g_hHook != NULL );
}
HOOKDLL_API int WINAPI UnInstallHook(void)
{
return UnhookWindowsHookEx( g_hHook );
}
经测试,发现以下问题:1. 在 Hook 处理函数中
if( code == HC_ACTION)
{
if( pStruct->message == g_nHOOKMsg )
{
::UnhookWindowsHookEx(g_hHook);
MessageBox(NULL, "Successed to inject DLL", "Success", MB_OK);
}
}
MessageBox 本身会触发WH_GETMESSAGE 钩子,但在弹出 MessageBox 之前调用 UnhookWindowsHookEx(),结果还是会
连续弹出N个 MessageBox...
2. 一旦创建HOOK的程序关掉, 目录程序中的 Hook.dll 也会卸载掉.