1.RVA to RAW
PE文件加载到内存时,每个节区都要准确完成内存地址与文件偏移的映射。这种映射便称为RVA to RAW,实现这个过程需要经过以下的步骤。
1.查找RVA所在节区。
2.使用公式计算出文件偏移。
根据IMAGE_SECTION_HEADER结构体,换算公式如下。
RAW - PoniterToRawData = RVA - VirtualAddress
RAW = RVA - VirtualAddress + PointerToRawData
2.IAT(Import Address Table,导入地址表)
IAT保存的内容与Windows操作系统的核心进、内存、DLL结构等有关。(即掌握了IAT便掌握了Windows操作系统的根基)。
1.DLL(Dynamic Linked Library)
加载DLL的方式有两种:一种是“显式链接”(Explicit Linking),程序使用DLL时加载,使用完毕后释放内存。另一种是“隐式链接”(Implicit Linking),程序开始时遍一同加载DLL,程序终止时,再释放占用的内存。IAT提供的机制便与隐式链接有关。
DLL重定位,DLL文件的ImageBase一般为10000000.比如某个程序使用a.dll和b.dll,OE装载器先把a.dll装载到内存的10000000(ImageBase)处,然后尝试把b.dll也装载到该处。但是由于该地址处已经装载了a.dll,所以PE装载器需要查找其他空白的内存空间(ex:3E000000),然后将b.dll装载进去。这就是DLL文件的重定位。
2.IMAGE_IMPOT_DESCRIPTOR
IMAGE_IMPORT_DESCRIPTOR结构体中记录着PE文件要导入哪些库文件。
IMAGE_OPTIONAL_HEADER32.DataDirectory[1].VirtualAddress
的值即是IMAGE_IMPORT_DESCRIPTOR结构体数组的起始地址(RVA值)。(第一个4字节为虚拟地址,第二个4字节为Size成员。)
注:Import:导入,向库提供服务(函数)。
Export:导出,从库向其他PE文件提供服务(函数)。
代码 IMAGE_IMPORT_DESCRIPTOR
typedef struct _IMAGE_IMPORT_DESCRIPTOR{
union{
DWORD
Characteristics;
DWORD
OriginalFirstThunk;
//INT(Import Name Table) address (RVA)
};
DWORD
TimeDatastamp;
DWORD
ForwarderChain;
DWORD
Name;
// library name string address (RVA)
DWORD
FirstThunk;
// IAT( Import Address Table) address (RVA)
} IMAGE_IMPORT_DESCRIPTOR;
typedef struct _IMAGE_IMPORT_BY_NAME{
WORD
Hint;
// ordinal
BYTE
Name[1];
// function name string
} IMAGE_IMPORT_BY_NAME , *PIMAGE_IMPORT_BY_NAME;
执行一个普通程序时往往需要导入多个库,导入多少库就存在多少个IMAGE_IMPORT_DESCRIPTOR结构体,这些结构体形成了数组,且结构体数组最后以NULL结构体结束。
IMAGE_IMPORT_DESCRIPTOR的重要成员如下
项目
含义
OriginalFirstThunk
INT的地址(RVA)
Name
库名称字符串的地址
(RVA)
FirstThunk
IAT的地址
(RVA)
注:INT与IAT是长整型(4个字节数据类型)数组,以NULL结束(未另外明确指出大小)。
INT中各元素的值为IMAGE_IMPORT_BY_NAME结构体指针(有时IAT也有相同的值)。
INT与IAT的大小应相同。
3.EAT
Windows操作系统中,“库”是为了方便其他程序调用而集中包含相关函数的文件(DLL/SYS)。Win32 API是最具代表性的库,其中的kernel32.dll文件称为最核心的库文件。
EAT是一种核心机制,它使不同的应用程序可以条用库文件中提供的函数(即只有通过EAT才能准确求得从相应库中导出函数的起始地址)。PE文件内部有且仅有一个用来说明库EAT的IMAGE_EXPORT_DIRECTORY结构体,并且保存着导出信息。
注:
IAT的结构体以数组的形式存在,且拥有多个成员。即说明PE文件可以同时导入多个库。
可以在PE文件的PE头中查找到IMAGE_EXPORT_DIRECTORY结构体的闻之。
IMAGE_OPTIONAL_HEADER32.DataDirectory[0].VirtualAddress
值即为结构身体数组的其实地址(RVA值)。
(第一个4字节为虚拟地址,第二个4字节为Size成员。)
代码
IMAGE_EXPORT_DIRECTORY结构体
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD
Characteristics;
DWORD
TimeDateStamp;
//creation time date stamp
WORD
MajorVersion;
WORD
MinorVersion;
DWORD
Name;
//address of library file neme
DWORD
Base;
//ordinal base
DWORD
NumberOfFunctions;
//number of functions
DWORD
NumberOfNames;
//number of names
DWORD
AddressOfFunctions;
//address of function start address array
DWORD
AddressOfName;
//address of function name string array
DWORD
AddressOfNameOrdinals;
//address of ordinal array
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
其中结构体中的重要成员如下
项目
含义
NumberOfFunctions
实际Export函数的个数
NumberOfNames
Export函数中具名的函数个数
AddressOfFunctions
Export函数地址数组(数组元素个数=
NumberOfFunctions
)
AddressOfNames
函数名称地址数组(
数组元素个数=
NumberOfNames
)
AddressOfNameOrdinals
Ordinal地址数组 (数组元素个数=
NumberOfNames)