转载来源:https://www.cnblogs.com/hookjc/

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的实现

  1. 建立一个MFC DLL工程

由于被实例的DLL用于MFC框架,因此创建的是MFC DLL,需要的话,也可以建立其他类型的DLL工程。

  1. 鼠标钩子回调函数

我们的DLL要跟随鼠标钩子注入到目标进程中,而鼠标钩子是系统钩子,我们需要实现其钩子回调函数。

/*

鼠标钩子子过程,目的是加载本dll到使用鼠标的程序中。

鼠标钩子的作用:当鼠标在某程序窗口中时,就会加载我们这个dll。

*/

LRESULT CALLBACK MouseProc(

int nCode,     // hook code

WPARAM wParam,// message identifier

LPARAM lParam // mouse coordinates

)

{

return CallNextHookEx(hhk,nCode,wParam,lParam);

}

  1. 安装鼠标钩子

调用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;

}

}

  1. 卸载鼠标钩子

//

// 卸载钩子

//

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;

}

  1. 导出我们的安装和卸载函数

.def内容如下:

将StarHook和StopHook函数导出,一遍主程序安装和卸载HOOK程序。

; HookDll.def : 声明 DLL 的模块参数。

LIBRARY "HookMessageBox"

EXPORTS

; 此处可以是显式导出

StartHook

StopHook

  1. 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;

}

  1. MFC DLL的ExitInstance()函数

int CHookDllApp::ExitInstance()

{

/*

dll退出时,一定要记得恢复原API的入口!!!

我们编写的dll会被注入到所有目标进程中,若dll退出时,没有恢复原API入口,

那么被挂钩的程序再次调用该API时,会发生错误。

因为我们的dll程序已经退出,但原API的入口仍为我们所定义的API的入口,这

时被挂钩的程序无法找到我们实现的API,然而原API的地址又没有被恢复,也就

调用不到原API,这时程序自然会发生崩溃了。

*/

HookOff();

return CWinApp::ExitInstance();

}

  1. HOOK API实现

  1. 注入函数,保存新的,原来的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_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

}

  1. 写内存函数

该函数主要完成向进程控制块写写指令的任务。供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);

}

  1. 用新API地址替换原API地址

/*

用新API地址替换原API地址

*/

void HookOn()

{

ASSERT(hProcess != NULL);

DWORD dwTemp,dwOldProtect,dwRet,dwWrited;

WriteMemory(pfMsgBoxA,newCodeA,CODE_LENGTH);

WriteMemory(pfMsgBoxW,newCodeW,CODE_LENGTH);

}

  1. 恢复原API地址

/*

恢复原API地址

*/

void HookOff()

{

ASSERT(hProcess != NULL);

DWORD dwTemp,dwOldProtect,dwRet,dwWrited;

WriteMemory(pfMsgBoxA,oldCodeA,CODE_LENGTH);

WriteMemory(pfMsgBoxW,oldCodeW,CODE_LENGTH);

}

  1. 新API定义

/*

自己用于替换的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;

}

  1. 提升权限函数

这段代码并不是必须的,但有些时候会出现程序权限不足以获取进程句柄的情况,这个时候需要在代码执行前调用该函数来提高程序的权限。

/*

提升权限

*/

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 窗体实现

  1. StartHook

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

}

}

  1. StopHook

//

// 终止 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成功"));

}

  1. MessageBoxA

// MessageBoxA

void CHookWindowDlg::OnBnClickedButtonMsga()

{

// TODO: 在此添加控件通知处理程序代码

MessageBoxA(m_hWnd,"这是正常的MessageBoxA...","哈哈",0);

}

  1. MessageBoxW

// MessageBoxW

void CHookWindowDlg::OnBnClickedButtonMsgw()

{

// TODO: 在此添加控件通知处理程序代码

MessageBoxW(_T("这是正常的MessageBoxW..."),_T("呵呵"),0);

}

0x03 测试

本实例在自己实现的API中打印一句自己的话,然后再弹出原本的对话框。测试结果如下:

  1. 启动钩子

  1. 单击"MessageBoxA"按钮,调用MessageBoxA函数

    可以看到,先弹出了我们自己的对话框,然后才弹出真正的对话框。

  1. 单击"MessageBoxW"按钮,调用MessageBoxW函数。

    可以看到,先弹出我们的对话框,然后才弹出真正的对话框。

  1. 记事本的对话框也被HOOK了。

打开技术本,打开查找对话框,然后输入一个字符串,"查找一下",这个时候同样先弹出我们的对话框,然后才弹出原来的,找不到对话框。

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 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;

}

来源:python脚本自动迁移

