注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

无翼风的网易博客

欢迎光临无翼风的网易博客

 
 
 

日志

 
 

我的学习笔记之三——inline使用DLL进行全局HOOK(ring3_inline_dll_hook_Messagebox)  

2008-12-23 21:23:30|  分类: 编程与电脑技术 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

前一篇学习了修改导入表来HOOK API,虽然是自己HOOK自己,但稍改一下,变成DLL就可以全局HOOK,因为windows有数据执行保护会拦截,所以就不再深入。
还有一种HOOK API法叫INLINE HOOK就是采用JMP法。长话短说,所谓的API HOOK指的就是 :系统函数接口的钩子。当系统函数进行调用时,首先进入我们指定的函数,然后再执行系统的函数。IAT是修改EXE的导入地址,而JMP修改的是DLL中函数中的内容。我们知道,系统函数都是以DLL封装起来的,应用程序应用到系统函数时,应首先把该DLL加载到当前的进程空间中,调用的系统函数的入口地址,可以通过GetProcAddress函数进行获取。当系统函数进行调用的时候,首先把所必要的信息保存下来(包括参数和返回地址,等一些别的信息),然后就跳转到函数的入口地址,继续执行。其实函数地址,就是系统函数“可执行代码”的开始地址。那么怎么才能让函数首先执行我们的函数呢?呵呵,应该明白了吧,把开始的那段可执行代码替换为我们自己定制的一小段可执行代码,这样系统函数调用时,不就按我们的意图乖乖行事了吗?其实,就这么简单。
也就是说:如果我们已经挂钩好了系统函数。那么当系统进行系统调用时,进入DLL对应的函数,首先就碰到我们的Jmp XXXX指令,而这条指令作用就是跳到我们的函数中去执行。总体流程应该如下:

保存系统函数入口-等待进入我们的函数-恢复系统函数入口-可以做一些我们想做的操作-调用系统函数 -挂接系统函数-保存系统函数入口

有几点很重要(1)JMP后面是我们函数的地址,此处要准确,计算公式为XXXX = 我的函数入口指针(地址)- 系统函数入口指针(地址)- sizeof (Jmp XXXX指令的大小);(2)替换掉的代码一定要保存好,以便随时恢复,否则肯定出错(3)拦截函数中返回值要和正确调用正确函数一至,以无逢提交给系统
下面给出具体的DLL代码

#include <windows.h>

HHOOK g_hHook;
HINSTANCE g_hinstDll;
FARPROC fpMessageBoxA;

HMODULE hModule;
BYTE OldMessageBoxACode[
5],NewMessageBoxACode[5];
DWORD dwIdOld,dwIdNew;
BOOL bHook
=false;

void HookOn();
void HookOff();
BOOL Init();
int WINAPI MyMessageBoxA(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
//---------------------------------------------------------------------------
// 空的钩子函数
LRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)
{
    
return(CallNextHookEx(g_hHook,nCode,wParam,lParam));
}
//---------------------------------------------------------------------------
// 输出,安装空的钩子函数
extern"C"__declspec(dllexport) bool InstallHook()
{
     g_hinstDll
=LoadLibrary("dll.dll"); // 这里的文件名为Dll本身的文件名
     g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0);
    
if (!g_hHook)
     {
      MessageBoxA(NULL,
"SET ERROR","ERROR",MB_OK);
    
return(false);
     }
    
