《Windows PE》4.1.3 IAT函数地址表

IAT(Import Address Table)表又称为函数地址表,是Windows可执行文件中的一个重要数据结构,用于存储导入函数的实际入口地址。

在可执行文件中,当一个模块需要调用另一个模块中的函数时,通常会使用导入函数的方式进行。导入函数的入口地址在程序加载时并不确定,需要在运行时进行动态链接,以获取实际的函数入口地址。IAT表就是用来存储这些实际的函数入口地址。

IAT表是一个由函数指针构成的表格,每个函数指针对应一个导入函数。在Windows可执行文件中,IAT表是一个以NULL结尾的函数指针数组,每个函数指针对应一个导入函数的实际入口地址。

IAT表通常是通过导入描述符(Import Descriptor)中的FirstThunk字段指向的地址来访问的。FirstThunk指向一个由IMAGE_THUNK_DATA结构体构成的表,每个IMAGE_THUNK_DATA结构体中的Function字段存储着导入函数的实际入口地址。

在程序加载时,操作系统会根据导入描述符中的INT表和IAT表进行动态链接,将导入函数的实际入口地址填充到IAT表中的函数指针对应的位置。这样,在程序运行时,就可以直接通过IAT表中的函数指针调用导入函数,而无需进行额外的解析和跳转。

 注意

IAT函数地址表中的函数指针是在程序加载和链接时被填充的,而导入表描述符中的IAT表中的函数指针在未绑定的状态下与INT表完全相同。如果导入表描述符的TimeDateStamp和ForwarderChain字段是一个特殊的标志值,如0xFFFFFFFF,表示导入函数已绑定,则IAT函数地址表中存储的是真实的导入函数地址。

实验二十五:如何定位IAT表?

我们以32位汇编版HelloWorld.exe为例,将其拖入WinHex,如下所示:

00000140   00 00 00 00 00 00 00 00  DC 20 00 00 3C 00 00 00   ........?..<...

00000150   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

00000160   00 00 00 00 00 00 00 00  00 40 00 00 10 00 00 00   .........@......

00000170   10 20 00 00 1C 00 00 00  00 00 00 00 00 00 00 00   . ..............

00000180   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

00000190   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

000001A0   00 20 00 00 10 00 00 00  00 00 00 00 00 00 00 00   . ..............

000001B0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

000001C0   2E 74 65 78 74 00 00 00  26 00 00 00 00 10 00 00   .text...&.......

000001D0   00 02 00 00 00 04 00 00  00 00 00 00 00 00 00 00   ................

