读书人

远程DLL中怎么设置全局钩子

发布时间: 2012-01-12 22:11:58 作者: rapoo

远程DLL中如何设置全局钩子。
我写了个DLL,然后用另一个程序将它当作远程线程注入到NOTEPAD.exe中,在DLL实现全局HOOK,在HOOKPROC中实现替换MESSAGEBOXA的前5字节为跳转到新API。
DLL代码如下:

// Test_DLL.cpp : Defines the entry point for the DLL application.
//
#include <windows.h>
#include "stdafx.h "

#pragma comment(lib, "ImageHlp ") //定义全局共享数据段
#pragma data_seg( "Shared ")

HMODULE g_hinstDll=NULL;
HHOOK g_hHook=NULL;

#pragma data_seg()
#pragma comment(linker, "/Section:Shared,rws ") //设置全局共享数据段的属性

FARPROC pfMessageBoxA;
int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);

BYTE OldMessageBoxACode[5],NewMessageBoxACode[5];//新旧API内存镜像前5字节
HMODULE hModule;
DWORD dwIdOld,dwIdNew;
BOOL bHook=false;

BOOL InstallHook();
BOOL UnInstallHook();

BOOL HookOn();
BOOL HookOff();

LRESULT WINAPI HookProc(int nCode,WPARAM wParam,LPARAM lParam);

/////////////////////////
// DllMain
/////////////////////////
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
if(!InstallHook())
{
MessageBoxA(NULL, "Error ", "InstallHook ",MB_OK);
return(false);
}
case DLL_THREAD_ATTACH:

case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
if(g_hHook) UnInstallHook();
break;
}
return TRUE;
}

/////////////////////////
// InstallHook 安装一个全局消息钩子
/////////////////////////
BOOL InstallHook()//输出安装空的钩子函数
{
g_hinstDll=LoadLibrary( "Test_DLL.dll ");//远程线程中不能再载入DLL,所以此处使用DLL中Hook()
g_hHook=SetWindowsHookEx ( WH_GETMESSAGE,(HOOKPROC)HookProc,g_hinstDll,0 );//钩子所监视的线程的线程号。0为全局钩子,监视全部线程
if (!g_hHook)
{
MessageBoxA(NULL, "SET ERROR ", "SET ERROR ",MB_OK);
return(false);
}
return(true);
}

/////////////////////////
// HookProc 在进程内准备好跳转到新API地址的代码
/////////////////////////
LRESULT WINAPI HookProc(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数
{
hModule=LoadLibrary( "user32.dll ");
pfMessageBoxA=GetProcAddress(hModule, "MessageBoxA ");// 获取目标API的地址
NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令
_asm
{
lea eax,MyMessageBoxA
mov ebx,pfMessageBoxA
sub eax,ebx
sub eax,5
mov dword ptr [NewMessageBoxACode+1],eax
}//写入地址到替换代码的缓存
dwIdNew=GetCurrentProcessId();//得到所属进程的ID*/

if (!HookOn())
MessageBoxA ( NULL, "HookOn失败 ", "HookOn失败 ", MB_OK );
return(CallNextHookEx(g_hHook,nCode,wParam,lParam));
}

/////////////////////////
// HookOn 修改进程中API的前5个字节,写入跳转到新API的代码
/////////////////////////
BOOL HookOn()
{
MessageBoxA(NULL, "开始修改 ", "HookOn开始修改 ",MB_OK);
HANDLE hProc;



//dwIdOld=dwIdNew;
hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄

//修改所属进程中MessageBoxA的前5个字节的属性为可写
if (!VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld)){
MessageBoxA(NULL, "HookOn1修改为可写时失败 ", "HookOn1修改为可写时失败 ",MB_OK);
return false;
}

//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA
if (!WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0)){
MessageBoxA(NULL, "HookOn2修改字节时失败 ", "HookOn2修改字节时失败 ",MB_OK);
return false;
}

//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性
if (!VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld)){
MessageBoxA(NULL, "HookOn3恢复属性时失败 ", "HookOn3恢复属性时失败 ",MB_OK);
return false;
}

bHook=true;
return true;
}
/////////////////////////
// UninstallHook
/////////////////////////
BOOL UnInstallHook()//输出御载钩子函数
{
return(UnhookWindowsHookEx(g_hHook));
}

/////////////////////////
// MyMessageBoxA
/////////////////////////
int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数
{
int nReturn=0;
dwIdNew=GetCurrentProcessId();//得到所属进程的ID
HookOff();//改回地址
nReturn=MessageBoxA(hWnd, "Hook成功 ",lpCaption,uType);
dwIdNew=GetCurrentProcessId();//得到所属进程的ID
HookOn();//改写地址
return(nReturn);
}

/////////////////////////
// HookOff
/////////////////////////
BOOL HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA
{
HANDLE hProc;
dwIdOld=dwIdNew;
hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);
VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);
WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0);
VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);
bHook=false;
return true;
}

注入后,用ICDSWORD查到NOTEPAD.EXE进程中确实有我这个DLL,但我在NOTEPAD.exe中写几个字再作新建时,弹出的MessageBox窗口并没有改变,而且我设的是全局钩子,打开其它加载有MessageBox所在的DLL的程序,也没见修改后的MessageBox出现。

我感觉是HOOKPROC没有起作用,请问是为什么?

[解决办法]
学习
帮顶
[解决办法]
调试下,看看有没有正确跳转啊,另外MessageBoxW也hook一下看看
[解决办法]
InstallHook()函数里面使用的SetWindowsHookEx函数的第三个参数hMod,直接使用DllMain函数的hModule参数就可以了,而不能使用LoadLibrary函数来得到模块句柄值。具体原因请参考MSDN里面的DllMain入口函数部分。这里我就不多讲了。

读书人网 >VC/MFC

热点推荐