标签:pe
关于PE结构导入表,以前只是手动分析,没有通过编程来实现。而且PE文件结构,不巩固的话,一段时间之后就会忘记,所以记录下这次试验,为IAT挂钩做好准备,也算是复习一下。
环境:windows xp sp3
IDE: vs 2008 sp1
build:release
#include <windows.h>
#include <stdio.h>
#include <DbgHelp.h>
#pragma comment(lib,"dbghelp.lib")
int main()
{
DWORD ModuleBase;
ModuleBase = (DWORD)GetModuleHandle(NULL);
DWORD dwNum=0;
PIMAGE_IMPORT_DESCRIPTOR pImpDes=(PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData((PVOID)ModuleBase,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&dwNum);//IID
printf("import_descriptor=%08x\n",pImpDes);
while (pImpDes->Name)
{
printf("dll name is %s\n",pImpDes->Name+ModuleBase);
PIMAGE_THUNK_DATA pINT_thunk =(PIMAGE_THUNK_DATA)(pImpDes->OriginalFirstThunk+ModuleBase);
PIMAGE_THUNK_DATA pIAT_thunk =(PIMAGE_THUNK_DATA)(pImpDes->FirstThunk+ModuleBase);
//while(thunk)
while(pINT_thunk->u1.AddressOfData)
{
PIMAGE_IMPORT_BY_NAME pname = (PIMAGE_IMPORT_BY_NAME)(pINT_thunk->u1.AddressOfData+ModuleBase);
//printf("funcname=%s\n",pname->Name+ModuleBase);
DWORD addr = (DWORD) pIAT_thunk->u1.Function;
DWORD* where = &(pIAT_thunk->u1.Function);
printf("funcname=%s \t addr=%08x\t \t funaddr=%08x\n",pname->Name,where,addr);
pINT_thunk++;
pIAT_thunk++;
}
pImpDes++;
}
return 0;
}
本来是打算用vc6.0
去完成的,但是dbghelp.h
提示找不到,就用vs了。
ImageDirectoryEntryToData
可以直接定位导入表描述地址,需要添加dbghelp.lib
.IID
,输入了多少dll,就有多少个IID
结构,这些IID在内存中连续排列,以一个字段全为0的IID表示结束。从IID
的数量可以看出导入了多少个DLL。INT
和IAT
也都是DWORD
大小的结构,导入了多少函数,就在内存中连续排列多少个,以一个字段为0的元素表示结束。 从IAT(或者INT)数组长度减去1可以得到导入的函数数目。IID,INT,IAT
他们都是结构体数组,所以是连续排列的,不是链式结构。关于代码的一些说明:
//printf("funcname=%s\n",pname->Name+ModuleBase);
注意到我将这句给注释了,是因为理解错误。我本来以为name是个地址,RVA类型,所以要加基址。但是最后发现Byte Name[1]
中已经存放了字符串,而不是字符串的相对偏移指针,所以直接指向就行了。
在写遍历的时候,犯了一个错误。就是对指针和内容没有区分开。while(pINT_thunk->u1.AddressOfData)是对的,但是我之前写成了while(pINT_thunk)
,PINT_thunk
是指针,是INT数组的地址,而不是INT数组的内容 ,使用错误的语句执行后会有异常,原因是到了INT为0
时,&INT(即pINT_thunk)
也不为0. INT结束的标志是内容为0,而不是指针为0.
执行效果图
在OD中测试,在数据窗口下ctrl+g
跳转到402000,右键选择长型->地址
,即将数据解释为地址类型。
从图中可以看出来,两个dll之间的IAT差了4字节,这4字节就是各自IAT数组的结束标志。
有意思的是实验中,不同的dll对应的INT和IAT基本上都是连续的,这是编译器做的,实际上每个dll的INT和IAT分别由各自IID中的字段来决定他们的位置(里面有各自的RVA指针),可以在内存中同一个段内任意分布。
但是IID数组在内存中一定是连续的
标签:pe
原文地址:http://blog.csdn.net/bugmeout/article/details/45461851