您的位置:首页 > 其它

通过WINNT.H定义的结构体,获取进程IAT表

2016-06-02 19:18 429 查看
在前面的文章里,学习PE结构都是通过手动的方式去计算PE结构的NT映象头,NT可选头之类的,手动计算确实有利于加深对PE结构的熟悉程度,但是,在实际编程的时候,利用一些数据结构会让程序更高效,更简洁..于是,顺便记录了下通过WINNT.H自定义的结构体,来获取本进程的IAT表

注 : 转载请注明来源 enjoy5512的博客 http://blog.csdn.net/enjoy5512

打开WINNT.H文件可以看到里面定义了大量的结构体,正是这些已定义好的结构体,让我们能更方便的去获取PE文件的结构信息



获取IAT表大致过程:

1) 获取模块信息

2) 获取DOS头

3) 获取NT映象头

4) 获取NT可选映象头

5) 获取IAT表地址

6) 循环遍历IAT表,获取导入函数信息

测试代码

具体解释请看代码的注释

/////////////////////////////////////////////////////////////////////////////
//  文件名 : test.c
//  工程 : test
//  作者 : enjoy5512   修改者 : enjoy5512   最后优化注释者 : enjoy5512
//  个人技术博客 : blog.csdn.net/enjoy5512
//  个人GitHub   : github.com/whu-enjoy
//  csdn code    : code.csdn.net/enjoy5512
//  描述 : 使用WINNT.h中自带的PE文件结构体,获取本进程的IAT表
//  主要函数 :
//  版本 : 最终确定版  完成日期 : 2016年6月2日 19:06:21
//  修改 :
/////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <windows.h>

int main()
{
HMODULE hMod;                               //保存模块句柄
PIMAGE_DOS_HEADER pDosHeader;               //PE DOS头结构体
PIMAGE_NT_HEADERS pNTHeaders;               //PE NT头结构体
PIMAGE_OPTIONAL_HEADER pOptHeader;          //PE可选头结构体
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor; //PE函数导入表结构体

//多导入一个dll函数测试
MessageBox(NULL,"导入了user32.dll 的MessageBox函数","test",NULL);

//获取本进程模块句柄
hMod = GetModuleHandle(NULL);

//获取本进程PE DOS结构体
pDosHeader = (PIMAGE_DOS_HEADER)hMod;

//根据DOS的e_lfanew得到NT映像头结构体
pNTHeaders = (PIMAGE_NT_HEADERS)((BYTE *)hMod + pDosHeader->e_lfanew);

//获取本进程的NT可选头结构体
pOptHeader = (PIMAGE_OPTIONAL_HEADER)&(pNTHeaders->OptionalHeader);

//获取本进程的函数导入表结构体
pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE *)hMod + pOptHeader->DataDirectory[1].VirtualAddress);

//循环遍历函数导入表的IMAGE_IMPORT_DESCRIPTOR结构体
while(pImportDescriptor->FirstThunk)
{
//获取函数名地址IMAGE_THUNK_DATA结构体
PIMAGE_THUNK_DATA pFuncNameAddr = (PIMAGE_THUNK_DATA)((BYTE *)hMod + pImportDescriptor->OriginalFirstThunk);

//获取函数在内存中的地址IMAGE_THUNK_DATA结构体
PIMAGE_THUNK_DATA pFuncAddr = (PIMAGE_THUNK_DATA)((BYTE *)hMod + pImportDescriptor->FirstThunk);

//获取本导入dll的dll文件名
char *pDllName = (char *)((BYTE *)hMod + pImportDescriptor->Name);
printf("%s\n",pDllName);

//循环遍历函数导入表的函数名列表
while(pFuncNameAddr->u1.Function)
{
//获取函数导入序号
WORD *iNo = ((BYTE *)hMod + (DWORD)pFuncNameAddr->u1.AddressOfData);

//获取函数名
char *pFuncName = (char *)((BYTE *)hMod + (DWORD)pFuncNameAddr->u1.AddressOfData + 2);

//获取函数名对应的函数在内存中的地址
PDWORD lpAddr = pFuncAddr->u1.AddressOfData;

printf("%0 4X : %s    %#X\n",*iNo, pFuncName, lpAddr);

//指向下一个函数
pFuncNameAddr++;
pFuncAddr++;
};

getchar();
//指向下一个dll
pImportDescriptor++;
};

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息