导入表修复

IAT修复

IAT修复有双层循环,第一层循环是判断还有没有dll文件,第二层循环是判断dll内的函数到没到头。

导入表的访问从IMAGE_DATA_DIRECTORY结构开始

pehdr.peNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]

在pe的基地址加上这个IMAGE_DATA_DIRECTORY的VA,访问到第一个PIMAGE_IMPORT_DESCRIPTOR结构

IMAGE_IMPORT_DESCRIPTOR 结构体布局

| 偏移 | 字段名称 | 类型 | 大小(字节) | 说明 |

|——|———-|——|————|——|

| 0x00 | OriginalFirstThunk | DWORD | 4 | 指向 INT (导入名称表) 的 RVA |

| 0x04 | TimeDateStamp | DWORD | 4 | 时间戳,0表示未绑定 |

| 0x08 | ForwarderChain | DWORD | 4 | 转发链信息 |

| 0x0C | Name | DWORD | 4 | 指向 DLL 名称字符串的 RVA |

| 0x10 | FirstThunk | DWORD | 4 | 指向 IAT (导入地址表) 的 RVA |

第一层循环就是PIMAGE_IMPORT_DESCRIPTOR→name≠0时

IMAGE_IMPORT_DESCRIPTOR 这个结构体里面可以获取OriginalFirstThunk 和FirstThunk 的RVA

加载dll,用LoadLibraryA加载base+PIMAGE_IMPORT_DESCRIPTOR→name

OriginalFirstThunk 和FirstThunk 都是PIMAGE_THUNK_DATA结构

这俩都通过基地址加上RVA获得

其中OriginalFirstThunk 是不变的,专门保存函数的名字和信息

FirstThunk 是应该改变的,pe文件加载后变成FirstThunk.function变成实际地址

所以通过OriginalFirstThunk 访问u1联合体,

IMAGE_SNAP_BY_ORDINAL(OriginalFirstThunk .u1.ordinal)宏判断是否用ordinal获取函数地址

如果不是,就用OriginalFirstThunk .u1.AddressOfData

值得注意的是,为了获取dll里全部应该获取的函数,需要在这一层循环中每次获取OriginalFirstThunk 和FirstThunk时加上一个他们的大小,以跳到下一个OriginalFirstThunk 和FirstThunk。

最后在最外出循环PIMAGE_IMPORT_DESCRIPTOR自增,跳到下一个PIMAGE_IMPORT_DESCRIPTOR获取dll。