Hook使用实例

本文介绍了一种通过更改程序的数据结构或代码结构来改变程序运行路径的方法——Hook技术,并分为用户模式Hook、内核模式Hook和Inline Function Hook三部分进行讲解。用户模式Hook包括IAT-hook和Dll-inject两种方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【文章标题】: 必备绝技--Hook大法(上)
【文章作者】: LvG
【作者邮箱】:  LvG2008@gmail.com
【作者声明】: 这没有什么新鲜东西,其内容全部来自于前辈,姑且当作学习笔记。文字用自己的话写出,四段代码均出自别人(知道作者的,以注明),但短小精悍,就写在一起了,便于察看。欢迎指正。
--------------------------------------------------------------------------------
【详细过程】
  hook概念:是一种通过更改程序的数据结构或代码结构从而改变程序运行路线的一种方法。(纯属本人自己观点) 
      分类:从上面的概念来看,一种是改变程序的数据结构,如:IAT-hook,Dll-inject及Direct Kernel Object Manipulation(DKOM)。一种是Inline Function Hooking。
      用途:现在这种方法普遍运用于各类程序中,如加壳,杀软,病毒,Rootkits等等。
  本文从难以程度上主要分三块详细介绍:一.用户模式Hook:IAT-hook,Dll-inject二.内核模式Hook:ssdt-hook,idt-hook,int 2e/sysenter-hook三.Inline Function Hook;
  这次先来看第一部分
  Ⅰ.用户模式Hook
  一.IAT-hooking
  (一)一般原理:IAT是Import Address Table(输入地址表)的简写,这需要你知道关于win PE格式的了解。现在应用程序中的大多数函数都是windows api,而这些函数一般都由几个系统dll导出,如user32.dll,kernel32.dll,advapi32.dll等。如果程序要运用这些函数,就的从这些dll文件中导入,程序会把导入的函数放到一个叫IAT的数据结构中。我们可以先找到自己需要hook的函数,然后把目标函数的地址改成我们自己的hook函数,最后在恢复到目标函数的地址。这样一来,目标函数被调用时,我们的hook函数也就别调用了。如果这个hook函数是病毒,是后门,是。。。。。。。。由于是在目标函数进程的空间内,所以这个hook函数也就不会被发现。