return(true);
}
//---------------------------------------------------------------------------
// 输出,Uninstall钩子函数
extern"C"__declspec(dllexport) bool UninstallHook()
{
     HookOff()
    
return(UnhookWindowsHookEx(g_hHook));
}
//---------------------------------------------------------------------------
// 初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令
BOOL Init()
{
     hModule
=LoadLibrary("user32.dll");
     fpMessageBoxA
=GetProcAddress(hModule,"MessageBoxA");
    
if(fpMessageBoxA==NULL) return false;
     _asm
     {
       pushad
       lea edi,OldMessageBoxACode
       mov esi,fpMessageBoxA
       cld
       movsd
       movsb
       popad
     }
     NewMessageBoxACode[
0] = 0xe9; // jmp MyMessageBoxA的相对地址的指令
     _asm
     {
       lea eax,MyMessageBoxA
       mov ebx,fpMessageBoxA
       sub eax,ebx
       sub eax,
5
       mov dword ptr [NewMessageBoxACode
+ 1],eax
     }
     dwIdNew
= GetCurrentProcessId(); // 得到所属进程的ID
     dwIdOld = dwIdNew;
     HookOn();
// 开始拦截
    return(true);
}
//---------------------------------------------------------------------------
// 首先关闭拦截,然后才能调用被拦截的Api 函数
int WINAPI MyMessageBoxA(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType)
{
    
int nReturn;
     HookOff();
     nReturn
= MessageBoxA(hWnd,"来自钩子中的内容",lpCaption,MB_OK | MB_ICONINFORMATION);
     HookOn();
    
return(nReturn);
}
void HookOn()
{
     HANDLE hProc;
     dwIdOld
= dwIdNew;
    
// 得到所属进程的句柄
     hProc = OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);
    
// 修改所属进程中MessageBoxA的前5个字节的属性为可写
     VirtualProtectEx(hProc,fpMessageBoxA,5,PAGE_READWRITE,&dwIdOld);
    
// 将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA
     WriteProcessMemory(hProc,fpMessageBoxA,NewMessageBoxACode,5,0);
    
// 修改所属进程中MessageBoxA的前5个字节的属性为原来的属性
     VirtualProtectEx(hProc,fpMessageBoxA,5,dwIdOld,&dwIdOld);
     bHook
=true;
}
//---------------------------------------------------------------------------
// 将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA
void HookOff()
{
     HANDLE hProc;
     dwIdOld
= dwIdNew;
     hProc
= OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);
     VirtualProtectEx(hProc,fpMessageBoxA,
5,PAGE_READWRITE,&dwIdOld);
     WriteProcessMemory(hProc,fpMessageBoxA,OldMessageBoxACode,
5,0);
     VirtualProtectEx(hProc,fpMessageBoxA,
5,dwIdOld,&dwIdOld);
     bHook
= false;
}
//---------------------------------------------------------------------------
int WINAPI DllMain(HINSTANCE hinst,unsigned long reason,void* lpReserved)
{
    
switch (reason)
     {
      
case DLL_PROCESS_ATTACH:
        
if(!Init())
         {
             MessageBoxA(NULL,
"Init","ERROR",MB_OK);
            
return(false);
         }
      
case DLL_PROCESS_DETACH:
        
if(bHook) UninstallHook();
        
break;
     }
    
return TRUE;

网上有个代码和这一样,我这里有两处改了下,否则不行。
记住这个是全局HOOK Messagebox,会挂住系统中大部分进程。关于DLL全局HOOK,我不打算再说,其实就是把DLL加载到系统的每个进程空间,HOOK住所有进程,注意说的是每个进程,你也看到了是用WH_GETMESSAGE消息加载全局钩子的,没消息循环的进程当然钩不住了,另外有和程序对进程和模块实施了保护也不行,有的程序会拦截全局钩子的加载,你可能会失败。
此法也存在明显不足,因为当有个程序使用Messagebox时,会进入我们的DLL的MyMessageBoxA中,而它在此先做了HOOKOFF又做了HOOKON,如果有个程序是多线程调用MessageBoxA,可能会出现这个写时那个读,没写完就要读从而出错,windows核心编程早就说了它的不足。最后提醒一下,有的弹出式对话框并不是调用的MessageBoxA,要HOOK住系统中所有的弹出式对话框还要HOOK另个版本MessageBoxW或更多的API。

版权所有,如需引用请注明作者和出处

  评论这张
 
阅读(818)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018