000001E0   00 00 00 00 20 00 00 60  2E 72 64 61 74 61 00 00   .... ..`.rdata..

000001F0   5E 01 00 00 00 20 00 00  00 02 00 00 00 06 00 00   ^.... ..........

00000200   00 00 00 00 00 00 00 00  00 00 00 00 40 00 00 40   ............@..@

00000210   2E 64 61 74 61 00 00 00  1B 00 00 00 00 30 00 00   .data........0..

00000220   00 02 00 00 00 08 00 00  00 00 00 00 00 00 00 00   ................

00000230   00 00 00 00 40 00 00 C0  2E 72 65 6C 6F 63 00 00   ....@..?reloc..

00000240   10 00 00 00 00 40 00 00  00 02 00 00 00 0A 00 00   .....@..........

00000250   00 00 00 00 00 00 00 00  00 00 00 00 40 00 00 42   ............@..B

首先我们查找数据目录项的第12项,即IAT表项。位于00000220H地址处的RVA值为00002010H,大小为0000001CH。

此RVA地址同样位于.rdata节区。

IAT表的FOA地址=00002000H-00002000H+600H=600H。

00000600   42 21 00 00 00 00 00 00  28 21 00 00 00 00 00 00   B!......(!......

00000610   00 00 00 00 E4 68 03 66  00 00 00 00 0D 00 00 00   ....鋒.f........

00000620   B0 00 00 00 2C 20 00 00  2C 06 00 00 00 00 00 00   ?.., ..,.......

00000630   00 10 00 00 26 00 00 00  2E 74 65 78 74 00 00 00   ....&....text...

00000640   00 20 00 00 10 00 00 00  2E 69 64 61 74 61 24 35   . .......idata$5

00000650   00 00 00 00 10 20 00 00  1C 00 00 00 2E 72 64 61   ..... .......rda

00000660   74 61 00 00 2C 20 00 00  B0 00 00 00 2E 72 64 61   ta.., ..?...rda

00000670   74 61 24 7A 7A 7A 64 62  67 00 00 00 DC 20 00 00   ta$zzzdbg...?..

00000680   28 00 00 00 2E 69 64 61  74 61 24 32 00 00 00 00   (....idata$2....

00000690   04 21 00 00 14 00 00 00  2E 69 64 61 74 61 24 33   .!.......idata$3

000006A0   00 00 00 00 18 21 00 00  10 00 00 00 2E 69 64 61   .....!.......ida

000006B0   74 61 24 34 00 00 00 00  28 21 00 00 36 00 00 00   ta$4....(!..6...

000006C0   2E 69 64 61 74 61 24 36  00 00 00 00 00 30 00 00   .idata$6.....0..

000006D0   1B 00 00 00 2E 64 61 74  61 00 00 00 20 21 00 00   .....data... !..

000006E0   00 00 00 00 00 00 00 00  36 21 00 00 08 20 00 00   ........6!... ..

000006F0   18 21 00 00 00 00 00 00  00 00 00 00 50 21 00 00   .!..........P!..

00000700   00 20 00 00 00 00 00 00  00 00 00 00 00 00 00 00   . ..............

00000710   00 00 00 00 00 00 00 00  42 21 00 00 00 00 00 00   ........B!......

00000720   28 21 00 00 00 00 00 00  B1 01 4D 65 73 73 61 67   (!......?Messag

00000730   65 42 6F 78 41 00 75 73  65 72 33 32 2E 64 6C 6C   eBoxA.user32.dll

00000740   00 00 9B 00 45 78 69 74  50 72 6F 63 65 73 73 00   ..?ExitProcess.

00000750   6B 65 72 6E 65 6C 33 32  2E 64 6C 6C 00 00 00 00   kernel32.dll....

       IAT表内包含两个函数名的RVA地址:

       第一个:00002142H转为FOA地址为742H,是kernel32.dll中的ExitProcess函数。

       第二个:00002128H转为FOA地址为728H,是user32.dll中的MessagBoxA函数。

       我们再来看一下导入表描述符中的桥2(FirstThunk字段),指向IAT表。

       第一个导入表描述符FirstThunk字段的值为00002008H,转为FOA地址为608H,其RVA值为00002128H,即user32.dll中的MessagBoxA函数。

       第二个导入表描述符FirstThunk字段的值为00002000H,转为FOA地址为600H,其RVA值为00002142H,即kernel32.dll中的ExitProcess函数。

 

总结

       我们会发现,在未绑定导入函数的情况下,实验二十五中给出的IAT函数地址表中数据与INT表中的数据完全相同。如果已绑定导入函数,则IAT表直接存储真实的函数入口地址。我们将在下一节中详细讲述。

实验二十六:遍历IAT函数地址表。

我们以32位和64位记事本程序为例:

/*------------------------------------------------------------------------

 FileName:PrintImportDescriptor.c

 实验26:遍历IAT表(支持32位和64位PE)

 (c) bcdaren, 2024

-----------------------------------------------------------------------*/

#include <stdio.h>

#include <windows.h>

#define WIN64

PBYTE loadPE(LPCWSTR szFile);

VOID iat32(PBYTE lpvResult);

VOID iat64(PBYTE lpvResult);

DWORD RvaToFoa(PIMAGE_NT_HEADERS ntHeaders, DWORD rva);

int main(int argc, char* argv[])

{

    LPCWSTR szFileName = TEXT("c:\\notepad64.exe");

    //PCWSTR szFileName = TEXT("c:\\HelloWorld.exe");

    PBYTE lpAddress = NULL; //PE文件内存映射文件地址

    lpAddress = loadPE(szFileName);

    if (lpAddress)

    {

        printf("%ls\n", szFileName);

#ifdef WIN64

        iat64(lpAddress);

#else

        iat32(lpAddress);

#endif

    }

    system("pause");

    return 0;

}

//创建PE文件映射对象

PBYTE loadPE(LPCWSTR szFile)

{

    HANDLE hFile;

    LPVOID lpvResult, lpvResult2;

    char buffer[16] = { 0 };

    DWORD dwPageSize;

    DWORD dwBytesRead = 0;

    BOOL bReadFile;

    PIMAGE_DOS_HEADER psImageDOSHeader;

#ifdef WIN64

    PIMAGE_NT_HEADERS64 psImageNTHeader;

#else

    PIMAGE_NT_HEADERS32 psImageNTHeader;

#endif

    PIMAGE_SECTION_HEADER sImageSecctionHeader[20]; //节表项

相关推荐

《Windows PE》18.3 壳破解

看完了上一节,读者应该会有些感慨,破解是如此的简单。如果你是收费商业软件的一方,肯定会觉得应该需要做点什么。在本章的第一节,我们介绍了很多种不同的验证方式,可以根据具体情况,选择一种合适的验证方法。但是,不论采用什么样的验证方式,验证本身也是需要防护的。我们可以使用加密壳对验证代码进行加密保护。因此,加密壳又被称之为保护的保护。本节我们将介绍register.exe使用UPX壳加密,然后再破解的方法。脱壳后破解带壳破解。

bcdaren的博客 1182

《Windows PE》17.3 FSG壳

回顾第十六章PE病毒的16.2.2病毒分析案例一中,我们分析的病毒样本Lab01-03.exe使用了FSG壳。本节我们就来详细分析FSG壳。静态分析手工脱壳。

bcdaren的博客 953

《Windows PE》16.4.2 病毒查杀

当单步执行到从入口地址开始的0x61地址处(第一条PUSH指令的下一条指令地址01013061H)时,从context上下文中取出栈顶stCT.Esp的值(000DFF80H),然后调用ReadProcessMemory函数读取该地址处存储的原程序入口地址。接下来我们还是以Win32.Capric.exe的“X病毒”为例,首先使用手工的方法清理病毒,然后再写一个针对该病毒的专杀工具。由上一小节对病毒源代码的分析我们得知,如果需要彻底修复被感染的目标文件,我们需要将被病毒修改的部分逐一进行修复。

bcdaren的博客 1142

《Windows PE》15.1 资源捆绑

在下载应用程序时,我们会发现一些特殊的EXE应用程序。当我们运行EXE程序时会同时下载或生成若干个其他应用程序,并自动运行。这个过程通常会以一种静默的方式悄悄地进行。我们将这一技术称之为EXE捆绑。之所以这样做,好的方面是简化程序下载安装的过程。坏的方面是一些流氓软件可以借此牟利,侵犯用户的选择权。本章介绍两种常用的EXE捆绑的实现方法。本章学习知识概要:资源捆绑补丁捆绑。

bcdaren的博客 1146

《Windows PE》14.1最后一节插入补丁程序

如果我们希望添加不同功能的补丁,只需要替换补丁DLL就可以了。00010430 03 F3 8B 76 78 03 F3 8B 7E 20 03 FB 8B 4E 14 56 .髬vx.髬~ .麐N.V。00010420 00 00 00 8B 40 0C 8B 70 1C AD 8B 58 08 8B 73 3C ...婡.媝.瓔X.媠

bcdaren的博客 1008

《Windows PE》12.4 万能补丁

本节我们将介绍基于嵌入式补丁的万能补丁技术。万能补丁原理示例程序。

bcdaren的博客 1070

《Windows PE》11.2.1 PE变形技术

恶意软件使用PE变形技术来修改PE文件的结构和代码,以产生不同的变种,从而使每个实例看起来不同,难以被传统的基于特征的病毒检测技术所识别。■●代码混淆:恶意软件使用各种技术,如指令替换、指令重排、无用代码插入等,来修改PE文件的代码,使其难以分析和识别。这样可以改变程序的控制流,增加分析的复杂性。【注】我们将在PE加密壳一章详细讲解代码混淆。●API重命名:恶意软件可能会修改PE文件中调用的系统API函数的名称,使其与正常的API名称不同。

bcdaren的博客 6868

《Windows PE》9.2 动态加载技术-获取kernel32.dll基址

上一节中我们介绍了如何动态调用DLL的方法。首先调用LoadLibrary函数动态加载DLL,然后调用GetProcAddress通过函数名获取DLL内的函数地址。但是LoadLibrary和GetProcAddress函数的调用仍然依赖于PE文件内的导入表和函数地址表的存在。在操作系统加载PE文件到内存时获取这两个函数的地址。本节我们将介绍一种完全不依赖于导入表和函数地址表的方法,实现对DLL动态链接库中函数的调用。简单来说,需要经过以下三步:步骤1获取kernel32.dll的基地址。

bcdaren的博客 1771

《Windows PE》7.4 资源表应用

本节我们将通过两个示例程序,演示对PE文件内图标资源的置换与提取。更改图标提取图标资源。

bcdaren的博客 1102

《Windows PE》7.3 遍历资源表

文件偏移:00003AB8 (代码页=0804, 长度2字节)文件偏移:00003AC0 (代码页=0804, 长度2字节)2.示例程序对于非资源内容(例如应用程序清单)归类于自定义资源类型。文件偏移:00007DD0 (代码页=0409, 长度381字节)●模块五:RvaToFileOffset.c(略)●模块七:GetResourceInfo.c。●模块六:Getpeinfo.c(略)●模块四:pemain.c(略)●模块1:resource.h。●模块2:peinfo.rc。●模块三:info.h。

bcdaren的博客 460

《Windows PE》7.2 资源表

在资源表中,IMAGE_RESOURCE_DIRECTORY_ENTRY 的 OffsetToData 字段指向一个 IMAGE_RESOURCE_DATA_ENTRY 结构,该结构描述了资源数据的位置和相关属性。PE 对话框资源的起始位置 01 00 FF FF 00 00 00 00 00 00 00 00 是对话框资源的标识符,用于识别和定位对话框资源在 PE 文件中的位置。资源的每一级目录都会有一个资源目录头,它标识 了该类资源的属性、创建日期和版本等信息,其中也包含了随后的目录项的数量描述信息。

bcdaren的博客 1254

《Windows PE》7.1 资源分类

自定义资源是指在程序中使用的非标准资源,这些资源可以是任何类型的数据或文件,用于存储和使用程序所需的特定信息或内容。在资源脚本文件(.rc 文件)中,可以使用自定义的资源类型来定义和描述这些资源。其在资源 文件中的定义语法如下:资源 ID 类型 ID [DISCARDABLE]BEGIN数据定义……END以下是一个示例:上述代码中,IDR_CUSTOM1 是自定义资源的唯一标识符(ID),CUSTOM 是自定义资源类型指示符,custom.dat 是自定义资源文件的名称。

bcdaren的博客 941

《Windows PE》6.4.2 远程注入DLL

测试步骤:当PEHeader.exe运行时,运行remoteThread.exe,点击文件菜单”插入到PEHeader.exe”,就可以将DLL远程注入到进程PEHeader.exe中了。对比无DLL注入的方法,使用DLL注入的方法不需要对代码和数据进行重定位(由操作系统自动完成),省去了很多不必要的麻烦,因此也是我们常用的方法。写一个窗口程序,将一个dll通过远程注入的方法,注入到第三章的示例程序PEHeader.exe中,支持32位和64位PE。1.打开本地进程(调用OpenProcess函数)。

bcdaren的博客 578

《Windows PE》6.4.1 无 DLL远程注入

一旦你的ThreadFunc中有错误,远程线程会立即崩溃。这样,远程进程中的ThreadFunc就会执行不存在的内存数据(至少没有在它自己的内存空间中)。如果我们能够熟练的掌握汇编语言,当然也可以直接使用汇编语言编写一个无DLL注入的程序,毕竟使用汇编语言可以非常方便的直接对代码和数据进行重定位,这是C语言无法做到的。如果这个有争议的CALL是编译器添加的(因为一些不该打开的编译开关比如/GZ打开了),它要么在ThreadFunc的开头要么在ThreadFunc接近结尾的地方。

bcdaren的博客 957

《Windows PE》6.3 无导入表和重定位表PE文件

本节我们将演示一个无导入表、无重定位表,并且只有一个.text节区的汇编代码程序。汇编代码重定位。

bcdaren的博客 533

6.2 遍历重定位表

本节我们将编写一个遍历重定位表的示例程序,打印重定位表。遍历重定位表。

bcdaren的博客 449

《Windows PE》6.1 重定位表

重定位表(relocation table)是在可执行文件或动态链接库(DLL)中用于指示系统在加载时对代码和数据进行重新定位的数据结构。在可执行文件或 DLL 中,代码和数据通常是使用相对地址进行引用的。当将可执行文件或 DLL 加载到内存中时,如果加载地址与文件中的基地址不匹配,就需要对代码和数据进行重新定位,以确保引用的地址正确。重定位表重定位表的结构与解析重定位表的修改。

bcdaren的博客 1481

《Windows PE》5.3 导出表应用

本节我们将通过三个实验来说明导出表的应用。实验一修改导出表中的函数地址。实验二直接替换导出函数的代码。实验三导出私有函数修改导出函数地址替换导出函数代码导出私有函数。

bcdaren的博客 1130

《Windows PE》5.2 遍历导出表

这段代码使用了 EnumProcessModules 函数遍历进程中的模块,并使用 GetModuleInformation 函数获取模块的基址。32位和64位PE文件导出表描述符是相同的,遍历导出表的区别只有两点,32位基址和64位基址,以及NT32位NT头和64位NT头的区别。实验34:方法一,使用常规方法实现,将程序读到内存指定位置,进行磁盘与内存的转换。实验35:方法二,使用常规方法实现,将程序读到内存指定位置,进行磁盘与内存的转换。使用常规方法实现,将程序读到内存指定位置,进行磁盘与内存的转换。

bcdaren的博客 1442

《Windows PE》5.1 导出表

该值也是一个指针,与AddressOfNames是一一对应关系,所不同的是,AddressOfNames指向的是字符串的指针数组,而AddressOfNameOrdinals则指向了该函数在AddressOfFunctions中的索引值。●导出函数序号表(Export Function Ordinal Table)是PE文件中导出表的一部分,用于映射导出函数的序号和地址。DLL中的第一个导出函数并不是从0开始的,某导出函数的编号等于从AddressOfFunctions开始的顺序号加上这个值。

bcdaren的博客 1450

《Windows PE》4.3 延迟加载导入表

与导入表不同的是,它所记录的这些DLL动态链接库并不会被操作系统的PE加载器加载,只有等到由其登记的相关函数被应用程序调用时,PE中注册的延迟加载函数才会根据延迟加载导入表中对该函数的描述,动态加载相关链接库并修正函数的VA地址,实现对函数的调用。不过,如果用户选择了Print命令,你就可以调用该DLL中的一个函数,然后它就能够自动进行DLL的加载。5.延迟加载的DLL具备的另一个特性是,按照默认设置,调用的函数可以与一些内存地址相链接,在这些内存地址上,系统认为函数将位于一个进程的地址中。

bcdaren的博客 1211

《Windows PE》4.2 绑定导入表

绑定导入表(Bound Import Table)是文件中的一个数据结构,用于存储已经绑定(即完成绑定导入)的外部函数的信息。绑定导入表数据结构实例分析。

bcdaren的博客 921

《Windows PE》4.1.4 手工重构导入表

【可选项】可以选择修改的字段包括导入表的大小、IAT表的大小、.text节区的实际大小、.rdata节区的实际大小和.data节区的实际大小。●手工实现,将Regedit.exe程序的代码、数据、IAT表和导入表添加到HelloWorld.exe程序中,并可以正确运行。第二步:定位副本文件中的.data节区,将Regedit.exe程序的.data节区数据写入到副本文件.data节区的结尾处。第八步:将Regedit.exe程序的.text节区数据复制到.text节区,并修正参数地址以及FF25跳转地址。

bcdaren的博客 1362

《Windows PE》4.1导入表

IMAGE_IMPORT_BY_NAME结构体用于描述PE文件中的导入地址表(Import Address Table,IAT)或原始未绑定导入地址表(Original Unbound Import Address Table)中,通过名称进行导入的函数的信息。然后根据导入表FOA地址,在PE文件中找到导入表描述符的起始地址,循环遍历获取导入表描述符的OriginalFirstThunk字段中保存的RVA地址,将此RVA地址转换为FOA地址,即INT表IMAGE_THUNK_DATA的起始地址。

bcdaren的博客 1958

《Windows PE》3.2.4节表

节表由多个节表项(IMAGE_SECTION_ HEADER)组成,每个节表项(40个字节)记录了 PE中与某个特定的节有关的信息,如节的属性、节 的大小、在文件和内存中的起始位置等。节表中节的数量由字段IMAGE_FILE_HEADER. NumberOfSections来定义。●节表项的数据结构详细定义如下:typedef struct _IMAGE_SECTION_HEADER { BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; // 节区名称,8 字节 u

bcdaren的博客 2025

《Windows PE》3.2.3 NT头-扩展头

4.32位HelloWorld.exe(Win XP汇编版本)文件偏移地址0000013CH地址处,将默认0010H修改为0000~0010H之间的任一值,我们会发现,当数据目录项的数目大于等于2时,PE文件可以在Windows 10系统正常运行。1.32位HelloWorld.exe(Win XP汇编版本)文件偏移地址0000013CH地址处,将默认0010H修改为0000~0010H之间的任一值,我们会发现,当数据目录项的数目大于等于2时,PE文件可以在Windows 10系统正常运行。

bcdaren的博客 1341

《Windows PE》3.2.3 NT头-文件头

原因是运行程序时,系统使用LoadString函数加载命令行参数字符串,如果第一个参数为自身的句柄,则会在当前路径或系统路径下寻找资源PE文件(没有代码的资源文件),名称为***.exe.mui。DOS块的后面接着就是NT头了。NT头包含了PE文件的各种信息,包括文件的签名、文件头和扩展头。在32位的PE文件中,Signature的值为0x00004550(或者ASCII字符"PE\0\0"),在64位的PE文件中,Signature的值同样为0x00004550(或者ASCII字符"PE\0\0")。

bcdaren的博客 1252

《Windows PE》3.2 PE头结构-DOS头和DOS块

在VS中输入#include "winnt.h" ,点击右键,打开文档。然后搜索 IMAGE_DOS_HEADER 或者在程序里面输入IMAGE_DOS_HEADER 按F12转到定义。■。

bcdaren的博客 1617

《Windows PE》3.1 基本概念

在正式讲解PE文件格式之前,我们有必要先熟悉和PE相关的一些基本概念,以便于更好的理解和掌握PE文件格式。地址指针数据目录项节对齐方式字符串编码格式。

bcdaren的博客 1692

《Windows PE》2.2.2 加载PE文件二

doc .mp3 .jpg等等都是有文件格式的,我们只需要关心.exe和.dll文件格式,因为.exe和.dll文件是可执行文件格式,其他的文件是不可执行的,不能在CPU上运行的。比如: PE 它是windows下的文件格式,是MZ打头的(4D5A)只有两个字节,后面很大一片就是对这个结构体的管理,比如代码在什么位置,图像在什么位置,文字在什么位置,在前面PE头中都是有记录的。除了默认的PE头之外,每个节区都是有命名的,例如.text节区为代码段,.data节区为数据段,.rsrc节区保存资源。

bcdaren的博客 1259
上一篇: 《Windows PE》4.1导入表
下一篇: 《Windows PE》4.1.4 手工重构导入表
bcdaren
bcdaren 昆山爱达人信息技术有限公司官方账号 昆山爱达人信息技术有限公司官方账号
博客等级 码龄10年 2910粉丝 149原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值