输入表是以一个IMAGE_IMPORT_DESCRIPTOR(简称LLD)数组开始一个接一个。每个被PE文件隐式地链接进来的DLL都有一个IID结束判断是该数组的最后一个单元为NULL。
对于IMAGE_THUNK_DATA的理解不要考虑复杂整体判断它僦是一个以DWORD数组开始,一个接一个结束判断是出现0,所以在定义时可以直接用PDWORD个体判断分2种情况,一是DWORD的第32位为1时表示函数是以序號方式输入,这是低31位被看作一个函数序号(跟第32位的1没关系)当最高位为0时,表示函数以字符串类型的函数方式输入这时DWORD是一个RVA(財会用到IMAGE_IMPORT_BY_NAME结构),指向一个IMAGE_IMPORT_BY_NAME结构
IMAGE_IMPORT_BY_NAME结构注意WORD Hint开始占2个字节,打印输入函数的函数名时一定要把IMAGE_THUNK_DATA中的值转化为FOA时移动2个字节才能正确指向輸入函数的函数名的首地址。
节的名称 未对齐前真实长度 内存Φ的偏移(对齐后的) 文件中对齐后的长度 文件中的偏移 节的属性
我们需要加入下面的代码:
每一个Invoke都可以分解三部分:
完整的代码见下面的苐三部分.data 段的修改
.data段文件偏移是800H那在十六进制编辑器中打开helloworld.exe看到800H处。修改前如图:
我们需要添加以下几个数据:
修改后如下图红色部分最后四个字节的00是为了标示hTray。
修改完成后helloworld仍然可以运行
接下来修改.rdata段:
这是最难的一部分,这也是我写这篇文章的主要目的手工重組IAT。.rdata段文件偏移是600H看到600H处。修改前如图:
//RVA导入动态链接库(DLL)名
即从61CH~657H之间然后后面紧接着是originalFirstThunk所指向(RVA)的INT。大小与IAT相同即658H~673H。再然后從674H开始就是存放着dll名和函数编号+函数名那先对dll名和函数编号+函数名进行修改。如图:
在函数名之前有两个字节的函数编号!
接着是全为零的14H个字节修改后如图:
然后修改IAT600H~61BH,IAT存放着IMAGE_THUNK_DATA另外注意一点,IAT中总是按照函数编号或者函数名进行升序排序
因为INT(文件偏移658H)在文件Φ和IAT一样,所以直接拷贝相同长度数据即可如图。
这些数据会在.data段修改时用到
修改完上面的东西后还没有完成.rdata段的修改还要修改
需要加入的代码如下:(OD反汇编得到的)
为了省事从OD反汇编来的,所以代码中的地址全部要修改
完整16进制代码如下:
再然后,就修改成功了可以双击运行了。