HOOK API(三)—— HOOK 所有程序的 MessageBox
HOOK API(三)
—— HOOK 所有程序的 MessageBox
原文出处:http://www.cnblogs.com/fanling999/p/4595035.html
程序源代码:https://github.com/hfl15/windows_kernel_development/tree/master/demo_source_code/HoolAllMessageBox
0x00 前言
本实例要实现HOOK MessageBox,包括MessageBoxA和MessageBoxW,其实现细节与HOOK API(二)中介绍的基本类似,唯一不同的是,本实例要实现对所有程序的HOOK MessageBox,即无论系统中哪一个程序调用MessageBox都会被重定向到我们实现的新的API中。
之前说过,在Windows中,每个进程都有自己的地址空间,进程不能调用别的进程中的函数。这里涉及到一个关键,如何让我们实现的新的API调用地址存在于所有进程的地址空间中呢?如果这无法实现的话,其他进程就无法调用到我们所实现的API。这里涉及到的关键就是,如何将我们的代码注入到别的进程中。
这里有一个实现手段,就是将我们实现的代码随着系统钩子注入到目标进程中,我们在HOOK API (一)中讲过鼠标钩子,鼠标钩子一旦启动,就会存在于每个当前运行的进程中,实现对屏幕坐标的定位。还有一个关键就是,这样的钩子需要注入到多个目标进程中,那么这就要在动态链接库(DLL)中实现,然后启动某一主调进程将这样一个DLL注入到目标进程中,从而实现HOOK API。
本实例介绍如何将实现了HOOK MessageBox的DLL注入到所有进程中的过程。
0x01 HOOK DLL的实现
建立一个MFC DLL工程
由于被实例的DLL用于MFC框架,因此创建的是MFC DLL,需要的话,也可以建立其他类型的DLL工程。
鼠标钩子回调函数
我们的DLL要跟随鼠标钩子注入到目标进程中,而鼠标钩子是系统钩子,我们需要实现其钩子回调函数。
/*鼠标钩子子过程,目的是加载本dll到使用鼠标的程序中。鼠标钩子的作用:当鼠标在某程序窗口中时,就会加载我们这个dll。 */LRESULT CALLBACK MouseProc(int nCode, // hook codeWPARAM wParam,// message identifierLPARAM 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; 此处可以是显式导出StartHookStopHook
MFC DLL的InitInstance()函数
/*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; }
MFC DLL的ExitInstance()函数
int CHookDllApp::ExitInstance(){/*dll退出时,一定要记得恢复原API的入口!!!我们编写的dll会被注入到所有目标进程中,若dll退出时,没有恢复原API入口,那么被挂钩的程序再次调用该API时,会发生错误。因为我们的dll程序已经退出,但原API的入口仍为我们所定义的API的入口,这时被挂钩的程序无法找到我们实现的API,然而原API的地址又没有被恢复,也就调用不到原API,这时程序自然会发生崩溃了。*/HookOff();return CWinApp::ExitInstance(); }
HOOK API实现
- 注入函数,保存新的,原来的API的入口
该函数的主要功能是保存新的和原来的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_LENGTHrep movsb}_asm{lea edi,oldCodeWmov esi,pfMsgBoxWcldmov ecx,CODE_LENGTHrep 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,MyMessageBoxWmov ebx,pfMsgBoxWsub eax,ebxsub eax,CODE_LENGTHmov dword ptr [newCodeW + 1],eax}HookOn(); // 开始HOOK }
该函数主要完成向进程控制块写写指令的任务。供HookOn()和HookOff()调用,用来将原API入口,或新的API入口写入到进程的地址空间中。
/*将长度为length的pcode写入到地址lpAddress中。 */ void WriteMemory(LPVOID lpAddress,BYTE* pcode,int length){// 保证本进程句柄不为NULLASSERT(hProcess != NULL);DWORD dwTemp,dwOldProtect,dwRet,dwWrited;// 修改API入口前length个字节为 jmp xxxxVirtualProtectEx(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; }
0x02 HOOK 窗体实现
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); }
0x03 测试
本实例在自己实现的API中打印一句自己的话,然后再弹出原本的对话框。测试结果如下:
可以看到,先弹出了我们自己的对话框,然后才弹出真正的对话框。
可以看到,先弹出我们的对话框,然后才弹出真正的对话框。
打开技术本,打开查找对话框,然后输入一个字符串,"查找一下",这个时候同样先弹出我们的对话框,然后才弹出原来的,找不到对话框。
0x04 附录——HOOK DLL关键源码
// 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 codeWPARAM wParam,// message identifierLPARAM lParam // mouse coordinates ) {return CallNextHookEx(hhk,nCode,wParam,lParam); }/*将长度为length的pcode写入到地址lpAddress中。 */ void WriteMemory(LPVOID lpAddress,BYTE* pcode,int length){// 保证本进程句柄不为NULLASSERT(hProcess != NULL);DWORD dwTemp,dwOldProtect,dwRet,dwWrited;// 修改API入口前length个字节为 jmp xxxxVirtualProtectEx(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_LENGTHrep movsb}_asm{lea edi,oldCodeWmov esi,pfMsgBoxWcldmov ecx,CODE_LENGTHrep 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,MyMessageBoxWmov ebx,pfMsgBoxWsub eax,ebxsub eax,CODE_LENGTHmov 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; }
转载于:https://www.cnblogs.com/fanling999/p/4595035.html
HOOK API(三)—— HOOK 所有程序的 MessageBox相关推荐
- HOOK API(二)—— HOOK自己程序的 MessageBox
0x00 前言 以下将给出一个简单的例子,作为HOOK API的入门.这里是HOOK 自己程序的MessageBox,即将自己程序对MessageBox API的调用重定向到自己实现的API中,在自己 ...
- 汇编Ring 3下实现 HOOK API
[文章标题]汇编ring3下实现HOOK API [文章作者]nohacks(非安全,hacker0058) [作者主页]hacker0058.ys168.com [文章出处]看雪论坛(bbs.ped ...
- HOOK API技术
HOOK API技术 HOOK学习笔记与心得 奇技淫巧之调试被远程线程注入的DLL windows核心编程_系统消息与自定义钩子hook使用 [Windows Dll Injection.Proces ...
- android hook api
搞了好几个星期,终于有点头绪,欢迎交流.转载请注明出处http://blog.csdn.net/lingfong_cool/article/details/8109290. android安全可以从三 ...
- Windows Dll Injection、Process Injection、API Hook、DLL后门/恶意程序入侵技术
catalogue 1. 引言 2. 使用注册表注入DLL 3. 使用Windows挂钩来注入DLL 4. 使用远程线程来注入DLL 5. 使用木马DLL来注入DLL 6. 把DLL作为调试器来注入 ...
- Hook API (C++)
一.基本概念: 钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且 所监视的窗口可以是其他进程所创建的.当消息到达后,在目标窗口处理函数 ...
- Ring3下Inline Hook API
用CreateFile为例子,讲解一下Ring3下的Inline Hook API,基本原理很简单 1.获取CreateFile函数的地址 2.读取CreateFile函数的前8个字节 3.将Crea ...
- Windows内核API HOOK 之 Inline Hook
来源:CSDN 作者:daiwen 名字起得好,Inline hook,乍一听,似乎很高深.此处的Inline,我以为,意指将汇编代码直接写入内核API的内存区域.Inline Hook不像用户态 ...
- Windows下Hook API技术小结 (转)
1.基本概念 钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的.当消息到达后,在目标窗口处理函数之前 ...
- HOOK大法实现不修改程序代码给程序添加功能
[文章标题]: HOOK大法实现不修改程序代码给程序添加功能 [文章作者]: 0x18c0 [软件名称]: Scylla [使用工具]: OD.Stub_PE.ResHacker [版权声明]: 本文 ...
最新文章
- 【算法学习笔记】57. 前缀树 字典序优化技巧 STL学习 SJTU OJ 1366 前缀匹配
- hadoop1.2.1安装配置
- 【年度学术大会合集】SIGGRAPH,KDD,AAAI,NIPS…这些你想参加的会议
- Linux基础第一章 概述
- 正确解读PHP获取时间错误原因
- 《2017中国大数据及AI人才发展报告》均薪38万,招聘猛增6倍
- 专升本的学生和高考考上本科的学生一样吗
- Linux之父道歉后,Linux社区颁布开发人员行为准则
- Thinkphp5.1整合支付宝APP支付
- 基于R统计分析——样本与分布
- MySQL表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock)
- 游戏中BUFF的实现
- 基于android系统的单词学习软件设计与开发【附项目源码+论文说明】分享
- 为什么android手机内存不够,安卓手机内存不足怎么办?安卓手机内存越来越小解决方法汇总...
- 一个主机可以接几个php,一台主机如何连接两个显示器
- android gif图片闪烁,Android中动态显示gif图片
- 如何基于SSM设计实现一个学生学籍管理系统
- 【转】 学习ios(必看经典)牛人40天精通iOS开发的学习方法【2015.12.2
- Problem E: 农夫果园
- matlab仿真及分析,CSMACD性能分析及MATLAB仿真.pdf
热门文章
- vsbutton中的集合编辑器怎么打开_理工科学生的好帮手,EdrawMath数学公式编辑器...
- 浅谈ES6中的rest参数
- linux SSH rsa认证方式登录需理清的问题
- 结对编程之求首尾相连数组中最大子数组的和
- YUM服务那些事---详解YUM服务
- [翻译]Monocular Visual Odometry using OpenCV
- xgboost算模型输出的解释
- 阿里云发布ET奥运大脑,推进奥运进入数字时代
- IDC预测:2021vCPE软硬件市场将达到30亿美元
- 介绍一下python getopt 模块