Processing math: 100%

道隐于小成,言隐于荣华

PE文件格式分析

该部分为恶意代码检测课程的笔记备份。

概况

PE文件主要分这几部分:MZ头部、DOS Stub、NT头(包含文件标识、PE文件头、可选文件头)、节表、节。整体结构图如下:

头与节划分如下:

20161128152136783

注意:图中所说的“PE文件头“是指NT头。但为了区分子项PE文件头本作业中所有PE文件头均为NT头的子项IMAGE_File_HEADER,而图中的”PE文件头“均用NT头表示。

MZ头部

用记事本打开任何一个镜像文件,其头2个字节必为字符串“MZ”,这是Mark Zbikowski的姓名缩写,他是最初的MS-DOS设计者之一。然后是一些在MS-DOS下的一些参数,这些参数是在MS-DOS下运行该程序时要用到的。在这些参数的末尾也就是文件的偏移0x3C(第60字节)处是是一个4字节的PE文件签名的偏移地址。该地址有一个专用名称叫做“E_lfanew”。

MZ头部由IMGAE_DOS_HEADER定义,共64字节,MZ头部具体参数如下表所示:

深度截图_选择区域_20200309172129

PE文件内容 字段名 含义 偏移量 长度
5A4DH e_magic DOS文件可执行标记,MZ作为识别标志 00H WORD
0090H e_cblp 文件最后页字节数 02H WORD
0003H e_cp 文件页数 04H WORD
0000H e_crlc 重定位表指针数 06H WORD
0004H e_cparhdr 头部尺寸 08H WORD
0000H e_minalloc 最小附加段大小 0AH WORD
FFFFH e_maxalloc 最大附加段大小 0CH WORD
0000H e_ss DOS代码的初始化堆栈SS 0EH WORD
00B8H e_sp DOS代码初始化堆栈指针SP 10H WORD
0000H e_csum 补码校验值 12H WORD
0000H e_ip DOS代码初始化指令入口(指针IP) 14H WORD
0000H e_cs DOS代码的初始化堆栈入口CS 16H WORD
0004H e_lfarlc 重定位表字节偏移量 18H WORD
0000H e_ovno 覆盖号 1AH WORD
00000000 00000000H e_res[4] 保留字 1CH 4 WORD
0000H e_oemid OEM标识符 24H WORD
0000H e_oeminfo OEM信息 26H WORD
00000000000000000000 00000000000000000000H e_res2[10] 保留字,e_res2[10] 29H 10 WORD
000000B0H e_lfanew PE头相对于文件的偏移地址,指出了真正的PE文件头在文件中的位置,这个位置总是以8字节为单位对齐的 3CH LONG

DOS Stub

紧跟着E_lfanew的是一个MS-DOS程序。那是一个运行于MS-DOS下的合法应用程序。当可执行文件(一般指exe、com文件)运行于MS-DOS下时,这个程序显示“This program cannot be run in DOS mode(此程序不能在DOS模式下运行)”这条消息。

MZ头后是一个整个DOS Stub字节块,其内容随使用的链接器的不同而不同,PE中并没有与之相关的结构。

NT头

NT头由IMAGE_NT_HEADERS结构定义,共248字节,也有观点认为为244字节(不包括PE文件标志),NT头的具体参数如下:

偏移量 字段名 长度 含义
00H Signature DWORD PE文件标识,在一个PE文件中该字段被设置为4550H
04H FileHeader IMAGE_FILE_HEADER PE文件头
18H OptionalHeader IMAGE_OPTIONAL_HEADER32 可选文件头

PE文件头

PE文件头,共20字节,其偏移量相对于NT头而言的具体参数如下:

PE文件内容 字段名 含义 偏移量 长度
014CH Machine 运行平台,可执行文件的目标CPU类型 04H WORD
0003H NumberOfSections 文件的区块数目 06H WORD
428F4D9BH TimeDateStamp 文件创建日期和时间,表明文件是何时被创建的,这个值是自1970年1月1日以来用格林威治时间(GMT)计算的秒数 08H DWORD
00000000H PointerToSymbolTable 指向符号表(主要用于调试),COFF 符号表的文件偏移位置 0CH DWORD
00000000H NumberOfSymbols 符号表中符号个数,如果有COFF 符号表,它代表其中的符号数目,如果想找到COFF 符号表的结束位置,则需要这个变量。 10H DWORD
00E0H SizeOfOptionalHeader IMAGE_OPTIONAL_HEADER32 结构大小 14H WORD
010FH Characteristics 文件属性,有选择的通过几个值可以运算得到 16H WORD

