iathook詳解

iathook是Windows API Hook技術中的一種,它通過修改導入表中的dll導入函數地址,使得被Hook的函數在實際調用時會轉而調用Hook函數。iathook的實現方法有多種,本文將從iathook原理、iathook易語言、iathook缺點、iathook運行遠程線程等方面對它進行詳細的分析和闡述。

一、iathook原理

在程序載入時,Windows會讀取程序的導入表,來確定程序需要依賴哪些dll庫,並會將這些函數的地址填充到相應的位置。在導入表中,每個dll庫都會對應一個導入描述符(Import Descriptor),它包含了被目標dll庫導出的函數的一份名單,順序排列在該描述符中。每個此類函數都對應一個導入名稱表(Import Name Table),其用於存儲導入描述符中每個函數的名稱與地址。

iathook實際上就是通過修改目標dll庫的導入名稱表中的函數地址,從而將被Hook函數重定向到Hook函數。其原理如下所示:

    1. 找到Windows API函數所在的dll庫,例如kernel32.dll;
    2. 在該dll庫的導入描述符中,找到被Hook函數的導入名稱表,並獲取其地址;
    3. 運行時修改該導入名稱表的相關函數地址,使其指向Hook函數地址;
    4. 當被Hook函數被調用時,實際會轉而調用Hook函數;

下面是iathook原理的代碼實現:

    PIMAGE_IMPORT_DESCRIPTOR iid = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(
            hModule, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size
        );
    while (iid->Name) {
        PIMAGE_THUNK_DATA pNameTable = (PIMAGE_THUNK_DATA)(rva2ptr(hModule, iid->FirstThunk));
        PIMAGE_THUNK_DATA pAddrTable = (iid->OriginalFirstThunk) 
            ? (PIMAGE_THUNK_DATA)(rva2ptr(hModule, iid->OriginalFirstThunk))
            : pNameTable;
        
        for (; pAddrTable->u1.Function != NULL; pAddrTable++, pNameTable++) {
            if (pAddrTable->u1.Function == fpHookedFunction) {
                DWORD dwOldProtect, dwNewProtect;
                VirtualProtect((LPVOID)&pNameTable->u1.Function, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect);
                pNameTable->u1.Function = (DWORD)fpHookFunction;
                VirtualProtect((LPVOID)&pNameTable->u1.Function, sizeof(DWORD), dwOldProtect, &dwNewProtect);
            }
        }
        iid++;
    }

二、iathook易語言

iathook在易語言中也是可以實現的,易語言中的關鍵函數有:

  • memory.LoadPEFile:用於載入dll文件到內存中;
  • memory.GetPEFileBase:獲取dll文件在內存中的基地址;
  • memory.GetVirtualAddress:獲取導入表中函數的地址;
  • memory.WriteDWord:用於修改導入表中函數的地址;

下面是在易語言中實現iathook的代碼示例:

    //聲明iathook函數指針類型
    typedef void (*fpIATHook)(void);
    fpIATHook pfnOldFunc = NULL;
    
    //調用memory函數以獲取目標dll的句柄和基地址
    HMODULE hModule = memory.LoadPEFile("TargetDLL.dll");
    DWORD dwBaseAddr = memory.GetPEFileBase(hModule);
    
    //獲取需要Hook的函數地址以及導入表地址
    LPSTR szHookFuncName = "TargetFunction";
    LPSTR szImportDllName = "TargetDLL.dll";
    LPSTR szImportFuncName = "TargetFunction";
    DWORD dwIATBase = memory.GetVirtualAddress(dwBaseAddr, szImportDllName, szImportFuncName);
    DWORD *pdwOrgIATEntry = (DWORD*)memory.GetVirtualAddress(dwBaseAddr, szImportDllName, szHookFuncName);
    
    //備份原函數地址,並修改導入表中函數的地址
    pfnOldFunc = (fpIATHook)(*pdwOrgIATEntry);
    memory.WriteDWord((DWORD)(&pdwOrgIATEntry[0]), (DWORD)(&HookFunction));
    
    //Hook完成,可以調用目標函數時,實際上會調用自定義的Hook函數
    TargetFunction(Param1, Param2, ...);
    
    //取消Hook,將原函數地址恢復到導入表中
    memory.WriteDWord((DWORD)(&pdwOrgIATEntry[0]), (DWORD)(pfnOldFunc));

三、iathook缺點

iathook雖然實現簡單,但是在安全性上存在很大的漏洞和缺點,下面是一些iathook的缺點:

  • 易受反Hook,因為其僅是修改導入表中函數的地址,所以易受到反Hook,從而直接執行原本的函數,導致Hook失效;
  • 無法Hook外部函數,如果被Hook的函數在導入表中沒有,而在外部dll庫中,那麼iathook也將無法Hook該函數;
  • 無法HookGetProcAddress,因為GetProcAddress函數返回的地址是動態的,而不是固定的地址,iathook無法修改其地址,因此無法Hook該函數
  • 修改導入表可能引起程序崩潰,特別是在多線程環境下,修改導入表可能會導致程序崩潰,所以在iathook的應用中,需要特別小心處理。

