S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理
方法介绍:把你的代码放到一个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, 
00);

    
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, 
00);

    
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 也会卸载掉.

Feedback

# re: DLL Inject -- 一、Windows 钩子(Hooks)  回复  更多评论   

2010-02-02 22:41 by S.l.e!ep.¢%
LRESULT CALLBACK GetMsgProc(
int code, // hook code
WPARAM wParam, // removal option
LPARAM lParam // message
)
{
return (LRESULT)CallNextHookEx(g_hook,code,wParam,lParam);
}

...
switch(uMsg)
{
....
case WM_COMMAND:
if(LOWORD(wParam) == IDC_INSTALLHOOK)
{
g_hook = SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,GetModuleHandle("xxx.dll"),0);
/*g_hook = SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,NULL,dwThreadID);*/
}
return TRUE;
....
}


....................... 全局钩子(SetWindowsHookEx( , , , 0)) 钩子代码在dll

hook.dll

..
BOOL WINAPI DllMain(
HINSTANCE hModule,
DWORD dwReason,
LPVOID lpvReserved
)
{
if(dwReason == DLL_PROCESS_ATTACH)
{
MessageBox(NULL,"hello","hello",0); // *
return TRUE;
}
}

# re: DLL Inject -- 一、Windows 钩子(Hooks) - (1)  回复  更多评论   

2010-02-05 13:14 by 99书城
上课的富士康就是

# re: DLL Inject -- 一、Windows 钩子(Hooks) - (1)[未登录]  回复  更多评论   

2010-05-20 00:14 by 123
做hook函数处理的时候都非常的小心,第一次看你的代码的就吓了一跳

居然在hook函数里做这么多事情,一般就是检查消息该不该传递给下一hook罢了。

如果有事情要做应该在dllmain里处理。

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理