导入表是杀毒软件厂商非常关注的部位尤其是启发式扫描。所以,了解导入表的结构对免杀技术是必不可少的。
下文我们从大家最常用的notepad.exe的分析来揭开导入表的神秘面纱。
首先用LoadPE工具加载notepad.exe。查看其区段表和目录表信息。
第一步:计算转换因子
从目录表的输入表的RVA(相对虚拟地址)查找在区段表中的位置。这里的RVA是0x7604对应的是区段表的.text区段。
转换因子 = Voffeset - Roffset
1000 - 400 = C00 (注意这里显示的都是十六进制,以下同,不再赘述)
C00就是记事本的导入表对应的转换因子。转化因子就是内存地址和文件地址的转换差。
内存地址-转换因子 = 文件地址
文件地址+转换因子 = 内存地址
第二步:了解IMAGE_IMPORT_DESCRIPTOR结构
计算导入表的文件地址为
7604 - C00 = 6A04
我们用UE查看6A04处的内容如下:
红框部分代表了一个IMAGE_IMPORT_DESCRIPTOR结构。
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics; // 0 for terminating null import descriptor
DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
};
DWORD TimeDateStamp;
DWORD ForwarderChain; // -1 if no forwarders
DWORD Name;
DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses)
} IMAGE_IMPORT_DESCRIPTOR;
这里我们主要关心是加粗的内容,对应内容如下表:
字段 | 相对内存虚拟地址 | 文件地址 | 内容 |
OriginalFirstThunk | 00007990 | 6D90 | 指向导入函数名字结构体数组指针 |
Name | 00007AAC | 6EAC | 指向导入库名字 |
FirstThunk | 000012C4 | 6C4 | 指向IAT导入地址表偏移 |
第三步:分析OriginalFirstThunk字段
首先用UE查看地址为6D90(7990-C00)的数据如下:
这里红色框起来的数据是一个指向IMAGE_THUNK_DATA32结构体的指针数据。全0也就是绿色框起来的部分代表一个导入库的结束。由于数组元素是指针 所以,这里第一个导入库的数组元素有9个,所以导入的函数也有9个。
首先我们查看内存偏移6E7A(00007A7A-C00)处的IMAGE_THUNK_DATA32结构体数据。
该结构体的第一个元素(2字节)代表导出的函数的序号0F。后边是导出函数名,不定长,但必须以0结尾。这里代表的函数名是PageSetupDlgW。我们可以依次找出这个导入库的所有导出函数信息。
下面我们验证一下。用LoadPe查看导入表信息如下图所示:
由此可以确认我们找的完全正确。
第四步:分析Name字段
首先用UE查看地址为6EAC(7AAC-C00)的数据如下
由此可见6EAC指向的是一个字符串comdlg32.dll。与LoadPE中显示的DLL的名称相符。
第五步:分析FirstThunk字段
FirstThunk是与IAT表关联的。
导入地址表(IAT):Import Address Table 由于导入函数就是被程序调用但其执行代码又不在程序中的函数,这些函数的代码位于一个或者多个DLL 中.当PE 文件被装入内存的时候,Windows 装载器才将DLL 装入,并将调用导入函数的指令和函数实际所处的地址联系起来(动态连接),这操作就需要导入表完成.其中导入地址表就指示函数实际地址。
我们还是首先查看文件地址6C4(12C4-C00)的内容如下:
我们可以看到这里指向的也是9个函数地址。其中第一个函数地址是76344906
下面我们查看该程序在OD中加载起来的这个地址是什么。
由此可见这个地址正是PageSetupDlgW的加载地址。
至此,关于导入表与IAT和一系列的导入函数之间的关系都已非常清晰。