PE文件头的Machine字段参数如下表所示:

大小 预定义值 含义
0x014C IMAGE_FILE_MACHINE_I386 x86平台
0x0200 IMAGE_FILE_MACHINE_IA64 Intel Itanium平台
0x8664 IMAGE_FILE_MACHINE_AMD64 x64平台

PE文件头的Characteristics字段参数如下表所示:

大小 预定义值 含义
0x0001 IMAGE_FILE_RELOCS_STRIPPED 重定位表从文件中剥离
0x0002 IMAGE_FILE_EXECUTABLE_IMAGE 可执行文件
0x0004 IMAGE_FILE_LINE_NUMS_STRIPPED COFF行号从文件中剥离
0x0008 IMAGE_FILE_LOCAL_SYMS_STRIPPED COFF符号表入口从文件中剥离
0x0010 IMAGE_FILE_AGGRESIVE_WS_TRIM 积极修剪工作集,过时了
0x0020 IMAGE_FILE_LARGE_ADDRESS_AWARE 应用能处理大于2G的地址
0x0080 IMAGE_FILE_BYTES_REVERSED_LO 保留字
0x0100 IMAGE_FILE_32BIT_MACHINE 电脑支持32位字
0x0200 IMAGE_FILE_DEBUG_STRIPPED 调试信息移动并存储到其他地方
0x0400 IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 若为可移动媒体则从swap中拷贝运行
0x0800 IMAGE_FILE_NET_RUN_FROM_SWAP 若为网络则 从swap中拷贝运行
大小 预定义值 含义
0x1000 IMAGE_FILE_SYSTEM 文件是系统文件
0x2000 IMAGE_FILE_DLL 文件是DLL文件,不能直接运行
0x4000 IMAGE_FILE_UP_SYSTEM_ONLY 文件只能运行在单处理器计算机中
0x8000 IMAGE_FILE_BYTES_REVERSED_HI 保留字

可选文件头

可选文件头由IMAGE_OPTIONAL_HEADER结构定义,共224字节,其偏移量相对于NT头的具体参数如下:

PE文件内容 字段名 含义 偏移量 长度
010BH Magic 标志字, ROM 映像(0107H),普通可执行文件(010BH) 18H WORD
05H MajorLinkerVersion 链接程序的主版本号 1AH BYTE
0CH MinorLinkerVersion 链接程序的次版本号 1BH BYTE
00002000H SizeOfCode 所有含代码的节的总大小 1CH DWORD
00004000H SizeOfInitializedData 所有含已初始化数据的节的总大小 20H DWORD
00000000H SizeOfUninitializedData 所有含未初始化数据的节的大小 24H DWORD
00001000H AddressOfEntryPoint 程序执行入口RVA,指出文件被执行时的入口地址,可执行文件上附加了一段代码并想首先被执行,只需将其指向附加代码 28H DWORD
00001000H BaseOfCode 代码的区块的起始RVA 2CH DWORD
00002000H BaseOfData 数据的区块的起始RVA 30H DWORD
00040000H ImageBase 程序的首选装载地址,指出文件的优先装入地址 34H DWORD
00001000H SectionAlignment 内存中的区块的对齐大小,每个节被装入的地址必定是本字段指定数值的整数倍 38H DWORD
00000200H FileAlignment 文件中的区块的对齐大小,指定了节存储在磁盘文件中时的对齐单位 3CH DWORD
0004H MajorOperatingSystemVersion 要求操作系统最低版本号的主版本号 40H WORD
0000H MinorOperatingSystemVersion 要求操作系统最低版本号的副版本号 42H WORD
0000H MajorImageVersion 可运行于操作系统的主版本号 44H WORD
0000H MinorImageVersion 可运行于操作系统的次版本号 46H WORD
0004H MajorSubsystemVersion 要求最低子系统版本的主版本号 48H WORD
0000H MinorSubsystemVersion 要求最低子系统版本的次版本号 4AH WORD
00000000H Win32VersionValue 莫须有字段,不被病毒利用的话一般为0 4CH DWORD
00004000H SizeOfImage 映像装入内存后的总尺寸 50H DWORD
00000400H SizeOfHeaders 所有头 + 区块表的尺寸大小 54H DWORD
00000000H CheckSum 映像的校检和 58H DWORD
0002H Subsystem 可执行文件期望的子系统,决定了系统如何为程序建立初始的界面 5CH WORD
0000H DllCharacteristics DllMain()函数何时被调用,默认为 0 5EH WORD
00100000H SizeOfStackReserve 初始化时的栈大小 60H DWORD
00001000H SizeOfStackCommit 初始化时实际提交的栈大小 64H DWORD
00100000H SizeOfHeapReserve 初始化时保留的堆大小 68H DWORD
00001000H SizeOfHeapCommit 初始化时实际提交的堆大小 6CH DWORD
00000000H LoaderFlags 与调试有关,默认为 0 70H DWORD
00000010H NumberOfRvaAndSizes 下边数据目录的项数,这个字段自Windows NT 发布以来一直是16 74H DWORD
- DataDirectory 数据目录表,由16个相同的IMAGE_DATA_DIRECTORY结构组成 78H 16 IMAGE_DATA_DIRECTORY