关于WIN PE格式的详细知识可参见:http://bbs.pediy.com/showthread.php?t=31840及<<加密与解密>>。
  (二)大体框架:这里用伪码给个一般框架,以便有个大体印象。
  文件1:myhookfun()
        {
             可以创建一个新的线程,去执行木马或后门等功能
        }
  文件2: include <文件1>
     寻找目标模块(GetModuleHandle),目标函数(GetProcAddress)
    if(目标函数找到)
       根据pe结构,在目标模块中定位目标函数的IAT地址(这个地址在加载时就确定了)
       if (目标函数在IAT中的地址找到)
           用我们的myhookfun()地址取代
       esle 退出
    esle 退出
    
  当然也可以合成一个文件,但这样分开的好处是可以实现模块化,可以分别关心各自的功能,也便于以后重用。
  (三)代码实例:
      .486 
      .model flat, stdcall 
      option casemap:none 
  
  include   windows.inc 
  include   kernel32.inc 
  includelib   kernel32.lib 
  include   user32.inc 
  includelib   user32.lib 
  
      .data 
  szMsgTitle  db   "IAT Hook", 0 
  szModule   db   "user32.dll", 0 
  szTargetFunc   db   "GetForegroundWindow", 0 
  szHooked   db   "This is in the hooked function - Seems to have worked.", 0 
  szFail     db   "Failed.", 0 
  
      .data? 
  
  IATHook   PROTO   STDCALL :DWORD, :DWORD, :DWORD 
  HookProc PROTO   STDCALL :LPVOID 
  
      .code 
  HookProc   proc   Arg1:LPVOID 
            invoke   MessageBox, NULL, addr szHooked, addr szMsgTitle, MB_OK 
            ret 
  HookProc   endp 
  
  IATHook   proc   pDLLName:LPVOID, pOldAddr:LPVOID, pNewAddr:LPVOID 
         LOCAL   hModule:HANDLE 
         LOCAL   dwVirtualAddr:DWORD 
         LOCAL   dwOrigProtect:DWORD 
         LOCAL   dwDllFound:DWORD 
         LOCAL   dwFunctionFound:DWORD 
             ;Local variables 
      
         .if   pDLLName == NULL 
             ;Check for NULL pointer 
              xor   eax, eax 
              ret 
         .endif 
         .if   pOldAddr == NULL 
             ;Check for NULL pointer 
              xor   eax, eax 
              ret 
         .endif 
         .if   pOldAddr == NULL 
             ;Check for NULL pointer 
              xor   eax, eax 
              ret 
         .endif 
      
         mov dwDllFound, 0 
         mov dwFunctionFound, 0 
             ;Initialize 
      
         invoke   GetModuleHandle, NULL 
             ;Get the main module's base address 
         mov   hModule, eax 
             ;Copy it into hModule 
      
         mov   edi, hModule 
         assume   edi:ptr IMAGE_DOS_HEADER 
             ;Make edi act as IMAGE_DOS_HEADER struct 
         .if   edi == NULL 
             ;Check for NULL pointer 
              xor   eax, eax 
              ret 
                ;Return 0 
         .endif 
      
         .if   [edi].e_magic != IMAGE_DOS_SIGNATURE 
             ;0x4D 0x5A (MZ) 
              xor   eax, eax 
              ret 
                ;Return 0 
         .endif 
      
         add   edi, [edi].e_lfanew 
             ;pNtHeader = (IMAGE_NT_HEADERS*)((DWORD)pDosHeader + (DWORD)pDosHeader->e_lfanew); 
      
         assume   edi:ptr IMAGE_NT_HEADERS 
             ;Make edi act as IMAGE_NT_HEADERS struct 
         .if   edi == NULL 
             ;Check for NULL pointer 
              xor   eax, eax 
              ret 
                ;Return 0 
         .endif 
      
         .if   [edi].Signature != IMAGE_NT_SIGNATURE 
             ;If it's an invalid NT header 
             ;0x50 0x45 0x00 0x00 (PE/0/0) 
              xor   eax, eax 
              ret 
                ;Return 0 
         .endif 
      
         mov   edx, [edi].OptionalHeader.DataDirectory[sizeof IMAGE_DATA_DIRECTORY].VirtualAddress 
         mov   dwVirtualAddr, edx 
             ;Copy the VirtualAddress into dwVirtualAddr 
      
         .if   dwVirtualAddr == 0 
             ;Invalid virtual address 
              xor   eax, eax 
              ret 
                ;Return 0 
         .endif    
  
         mov   edi, hModule 
         add   edi, dwVirtualAddr 
             ;pImportHeader = (IMAGE_IMPORT_DESCRIPTOR*)((DWORD)pDosHeader + dwVirtualAddr); 
      
         assume   edi:ptr IMAGE_IMPORT_DESCRIPTOR 
             ;Make edi act as IMAGE_IMPORT_DESCRIPTOR struct 
         .if   edi == NULL 
             ;Check for NULL pointer 
              xor   eax, eax 
              ret 
                ;Return 0 
         .endif 
      
         .while [edi].Name1 != NULL 
              mov   ecx, hModule 
              add   ecx, [edi].Name1 
                ;pModuleLabel = (char*)((DWORD)pDosHeader + (DWORD)pImportHeader->Name); 
  
              mov   edx, pDLLName 
              invoke   lstrcmpi, ecx, edx 
                ;Check if this is the DLL we are looking for 
         
              .if   eax == 0 
                ;This is the DLL we are looking for 
                 mov dwDllFound, 1 
                 ;Set ecx to 0, so we know later if the DLL was found 
               .break 
              .endif 
         
              add edi, sizeof IMAGE_IMPORT_DESCRIPTOR 
                ;Next DLL 
         .endw 
      
         .if   dwDllFound != 1 
             ;If the DLL wasn't found 
              xor   eax, eax 
              ret 
                ;Return 0 
         .endif 
      
         mov   edi, [edi].FirstThunk 
         add   edi, hModule 
             ;pThunkData = (IMAGE_THUNK_DATA*)((DWORD)pDosHeader + (DWORD)pImportHeader->FirstThunk); 
      
         assume   edi:ptr IMAGE_THUNK_DATA 
             ;Make edi act as IMAGE_THUNK_DATA struct 
      
         .while   [edi].u1.Function != NULL 
              mov ecx, hModule 
              add ecx, [edi].u1.Function 
         
              mov edx, [edi].u1.Function 
                ;Copies the current functions address (in the IAT table) into edx 
         
            .if   pOldAddr == edx 
                ;If this is the function we are going to hook 
                  lea ebx, [edi].u1.Function 
                    ;Copy the address in the table that the function is stored in, into ebx 
               
                  invoke VirtualProtect, ebx, 4, PAGE_WRITECOPY, addr dwOrigProtect 
                    ;Unprotect the memory where we are going to overwrite (We need 4 bytes --- DWORD = 4 bytes) 
               
                  mov eax, pNewAddr 
                    ;Copy the address we are going to replace it with into eax 
                  mov [ebx], eax 
                    ;Patch the address 
                           
                  invoke VirtualProtect, ebx, 4, addr dwOrigProtect, NULL 
                    ;Restore the original protection level 
               
                  mov dwFunctionFound, 1 
                    ;Set the value, for later 
               
                  .break 
            .endif 
         
              add   edi, sizeof IMAGE_THUNK_DATA 
                ;Next thunk 
         .endw 
      
         .if   dwFunctionFound != 1 
             ;If the function wasn't found 
              xor   eax, eax 
              ret 
                ;Return 0 
         .endif 
      
         
           mov eax, 1 
           ret 
             ;Return 1 
      
             ;Success 
  IATHook   endp 
  
  start: 
         invoke   GetModuleHandle, addr szModule 
         invoke   GetProcAddress, eax, addr szTargetFunc 
      
         mov   ebx, HookProc 
      
         invoke   IATHook, addr szModule, eax, ebx      ;Redirect GetForegroundWindow (eax) to HookProc (ebx) 
         .if   eax == 0 
              invoke   MessageBox, NULL, addr szFail, addr szMsgTitle, MB_OK 
              invoke   ExitProcess, 0 
         .endif 
  
             ;Is now hooked, hopefully.. so lets call it 
         invoke   GetForegroundWindow 
      
         invoke   ExitProcess, 0 
  end     start
  
  (四)局限性:1当程序运用一种叫late-demand binding技术,函数被调用时才定位地址,这样以来就不能在IAT中定位目标函数地址了.2当目标程序用动态加载(LoadLibrary)时,这种方法也将失效.
  
  二.Dll-Injecting
  (一)通过注册表注入Dll
  1.一般原理:Windows的注册表中有这样一个键值,
  HKEY_LOCAL_MACHINE/Software/Microsoft/Windows NT/CurrentVersion/Windows/AppInit_Dlls 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值