谈一谈importedfunction table。
EXE/DLL 在被加载内存之前,存放在PE 文件的imported table(或称为.idata)中的信息是给加载器用来决定函数地址并修补它们,以便完成image 用的。而在被加载之后, .idata 内含的是指针,指向EXE/DLL的输入函数。.idata section(imported table)是以一个IMAGE_IMPORT_DESCRIPTOR数组开始。在PE文件中联结(implicitly link)的DLLs 都会在此有一个对应的IMAGE_IMPORT_DESCRIPTOR 结构。最后一个IMAGE_IMPORT_DESCRIPTOR结构的内容全部为NULL,以此作为结束符号。IMAGE_IMPORT_DESCRIPTOR的格式描述如下:
DWORD Characteristics/OriginalFirstThunk:这是一个偏移值(一个RVA),对应于一个输入函数。DWORD TimeDateStamp:这是文件的产生时刻。通常此栏为0 。然而微软的B I N D 程序可以将此IMAGE_IMPORT_DESCRIPTOR所对应的DLL的产生时刻写到这里来。
DWORD ForwarderChain:这个字段关系到所谓的forwarding(转交),意味着一个DLL 函数在参考(呼叫、利用)另一个DLL。这个字段内含一个索引,指向FirstThunk数组。被这个索引所指定的函数就是一个转交函数。DWORD Name:这是一个RVA,指向一个以NULL为结束字符的ASCII字符串,内含imported DLL的名称。PIMAGE_THUNK_DATA FirstThunk:这是一个R V A , 指向一个D W O R D s(IMAGE_THUNK_DATA)数组。大部分情况下,该D W O R D 被解释为一个指向IMAGE_IMPORT_BY_NAME 结构的指针。然而,以函数序号(而非函数名称)输入,也是有可能的。IMAGE_IMPORT_DESCRIPTOR结构中,最重要的部分是i m p o r t e d D L L 的名称以及两个IMAGE_THUNK_DATA DWORDs 数组。每一个IMAGE_THUNK_DATA DWORDs对应一个输入函数。在EXE 文件中,两个数组(分别由Characteristics 和FirstThunk 栏位指向)平行存在,并且都以NULL 为结束符号。第一个数组(由Characteristics 指向)从不被修改,有时候它又被称为hint-name table。第二个数组(由FirstThunk 指向)则被加载器改写。载入器一一检阅每一个IMAGE_THUNK_DATA, 并找出它所记录的函数的地址,然后把位址写入IMAGE_THUNK_DATA这个DWORD 之中。
我们在改写API Hook 那一节谈过,对DLL 函数的呼叫会导致一个JMP DWORD PTR[XXXXXXXX]指令。[XXXXXXXX]事实上参考到FirstThunk数组中的一个元素。由于这个IMAGE_THUNK_DATA 数组内容已被加载器改写为输入函数的地址,所以它又被称为ImportedAddress Table(IAT)。
我希望大家能仔细地研究一下MSDN里关于这方面的文章。你天天编程都和PE文件打交道,不了解可不行哟。我感觉说得太多了。我之所以说了这么多,特别是对IMAGE_IMPORT_DESCR