可选文件头Subsystem字段具体参数如下表所示:

取值 预定义值 含义
0 IMAGE_SUBSYSTEM_UNKNOWN 未知子系统
1 IMAGE_SUBSYSTEM_NATIVE 不需要子系统
2 IMAGE_SUBSYSTEM_WINDOWS_GUI Windows图形界面
3 IMAGE_SUBSYSTEM_WINDOWS_CUI Windows控制台界面
5 IMAGE_SUBSYSTEM_OS2_CUI OS2控制台界面
7 IMAGE_SUBSYSTEM_POSIX_CUI POSIX控制台界面
8 IMAGE_SUBSYSTEM_NATIVE_WINDOWS 不需要Windows子系统
9 IMAGE_SUBSYSTEM_WINDOWS_CE_GUI WIndows CE图形界面

可选文件头的DataDirectory字段的具体参数如下表所示:

PE文件内容 预定义值 对应数据块 索引
0000000000000000H IMAGE_DIRECTORY_ENTRY_EXPORT 导出表入口 0
0000003C00002014H IMAGE_DIRECTORY_ENTRY_IMPORT 引入表入口 1
0000000000000000H IMAGE_DIRECTORY_ENTRY_RESOURCE 资源 2
0000000000000000H IMAGE_DIRECTORY_ENTRY_EXCEPTION 异常 3
0000000000000000H IMAGE_DIRECTORY_ENTRY_SECURITY 安全 4
0000000000000000H IMAGE_DIRECTORY_ENTRY_BASERELOC 重定位表 5
0000000000000000H IMAGE_DIRECTORY_ENTRY_DEBUG 调试信息 6
0000000000000000H IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 版权信息 7
0000000000000000H IMAGE_DIRECTORY_ENTRY_GLOBALPTR - 8
0000000000000000H IMAGE_DIRECTORY_ENTRY_TLS 线程分配本地存储 9
0000000000000000H IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 加载设置 10
0000000000000000H IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 绑定引入表入口 11
0000001400002000H IMAGE_DIRECTORY_ENTRY_IAT 引入函数地址表入口 12
0000000000000000H IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 延时引入表入口 13
0000000000000000H IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR COM描述符 14
0000000000000000H 未使用 15

IMAGE_DATA_DIRECTORY结构用伪代码描述如下:

typedef struct IMAGE_DATA_DIRECTORY{
    DWORD VirtualAddress;
    DWORD Size;
}IMAGE_DATA_DIRECTORY;

节表

PE文件中所有节的属性都被定义在节表中,节表由一系列的IMAGE_SECTION_HEADER结构排列而成,每个结构用来描述一个节,结构的排列顺序和它们描述的节在文件中的排列顺序是一致的。

节表中 IMAGE_SECTION_HEADER 结构的总数总是由PE文件头 IMAGE_NT_HEADERS 结构中的 FileHeader.NumberOfSections 字段来指定的。全部有效结构的最后以一个空的IMAGE_SECTION_HEADER结构作为结束,所以节表中IMAGE_SECTION_HEADER结构数量等于节的数量加一。

其中,IMAGE_SECTION_HEADER结构共占用40字节,具体参数如下表所示:

.text表头 .rdata表头 .data表头 字段名 含义 偏移量 长度
00000074 7865742EH 00006174 6164722EH 00000061 7461642EH Name[IMAGE_SIZEOF_SHORT_NAME] 节区名称,通过8位的ASCII 码名,用来定义区块的名称 00H 8 BYTE
00000046H 000000A6H 0000008EH Misc 联合结构,用于记录物理地址或者真实长度,一般取后者 08H DWORD
00001000H 00002000H 00003000H VirtualAddress 节区的RVA地址,按照内存页来对齐,数值总是 SectionAlignment 的值的整数倍。 0CH DWORD
00000200H 00000200H 00000200H SizeOfRawData 在文件中对齐后的尺寸,在磁盘中所占的大小 10H DWORD
00000400H 00000600H 00000800H PointerToRawData 在文件中的偏移量,数值是从文件头开始算起的偏移量 14H DWORD
00000000H 00000000H 00000000H PointerToRelocations 重定位的偏移量,在OBJ 文件中使用以表示本区块重定位信息的偏移值。 18H DWORD
00000000H 00000000H 00000000H PointerToLinenumbers 行号表的偏移量(供调试使用) 1CH DWORD
0000H 0000H 0000H NumberOfRelocations 在OBJ文件中使用,重定位项数目 1EH WORD
0000H 0000H 0000H NumberOfLinenumbers 行号表中行号的数目 20H WORD
60000020H 40000040H C0000040H Characteristics 节属性如可读,可写,可执行等 24H DWORD

IMAGE_SECTION_HEADER结构的Characteristics字段具体参数如下:

大小 预定义值 含义
0x00000040 IMAGE_SCN_CNT_INITIALIZED_DATA 该区块包含以初始化的数据
0x00000080 IMAGE_SCN_CNT_UNINITIALIZED_DATA 该区块包含未初始化的数据
0x02000000 IMAGE_SCN_MEM_DISCARDABLE 该区块可被丢弃,因为当它一旦被装入后, 进程就不在需要它了,典型的如重定位区块
0x10000000 IMAGE_SCN_MEM_SHARED 该区块为共享区块
0x20000000 IMAGE_SCN_MEM_EXECUTE 该区块可以执行。通常当0x00000020被设置 时候,该标志也被设置
0x40000000 IMAGE_SCN_MEM_READ 该区块可读,可执行文件中的区块总是设置该 标志
0x80000000 IMAGE_SCN_MEM_WRITE 该区块可写
0x00000020 MAGE_SCN_CNT_CODE 包含代码,常与 0x10000000一起设置

IMAGE_SECTION_HEADER结构的Msic联合结构用伪代码描述如下:

typedef union Misc{
    DWORD PyhsicalAddress;//物理地址
    DWORD VirtualSize;//真实长度
}Misc;

通常,节的数据在逻辑上是关联的。PE文件至少具有两个节:代码节和数据节。一般常见命名的节区及其描述如下表所示:

节区名称 描述
.text 默认的代码节区,内容全是指令代码。链接程序把所有目标文件的.text块链接成一个大的.text块
.data 默认的读/写数据节区,全局变量、静态变量放在这里
.rdata 默认的只读数据节区,程序中很少用到该节区,一般用于在微软的链接程序产生的EXE中存放调试目录,或者用于存放说明字符串
.idata 包含其他外来的DLL函数以及数据信息
.edata 输出表。当创建一个输出API或者数据的可执行文件时链接程序会创建一个.EXP文件,其中包含一个.edata节区,其最终加入到可执行文件中
.rsrc 资源,包含模块的全部资源,只读的节区,无法合并
.bss 未初始化数据,很少使用
.crt 用于支持C++g运行时所添加的数据
.tls 线程局部存储器,用于支持通过deeplspec(thread)声明的线程局部存储变量的数据
.reloc 可执行文件的基址重定位,基址重定位一般为DLL所需要
.sdata 相对于全局指针的可被定位的“短的”读/写数据
.srdata 相对于全局指针的可被定位的“短的”只读数据
.pdata 异常表,包含一个CPU特定的IMAGE_RUNTIME_FUNCTION_ENTRY结构数组,由DataDirectory的IMAGE_DIRECTORY_ENTRY_EXCEPTION指向它
.debug$S OBJ文件中的Codeview格式的符号
.debug$T OBJ文件中的Codeview格式的类型记录
.debug$P 当使用预编译的头时,可以在OBJ文件中找到
.drectve 包含链接程序命令,只能在OBJ文件中找到
.didat 延迟装入的输入数据

引入函数节

