代码如下:
DLL部分:
---------------------------------------------
BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
glhInstance = hInstance;
pCHC=new CHookClass("user32.dll","MessageBoxW",MessageBoxWProxy);
pCHC->HookOn();
break ;
case DLL_PROCESS_DETACH:
delete pCHC;
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
// WH_GETMESSAGE钩子处理过程
LRESULT CALLBACK GetMsgHookProc(int nCode,WPARAM wparam,LPARAM lparam)
{// 什么也不做(只是为了进入其它进程)
return CallNextHookEx(glhMsgHook,nCode,wparam,lparam);
}
DLLEXPORT BOOL InstallHOOK( void )
{
if (glhMsgHook == NULL ){
glhMsgHook = SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)GetMsgHookProc,glhInstance,0 );
}
if (glhMsgHook == NULL) {
return FALSE;
}
return TRUE;
}
// 卸载钩子
DLLEXPORT BOOL UninstallHOOK(void)
{
BOOL bResult=FALSE;
if(glhMsgHook){
bResult= UnhookWindowsHookEx(glhMsgHook);
if(bResult){
glhMsgHook=NULL;
}
}
return bResult;
}
DLL头文件:
---------------------------------------------
class CHookClass{
CHookClass(const CHookClass&);
// 不准拷贝和赋值
CHookClass &operator=(const CHookClass&);
// 栈对齐为1字节
#pragma pack(push,1)
struct TJmpCode{
char Jmp;
DWORD Ptr;
};
#pragma pack(pop)
public:
CHookClass(const char *LibName, // DLL名
const char *FuncName, // 目标函数名
void *NewFuncPtr); // 用于替换的函数指针
~CHookClass();
void HookOn(); // 开启 API Hook
void HookOff(); // 关闭 API Hook
void Lock(); // 进入临界区
void Unlock(); // 退出临界区
bool IsHooked(){
return _IsHooked; // 取Hook状态
}
private:
TJmpCode _OrgCode; // 原函数头5个字节
TJmpCode _NewCode; // 新函数头5个字节(jmp FuncPtr)
void *_TagFuncPtr; // 目标函数指针
HANDLE _CurProcess; // 当前进程
bool _IsHooked; // 显示是否被Hook了
CRITICAL_SECTION _cs; // 临界区
};
// 构造
CHookClass::CHookClass(const char *LibName, const char *FuncName, void *NewFuncPtr)
:_TagFuncPtr(NULL),_IsHooked(false),_CurProcess(0)
{
// 取目标API地址
HMODULE hModule=GetModuleHandle(LibName);
_TagFuncPtr=GetProcAddress(hModule, FuncName);
if(_TagFuncPtr==NULL) throw(-1);
// 保存原函数前五字节
CopyMemory(&_OrgCode,_TagFuncPtr,5);
// 新的五字节为 jmp 偏移
_NewCode.Jmp=0xe9;
_NewCode.Ptr=DWORD(NewFuncPtr)-DWORD(_TagFuncPtr)-5;
// 以特权方式打开当前进程
_CurProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE, GetCurrentProcessId());
LogInfo("当前进程句柄%d",_CurProcess);
InitializeCriticalSection(&_cs);
}
// 析构
CHookClass::~CHookClass()
{
if(_IsHooked) HookOff();
DeleteCriticalSection(&_cs);
}
void CHookClass::HookOn()
{// !开启 API Hook
if(!_IsHooked){
DWORD dwOldProtect;
VirtualProtectEx(_CurProcess, _TagFuncPtr, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
WriteProcessMemory(_CurProcess, _TagFuncPtr, &_NewCode, 5, NULL);
VirtualProtectEx(_CurProcess, _TagFuncPtr, 5, dwOldProtect, &dwOldProtect);
_IsHooked=true;
LogInfo("进程%d的API修改完成",GetCurrentProcessId());
}
}
void CHookClass::HookOff()
{// !关闭 API Hook
if(_IsHooked){
DWORD dwOldProtect;
VirtualProtectEx(_CurProcess, _TagFuncPtr, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
WriteProcessMemory(_CurProcess, _TagFuncPtr, &_OrgCode, 5, NULL);
VirtualProtectEx(_CurProcess, _TagFuncPtr, 5, dwOldProtect, &dwOldProtect);
_IsHooked=false;
}
}
有查看调度日志时发现,很多进程都载入了APIHOOK.dll, 而且在HookOn时都有改写MessageBoxW,为什么其它进程无效呀? APIHOOK.DLL已和这些进程在同一地址空间了呀,郁闷。。。 望各位大侠不吝赐教!
12 个解决方案
#1
我没有仔细看你的逻辑,既然你说在其他进程已经加载并hook成功了,那么,你是否确定调用了MessageBoxWProxy这个函数呢?
#2
Windows消息分为队列消息和非队列消息,WH_GETMESSAGE不能取到非队列消息,用SendMessage发送的消息不经过队列,用PostMessage发送的消息被放入队列
#3
不懂C++语法,不过以前用汇编写过一个全局HOOK的DLL,流程与你的不同.
一,你_CurProcess句柄的获取,我是在DLL_PROCESS_ATTACH时调用GetCurrentProcess得到,参考自老罗的<<WINDOWS环境下32位汇编语言程序设计>>.这个函数只有在这个时候调用才能得到正确的句柄(书中的意思).
二,所有涉及修改的内存操作都使用ReadProcessMemory/WriteProcessMemory来完成.
三,DLL中有一个标志,用于判断是否已经被HOOK了.
四,HOOK的过程写在CALLBACK GetMsgHookProc中,通过判断上面的标志来决定是否HOOK,并与主进程建立通讯.因此在DLL被加载到目标进程后,当有一个消息到来时,才开始HOOK.
而你的代码是在DLL_PROCESS_ATTACH时就调用了HOOK的过程,这个时机不知道是否正确.
五,以上仅供参考......
一,你_CurProcess句柄的获取,我是在DLL_PROCESS_ATTACH时调用GetCurrentProcess得到,参考自老罗的<<WINDOWS环境下32位汇编语言程序设计>>.这个函数只有在这个时候调用才能得到正确的句柄(书中的意思).
二,所有涉及修改的内存操作都使用ReadProcessMemory/WriteProcessMemory来完成.
三,DLL中有一个标志,用于判断是否已经被HOOK了.
四,HOOK的过程写在CALLBACK GetMsgHookProc中,通过判断上面的标志来决定是否HOOK,并与主进程建立通讯.因此在DLL被加载到目标进程后,当有一个消息到来时,才开始HOOK.
而你的代码是在DLL_PROCESS_ATTACH时就调用了HOOK的过程,这个时机不知道是否正确.
五,以上仅供参考......
#4
我不需要所有进程都挂上DLL,有消息循环的挂上即可。比如现在是我确定记事本已挂上了APIHOOK.DLL,而且代码 :LogInfo("进程%d的API修改完成",GetCurrentProcessId());已确实执行了。为什么会拦截不到MessageBoxW呢:(, 我用远程注入修改IAT的方式可以拦截这个函数的,说明记事本程序的确是调用了MessageBoxW。
#5
关于宿主进程句柄的获取没有问题的:我的日志记录如下:
当前进程句柄1480
进程2060的API修改完成
当前进程句柄0
进程1044的API修改完成
当前进程句柄0
进程3556的API修改完成
进程3272的API修改完成
当前进程句柄4040
进程836的API修改完成
当前进程句柄4756
进程3984的API修改完成
当前进程句柄0
进程1236的API修改完成
当前进程句柄4412
进程2180的API修改完成
当前进程句柄2696
进程252的API修改完成
当前进程句柄0
进程2184的API修改完成
当前进程句柄0
进程980的API修改完成
当前进程句柄0
进程552的API修改完成
进程836的API修改完成
在DLL_PROCESS_ATTACH时就调用了HOOK的过程(这点不知道会不会有影响),但看起来象是没影响的,如上面的日志所示。
走过路过的大侠们,帮帮忙。
#6
那剩下的只有调试的问题了,这个基本上就是你自己的事了
#7
楼主用hook注入啊,我都是用CreateRemoteThread注入的,感觉比hook好用的。
#8
CreateRemoteThread 我实现了,只是不明白用HOOK为什么实现不了,望大侠们不吝赐教!
#9
昨晚试了用VC6 生成, 居然一切OK, 天哪,偶要崩溃了!为什么用VS2008 或VS2010生成的就只能HOOK 自己。而VC6 生成的都可以HOOK ,explore,notepad都行. 高手们,大侠们,指点指点,谢谢了!
#10
建议楼主,先对一些简单的程序,进行钩子注入
#11
嗯,想写个全局Hook API啊,这可不是闹着玩的。
没有仔细看你的代码,但,估计你是遭遇到Windows的copy-on-write机制了,
建议看看这篇,或许对你有帮助。
绕过Copy-On-Write机制安装全局Hook
http://dev.firnow.com/course/3_program/c++/cppsl/20081117/151293.html
没有仔细看你的代码,但,估计你是遭遇到Windows的copy-on-write机制了,
建议看看这篇,或许对你有帮助。
绕过Copy-On-Write机制安装全局Hook
http://dev.firnow.com/course/3_program/c++/cppsl/20081117/151293.html
#12
我也遇到过类似经历,而且是Debug版,可以Release版通不过,也是一头雾水啊。不知道是不是跟VS2008的编译优化有关???
#1
我没有仔细看你的逻辑,既然你说在其他进程已经加载并hook成功了,那么,你是否确定调用了MessageBoxWProxy这个函数呢?
#2
Windows消息分为队列消息和非队列消息,WH_GETMESSAGE不能取到非队列消息,用SendMessage发送的消息不经过队列,用PostMessage发送的消息被放入队列
#3
不懂C++语法,不过以前用汇编写过一个全局HOOK的DLL,流程与你的不同.
一,你_CurProcess句柄的获取,我是在DLL_PROCESS_ATTACH时调用GetCurrentProcess得到,参考自老罗的<<WINDOWS环境下32位汇编语言程序设计>>.这个函数只有在这个时候调用才能得到正确的句柄(书中的意思).
二,所有涉及修改的内存操作都使用ReadProcessMemory/WriteProcessMemory来完成.
三,DLL中有一个标志,用于判断是否已经被HOOK了.
四,HOOK的过程写在CALLBACK GetMsgHookProc中,通过判断上面的标志来决定是否HOOK,并与主进程建立通讯.因此在DLL被加载到目标进程后,当有一个消息到来时,才开始HOOK.
而你的代码是在DLL_PROCESS_ATTACH时就调用了HOOK的过程,这个时机不知道是否正确.
五,以上仅供参考......
一,你_CurProcess句柄的获取,我是在DLL_PROCESS_ATTACH时调用GetCurrentProcess得到,参考自老罗的<<WINDOWS环境下32位汇编语言程序设计>>.这个函数只有在这个时候调用才能得到正确的句柄(书中的意思).
二,所有涉及修改的内存操作都使用ReadProcessMemory/WriteProcessMemory来完成.
三,DLL中有一个标志,用于判断是否已经被HOOK了.
四,HOOK的过程写在CALLBACK GetMsgHookProc中,通过判断上面的标志来决定是否HOOK,并与主进程建立通讯.因此在DLL被加载到目标进程后,当有一个消息到来时,才开始HOOK.
而你的代码是在DLL_PROCESS_ATTACH时就调用了HOOK的过程,这个时机不知道是否正确.
五,以上仅供参考......
#4
我不需要所有进程都挂上DLL,有消息循环的挂上即可。比如现在是我确定记事本已挂上了APIHOOK.DLL,而且代码 :LogInfo("进程%d的API修改完成",GetCurrentProcessId());已确实执行了。为什么会拦截不到MessageBoxW呢:(, 我用远程注入修改IAT的方式可以拦截这个函数的,说明记事本程序的确是调用了MessageBoxW。
#5
关于宿主进程句柄的获取没有问题的:我的日志记录如下:
当前进程句柄1480
进程2060的API修改完成
当前进程句柄0
进程1044的API修改完成
当前进程句柄0
进程3556的API修改完成
进程3272的API修改完成
当前进程句柄4040
进程836的API修改完成
当前进程句柄4756
进程3984的API修改完成
当前进程句柄0
进程1236的API修改完成
当前进程句柄4412
进程2180的API修改完成
当前进程句柄2696
进程252的API修改完成
当前进程句柄0
进程2184的API修改完成
当前进程句柄0
进程980的API修改完成
当前进程句柄0
进程552的API修改完成
进程836的API修改完成
在DLL_PROCESS_ATTACH时就调用了HOOK的过程(这点不知道会不会有影响),但看起来象是没影响的,如上面的日志所示。
走过路过的大侠们,帮帮忙。
#6
那剩下的只有调试的问题了,这个基本上就是你自己的事了
#7
楼主用hook注入啊,我都是用CreateRemoteThread注入的,感觉比hook好用的。
#8
CreateRemoteThread 我实现了,只是不明白用HOOK为什么实现不了,望大侠们不吝赐教!
#9
昨晚试了用VC6 生成, 居然一切OK, 天哪,偶要崩溃了!为什么用VS2008 或VS2010生成的就只能HOOK 自己。而VC6 生成的都可以HOOK ,explore,notepad都行. 高手们,大侠们,指点指点,谢谢了!
#10
建议楼主,先对一些简单的程序,进行钩子注入
#11
嗯,想写个全局Hook API啊,这可不是闹着玩的。
没有仔细看你的代码,但,估计你是遭遇到Windows的copy-on-write机制了,
建议看看这篇,或许对你有帮助。
绕过Copy-On-Write机制安装全局Hook
http://dev.firnow.com/course/3_program/c++/cppsl/20081117/151293.html
没有仔细看你的代码,但,估计你是遭遇到Windows的copy-on-write机制了,
建议看看这篇,或许对你有帮助。
绕过Copy-On-Write机制安装全局Hook
http://dev.firnow.com/course/3_program/c++/cppsl/20081117/151293.html
#12
我也遇到过类似经历,而且是Debug版,可以Release版通不过,也是一头雾水啊。不知道是不是跟VS2008的编译优化有关???