全局 HOOK API (通过钩子) ,请大侠们帮帮忙

wwstudio_cn 2010-07-05 09:09:48
我上网参照一些神人的代码想写个全局API HOOK, 大致是这样实现的,做了一个全局钩子(WH_GETMESSAGE)来确保含有修改API代码的DLL被加载到很多进程中。DLL有个类,在加载的时候初始化,修改API(MessageBoxW). 现在好像DLL都被那些进程正确加载了,而且都进行了API的修改,但是为什么只对我本进程有效,其它进程都无效, 和COPY ON WRITE有关吗?

代码如下:
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已和这些进程在同一地址空间了呀,郁闷。。。 望各位大侠不吝赐教!
...全文
618 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
oklamp 2010-08-16
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 wwstudio_cn 的回复:]
昨晚试了用VC6 生成, 居然一切OK, 天哪,偶要崩溃了!为什么用VS2008 或VS2010生成的就只能HOOK 自己。而VC6 生成的都可以HOOK ,explore,notepad都行. 高手们,大侠们,指点指点,谢谢了!
[/Quote]
我也遇到过类似经历,而且是Debug版,可以Release版通不过,也是一头雾水啊。不知道是不是跟VS2008的编译优化有关???
oklamp 2010-08-16
  • 打赏
  • 举报
回复
嗯,想写个全局Hook API啊,这可不是闹着玩的。
没有仔细看你的代码,但,估计你是遭遇到Windows的copy-on-write机制了,
建议看看这篇,或许对你有帮助。

绕过Copy-On-Write机制安装全局Hook
http://dev.firnow.com/course/3_program/c++/cppsl/20081117/151293.html
x858078 2010-07-07
  • 打赏
  • 举报
回复
建议楼主,先对一些简单的程序,进行钩子注入
wwstudio_cn 2010-07-07
  • 打赏
  • 举报
回复
昨晚试了用VC6 生成, 居然一切OK, 天哪,偶要崩溃了!为什么用VS2008 或VS2010生成的就只能HOOK 自己。而VC6 生成的都可以HOOK ,explore,notepad都行. 高手们,大侠们,指点指点,谢谢了!
wwstudio_cn 2010-07-06
  • 打赏
  • 举报
回复
CreateRemoteThread 我实现了,只是不明白用HOOK为什么实现不了,望大侠们不吝赐教!
wwstudio_cn 2010-07-06
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 myjian 的回复:]
不懂C++语法,不过以前用汇编写过一个全局HOOK的DLL,流程与你的不同.

一,你_CurProcess句柄的获取,我是在DLL_PROCESS_ATTACH时调用GetCurrentProcess得到,参考自老罗的<<WINDOWS环境下32位汇编语言程序设计>>.这个函数只有在这个时候调用才能得到正确的句柄(书中的意思).

二,所有涉及修改的内存操作都使用ReadProcessM……
[/Quote]

关于宿主进程句柄的获取没有问题的:我的日志记录如下:
当前进程句柄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的过程(这点不知道会不会有影响),但看起来象是没影响的,如上面的日志所示。

走过路过的大侠们,帮帮忙。
wwstudio_cn 2010-07-06
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 liuxiaoyi666 的回复:]
Windows消息分为队列消息和非队列消息,WH_GETMESSAGE不能取到非队列消息,用SendMessage发送的消息不经过队列,用PostMessage发送的消息被放入队列
[/Quote]
我不需要所有进程都挂上DLL,有消息循环的挂上即可。比如现在是我确定记事本已挂上了APIHOOK.DLL,而且代码 :LogInfo("进程%d的API修改完成",GetCurrentProcessId());已确实执行了。为什么会拦截不到MessageBoxW呢:(, 我用远程注入修改IAT的方式可以拦截这个函数的,说明记事本程序的确是调用了MessageBoxW。
magic7004 2010-07-06
  • 打赏
  • 举报
回复
楼主用hook注入啊,我都是用CreateRemoteThread注入的,感觉比hook好用的。
嗷嗷叫的老马 2010-07-06
  • 打赏
  • 举报
回复
不懂C++语法,不过以前用汇编写过一个全局HOOK的DLL,流程与你的不同.

一,你_CurProcess句柄的获取,我是在DLL_PROCESS_ATTACH时调用GetCurrentProcess得到,参考自老罗的<<WINDOWS环境下32位汇编语言程序设计>>.这个函数只有在这个时候调用才能得到正确的句柄(书中的意思).

二,所有涉及修改的内存操作都使用ReadProcessMemory/WriteProcessMemory来完成.

三,DLL中有一个标志,用于判断是否已经被HOOK了.

四,HOOK的过程写在CALLBACK GetMsgHookProc中,通过判断上面的标志来决定是否HOOK,并与主进程建立通讯.因此在DLL被加载到目标进程后,当有一个消息到来时,才开始HOOK.

而你的代码是在DLL_PROCESS_ATTACH时就调用了HOOK的过程,这个时机不知道是否正确.

五,以上仅供参考......
嗷嗷叫的老马 2010-07-06
  • 打赏
  • 举报
回复
那剩下的只有调试的问题了,这个基本上就是你自己的事了
  • 打赏
  • 举报
回复
Windows消息分为队列消息和非队列消息,WH_GETMESSAGE不能取到非队列消息,用SendMessage发送的消息不经过队列,用PostMessage发送的消息被放入队列
masefee 2010-07-05
  • 打赏
  • 举报
回复
我没有仔细看你的逻辑,既然你说在其他进程已经加载并hook成功了,那么,你是否确定调用了MessageBoxWProxy这个函数呢?

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