引入函数节一般为.rdata节,其前面三部分为:IMPORT Address Table、引入目录表(IMPORT Directory Table)、IMPORT Name Table、IMPORT Hints/Names & DLL Name。

位置 定义 描述
红色位置 IMPORT Address Table 在IAT中记录的地址,每个函数的地址以DWORD大小为一项,每一DLL的地址以4字节的0结尾,一个DLL中可能存在多个函数的地址,同一DLL多个函数接连在一起。
黄色区域 IMPORT Directory Table 在引入目录表中,如果有n个DLL,则有n+1个IMAGE_IMPORT_DESCRIPTOR项,大小为(n+1) 20字节。在引入目录表中最后一个IMAGE_IMPORT_DESCRIPTOR项全为0,即最后20字节的0结尾。
蓝色区域 IMPORT Name Table 每个函数指向名字的地址以DWORD大小为一项,每一DLL的地址以4字节的0结尾,一个DLL中可能存在多个函数名地址,其顺序与IAT不一定相同(尤其要注意),同一DLL多个函数连在一起。
紫色区域 IMPORT Hints/Names & DLL Name 记录DLL名字、函数名字字符串等信息

引出函数节

引出函数节一般为.edata节,这是PE文件中向其他程序提供调用函数列表、函数所在位置的地址以及具体代码实现的部分。

在引出函数中,需要引出目录表。引出目录表的结构由IMAGE_EXPORT_DIRECTORY定义,引出目录表的结构用伪代码描述如下:

typedef strcut IMAGE_EXPORT_DIRECTORY{
    DWORD Characteristics;
    DWORD TimeDataStamp;
    WORD MajorVersion;
    WORD MinorVersion;
    DWORD Name;
    DWORD Base;
    DWORD NumberOfFunctions;
    DWORD NumberOfNames;
    DWORD AddressOfFunctions;
    DWORD AddressOfNames;
    DWORD AddressOfNameOrdinals;
}_IMAGE_EXPORT_DIRECTORY;

其具体参数如下表所示:

字段名 描述 偏移量 大小
Characteristics 特征,一般为0 00H DWORD
TimeDataStamp 文件生成时间 04H DWORD
MajorVersion 主版本号 08H WORD
MinorVersion 次版本号 0AH WORD
Name 指向DLL的名字 0CH DWORD
Base 开始的序列号 10H DWORD
NumberOfFunctions 函数地址数组的项数 14H DWORD
NumberOfNames 名字地址数组的项数 18H DWORD
AddressOfFunctions 指向函数地址数组的导出函数地址表(EAT,Export Address Table) 1CH DWORD
AddressOfNames 指向函数名数组的导出函数名地址表(ENT,Export Address Table) 20H DWORD
AddressOfNameOrdinals 指向函数索引序列号数组的函数序号表(EOT,Export Oridinal Table) 24H DWORD

导出地址表结构如下:

typedef struct IMAGE_Export_Address_Table{
    union{
        DWORD dwExportRVA;//指向导出地址
        DwORD dwFurwarderRVA;//指向另一个DLL中某个API函数名
    }
}

导出名字表结构如下:

typedef struct IMAGE_Export_Name_Table{
    DWORD dwPointer;
}_IMAGE_Export_Name_Table;

导出序号表结构如下:

typedef struct IMAGE_Export_Ordinal_Table{
    WORD dwOrdinal;//保存各导出函数的函数地址在导出地址表的序
}_IMAGE_Export_Ordinal_Table;

与导入函数的双桥结构不同的是,导出函数名字表和导出地址表不是一一对应关系的。因为一个函数可能有多个名字,有的函数没名字而通过序号导出。

导入函数表与导入机制

引入目录表(或称函数引入表),位于可选文件头的DataDirectory数组IMAGE_DIRECTORY_ENTRY_IMPORT索引。 程序需要执行dll相关代码,则相关代码指令必须存在于进程地址空间,操作系统在加载的时候会根据引入目录表的描述将需要调用的函数指令加载到进程空间。

导入描述符

引入目录表实际上是一个 IMAGE_IMPORT_DESCRIPTOR 结构数组,表中数据的起始部分是多组导入描述符结构,每个结构包含PE文件引入函数的一个相关DLL的信息。其具体参数如下表所示:

IMAGE_IMPORT_DESCRIPTOR 结构通过伪代码描述如下:

