下面这段代码是一个动态链接库的源码,它用于挂接MessageBoxW的调用
#include
<
windows.h
>
#include < ImageHlp.h > // for ImageDirectoryEntryToData
#include < TlHelp32.h > // for Module32First,MODULEENTRY32 and CreateToolhelp32Snapshot
#pragma comment(lib,"ImageHlp") // for ImageDirectoryEntryToData
#pragma data_seg("Shared")
HHOOK hhk = NULL; // shared by all process,must be initilized
#pragma data_seg()
#pragma comment(linker, "/Section:Shared,rws") // tell the linker to put hhk into the Shared section
// 钩子函数.它只简单地把消息传递到下一个钩子过程
LRESULT CALLBACK GetMsgProc( int nCode, WPARAM wParam, LPARAM lParam ){
return CallNextHookEx(hhk,nCode,wParam,lParam);
}
// 替换了的MessageBoxW.注意函数原型要和原来的一致,包括WIAPI
// 它显示一个消息框指明MessageBoxW已被截获
int WINAPI MyMessageBoxW( HWND hwnd,LPCWSTR lpszContent,LPCWSTR lpszCaption,UINT uType ){
MessageBoxW(hwnd,L " Call to MessageBoxW is interceptedZZZZZZZZZZ! " ,L " Hook " ,MB_OK);
return MessageBoxW( hwnd,lpszContent,lpszCaption,uType);
}
// 修改输入表
VOID ModifyIAT(HMODULE hmodCaller,LPCSTR szDllName,PROC pfnOrg,PROC pfnNew){
PIMAGE_THUNK_DATA pITD;
ULONG ulSize;
// 对每一个用到的dll,在输入表中都用一个IMAGE_IMPORT_DESCRIPTOR类型的
// 结构体保存该dll的信息
PIMAGE_IMPORT_DESCRIPTOR pIID;
// 用ImageDirectoryEntryToData可以取得输入表中的第一项
// 参数IMAGE_DIRECTORY_ENTRY_IMPORT指明要取得输入表,而不是其他表
pIID = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(hmodCaller,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT, & ulSize);
// 如果pIID为NULL,表示该模块没有输入表,返回
if ( ! pIID )
return ;
// IMAGE_IMPORT_DESCRIPTOR有一个Name的成员,该成员是dll名字的RVA
// hmodCaller实质是模块映射到进程空间中的基地址,通过将它转换为PBYTE类型,
// 再加上Name这个RVA就可以得到这项IMAGE_IMPORT_DESCRIPTOR记录的dll的名字
// 将这个名字与我们要挂接的dll的名字比较
// 如果两个名字不同,则pIID++取下一项IMAGE_IMPORT_DESCRIPTOR
for (; pIID -> Name; pIID ++ ){
if ( ! lstrcmpiA( szDllName,(LPSTR)((PBYTE)hmodCaller + pIID -> Name) ) )
break ;
}
// 如果遍历完所有dll都没有找到我们要挂接的dll,则返回
if ( ! pIID -> Name )
return ;
// 可以从一个dll中输入多个函数.对每一个输入的函数,用一个IMAGE_THUNK_DATA
// 结构体保存它的信息.在IMAGE_IMPORT_DESCRIPTOR中,有一个FirstThunk成员记录着
// 第一个IMAGE_THUNK_DATA(这个IMAGE_THUNK_DATA保存着第一个输入函数的信息)的RVA
// 我们用与取得dll名字一样的方法(基址+RVA)取得这个IMAGE_THUNK_DATA
pITD = (PIMAGE_THUNK_DATA)( (PBYTE)hmodCaller + pIID -> FirstThunk );
// IMAGE_THUNK_DATA有一个ul成员,它是一个共同体.通过这个共同体的Function成员,我们
// 可以得到输入函数在进程空间中的真实地址
// 将这个真实地址和我们要挂接的函数的地址比较,如果相同,则修改
// 否则pITD++取下一个输入函数的信息
for (; pITD -> u1.Function ; pITD ++ ){
PROC * ppfn = (PROC * ) & pITD -> u1.Function;
if ( * ppfn == pfnOrg ){
WriteProcessMemory(GetCurrentProcess(),ppfn, & pfnNew, sizeof (pfnNew),NULL);
return ;
}
}
}
// 安装钩子
_declspec(dllexport) VOID SetHook(){
if ( ! hhk ){
HINSTANCE hInst = LoadLibrary( TEXT( " HOOKAPILIB.DLL " ) );
if ( ! hInst )
return ;
hhk = SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,hInst, 0 );
FreeLibrary( hInst );
}
}
// 缷载钩子
_declspec(dllexport) VOID UnHook(){
if ( hhk ){
/* ModifyIAT(
hCurrentProcess,
"USER32.DLL",
(PROC)MyMessageBoxW,
GetProcAddress( GetModuleHandle("USER32.DLL"),"MessageBoxW" )
); */
UnhookWindowsHookEx( hhk );
}
}
// dll的入口函数.每当这个dll被映射到一个进程的地址空间中,我们就挂接MessageBoxW
// 在dll从进程的地址空间中缷载时,我们将原来的MessageboxW的地址写回进程中
// 要取得这个进程的基地址,要用到MODULEENTRY32和CreateToolhelp32Snapshot
// MODULEENTRY32的hModule成员就是进程的基地址
BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpvReserved ){
HMODULE hCurrentProcess;
MODULEENTRY32 me32;
HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE,GetCurrentProcessId() );
me32.dwSize = sizeof ( MODULEENTRY32 );
Module32First(hSnapshot, & me32);
hCurrentProcess = me32.hModule;
switch ( dwReason ){
case DLL_PROCESS_ATTACH:
ModifyIAT(
hCurrentProcess,
" USER32.DLL " ,
GetProcAddress( GetModuleHandle( " USER32.DLL " ), " MessageBoxW " ),
(PROC)MyMessageBoxW
);
break ;
case DLL_PROCESS_DETACH:
ModifyIAT(
hCurrentProcess,
" USER32.DLL " ,
(PROC)MyMessageBoxW,
GetProcAddress( GetModuleHandle( " USER32.DLL " ), " MessageBoxW " )
);
break ;
}
return TRUE;
}
#include < ImageHlp.h > // for ImageDirectoryEntryToData
#include < TlHelp32.h > // for Module32First,MODULEENTRY32 and CreateToolhelp32Snapshot
#pragma comment(lib,"ImageHlp") // for ImageDirectoryEntryToData
#pragma data_seg("Shared")
HHOOK hhk = NULL; // shared by all process,must be initilized
#pragma data_seg()
#pragma comment(linker, "/Section:Shared,rws") // tell the linker to put hhk into the Shared section
// 钩子函数.它只简单地把消息传递到下一个钩子过程
LRESULT CALLBACK GetMsgProc( int nCode, WPARAM wParam, LPARAM lParam ){
return CallNextHookEx(hhk,nCode,wParam,lParam);
}
// 替换了的MessageBoxW.注意函数原型要和原来的一致,包括WIAPI
// 它显示一个消息框指明MessageBoxW已被截获
int WINAPI MyMessageBoxW( HWND hwnd,LPCWSTR lpszContent,LPCWSTR lpszCaption,UINT uType ){
MessageBoxW(hwnd,L " Call to MessageBoxW is interceptedZZZZZZZZZZ! " ,L " Hook " ,MB_OK);
return MessageBoxW( hwnd,lpszContent,lpszCaption,uType);
}
// 修改输入表
VOID ModifyIAT(HMODULE hmodCaller,LPCSTR szDllName,PROC pfnOrg,PROC pfnNew){
PIMAGE_THUNK_DATA pITD;
ULONG ulSize;
// 对每一个用到的dll,在输入表中都用一个IMAGE_IMPORT_DESCRIPTOR类型的
// 结构体保存该dll的信息
PIMAGE_IMPORT_DESCRIPTOR pIID;
// 用ImageDirectoryEntryToData可以取得输入表中的第一项
// 参数IMAGE_DIRECTORY_ENTRY_IMPORT指明要取得输入表,而不是其他表
pIID = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(hmodCaller,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT, & ulSize);
// 如果pIID为NULL,表示该模块没有输入表,返回
if ( ! pIID )
return ;
// IMAGE_IMPORT_DESCRIPTOR有一个Name的成员,该成员是dll名字的RVA
// hmodCaller实质是模块映射到进程空间中的基地址,通过将它转换为PBYTE类型,
// 再加上Name这个RVA就可以得到这项IMAGE_IMPORT_DESCRIPTOR记录的dll的名字
// 将这个名字与我们要挂接的dll的名字比较
// 如果两个名字不同,则pIID++取下一项IMAGE_IMPORT_DESCRIPTOR
for (; pIID -> Name; pIID ++ ){
if ( ! lstrcmpiA( szDllName,(LPSTR)((PBYTE)hmodCaller + pIID -> Name) ) )
break ;
}
// 如果遍历完所有dll都没有找到我们要挂接的dll,则返回
if ( ! pIID -> Name )
return ;
// 可以从一个dll中输入多个函数.对每一个输入的函数,用一个IMAGE_THUNK_DATA
// 结构体保存它的信息.在IMAGE_IMPORT_DESCRIPTOR中,有一个FirstThunk成员记录着
// 第一个IMAGE_THUNK_DATA(这个IMAGE_THUNK_DATA保存着第一个输入函数的信息)的RVA
// 我们用与取得dll名字一样的方法(基址+RVA)取得这个IMAGE_THUNK_DATA
pITD = (PIMAGE_THUNK_DATA)( (PBYTE)hmodCaller + pIID -> FirstThunk );
// IMAGE_THUNK_DATA有一个ul成员,它是一个共同体.通过这个共同体的Function成员,我们
// 可以得到输入函数在进程空间中的真实地址
// 将这个真实地址和我们要挂接的函数的地址比较,如果相同,则修改
// 否则pITD++取下一个输入函数的信息
for (; pITD -> u1.Function ; pITD ++ ){
PROC * ppfn = (PROC * ) & pITD -> u1.Function;
if ( * ppfn == pfnOrg ){
WriteProcessMemory(GetCurrentProcess(),ppfn, & pfnNew, sizeof (pfnNew),NULL);
return ;
}
}
}
// 安装钩子
_declspec(dllexport) VOID SetHook(){
if ( ! hhk ){
HINSTANCE hInst = LoadLibrary( TEXT( " HOOKAPILIB.DLL " ) );
if ( ! hInst )
return ;
hhk = SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,hInst, 0 );
FreeLibrary( hInst );
}
}
// 缷载钩子
_declspec(dllexport) VOID UnHook(){
if ( hhk ){
/* ModifyIAT(
hCurrentProcess,
"USER32.DLL",
(PROC)MyMessageBoxW,
GetProcAddress( GetModuleHandle("USER32.DLL"),"MessageBoxW" )
); */
UnhookWindowsHookEx( hhk );
}
}
// dll的入口函数.每当这个dll被映射到一个进程的地址空间中,我们就挂接MessageBoxW
// 在dll从进程的地址空间中缷载时,我们将原来的MessageboxW的地址写回进程中
// 要取得这个进程的基地址,要用到MODULEENTRY32和CreateToolhelp32Snapshot
// MODULEENTRY32的hModule成员就是进程的基地址
BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpvReserved ){
HMODULE hCurrentProcess;
MODULEENTRY32 me32;
HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE,GetCurrentProcessId() );
me32.dwSize = sizeof ( MODULEENTRY32 );
Module32First(hSnapshot, & me32);
hCurrentProcess = me32.hModule;
switch ( dwReason ){
case DLL_PROCESS_ATTACH:
ModifyIAT(
hCurrentProcess,
" USER32.DLL " ,
GetProcAddress( GetModuleHandle( " USER32.DLL " ), " MessageBoxW " ),
(PROC)MyMessageBoxW
);
break ;
case DLL_PROCESS_DETACH:
ModifyIAT(
hCurrentProcess,
" USER32.DLL " ,
(PROC)MyMessageBoxW,
GetProcAddress( GetModuleHandle( " USER32.DLL " ), " MessageBoxW " )
);
break ;
}
return TRUE;
}
#include
<
windows.h
>
#define DLLNAME "HOOKAPILIB.DLL"
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ( " HOOKAPI " ) ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if ( ! RegisterClass ( & wndclass)){
MessageBox(NULL,TEXT( " DDFD " ),TEXT( " DDDFAS " ),MB_OK);
return 0 ;
}
hwnd = CreateWindow (szAppName, // window class name
TEXT ( " HOOKAPI " ), // window caption
WS_OVERLAPPEDWINDOW, // window style
462 , // initial x position
353 , // initial y position
100 , // initial x size
62 , // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
if ( hwnd ){
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
}
while (GetMessage ( & msg, NULL, 0 , 0 ))
{
TranslateMessage ( & msg) ;
DispatchMessage ( & msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
PROC SetHook;
HINSTANCE hInst = LoadLibrary(DLLNAME);
if ( ! hInst ){
DestroyWindow(hwnd);
MessageBox(hwnd,TEXT( " Can not load dll! " ),TEXT( " HOOKAPI " ),MB_ICONHAND);
PostQuitMessage( 0 );
return 0 ;
}
SetHook = GetProcAddress(hInst, " SetHook " );
if ( ! SetHook ){
DestroyWindow(hwnd);
MessageBox(hwnd,TEXT( " Can not find function! " ),TEXT( " HOOKAPI " ),MB_ICONHAND);
PostQuitMessage( 0 );
return 0 ;
}
// 安装钩子,这样我们的dll就被映射到每一个gui程序的进程空间中
SetHook();
FreeLibrary(hInst);
return 0 ;
}
case WM_DESTROY:
{
PROC UnHook;
HINSTANCE hInst = LoadLibrary(DLLNAME);
if ( ! hInst ){
MessageBox(hwnd,TEXT( " Can not load dll! " ),TEXT( " HOOKAPI " ),MB_ICONHAND);
PostQuitMessage( 0 );
return 0 ;
}
UnHook = GetProcAddress(hInst, " UnHook " );
if ( ! UnHook ){
MessageBox(hwnd,TEXT( " Can not find function! " ),TEXT( " HOOKAPI " ),MB_ICONHAND);
PostQuitMessage( 0 );
return 0 ;
}
// 退出之前我们要缷载钩子
UnHook();
PostQuitMessage ( 0 ) ;
return 0 ;
}
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
#define DLLNAME "HOOKAPILIB.DLL"
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ( " HOOKAPI " ) ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if ( ! RegisterClass ( & wndclass)){
MessageBox(NULL,TEXT( " DDFD " ),TEXT( " DDDFAS " ),MB_OK);
return 0 ;
}
hwnd = CreateWindow (szAppName, // window class name
TEXT ( " HOOKAPI " ), // window caption
WS_OVERLAPPEDWINDOW, // window style
462 , // initial x position
353 , // initial y position
100 , // initial x size
62 , // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
if ( hwnd ){
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
}
while (GetMessage ( & msg, NULL, 0 , 0 ))
{
TranslateMessage ( & msg) ;
DispatchMessage ( & msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
PROC SetHook;
HINSTANCE hInst = LoadLibrary(DLLNAME);
if ( ! hInst ){
DestroyWindow(hwnd);
MessageBox(hwnd,TEXT( " Can not load dll! " ),TEXT( " HOOKAPI " ),MB_ICONHAND);
PostQuitMessage( 0 );
return 0 ;
}
SetHook = GetProcAddress(hInst, " SetHook " );
if ( ! SetHook ){
DestroyWindow(hwnd);
MessageBox(hwnd,TEXT( " Can not find function! " ),TEXT( " HOOKAPI " ),MB_ICONHAND);
PostQuitMessage( 0 );
return 0 ;
}
// 安装钩子,这样我们的dll就被映射到每一个gui程序的进程空间中
SetHook();
FreeLibrary(hInst);
return 0 ;
}
case WM_DESTROY:
{
PROC UnHook;
HINSTANCE hInst = LoadLibrary(DLLNAME);
if ( ! hInst ){
MessageBox(hwnd,TEXT( " Can not load dll! " ),TEXT( " HOOKAPI " ),MB_ICONHAND);
PostQuitMessage( 0 );
return 0 ;
}
UnHook = GetProcAddress(hInst, " UnHook " );
if ( ! UnHook ){
MessageBox(hwnd,TEXT( " Can not find function! " ),TEXT( " HOOKAPI " ),MB_ICONHAND);
PostQuitMessage( 0 );
return 0 ;
}
// 退出之前我们要缷载钩子
UnHook();
PostQuitMessage ( 0 ) ;
return 0 ;
}
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
下面我们把我们的截获做得彻底些
下面新的dll的代码,里面加入了对LoadLibraryA和GetProcAddress的截获
#include
<
windows.h
>
#include < ImageHlp.h >
#include < TlHelp32.h >
#pragma comment(lib,"ImageHlp")
#pragma data_seg("Shared")
HHOOK hhk = NULL;
#pragma data_seg()
#pragma comment(linker, "/Section:Shared,rws")
HMODULE hmodThisDll;
LRESULT CALLBACK GetMsgProc( int nCode,WPARAM wParam,LPARAM lParam){
return CallNextHookEx(hhk,nCode,wParam,lParam);
}
int WINAPI MyMessageBoxW(HWND hwnd,LPCWSTR lpszContent,LPCWSTR lpszCaption,UINT uType){
MessageBoxW(hwnd,L " Call to MessageBoxW is intercepted! " ,L " HOOKAPILIB2 " ,MB_OK);
return MessageBoxW(hwnd,lpszContent,lpszCaption,uType);
}
VOID ModifyIAT(HMODULE hmodCaller,LPCSTR szDllName,PROC pfnOrg,PROC pfnNew){
PIMAGE_THUNK_DATA pITD;
ULONG ulSize;
PIMAGE_IMPORT_DESCRIPTOR pIID;
pIID = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(hmodCaller,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT, & ulSize);
if ( ! pIID )
return ;
for ( ; pIID -> Name; pIID ++ ){
if ( ! lstrcmpiA(szDllName,(LPSTR)((PBYTE)hmodCaller + pIID -> Name)) )
break ;
}
if ( ! pIID -> Name )
return ;
pITD = (PIMAGE_THUNK_DATA)((PBYTE)hmodCaller + pIID -> FirstThunk);
for ( ; pITD -> u1.Function ; pITD ++ ){
PROC * ppfn = (PROC * ) & pITD -> u1.Function;
if ( * ppfn == pfnOrg){
WriteProcessMemory(GetCurrentProcess() /* hmodCaller */ ,ppfn, & pfnNew, sizeof (pfnNew),NULL);
return ;
}
}
}
// 在这里枚举进程的所有模块,并修改各个模块对MessageBoxW的调用
// 这个枚举过程用到了Module32First和Module32Next
VOID ModifyIATs(LPCSTR szDllName,PROC pfnOrg,PROC pfnNew){
BOOL fOk = FALSE;
MODULEENTRY32 me32;
HANDLE hSnapshot;
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,GetCurrentProcessId());
me32.dwSize = sizeof ( me32 );
for ( fOk = Module32First( hSnapshot, & me32 ); fOk ; fOk = Module32Next(hSnapshot, & me32)){
if ( me32.hModule != hmodThisDll ){
ModifyIAT(me32.hModule,szDllName,pfnOrg,pfnNew);
}
}
CloseHandle( hSnapshot );
}
// LoadLriary的替代函数
HMODULE WINAPI MyLoadLibraryA( LPCSTR lpLibFileName ){
HMODULE hmod = LoadLibrary( lpLibFileName );
ModifyIAT( hmod, " USER32.DLL " ,
GetProcAddress(GetModuleHandle( " USER32.DLL " ), " MessageBoxW " ),MyMessageBoxW
);
return hmod;
}
// GetProcAddress的替代函数
FARPROC WINAPI MyGetProcAddress( HMODULE hModule,LPCSTR lpProcName ){
if ( hModule == GetModuleHandle( " USER32.DLL " ) &&
! lstrcmpiA(lpProcName, " MessageBoxW " ) )
return (PROC)MyMessageBoxW;
else
return GetProcAddress( hModule,lpProcName );
}
// _declspec(dllexport) VOID SetHook( DWORD dwThreadId ){
_declspec(dllexport) VOID SetHook( ){
if ( ! hhk ){
HINSTANCE hInst = LoadLibrary( " HOOKAPILIB2.DLL " );
if ( ! hInst )
return ;
hhk = SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,hInst, 0 );
FreeLibrary( hInst );
}
}
_declspec(dllexport) VOID UnHook(){
if ( hhk )
UnhookWindowsHookEx( hhk );
}
// 在DLL_PROCESS_ATTACH通知时,修改MessageBoxW,LoadLibraryA,GetProcAddress的地址
// 在DLL_PROCESS_DETACH通知时,将地址改回原来的地址
BOOL WINAPI DllMain(HINSTANCE hInstance,DWORD dwReason,LPVOID lpvReserved){
hmodThisDll = hInstance;
switch ( dwReason ){
case DLL_PROCESS_ATTACH:
ModifyIATs(
" USER32.DLL " ,
GetProcAddress(GetModuleHandle( " USER32.DLL " ),
" MessageBoxW " ),
(PROC)MyMessageBoxW);
ModifyIATs(
" KERNEL32.DLL " ,
GetProcAddress(GetModuleHandle( " KERNEL32.DLL " ), " LoadLibraryA " ),
(PROC)MyLoadLibraryA);
ModifyIATs( " KERNEL32.DLL " ,
GetProcAddress(GetModuleHandle( " KERNEL32.DLL " ), " GetProcAddress " ),
(PROC)MyGetProcAddress);
break ;
case DLL_PROCESS_DETACH:
ModifyIATs(
" USER32.DLL " ,
(PROC)MyMessageBoxW,
GetProcAddress(GetModuleHandle( " USER32.DLL " ),
" MessageBoxW " ));
ModifyIATs(
" KERNEL32.DLL " ,
(PROC)MyLoadLibraryA,
GetProcAddress(GetModuleHandle( " KERNEL32.DLL " ), " LoadLibraryA " ));
ModifyIATs(
" KERNEL32.DLL " ,
(PROC)MyGetProcAddress,
GetProcAddress(GetModuleHandle( " KERNEL32.DLL " ), " GetProcAddress " ));
break ;
}
return TRUE;
}
#include < ImageHlp.h >
#include < TlHelp32.h >
#pragma comment(lib,"ImageHlp")
#pragma data_seg("Shared")
HHOOK hhk = NULL;
#pragma data_seg()
#pragma comment(linker, "/Section:Shared,rws")
HMODULE hmodThisDll;
LRESULT CALLBACK GetMsgProc( int nCode,WPARAM wParam,LPARAM lParam){
return CallNextHookEx(hhk,nCode,wParam,lParam);
}
int WINAPI MyMessageBoxW(HWND hwnd,LPCWSTR lpszContent,LPCWSTR lpszCaption,UINT uType){
MessageBoxW(hwnd,L " Call to MessageBoxW is intercepted! " ,L " HOOKAPILIB2 " ,MB_OK);
return MessageBoxW(hwnd,lpszContent,lpszCaption,uType);
}
VOID ModifyIAT(HMODULE hmodCaller,LPCSTR szDllName,PROC pfnOrg,PROC pfnNew){
PIMAGE_THUNK_DATA pITD;
ULONG ulSize;
PIMAGE_IMPORT_DESCRIPTOR pIID;
pIID = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(hmodCaller,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT, & ulSize);
if ( ! pIID )
return ;
for ( ; pIID -> Name; pIID ++ ){
if ( ! lstrcmpiA(szDllName,(LPSTR)((PBYTE)hmodCaller + pIID -> Name)) )
break ;
}
if ( ! pIID -> Name )
return ;
pITD = (PIMAGE_THUNK_DATA)((PBYTE)hmodCaller + pIID -> FirstThunk);
for ( ; pITD -> u1.Function ; pITD ++ ){
PROC * ppfn = (PROC * ) & pITD -> u1.Function;
if ( * ppfn == pfnOrg){
WriteProcessMemory(GetCurrentProcess() /* hmodCaller */ ,ppfn, & pfnNew, sizeof (pfnNew),NULL);
return ;
}
}
}
// 在这里枚举进程的所有模块,并修改各个模块对MessageBoxW的调用
// 这个枚举过程用到了Module32First和Module32Next
VOID ModifyIATs(LPCSTR szDllName,PROC pfnOrg,PROC pfnNew){
BOOL fOk = FALSE;
MODULEENTRY32 me32;
HANDLE hSnapshot;
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,GetCurrentProcessId());
me32.dwSize = sizeof ( me32 );
for ( fOk = Module32First( hSnapshot, & me32 ); fOk ; fOk = Module32Next(hSnapshot, & me32)){
if ( me32.hModule != hmodThisDll ){
ModifyIAT(me32.hModule,szDllName,pfnOrg,pfnNew);
}
}
CloseHandle( hSnapshot );
}
// LoadLriary的替代函数
HMODULE WINAPI MyLoadLibraryA( LPCSTR lpLibFileName ){
HMODULE hmod = LoadLibrary( lpLibFileName );
ModifyIAT( hmod, " USER32.DLL " ,
GetProcAddress(GetModuleHandle( " USER32.DLL " ), " MessageBoxW " ),MyMessageBoxW
);
return hmod;
}
// GetProcAddress的替代函数
FARPROC WINAPI MyGetProcAddress( HMODULE hModule,LPCSTR lpProcName ){
if ( hModule == GetModuleHandle( " USER32.DLL " ) &&
! lstrcmpiA(lpProcName, " MessageBoxW " ) )
return (PROC)MyMessageBoxW;
else
return GetProcAddress( hModule,lpProcName );
}
// _declspec(dllexport) VOID SetHook( DWORD dwThreadId ){
_declspec(dllexport) VOID SetHook( ){
if ( ! hhk ){
HINSTANCE hInst = LoadLibrary( " HOOKAPILIB2.DLL " );
if ( ! hInst )
return ;
hhk = SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,hInst, 0 );
FreeLibrary( hInst );
}
}
_declspec(dllexport) VOID UnHook(){
if ( hhk )
UnhookWindowsHookEx( hhk );
}
// 在DLL_PROCESS_ATTACH通知时,修改MessageBoxW,LoadLibraryA,GetProcAddress的地址
// 在DLL_PROCESS_DETACH通知时,将地址改回原来的地址
BOOL WINAPI DllMain(HINSTANCE hInstance,DWORD dwReason,LPVOID lpvReserved){
hmodThisDll = hInstance;
switch ( dwReason ){
case DLL_PROCESS_ATTACH:
ModifyIATs(
" USER32.DLL " ,
GetProcAddress(GetModuleHandle( " USER32.DLL " ),
" MessageBoxW " ),
(PROC)MyMessageBoxW);
ModifyIATs(
" KERNEL32.DLL " ,
GetProcAddress(GetModuleHandle( " KERNEL32.DLL " ), " LoadLibraryA " ),
(PROC)MyLoadLibraryA);
ModifyIATs( " KERNEL32.DLL " ,
GetProcAddress(GetModuleHandle( " KERNEL32.DLL " ), " GetProcAddress " ),
(PROC)MyGetProcAddress);
break ;
case DLL_PROCESS_DETACH:
ModifyIATs(
" USER32.DLL " ,
(PROC)MyMessageBoxW,
GetProcAddress(GetModuleHandle( " USER32.DLL " ),
" MessageBoxW " ));
ModifyIATs(
" KERNEL32.DLL " ,
(PROC)MyLoadLibraryA,
GetProcAddress(GetModuleHandle( " KERNEL32.DLL " ), " LoadLibraryA " ));
ModifyIATs(
" KERNEL32.DLL " ,
(PROC)MyGetProcAddress,
GetProcAddress(GetModuleHandle( " KERNEL32.DLL " ), " GetProcAddress " ));
break ;
}
return TRUE;
}
而一个程序也可能通过GetProcAddress来获得MessageBoxW的真正地址,所以我们也要截获GetProcAddress的调用
下面是一个测试程序和一个测试用的dll.它通过三种方法调用MessageBoxW.第一种是直接调用.对这种调用,我们的第一个dll就可以截获.第二种是调用另外的dll中的函数,而这个另外的dll的函数调用了MessageBoxW.第三种是通过GetProcAddress来调用MessageBoxW
#include
<
windows.h
>
/* 注释1
_declspec(dllimport) int IndirectMessageBox( HWND hwnd );
#pragma comment(lib,"HOOKAPITESTLIB")
*/
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ( " HOOKAPITESTER " ) ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if ( ! RegisterClass ( & wndclass)){
MessageBox(NULL,TEXT( " DDFD " ),TEXT( " DDDFAS " ),MB_OK);
return 0 ;
}
hwnd = CreateWindow (szAppName, // window class name
TEXT ( " HOOKAPITESTER " ), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage ( & msg, NULL, 0 , 0 ))
{
TranslateMessage ( & msg) ;
DispatchMessage ( & msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONDOWN :
{
// IndirectMessageBox(hwnd); // 注释1
/* 注释2
HMODULE hmodNewlyLoaded;
//注意PROC定义的函数调用方式是WINAPI 的,
//所以,IndirectMessageBox也必须是WINAPI的,否则出现错误
PROC IndirectMessageBox;
hmodNewlyLoaded = LoadLibrary( TEXT("HOOKAPITESTLIB.DLL") );
IndirectMessageBox = GetProcAddress(hmodNewlyLoaded,"IndirectMessageBox");
IndirectMessageBox( hwnd );
FreeLibrary( hmodNewlyLoaded );
*/
// MessageBoxW(hwnd,L"HookAPITester",L"HookAPITester",MB_OK); // 注释0
PROC MessageBoxWPROC = GetProcAddress(
GetModuleHandle( " USER32.DLL " ), " MessageBoxW " );
MessageBoxWPROC(hwnd,L " HookAPITester " ,L " HookAPITester " ,MB_OK);
break ;
}
case WM_DESTROY:
PostQuitMessage ( 0 ) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
/* 注释1
_declspec(dllimport) int IndirectMessageBox( HWND hwnd );
#pragma comment(lib,"HOOKAPITESTLIB")
*/
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ( " HOOKAPITESTER " ) ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if ( ! RegisterClass ( & wndclass)){
MessageBox(NULL,TEXT( " DDFD " ),TEXT( " DDDFAS " ),MB_OK);
return 0 ;
}
hwnd = CreateWindow (szAppName, // window class name
TEXT ( " HOOKAPITESTER " ), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage ( & msg, NULL, 0 , 0 ))
{
TranslateMessage ( & msg) ;
DispatchMessage ( & msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONDOWN :
{
// IndirectMessageBox(hwnd); // 注释1
/* 注释2
HMODULE hmodNewlyLoaded;
//注意PROC定义的函数调用方式是WINAPI 的,
//所以,IndirectMessageBox也必须是WINAPI的,否则出现错误
PROC IndirectMessageBox;
hmodNewlyLoaded = LoadLibrary( TEXT("HOOKAPITESTLIB.DLL") );
IndirectMessageBox = GetProcAddress(hmodNewlyLoaded,"IndirectMessageBox");
IndirectMessageBox( hwnd );
FreeLibrary( hmodNewlyLoaded );
*/
// MessageBoxW(hwnd,L"HookAPITester",L"HookAPITester",MB_OK); // 注释0
PROC MessageBoxWPROC = GetProcAddress(
GetModuleHandle( " USER32.DLL " ), " MessageBoxW " );
MessageBoxWPROC(hwnd,L " HookAPITester " ,L " HookAPITester " ,MB_OK);
break ;
}
case WM_DESTROY:
PostQuitMessage ( 0 ) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
下面是一个测试dll,它有一个调用 了MessageBoxW的导出函数
#include
<
windows.h
>
int WINAPI IndirectMessageBox( HWND hwnd ){
return MessageBoxW(hwnd,
L " IndirectMessageBox " ,
L " HookAPITestLib " ,
MB_OK);
}
int WINAPI IndirectMessageBox( HWND hwnd ){
return MessageBoxW(hwnd,
L " IndirectMessageBox " ,
L " HookAPITestLib " ,
MB_OK);
}
LIBRARY
EXPORTS
IndirectMessageBox
EXPORTS
IndirectMessageBox
==============================
欢迎交流.如果你发现本文有错,或者有什么意见以改进,可以给我发邮件xkf.com.net@163.com