四、iathook運行遠程線程

iathook也能夠直接運行遠程線程,僅需要將需要Hook的函數引入模塊裝載入遠程線程的地址空間,並讀取和修改導入表中的地址。下面是iathook運行遠程線程的代碼示例:

    LPSTR szTargetDllName = "TargetModule.dll";
    LPSTR szTargetFuncName = "TargetFunction";
    LPSTR szHookFuncName = "HookFunction";
    
    //獲取遠程進程句柄和主模塊句柄
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
    HMODULE hModule = GetModuleHandle(NULL);
    
    //獲取遠程目標dll句柄和大小
    HMODULE hModRemote = NULL;
    DWORD dwModSize = 0;
    GetRemoteModuleHandle(hProcess, szTargetDllName, &hModRemote, &dwModSize);
    
    //將目標dll模塊裝載入遠程線程地址空間
    LPVOID pRemoteBase = VirtualAllocEx(hProcess, NULL, dwModSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    BOOL bWritten = WriteProcessMemory(hProcess, pRemoteBase, lpData, dwModSize, NULL);
    if (bWritten) {
        DWORD dwRemoteThreadId = 0;
        //運行遠程線程,執行iathook
        HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, 
                (LPTHREAD_START_ROUTINE)pfnLoadDll, pRemoteBase, 0, &dwRemoteThreadId);
        WaitForSingleObject(hRemoteThread, INFINITE);
        VirtualFreeEx(hProcess, pRemoteBase, 0, MEM_RELEASE);
        
        //查找導入表中函數地址並Hook
        DWORD dwRemoteBase = (DWORD)hModRemote;
        DWORD dwRemoteFunction = (DWORD)GetProcAddress(hModRemote, szTargetFuncName);
        DWORD dwImportAddrTable = GetIATAddress(dwRemoteBase, hModule, szTargetDllName);
        DWORD dwOldProtect = 0;
        VirtualProtectEx(hProcess, (LPVOID)dwImportAddrTable, 4, PAGE_READWRITE, &dwOldProtect);
        WriteProcessMemory(hProcess, (LPVOID)dwImportAddrTable, &dwRemoteFunction, sizeof(DWORD), NULL);
        VirtualProtectEx(hProcess, (LPVOID)dwImportAddrTable, 4, dwOldProtect, &dwOldProtect);
    }
    //done......

以上就是iathook的詳解,iathook雖然在實現上簡單,但是在實踐應用時,需要特別注意到其應用場景,了解其中的缺陷和漏洞,以便更好地利用它。

原創文章,作者:NWDN,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/148261.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
NWDN的頭像NWDN
上一篇 2024-11-03 15:15
下一篇 2024-11-03 15:15

相關推薦

  • 神經網路代碼詳解

    神經網路作為一種人工智慧技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網路的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網路模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁碟中。在執行sync之前,所有的文件系統更新將不會立即寫入磁碟,而是先緩存在內存…

    編程 2025-04-25
  • C語言貪吃蛇詳解

    一、數據結構和演算法 C語言貪吃蛇主要運用了以下數據結構和演算法: 1. 鏈表 typedef struct body { int x; int y; struct body *nex…

    編程 2025-04-25
  • nginx與apache應用開發詳解

    一、概述 nginx和apache都是常見的web伺服器。nginx是一個高性能的反向代理web伺服器,將負載均衡和緩存集成在了一起,可以動靜分離。apache是一個可擴展的web…

    編程 2025-04-25
  • MPU6050工作原理詳解

    一、什麼是MPU6050 MPU6050是一種六軸慣性感測器,能夠同時測量加速度和角速度。它由三個感測器組成:一個三軸加速度計和一個三軸陀螺儀。這個組合提供了非常精細的姿態解算,其…

    編程 2025-04-25
  • git config user.name的詳解

    一、為什麼要使用git config user.name? git是一個非常流行的分散式版本控制系統,很多程序員都會用到它。在使用git commit提交代碼時,需要記錄commi…

    編程 2025-04-25
  • Python輸入輸出詳解

    一、文件讀寫 Python中文件的讀寫操作是必不可少的基本技能之一。讀寫文件分別使用open()函數中的’r’和’w’參數,讀取文件…

    編程 2025-04-25
  • Java BigDecimal 精度詳解

    一、基礎概念 Java BigDecimal 是一個用於高精度計算的類。普通的 double 或 float 類型只能精確表示有限的數字,而對於需要高精度計算的場景,BigDeci…

    編程 2025-04-25
  • Python安裝OS庫詳解

    一、OS簡介 OS庫是Python標準庫的一部分,它提供了跨平台的操作系統功能,使得Python可以進行文件操作、進程管理、環境變數讀取等系統級操作。 OS庫中包含了大量的文件和目…

    編程 2025-04-25
  • 詳解eclipse設置

    一、安裝與基礎設置 1、下載eclipse並進行安裝。 2、打開eclipse,選擇對應的工作空間路徑。 File -> Switch Workspace -> [選擇…

    編程 2025-04-25

發表回復

登錄後才能評論