IMAGE_IMPORT_DESCRIPTOR {  
    union {  
        DWORD Characteristics;  
        DWORD OriginalFirstThunk;     //导入名字表的地址(RVA) 
    };  
    DWORD TimeDateStamp;     //时间戳
    DWORD ForwarderChain;    //链表的前一个结构
    DWORD Name;              //指向链接库的指针  
    DWORD FirstThunk;        //导入地址表的地址 (RVA)
} IMAGE_IMPORT_DESCRIPTOR;
偏移量 字段名 长度 含义
00H Characteristics/OriginalFirstThunk DWORD 联合结构,现在一般用于描述OriginalFirstThunk,即指向引入名字表(INT)的地址
04H TimeDataStamp DWORD 时间戳。映象绑定前,这个值是0,绑定后是引入模块的时间戳
08H ForwarderChain DWORD 链表的前一个结构,转发链。如果没有转发器,这个值是-1。
偏移量 字段名 长度 含义
0CH Name DWORD 指向链接库的指针,指向引入模块的名字
10H FirstThunk DWORD 指向输入地址表(IAT)的地址

函数引入过程

在程序执行时,PE文件通过可选文件头的IMAGE_DIRECTORY_ENTRY_IMPORT定位到函数引入节的引入目录表,对引入目录表项进行遍历查找,根据INT表定位函数在IAT中的位置,再通过IAT表绑定引入后的VA地址进行内存调用。

以PE文件中的MessageBox函数为例,在图中我们知道MessageBox字符串入口为例:

根据PE文件头部可知.rdata开始位置文件偏移量为600H,内存地址为2000H,又通过ASCII码可以知道其地址为68CH,因此我们知道内存地址应该为208CH,根据蓝色部分INT表查询可知第二个DLL的第一项为其内存地址,因此函数真实位置再跟据IAT表可知为208CH,同时根据双桥结构及其关系,我们也能看出来这个可执行程序未进行函数的绑定引入。

双桥结构及其关系

每一个结构IMAGE_IMPORT_DESCRIPTOR都对应的是一个唯一的dll文件。以及dll中的每个函数都可以通过”编号-名称”的方式找到,这就是引入目录表的双桥结构,如图所示:

OriginalFirstThunk指向的数组中每一项为一个结构,此结构的名称是IMAGE_THUNK_DATA。该结构实际上只是一个双字,但在不同的时刻却拥有不同的解释。该字段有两种解释:这个值是INT的地址,INT(Import Name Table)是一个存储了库文件函数名称的表。在装载的时候,PE装载器读取OriginalFirstThun获得INT,然后通过函数名称去获取函数的地址。

FirstThunk指向的是IAT(Import Address Table),也是IMAGE_THUNK_DATA,但是对于程序的装载,并不使用IAT进行函数的寻址,在通过INT寻址之后,将找到的地址填充到IAT中。后期需要用到函数的时候,可以使用GetProcAddressAPI函数进行获取。

而在IMAGE_THUNK_DATA结构数组中,则存放着指向IMAGE_IMPORT_BY_NAME结构数组的指针。

IMAGE_THUNK_DATA结构用伪代码描述如下:

typedef struct IMAGE_THUNK_DATA{
    union{
        DWORD ForwarderString;
        DWORD Function;
        DWORD Ordinal;//序号
        DWORD AddressOfData;//指向IMAGE_IMPORT_BY_NAME
    }
}IMAGE_THUNK_DATA;

IMAGE_THUNK_DATA结构字段具体说明如下表所示:

字段名 描述
ForwarderString 指向一个转向者字符串RVA
Function 被引入的函数的内存地址
Ordinal 被引入的API函数序号
AddressOfData 被引入的API的Hint和函数名字字符串信息

需要注意的是:当IMAGE_THUNK_DATA的数据最高位为0时通过函数名引入,指向IMPORT Hints/Names;为1时则通过序号引入函数。

IMAGE_IMPORT_BY_NAME结构用伪代码描述如下:

typedef struct IMAGE_IMPORT_BY_NAME {  
    WORD Hint;        //对dll中的每个函数进行标号,该值不是必须的
    BYTE Name;     //函数名称
} IMAGE_IMPORT_BY_NAME;

绑定引入前后双桥结构会发生变化,其变化如图所示:

绑定引入后,IAT中的地址从指向IMAGE_IMPORT_BY_NAME变为指向函数的VA地址。而INT仍然指向函数名地址。

posted @   FrancisQiu  阅读(75)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示