// HookMessageboxWindowDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "HookMessageboxWindow.h"
#include "HookMessageboxWindowDlg.h"
#include "afxdialogex.h"
// 定义API类型
#define CODE_LENGTH 5 // 入口指令长度
typedef int (WINAPI *TypeMessageBoxW)(HWND hwnd,LPCWSTR
lpText,LPCWSTR lpCaption,UINT uType);
TypeMessageBoxW OdlMsgBoxW = NULL; // 指向函数原型指针
FARPROC pfOldMsgBoxW; // 指向函数远指针
BYTE OldCode[CODE_LENGTH]; // 原系统API入口
BYTE NewCode[CODE_LENGTH]; // 自己实现的API的入口,(jmp
xxxx),xxxx为新API入口地址
HANDLE hProcess = NULL; // 本程序进程句柄
HINSTANCE hInst = NULL; // API所在的dll文件句柄
VOID HookOn(); // 开始HOOK
VOID HookOff(); // 停止HOOK
VOID GetApiEntrancy(); // 获取API入口地址
bool AdjustPrivileges();// 提高权限
//
// 自己定义的,用于替换相应API的,假的API
//
int WINAPI MyMessageBoxW(HWND hwnd,LPCWSTR lpText,LPCWSTR
lpCation,UINT uType)
{
TRACE(lpText);
/*
调用原函数之前,先停止HOOK,也就是恢复原系统API函数的入口,
否则无法调用到原API函数,而是继续调用自己的API,会造成死
循环,进而造成堆栈溢出,崩溃。
*/
HookOff();
/*
调用原来的MessageBoxW打印我们的信息。
*/
int ret = MessageBoxW(hwnd,_T("哈哈,被HOOK咯!!"),lpCation,uType);
/*
调用完原系统API后,记得恢复HOOK,也就是启动HOOK,将原API函数入口换成我们自己定义的函数入口,
否则下一次调用MessageBoxW的时候就无法转到我们自己定义的API函数中,也就无法实现HOOK。
*/
HookOff();
return ret;
}
/*
启动HOOK,将原API的入口地址换成我们自己定义函数的入口地址
*/
VOID HookOn()
{
//
// 确保本程序进程句柄hProcess不为NULL
//
ASSERT(hProcess!=NULL);
DWORD dwTemp;
DWORD dwOldProtect;
SIZE_T writedByte;
//
// 修改API入口的前5个字节,jmp xxxx
//
VirtualProtectEx(hProcess,pfOldMsgBoxW,CODE_LENGTH,PAGE_READWRITE,&dwOldProtect);
WriteProcessMemory(hProcess,pfOldMsgBoxW,NewCode,CODE_LENGTH,&writedByte);
if (writedByte == 0)
{
AfxMessageBox(_T("替换原API地址失败"));
}
VirtualProtectEx(hProcess,pfOldMsgBoxW,CODE_LENGTH,dwOldProtect,&dwTemp);
}
/*
定制HOOK,将入口换成原来的API入口地址
*/
VOID HookOff()
{
ASSERT(hProcess != NULL);
DWORD dwTemp;
DWORD dwOldProtect;
SIZE_T wirtedByte;
// 回复原API地址
VirtualProtectEx(hProcess,pfOldMsgBoxW,CODE_LENGTH,PAGE_READWRITE,&dwOldProtect);
WriteProcessMemory(hProcess,pfOldMsgBoxW,OldCode,CODE_LENGTH,&wirtedByte);
if (wirtedByte == 0)
{
AfxMessageBox(_T("回复原API地址失败"));
}
VirtualProtectEx(hProcess,pfOldMsgBoxW,CODE_LENGTH,dwOldProtect,&dwTemp);
}
/*
保存原API和新API的地址
*/
VOID GetApiEntrancy()
{
//
// 保存原来API地址
//
HMODULE hmod = LoadLibrary(_T("User32.dll"));
if ( NULL == hmod)
{
AfxMessageBox(_T("加载User32.dll失败"));
return;
}
OdlMsgBoxW = (TypeMessageBoxW)::GetProcAddress(hmod,"MessageBoxW");
pfOldMsgBoxW = (FARPROC)OdlMsgBoxW;
if ( pfOldMsgBoxW == NULL)
{
AfxMessageBox(_T("获取原API入口地址出错"));
return;
}
//
// 将原API的入口5个字节代码保存到OdeCode[]中
//
_asm
{
lea edi,OldCode // 取数组OldCode[]地址,存放到edi中
mov esi,pfOldMsgBoxW // 获取原API入口地址,存入esi中
cld // 设置方向
movsd // 移动dword ,4 Byte
movsb // 移动 1 Byte
}
//
// 新的API入口保存到NewCode[]中,即jmp xxxx,xxxx为新API地址,该指令总长度为5个字节
//
NewCode[0] = 0xe9; // 0xe9相当于jmp指令
_asm
{
lea eax,MyMessageBoxW
mov ebx,pfOldMsgBoxW
sub eax,ebx
sub eax,CODE_LENGTH
mov dword ptr[NewCode+1],eax
}
//
// 填充完毕,开始HOOK,即使用NewCode[]替换原API入口
//
HookOn();
}
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;
}
//
// 启动 HookMessageBoxW
//
void CHookMessageboxWindowDlg::OnBnClickedButtonStart()
{
// TODO: 在此添加控件通知处理程序代码
AdjustPrivileges(); // 提升权限,因为调用 OpenProcess()
需要合适的权限
DWORD dwPid = ::GetCurrentProcessId();
hProcess = OpenProcess(PROCESS_ALL_ACCESS,0,dwPid);
if (hProcess == NULL)
{
CString logInfo;
logInfo.Format(_T("获取进程句柄失败!!,进程 id = 0x%x
,错误代码 = 0x%x"),dwPid,GetLastError());
AfxMessageBox(logInfo);
return;
}
GetApiEntrancy(); // 获取新旧API入口,并开始HOOK
m_status.SetWindowText(_T("Hook已启动"));
}
//
// 终止 HookMessageBoxW
//
void CHookMessageboxWindowDlg::OnBnClickedButtonStop()
{
// TODO: 在此添加控件通知处理程序代码
HookOff();
m_status.SetWindowText(_T("Hook已停止"));
}
//
// 调用 HookMessageBoxW
//
void CHookMessageboxWindowDlg::OnBnClickedButtonCall()
{
// TODO: 在此添加控件通知处理程序代码
::MessageBoxW(m_hWnd,_T("这是正常的MessageBoxW"),_T("Hello"),0);
} |