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/n/148261.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
NWDNNWDN
上一篇 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

发表回复

登录后才能评论