HOOK API(三) —— HOOK 所有程序的 MessageBox的更多相关文章

  1. HOOK API(二)—— HOOK自己程序的 MessageBox

    HOOK API(二) —— HOOK自己程序的 MessageBox 0x00 前言 以下将给出一个简单的例子,作为HOOK API的入门.这里是HOOK 自己程序的MessageBox,即将自己程 ...

  2. HOOK API(二) —— HOOK自己程序的 MessageBox

    转载来源:https://www.cnblogs.com/hookjc/ 0x00 前言 以下将给出一个简单的例子,作为HOOK API的入门.这里是HOOK 自己程序的MessageBox,即将自己 ...

  3. 汇编Ring 3下实现 HOOK API

    [文章标题]汇编ring3下实现HOOK API [文章作者]nohacks(非安全,hacker0058) [作者主页]hacker0058.ys168.com [文章出处]看雪论坛(bbs.ped ...

  4. HOOK API(三)—— HOOK 所有程序的 MessageBox

    HOOK API(三) —— HOOK 所有程序的 MessageBox 0x00 前言 本实例要实现HOOK MessageBox,包括MessageBoxA和MessageBoxW,其实现细节与H ...

  5. Windows Dll Injection、Process Injection、API Hook、DLL后门/恶意程序入侵技术

    catalogue 1. 引言2. 使用注册表注入DLL3. 使用Windows挂钩来注入DLL4. 使用远程线程来注入DLL5. 使用木马DLL来注入DLL6. 把DLL作为调试器来注入7. 使用c ...

  6. HOOK API入门之Hook自己程序的MessageBoxW(简单入门)

    说到HOOK,我看了很多的资料和教程,无奈就是学不会HOOK,不懂是我的理解能力差,还是你们说的 不够明白,直到我看了以下这篇文章,终于学会了HOOK: http://blog.sina.com.cn ...

  7. HOOK API (一)——HOOK基础+一个鼠标钩子实例

    HOOK API (一)——HOOK基础+一个鼠标钩子实例 0x00 起因 最近在做毕业设计,有一个功能是需要实现对剪切板的监控和进程的防终止保护.原本想从内核层实现,但没有头绪.最后决定从调用层入手 ...

  8. HOOK大法实现不修改程序代码给程序添加功能

    [文章标题]: HOOK大法实现不修改程序代码给程序添加功能[文章作者]: 0x18c0[软件名称]: Scylla[使用工具]: OD.Stub_PE.ResHacker[版权声明]: 本文原创于0 ...

  9. 汇编 -- Hook API (MessageBoxW)

    说到HOOK.我看了非常多的资料和教程.无奈就是学不会HOOK.不懂是我的理解能力差.还是你们说的 不够明确,直到我看了下面这篇文章,最终学会了HOOK: http://blog.sina.com.c ...

随机推荐

  1. MySQL数据库报错 > 1366 - Incorrect string value: ‘\xE6\xB1\x9F\xE6\x96\x87‘ for column ‘Teacher‘ at row 1

    数据库报错这个多半是数据库在创建的时候没有选择字符编码,导致输入中文的时候出现报错. > 1366 - Incorrect string value: '\xE6\xB1\x9F\xE6\x96 ...

  2. 使用 JavaScript 中的 document 对象的属性,根据下拉框中选择的属性,更改页面中的字体颜色和背景颜色

    查看本章节 查看作业目录 需求说明: 使用 JavaScript 中的 document 对象的属性,根据下拉框中选择的属性,更改页面中的字体颜色和背景颜色 实现思路: 在页面的 <body&g ...

  3. golang 算法题 : 两数相加

    package mainimport "fmt"type ListNode struct { Val int Next *ListNode}func main() { l1 := ...

  4. Appium之xpath定位详解

    前面也说过appium也是以webdriver为基的,对于元素的定位也基本一致,只是增加一些更适合移动平台的独特方式,下面将着重介绍xpath方法,这应该是UI层元素定位最强大的方法啦! 以淘宝app ...

  5. notepad++加到右键

    win10系统左下角点击"开始"->运行->regedit,打开注册表编辑器 在HKEY_CLAsssEs_RooT→ * → shell 下,在shell下,新建项命 ...

  6. Zuul的应用

    一.介绍 注:Zuul中默认就已经集成了Ribbon负载均衡和Hystix熔断机制.但是所有的超时策略都是走的默认值,比如熔断超时时间只有1S,很容易就触发了. 二.依赖 <dependency ...

  7. Redis内存分析工具之redis-rdb-tools的安装与使用

    操作系统:Centos7    1.redis-rdb-tools工具是用python语言编写的,所以首先需要安装python: 安装: (1)用 wget 下载 python 2.7 并解压( 如果 ...

  8. ADD software version display

    ADD software version display ADD software version display1. Problem Description2. Analysis3. Solutio ...

  9. 《剑指offer》面试题42. 连续子数组的最大和

    问题描述 输入一个整型数组,数组里有正数也有负数.数组中的一个或连续多个整数组成一个子数组.求所有子数组的和的最大值. 要求时间复杂度为O(n). 示例1: 输入: nums = [-2,1,-3,4 ...

  10. 《剑指offer》面试题56 - I. 数组中数字出现的次数

    问题描述 一个整型数组 nums 里除两个数字之外,其他数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度是O(n),空间复杂度是O(1). 示例 1: 输入:nums = [4,1 ...