<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    Hook技術入門

    007bug2021-07-20 16:26:02

    0x00 前言

    要說在Hook技術里面最基礎的,那就是IAT Hook,它的原理就是通過修改PE結構中的IAT表,將其替換成我們自己定義的函數,最終實現Hook,所以在進行Hook之前,我們得很清楚的PE結構,接下來我們先講解一下怎么索引到IAT表。


    0x01 PE文件格式解析

    隨便拖一個程序進入Uedit進行分析

    這一部分就是PE文件的DOS頭,先看看DOS頭的結構體,咱邊看結構體邊分析:

    typedef struct IMAGE_DOS_HEADER
      {
            WORD e_magic;        WORD e_cblp;
            WORD e_cp;
            WORD e_crlc;
            WORD e_cparhdr;
            WORD e_minalloc;
            WORD e_maxalloc;
            WORD e_ss;
            WORD e_sp;
            WORD e_csum;
            WORD e_ip;
            WORD e_cs;
            WORD e_lfarlc;
            WORD e_ovno;
            WORD e_res[4];
            WORD e_oemid;
            WORD e_oeminfo;
            WORD e_res2[10];
            DWORD e_lfanew;            
      }IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
    

    在DOS頭里面最關鍵是兩個成員就是e_magic,e_lfanew(其他的可以忽略),e_magic就是DOS頭的標識,也就是MZ,為什么是MZ呢,其實就是Mark Zbikowski,他是MS-DOS主要開發者之一,為了紀念老人家,e_lfanew就是下一個頭的偏移(基于文件基址),可能有同學要有疑問了,為啥現在還要有這個DOS頭呢,因為微軟為了向下兼容,所以才沒有刪除DOS頭,那么加上偏移我們來看看:

    PE頭也有它自己的結構體,Signature和e_magic是一個道理,這里的Signature是PE。

    typedef struct IMAGE_NT_HEADERS   {        
         DWORD Signature;         
         IMAGE_FILE_HEADER FileHeader;
         IMAGE_OPTIONAL_HEADER32 OptionalHeader;   
    } IMAGE_NT_HEADERS,*PIMAGE_NT_HEADERS;
    

    選擇的區域是上面結構體中的FileHeader

    它也有自己的結構體,感興趣的小伙伴可以自己去查查每個字段的具體含義,這里就不展開了:

    typedef struct _IMAGE_FILE_HEADER {   
            WORD      Machine;                 //運行平臺 
            WORD      NumberOfSections;        //節表數目    
            DWORD     TimeDateStamp;           //時間戳     
            DWORD     PointerToSymbolTable;    
            DWORD     NumberOfSymbols;         //符號數  
            WORD      SizeOfOptionalHeader;    //可選部首長度 
            WORD      Characteristics;         //文件屬性 
    }
    

    說完FileHeader,重點就來了,那就是OptionalHeade,除去Signature,FileHeader剩下的就是OptionalHeade:


    結構體如下,我們關注其最重要的一個成員DataDirectory(數據目錄),它包含了我們要替換的導入表。

    typedef struct _IMAGE_OPTIONAL_HEADER {
      WORD                 Magic;
      BYTE                 MajorLinkerVersion;
      BYTE                 MinorLinkerVersion;
      DWORD                SizeOfCode;
      DWORD                SizeOfInitializedData;
      DWORD                SizeOfUninitializedData;
      DWORD                AddressOfEntryPoint;
      DWORD                BaseOfCode;
      DWORD                BaseOfData;
      DWORD                ImageBase;
      DWORD                SectionAlignment;
      DWORD                FileAlignment;
      WORD                 MajorOperatingSystemVersion;
      WORD                 MinorOperatingSystemVersion;
      WORD                 MajorImageVersion;
      WORD                 MinorImageVersion;
      WORD                 MajorSubsystemVersion;
      WORD                 MinorSubsystemVersion;
      DWORD                Win32VersionValue;
      DWORD                SizeOfImage;
      DWORD                SizeOfHeaders;
      DWORD                CheckSum;
      WORD                 Subsystem;
      WORD                 DllCharacteristics;
      DWORD                SizeOfStackReserve;
      DWORD                SizeOfStackCommit;
      DWORD                SizeOfHeapReserve;
      DWORD                SizeOfHeapCommit;
      DWORD                LoaderFlags;
      DWORD                NumberOfRvaAndSizes;
      IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
    } IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
    

    它妥妥的有十六張表,我們只關注導入表:



    typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    union {
    DWORD Characteristics;
    DWORD OriginalFirstThunk;    
    } DUMMYUNIONNAME;
    DWORD TimeDateStamp; 
    DWORD ForwarderChain; 
    DWORD Name;                   //指向DLL名字的RVA
    DWORD FirstThunk;         
    } IMAGE_IMPORT_DESCRIPTOR;
    

    這里面最重要的就是OriginalFirstThunk,Name,FirstThunk

    其中OriginalFirstThunk,FirstThunk分別指向INT和IAT表,心心念念的IAT表終于登場了,這兩個成員指向的都是同一個表,為什么這樣做等下說



    當我們的函數加載完成后,我們IAT指向了函數真正的地址

    在IAT在加載完真正的函數地址之后,如果沒有INT表來標識具體的函數名稱的話,操作系統就完全不知道它加載的這個函數名稱是啥,只有一個函數的實現偏移和實現,并不知道它是啥,所以才會有INT表的存在。


    0x02 IAT Hook 代碼編寫

    到此PE結構也就講解完了,也就可以開始寫IAT Hook

    我們的代碼應該包含以下功能:

    1.定義我們自己的Hook后的函數

    int WNAPI MyMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
    {
      return OldMessageBoxA(hWnd, "Hello NSDA", lpCaption, uType);
    }
    

    我們自己的MessageBox必須和原來的MessageBox的參數一模一樣,這樣才能保證在調用自己的函數的時候不會報錯

    2.接下來就是找到IAT表

    HMODULE ImageBase = GetModuleHandle(NULL);  //獲得模塊基地址                            
    PIMAGE_DOS_HEADER pDosHead = (PIMAGE_DOS_HEADER)(DWORD)ImageBase;                  
    DWORD dwTemp = (DWORD)pDosHead + (DWORD)pDosHead->e_lfanew;
    PIMAGE_NT_HEADERS pNtHead = (PIMAGE_NT_HEADERS)dwTemp;                                                           
    PIMAGE_OPTIONAL_HEADER pOpHead = (PIMAGE_OPTIONAL_HEADER)&pNtHead->OptionalHeader;
    
    DWORD dwInputTable = pOpHead->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;  
    DWORD dwTemp = (DWORD)GetModuleHandle(NULL) + dwInputTable;
    PIMAGE_IMPORT_DESCRIPTOR   pImport = (PIMAGE_IMPORT_DESCRIPTOR)dwTemp;
    PIMAGE_IMPORT_DESCRIPTOR   pCurrent = pImport;
    

    通過GetModuleHandle獲得模塊基地址之后,我們就可以拿到程序的DOS頭,PE頭,文件頭,可選頭

    3.接下來就是遍歷IAT將其替換成我們自己函數的地址

      while (*(DWORD*)pFirstThunk != NULL)                        
        {
          if (*(DWORD*)pFirstThunk == (DWORD)OldMessageBoxA)       
          {
            DWORD oldProtected;
            VirtualProtect(pFirstThunk, 0x1000, PAGE_EXECUTE_READWRITE, &oldProtected);  
            memcpy(pFirstThunk, (DWORD *)&dwTemp, 4);                                    
            VirtualProtect(pFirstThunk, 0x1000, oldProtected, &oldProtected);            
          }
          pFirstThunk++;
        }
    

    通過遍歷IAT表找到MessageBox的地址之后進行替換,有一點需要注意的,需要先修改文件的頁屬性才能進行替換(在XP系統上不用)

    完整代碼就不貼了,大伙們可以自己去嘗試把完整的代碼寫出來,下面看看Hook完的效果:

    文章作者: 廣軟NSDA安全團隊
    dwordtypedef
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    程序是指令、數據及其組織形式的描述,進程是程序的實體。在進程中當EXE模塊調用CreateFile()函數的時候,會去調用kernel32.dll模塊中的CreateFile()函數,因為真正的CreateFile()函數的實現在kernel32.dll模塊中。
    在Windows大部分應用都是基于消息機制,他們都擁有一個消息過程函數,根據不同消息完成不同功能,windows通過鉤子機制來截獲和監視系統中的這些消息。一般鉤子分局部鉤子與全局鉤子,局部鉤子一般用于某個線程,而全局鉤子一般通過dll文件實現相應的鉤子函數。
    全局鉤子注入在Windows大部分應用都是基于消息機制,他們都擁有一個消息過程函數,根據不同消息完成不同功能,windows通過鉤子機制來截獲和監視系統中的這些消息。一般鉤子分局部鉤子與全局鉤子,局部鉤子一般用于某個線程,而全局鉤子一般通過dll文件實現相應的鉤子函數。
    前言一次跟師傅交流時師傅談到有些EDR或AV,他們保護目標主機,甚至無進程,不經想到病毒實際上也常用這種技術。
    簡介這次實驗是在WIN7 X86系統上進程,使用的編譯器是VS2017。所謂的DLL注入,其實就是在其他的進程中把我們編寫的DLL加載進去。所以DLL注入的核心就是把要注入的DLL的路徑寫到目標進程中,然后在目標進程中調用LoadLibrary函數,并且指定參數為保存了DLL路徑的地址。要實現DLL注入,首先就要創建一個用來注入的DLL。
    最近在研究某數字殺軟的時候看到有個配置選項:這個自我保護實際上是加載360SelfProtection.sys驅動(看這名字應該還有360SelfProtection_win10.sys文件),在0環通過hook等手段保護注冊表項,重要進程進程等。
    Dll注入
    2021-11-08 14:57:41
    最近太忙啦XDM,又在做一些列的分析復現工作量有點大,更新要慢一點了。一致,也不會覆蓋其他的進程信息。
    在win2012以前的操作系統版本下,由于WDigest將明文儲存到lsass進程中,可以抓取明文密碼。
    DLL(Dynamic Link Library)文件為動態鏈接庫文件,又稱“應用程序拓展”,是軟件文件類型。在Windows中,許多應用程序并不是一個完整的可執行文件,它們被分割成一些相對獨立的動態鏈接庫,即DLL文件。
    007bug
    暫無描述
      亚洲 欧美 自拍 唯美 另类