本實例要實現HOOK MessageBox,包括MessageBoxA和MessageBoxW,其實現細節與HOOK API(二)中介紹的基本類似,唯一不同的是,本實例要實現對所有程序的HOOK MessageBox,即無論系統中哪一個程序調用MessageBox都會被重定向到我們實現的新的API中。
之前說過,在Windows中,每個進程都有自己的地址空間,進程不能調用別的進程中的函數。這裡涉及到一個關鍵,如何讓我們實現的新的API調用地址存在於所有進程的地址空間中呢?如果這無法實現的話,其他進程就無法調用到我們所實現的API。這裡涉及到的關鍵就是,如何將我們的代碼注入到別的進程中。
這裡有一個實現手段,就是將我們實現的代碼隨著系統鉤子注入到目標進程中,我們在HOOK API (一)中講過鼠標鉤子,鼠標鉤子一旦啟動,就會存在於每個當前運行的進程中,實現對屏幕坐標的定位。還有一個關鍵就是,這樣的鉤子需要注入到多個目標進程中,那麼這就要在動態鏈接庫(DLL)中實現,然後啟動某一主調進程將這樣一個DLL注入到目標進程中,從而實現HOOK API。
本實例介紹如何將實現了HOOK MessageBox的DLL注入到所有進程中的過程。
由於被實例的DLL用於MFC框架,因此創建的是MFC DLL,需要的話,也可以建立其他類型的DLL工程。
我們的DLL要跟隨鼠標鉤子注入到目標進程中,而鼠標鉤子是系統鉤子,我們需要實現其鉤子回調函數。
/*
鼠標鉤子子過程,目的是加載本dll到使用鼠標的程序中。
鼠標鉤子的作用:當鼠標在某程序窗口中時,就會加載我們這個dll。
*/
LRESULT CALLBACK MouseProc(
int nCode, // hook code
WPARAM wParam,// message identifier
LPARAM lParam // mouse coordinates
)
{
return CallNextHookEx(hhk,nCode,wParam,lParam);
}
調用SetWindowsHookEx() API可以安裝鼠標鉤子,其中SetWindowsHookEx() 原型如下:
HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId )
參數:
idHook表示鉤子類型,它是和鉤子函數類型一一對應的。比如,WH_KEYBOARD表示安裝的是鍵盤鉤子,WH_MOUSE表示是鼠標鉤子等等。
Lpfn是鉤子函數的地址。
HMod是鉤子函數所在的實例的句柄。對於線程鉤子,該參數為NULL;對於系統鉤子,該參數為鉤子函數所在的DLL句柄。
dwThreadId 指定鉤子所監視的線程的線程號。對於全局鉤子,該參數為NULL。
返回值:
SetWindowsHookEx返回所安裝的鉤子句柄。
//
// 安裝鉤子
//
BOOL WINAPI StartHook(HWND hWnd)
{
g_hWnd = hWnd;
hhk = ::SetWindowsHookEx(WH_MOUSE,MouseProc,g_hInstance,0);
if (hhk == NULL)
{
return FALSE;
}
else
{
return TRUE;
}
}
//
// 卸載鉤子
//
BOOL WINAPI StopHook()
{
/*
卸載鉤子時,一定要記得恢復原API入口。
這裡恢復的只是主程序的原API入口,其它程序的API入口還沒有被恢復。
因此我們必須處理dll退出過程,即在函數ExitInstance()中,調用恢復
API入口的函數HookOff(),只有這樣,其它程序再次調用原API時,才不
會發生錯誤。
當我們HOOK所有程序的某個系統API時,千萬要注意在ExitInstance()中
調用HookOff()!!!!!
*/
HookOff();
if (hhk!=NULL)
{
UnhookWindowsHookEx(hhk);
FreeLibrary(g_hInstance);
}
return TRUE;
}
.def內容如下:
將StarHook和StopHook函數導出,一遍主程序安裝和卸載HOOK程序。
; HookDll.def : 聲明 DLL 的模塊參數。
LIBRARY "HookMessageBox"
EXPORTS
; 此處可以是顯式導出
StartHook
StopHook
/*
dll程序入口,當程序加載dll時,會執行InitInstance()
*/
BOOL CHookDllApp::InitInstance()
{
CWinApp::InitInstance();
g_hInstance = AfxGetInstanceHandle();// 獲取當前DLL實例句柄
AdjustPrivileges(); // 提高權限
DWORD dwPid = ::GetCurrentProcessId();
hProcess = ::OpenProcess(PROCESS_ALL_ACCESS,0,dwPid);
if (hProcess == NULL)
{
CString str;
str.Format(_T("OpenProcess fail, and error code = %d"),GetLastError());
AfxMessageBox(str);
return FALSE;
}
Inject(); // 開始注入
return TRUE;
}
int CHookDllApp::ExitInstance()
{
/*
dll退出時,一定要記得恢復原API的入口!!!
我們編寫的dll會被注入到所有目標進程中,若dll退出時,沒有恢復原API入口,
那麼被掛鉤的程序再次調用該API時,會發生錯誤。
因為我們的dll程序已經退出,但原API的入口仍為我們所定義的API的入口,這
時被掛鉤的程序無法找到我們實現的API,然而原API的地址又沒有被恢復,也就
調用不到原API,這時程序自然會發生崩潰了。
*/
HookOff();
return CWinApp::ExitInstance();
}
該函數的主要功能是保存新的和原來的API入口,並且在最後啟動HOOK。需要注意的是,這個函數只能被調用一次,即只能進行一次注入操作。
/*
注入
*/
void Inject()
{
if ( TRUE == bIsInJected)
{
return;
}
bIsInJected = TRUE; // 保證只調用一次
//
// 獲取函數
//
HMODULE hmodle = ::LoadLibrary(_T("User32.dll"));
oldMsgBoxA = (TypeMsgBoxA) ::GetProcAddress(hmodle,"MessageBoxA");
pfMsgBoxA = (FARPROC)oldMsgBoxA;
oldMsgBoxW = (TypeMsgBoxW) ::GetProcAddress(hmodle,"MessageBoxW");
pfMsgBoxW = (FARPROC)oldMsgBoxW;
if (pfMsgBoxA == NULL)
{
AfxMessageBox(_T("獲取 MessageBoxA 函數失敗"));
return;
}
if ( pfMsgBoxW == NULL)
{
AfxMessageBox(_T("獲取 MessageBoxW 函數失敗"));
return;
}
//
// 保存原API地址
//
_asm
{
lea edi,oldCodeA // 取數組基地址
mov esi,pfMsgBoxA // API地址
cld // 設置方向
mov ecx,CODE_LENGTH
rep movsb
}
_asm
{
lea edi,oldCodeW
mov esi,pfMsgBoxW
cld
mov ecx,CODE_LENGTH
rep movsb
}
//
// 將新地址復制到入口
//
newCodeA[0] = newCodeW [0] = 0xe9; // jmp 指定代碼
_asm
{
lea eax,MyMessageBoxA // 新API地址
mov ebx,pfMsgBoxA // 原API地址
sub eax,ebx
sub eax,CODE_LENGTH // 跳轉地址 = 新API地址 - 原API地址 - 指令長度
mov dword ptr [newCodeA+1],eax // eax 32bit = 4 BYTE
}
_asm
{
lea eax,MyMessageBoxW
mov ebx,pfMsgBoxW
sub eax,ebx
sub eax,CODE_LENGTH
mov dword ptr [newCodeW + 1],eax
}
HookOn(); // 開始HOOK
}
該函數主要完成向進程控制塊寫寫指令的任務。供HookOn()和HookOff()調用,用來將原API入口,或新的API入口寫入到進程的地址空間中。
/*
將長度為length的pcode寫入到地址lpAddress中。
*/
void WriteMemory(LPVOID lpAddress,BYTE* pcode,int length)
{
//
// 保證本進程句柄不為NULL
//
ASSERT(hProcess != NULL);
DWORD dwTemp,dwOldProtect,dwRet,dwWrited;
//
// 修改API入口前length個字節為 jmp xxxx
//
VirtualProtectEx(hProcess,lpAddress,length,PAGE_READWRITE,&dwOldProtect);
dwRet = WriteProcessMemory(hProcess,lpAddress,pcode,length,&dwWrited);
if ( 0 == dwRet || 0 == dwWrited)
{
AfxMessageBox(_T("哭!!寫入失敗"));
}
VirtualProtectEx(hProcess,lpAddress,length,dwOldProtect,&dwTemp);
}
/*
用新API地址替換原API地址
*/
void HookOn()
{
ASSERT(hProcess != NULL);
DWORD dwTemp,dwOldProtect,dwRet,dwWrited;
WriteMemory(pfMsgBoxA,newCodeA,CODE_LENGTH);
WriteMemory(pfMsgBoxW,newCodeW,CODE_LENGTH);
}
/*
恢復原API地址
*/
void HookOff()
{
ASSERT(hProcess != NULL);
DWORD dwTemp,dwOldProtect,dwRet,dwWrited;
WriteMemory(pfMsgBoxA,oldCodeA,CODE_LENGTH);
WriteMemory(pfMsgBoxW,oldCodeW,CODE_LENGTH);
}
/*
自己用於替換的API
*/
int WINAPI MyMessageBoxA(HWND hWnd,LPCSTR lpText,LPCSTR lpCation,UINT uType)
{
int nRet = 0;
HookOff();
nRet = ::MessageBoxA(hWnd,"哈哈 ^_^,MessageBoxA 被 HOOK 咯",lpCation,uType);
nRet = ::MessageBoxA(hWnd,lpText,lpCation,uType);
HookOn();
return nRet;
}
int WINAPI MyMessageBoxW(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCation,UINT uType)
{
int nRet = 0;
HookOff();
nRet = ::MessageBoxW(hWnd,_T("O(∩_∩)O哈哈~,MMessageBoxW 被 HOOK 咯"),lpCation,uType);
nRet = ::MessageBoxW(hWnd,lpText,lpCation,uType);
HookOn();
return nRet;
}
這段代碼並不是必須的,但有些時候會出現程序權限不足以獲取進程句柄的情況,這個時候需要在代碼執行前調用該函數來提高程序的權限。
/*
提升權限
*/
bool AdjustPrivileges() {
HANDLE hToken;
TOKEN_PRIVILEGES tp;
TOKEN_PRIVILEGES oldtp;
DWORD dwSize=sizeof(TOKEN_PRIVILEGES);
LUID luid;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED) return true;
else return false;
}
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {
CloseHandle(hToken);
return false;
}
ZeroMemory(&tp, sizeof(tp));
tp.PrivilegeCount=1;
tp.Privileges[0].Luid=luid;
tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
/* Adjust Token Privileges */
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &oldtp, &dwSize)) {
CloseHandle(hToken);
return false;
}
// close handles
CloseHandle(hToken);
return true;
}
HINSTANCE g_hinstDll = NULL;
//
// 開始 HOOK
//
void CHookWindowDlg::OnBnClickedButtonStart()
{
// TODO: 在此添加控件通知處理程序代碼
g_hinstDll = LoadLibrary(_T("HookDll.dll"));
if ( NULL == g_hinstDll)
{
AfxMessageBox(_T("加載 HookDll.dll 失敗"));
}
typedef BOOL (CALLBACK *HookStart)(HWND hwnd);
HookStart hookStart = NULL;
hookStart = (HookStart)::GetProcAddress(g_hinstDll,"StartHook");
if ( NULL == hookStart)
{
AfxMessageBox(_T("獲取 StartHook 函數失敗"));
return;
}
bool ret = hookStart(m_hWnd);
if (ret)
{
m_list.InsertItem(m_list.GetItemCount(),_T("啟動鉤子成功"));
m_list.EnsureVisible(m_list.GetItemCount()-1,FALSE);
}
else
{
m_list.InsertItem(m_list.GetItemCount(),_T("啟動鉤子失敗"));
m_list.EnsureVisible(m_list.GetItemCount()-1,FALSE);
}
}
//
// 終止 HOOK
//
void CHookWindowDlg::OnBnClickedButtonStop()
{
// TODO: 在此添加控件通知處理程序代碼
typedef BOOL (CALLBACK* HookStop)();
HookStop hookStop = NULL;
if (NULL == g_hinstDll) // 一定要加這個判斷,若不為空的話就不需要在重新加載,否則會是不同的實例
{
g_hinstDll = LoadLibrary(_T("HookDll.dll"));
if (g_hinstDll == NULL)
{
AfxMessageBox(_T("加載 HookDll.dll 失敗"));
return;
}
}
hookStop = ::GetProcAddress(g_hinstDll,"StopHook");
if (hookStop == NULL)
{
AfxMessageBox(_T("獲取 StopHook 失敗"));
FreeLibrary(g_hinstDll);
g_hinstDll=NULL;
return;
}
hookStop();
if (g_hinstDll!= NULL)
{
::FreeLibrary(g_hinstDll);
}
m_list.InsertItem(m_list.GetItemCount(),_T("終止HOOK成功"));
}
// MessageBoxA
void CHookWindowDlg::OnBnClickedButtonMsga()
{
// TODO: 在此添加控件通知處理程序代碼
MessageBoxA(m_hWnd,"這是正常的MessageBoxA...","哈哈",0);
}
// MessageBoxW
void CHookWindowDlg::OnBnClickedButtonMsgw()
{
// TODO: 在此添加控件通知處理程序代碼
MessageBoxW(_T("這是正常的MessageBoxW..."),_T("呵呵"),0);
}
本實例在自己實現的API中打印一句自己的話,然後再彈出原本的對話框。測試結果如下:
打開技術本,打開查找對話框,然後輸入一個字符串,"查找一下",這個時候同樣先彈出我們的對話框,然後才彈出原來的,找不到對話框。
// HookDll.cpp : 定義 DLL 的初始化例程。
//
#include "stdafx.h"
#include "HookDll.h"
#include <Windows.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
/*
全局共享變量
*/
#pragma data_seg("Share")
HWND g_hWnd = NULL ; // 主窗口句柄
HINSTANCE g_hInstance = NULL; // 本dll實例句柄
HHOOK hhk = NULL; // 鼠標鉤子句柄
#pragma data_seg()
#pragma comment(linker,"/section:Share,rws")
HANDLE hProcess = NULL; // 當前進程
BOOL bIsInJected = FALSE; // 是否已注入標記
TCHAR* msgToMain = new TCHAR[200]; // 發給主調程序的信息
/*
原函數定義
*/
typedef int (WINAPI *TypeMsgBoxA)(HWND hWnd,LPCSTR lpText, LPCSTR lpCaption,UINT uType);
typedef int (WINAPI *TypeMsgBoxW)(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType);
TypeMsgBoxA oldMsgBoxA = NULL; // 用於保存原函數地址
TypeMsgBoxW oldMsgBoxW = NULL; // 用於保存原楷書地址
FARPROC pfMsgBoxA = NULL; // 指向原函數地址的遠指針
FARPROC pfMsgBoxW = NULL; // 指向原函數地址的遠指針
#define CODE_LENGTH 5
BYTE oldCodeA[CODE_LENGTH]; // 保存原來API入口代碼
BYTE oldCodeW[CODE_LENGTH]; // 保存原來API入口代碼
BYTE newCodeA[CODE_LENGTH]; // 保存新API入口代碼,jmp xxxx
BYTE newCodeW[CODE_LENGTH]; // 保存新API入口代碼,jmp xxxx
/*
自己編寫的API
*/
int WINAPI MyMessageBoxA(HWND hWnd,LPCSTR lpText,LPCSTR lpCation,UINT uType);
int WINAPI MyMessageBoxW(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCation,UINT uType);
/*
其它函數原型聲明
*/
void HookOn(); // 開始HOOK
void HookOff(); // 關閉HOOK
void Inject(); // 注入
BOOL WINAPI StartHook(HWND hWnd); // 加載鉤子
BOOL WINAPI StopHook(); // 卸載鉤子
bool AdjustPrivileges(); // 提升權限
//
//TODO: 如果此 DLL 相對於 MFC DLL 是動態鏈接的,
// 則從此 DLL 導出的任何調入
// MFC 的函數必須將 AFX_MANAGE_STATE 宏添加到
// 該函數的最前面。
//
// 例如:
//
// extern "C" BOOL PASCAL EXPORT ExportedFunction()
// {
// AFX_MANAGE_STATE(AfxGetStaticModuleState());
// // 此處為普通函數體
// }
//
// 此宏先於任何 MFC 調用
// 出現在每個函數中十分重要。這意味著
// 它必須作為函數中的第一個語句
// 出現,甚至先於所有對象變量聲明,
// 這是因為它們的構造函數可能生成 MFC
// DLL 調用。
//
// 有關其他詳細信息,
// 請參閱 MFC 技術說明 33 和 58。
//
// CHookDllApp
BEGIN_MESSAGE_MAP(CHookDllApp, CWinApp)
END_MESSAGE_MAP()
// CHookDllApp 構造
CHookDllApp::CHookDllApp()
{
// TODO: 在此處添加構造代碼,
// 將所有重要的初始化放置在 InitInstance 中
}
// 唯一的一個 CHookDllApp 對象
CHookDllApp theApp;
// CHookDllApp 初始化
/*
dll程序入口,當程序加載dll時,會執行InitInstance()
*/
BOOL CHookDllApp::InitInstance()
{
CWinApp::InitInstance();
g_hInstance = AfxGetInstanceHandle();// 獲取當前DLL實例句柄
AdjustPrivileges(); // 提高權限
DWORD dwPid = ::GetCurrentProcessId();
hProcess = ::OpenProcess(PROCESS_ALL_ACCESS,0,dwPid);
if (hProcess == NULL)
{
CString str;
str.Format(_T("OpenProcess fail, and error code = %d"),GetLastError());
AfxMessageBox(str);
return FALSE;
}
Inject(); // 開始注入
return TRUE;
}
int CHookDllApp::ExitInstance()
{
/*
dll退出時,一定要記得恢復原API的入口!!!
我們編寫的dll會被注入到所有目標進程中,若dll退出時,沒有恢復原API入口,
那麼被掛鉤的程序再次調用該API時,會發生錯誤。
因為我們的dll程序已經退出,但原API的入口仍為我們所定義的API的入口,這
時被掛鉤的程序無法找到我們實現的API,然而原API的地址又沒有被恢復,也就
調用不到原API,這時程序自然會發生崩潰了。
*/
HookOff();
return CWinApp::ExitInstance();
}
/*
提升權限
*/
bool AdjustPrivileges() {
HANDLE hToken;
TOKEN_PRIVILEGES tp;
TOKEN_PRIVILEGES oldtp;
DWORD dwSize=sizeof(TOKEN_PRIVILEGES);
LUID luid;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED) return true;
else return false;
}
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {
CloseHandle(hToken);
return false;
}
ZeroMemory(&tp, sizeof(tp));
tp.PrivilegeCount=1;
tp.Privileges[0].Luid=luid;
tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
/* Adjust Token Privileges */
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &oldtp, &dwSize)) {
CloseHandle(hToken);
return false;
}
// close handles
CloseHandle(hToken);
return true;
}
/*
鼠標鉤子子過程,目的是加載本dll到使用鼠標的程序中。
鼠標鉤子的作用:當鼠標在某程序窗口中時,就會加載我們這個dll。
*/
LRESULT CALLBACK MouseProc(
int nCode, // hook code
WPARAM wParam,// message identifier
LPARAM lParam // mouse coordinates
)
{
return CallNextHookEx(hhk,nCode,wParam,lParam);
}
/*
將長度為length的pcode寫入到地址lpAddress中。
*/
void WriteMemory(LPVOID lpAddress,BYTE* pcode,int length)
{
//
// 保證本進程句柄不為NULL
//
ASSERT(hProcess != NULL);
DWORD dwTemp,dwOldProtect,dwRet,dwWrited;
//
// 修改API入口前length個字節為 jmp xxxx
//
VirtualProtectEx(hProcess,lpAddress,length,PAGE_READWRITE,&dwOldProtect);
dwRet = WriteProcessMemory(hProcess,lpAddress,pcode,length,&dwWrited);
if ( 0 == dwRet || 0 == dwWrited)
{
AfxMessageBox(_T("哭!!寫入失敗"));
}
VirtualProtectEx(hProcess,lpAddress,length,dwOldProtect,&dwTemp);
}
/*
用新API地址替換原API地址
*/
void HookOn()
{
ASSERT(hProcess != NULL);
DWORD dwTemp,dwOldProtect,dwRet,dwWrited;
WriteMemory(pfMsgBoxA,newCodeA,CODE_LENGTH);
WriteMemory(pfMsgBoxW,newCodeW,CODE_LENGTH);
}
/*
恢復原API地址
*/
void HookOff()
{
ASSERT(hProcess != NULL);
DWORD dwTemp,dwOldProtect,dwRet,dwWrited;
WriteMemory(pfMsgBoxA,oldCodeA,CODE_LENGTH);
WriteMemory(pfMsgBoxW,oldCodeW,CODE_LENGTH);
}
/*
注入
*/
void Inject()
{
if ( TRUE == bIsInJected)
{
return;
}
bIsInJected = TRUE; // 保證只調用一次
//
// 獲取函數
//
HMODULE hmodle = ::LoadLibrary(_T("User32.dll"));
oldMsgBoxA = (TypeMsgBoxA) ::GetProcAddress(hmodle,"MessageBoxA");
pfMsgBoxA = (FARPROC)oldMsgBoxA;
oldMsgBoxW = (TypeMsgBoxW) ::GetProcAddress(hmodle,"MessageBoxW");
pfMsgBoxW = (FARPROC)oldMsgBoxW;
if (pfMsgBoxA == NULL)
{
AfxMessageBox(_T("獲取 MessageBoxA 函數失敗"));
return;
}
if ( pfMsgBoxW == NULL)
{
AfxMessageBox(_T("獲取 MessageBoxW 函數失敗"));
return;
}
//
// 保存原API地址
//
_asm
{
lea edi,oldCodeA // 取數組基地址
mov esi,pfMsgBoxA // API地址
cld // 設置方向
mov ecx,CODE_LENGTH
rep movsb
}
_asm
{
lea edi,oldCodeW
mov esi,pfMsgBoxW
cld
mov ecx,CODE_LENGTH
rep movsb
}
//
// 將新地址復制到入口
//
newCodeA[0] = newCodeW [0] = 0xe9; // jmp 指定代碼
_asm
{
lea eax,MyMessageBoxA // 新API地址
mov ebx,pfMsgBoxA // 原API地址
sub eax,ebx
sub eax,CODE_LENGTH // 跳轉地址 = 新API地址 - 原API地址 - 指令長度
mov dword ptr [newCodeA+1],eax // eax 32bit = 4 BYTE
}
_asm
{
lea eax,MyMessageBoxW
mov ebx,pfMsgBoxW
sub eax,ebx
sub eax,CODE_LENGTH
mov dword ptr [newCodeW + 1],eax
}
HookOn(); // 開始HOOK
}
//
// 安裝鉤子
//
BOOL WINAPI StartHook(HWND hWnd)
{
g_hWnd = hWnd;
hhk = ::SetWindowsHookEx(WH_MOUSE,MouseProc,g_hInstance,0);
if (hhk == NULL)
{
return FALSE;
}
else
{
return TRUE;
}
}
//
// 卸載鉤子
//
BOOL WINAPI StopHook()
{
/*
卸載鉤子時,一定要記得恢復原API入口。
這裡恢復的只是主程序的原API入口,其它程序的API入口還沒有被恢復。
因此我們必須處理dll退出過程,即在函數ExitInstance()中,調用恢復
API入口的函數HookOff(),只有這樣,其它程序再次調用原API時,才不
會發生錯誤。
當我們HOOK所有程序的某個系統API時,千萬要注意在ExitInstance()中
調用HookOff()!!!!!
*/
HookOff();
if (hhk!=NULL)
{
UnhookWindowsHookEx(hhk);
FreeLibrary(g_hInstance);
}
return TRUE;
}
/*
自己用於替換的API
*/
int WINAPI MyMessageBoxA(HWND hWnd,LPCSTR lpText,LPCSTR lpCation,UINT uType)
{
int nRet = 0;
HookOff();
nRet = ::MessageBoxA(hWnd,"哈哈 ^_^,MessageBoxA 被 HOOK 咯",lpCation,uType);
nRet = ::MessageBoxA(hWnd,lpText,lpCation,uType);
HookOn();
return nRet;
}
int WINAPI MyMessageBoxW(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCation,UINT uType)
{
int nRet = 0;
HookOff();
nRet = ::MessageBoxW(hWnd,_T("O(∩_∩)O哈哈~,MMessageBoxW 被 HOOK 咯"),lpCation,uType);
nRet = ::MessageBoxW(hWnd,lpText,lpCation,uType);
HookOn();
return nRet;
}