#include "stdafx.h"
//原函数类型定义
typedef int (WINAPI* MsgBoxW)(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);
MsgBoxW OldMsgBoxW = NULL;//指向原函数的指针
FARPROC pfOldMsgBoxW; //指向函数的远指针
BYTE OldCode[5]; //原系统API入口代码
BYTE NewCode[5]; //原系统API新的入口代码 (jmp xxxxxxxx)
HANDLE hProcess = NULL;//本程序进程句柄
HINSTANCE hInst = NULL;//API所在的dll文件句柄
void HookOn();
void HookOff();
void GetApiEntrance();
void OnBnClickedBtnStartHook();
void OnBnClickedBtnCallMsgBox();
void OnBnClickedBtnStopHook();
int WINAPI MyMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
{
TRACE(lpText);
HookOff();//调用原函数之前,记得先恢复HOOK呀,不然是调用不到的
//如果不恢复HOOK,就调用原函数,会造成死循环
//毕竟调用的还是我们的函数,从而造成堆栈溢出,程序崩溃。
int nRet = ::MessageBoxW(hWnd, _T("MessageBoxW被HOOK了"), lpCaption, uType);
HookOn();//调用完原函数后,记得继续开启HOOK,不然下次会HOOK不到。
return nRet;
}
//开启钩子的函数
void HookOn()
{
ASSERT(hProcess != NULL);
DWORD dwTemp = 0;
DWORD dwOldProtect;
//修改API函数入口前5个字节为jmp xxxxxx
VirtualProtectEx(hProcess, pfOldMsgBoxW, 5, PAGE_READWRITE, &dwOldProtect);
WriteProcessMemory(hProcess, pfOldMsgBoxW, NewCode, 5, 0);
VirtualProtectEx(hProcess, pfOldMsgBoxW, 5, dwOldProtect, &dwTemp);
}
//关闭钩子的函数
void HookOff()
{
ASSERT(hProcess != NULL);
DWORD dwTemp = 0;
DWORD dwOldProtect;
//恢复API函数入口前5个字节
VirtualProtectEx(hProcess, pfOldMsgBoxW, 5, PAGE_READWRITE, &dwOldProtect);
WriteProcessMemory(hProcess, pfOldMsgBoxW, OldCode, 5, 0);
VirtualProtectEx(hProcess, pfOldMsgBoxW, 5, dwOldProtect, &dwTemp);
}
//获取API函数入口前5个字节
//旧入口前5个字节保存在前面定义的字节数组BYTE OldCode[5]
//新入口前5个字节保存在前面定义的字节数组BYTE NewCode[5]
void GetApiEntrance()
{
HMODULE hmod = ::LoadLibrary(_T("User32.dll"));
OldMsgBoxW = (MsgBoxW)::GetProcAddress(hmod, "MessageBoxW");
pfOldMsgBoxW = (FARPROC)OldMsgBoxW;
if (pfOldMsgBoxW == NULL)
{
MessageBox(NULL, _T("获取原API入口地址出错"), _T("error!"), 0);
return;
}
_asm
{
lea edi, OldCode //获取OldCode数组的地址,放到edi
mov esi, pfOldMsgBoxW //获取原API入口地址,放到esi
cld //方向标志位,为以下两条指令做准备
movsd //复制原API入口前4个字节到OldCode数组
movsb //复制原API入口第5个字节到OldCode数组
}
NewCode[0] = 0xe9;//实际上0xe9就相当于jmp指令
_asm
{
lea eax, MyMessageBoxW //获取我们的MyMessageBoxW函数地址
mov ebx, pfOldMsgBoxW //原系统API函数地址
sub eax, ebx //int nAddr= UserFunAddr – SysFunAddr
sub eax, 5 //nAddr=nAddr-5
mov dword ptr[NewCode + 1], eax //将算出的地址nAddr保存到NewCode后面4个字节
//注:一个函数地址占4个字节
}
HookOn();
}
void OnBnClickedBtnStartHook()
{
DWORD dwPid = ::GetCurrentProcessId();
hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwPid);
GetApiEntrance();
printf("Hook已启动");
}
void OnBnClickedBtnCallMsgBox()
{
HWND m_hWnd = GetConsoleWindow();
::MessageBoxW(m_hWnd, _T("这是正常的MessageBoxW"), _T("Hello"), 0);
}
//停止HOOK
void OnBnClickedBtnStopHook()
{
HookOff();
printf("Hook未启动");
}
void main()
{
OnBnClickedBtnStartHook();
OnBnClickedBtnStopHook();
OnBnClickedBtnCallMsgBox();
}
原作者的程序是窗口的
我提取了下,改成dos了