通过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文件的结构信息
2) 获取DOS头
3) 获取NT映象头
4) 获取NT可选映象头
5) 获取IAT表地址
6) 循环遍历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; }
相关文章推荐
- LightOJ 1074 spfa判断负环
- 终端执行python脚本 (for Mac)
- RNN(Recurrent Neural Networks)公式推导和实现
- std::slice
- 【UGUI实战】游戏右上角CoinBar的自动调整
- 多击
- Java面向对象编程之异常处理机制
- SecureCRT密钥远程登录Linux 【转】
- 面试:字符串:产生括号
- UIView Class Reference
- avalon.js 1.4.6简单列表数据绑定ms-repeat ms-click
- 用php输入表格内容
- java多态
- 第二阶段冲刺——个人总结06
- 代码段接收并遍历返回值为动态游标的方法
- 高并发数据结构Disruptor解析(1)
- codeforces 677c Vanya and Label
- listView、gidView和spinner
- php 指针遍历、预定义数组和常用函数
- Talking about paper