PE结构学习02-导出表

导出表:

  • 上篇文章,我们学习了各种头,Dos,NT,节表头,我们知道,OptionalHeader指向的DataDirectory[]数组一共有16个:

  • 我们接下来要学习的有:
  1. IMAGE_DIRECTORY_ENTRY_IMPORT 导入表
  2. IMAGE_DIRECTORY_ENTRY_BASERELOC 基址重定位表
  3. IMAGE_DIRECTORY_ENTRY_EXPORT 导出表
  4. IMAGE_DIRECTORY_ENTRY_RESOURCE 资源表
  • 今天我们学习导出表:
  1. 我们知道dll文件,是动态链接库,里面有许多函数给别人调用,但是别人怎么知道里面有什么函数呢?就需要导出表清单给人家看,就如同你去餐厅点餐,却不知道餐厅有什么菜,这时服务生会拿出菜单来,这个菜单就如同导出表。
  2. 所有PE文件都可以有导出表,只是大部分情况下,exe不提供导出表而已。
  • 我们知道OptionalHeader指向的DataDirectory[]数组一共有16个,每个都是一样的结构:
  1. VirtualAddress  虚拟偏移地址
  2. size  大小
  • NtHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT ],这个数据目录表VirtualAddress指向的是导出表的地址:
typedef struct _IMAGE_EXPORT_DIRECTORY  { DWORD Characteristics;//未使用,总是定义为0  DWORD TimeDateStamp;//文件生成时间  WORD MajorVersion;//未使用,总是定义为0  WORD MinorVersion;//未使用,总是定义为0  DWORD Name; //模块的真实名称的RVA  DWORD Base; //基数,加上序数就是函数地址数组的索引值  DWORD NumberOfFunctions;//导出函数的总数  DWORD NumberOfNames; //以名称方式导出的函数的总数  DWORD AddressOfFunctions; // RVA from base of image指向输出函数地址的RVA  DWORD AddressOfNames; // RVA from base of image指向输出函数名字的RVA  DWORD AddressOfNameOrdinals; // RVA from base of image向输出函数序号的RVA 

} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY
  1. Characteristics:现在没有用到,一般为0。
  2. TimeDateStamp:导出表生成的时间戳,由连接器生成。
  3. MajorVersion,MinorVersion:看名字是版本,实际貌似没有用,都是0。
  4. Name:模块的名字,就是dll的名称。
  5. Base:序号的基数,按序号导出函数的序号值从Base开始递增。
  6. NumberOfFunctions:所有导出函数的数量。
  7. NumberOfNames:按名字导出函数的数量。
  8. AddressOfFunctions:一个RVA,指向一个DWORD数组,数组中的每一项是一个导出函数的RVA,顺序与导出序号相同。
  9. AddressOfNames:一个RVA,依然指向一个DWORD数组,数组中的每一项仍然是一个RVA,指向一个表示函数名字。
  10. AddressOfNameOrdinals:一个RVA,还是指向一个WORD数组,数组中的每一项与AddressOfNames中的每一项对应,表示该名字的函数在AddressOfFunctions中的序号。
typedef struct _IMAGE_IMPORT_BY_NAME { WORD Hint; CHAR Name[1];} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

  • AddressOfFunctions 指向所有函数的地址。
  • AddressOfNames 指向名字的地址。
  • AddressOfNameOrdinals 指向一个序号。
  • 查找导出表代码(c/c++):
int main(int argc, char *argv[])
{
 PIMAGE_DOS_HEADER Pdos = (PIMAGE_DOS_HEADER)GetModuleHandle(L"user32.dll");

 PIMAGE_NT_HEADERS Pnt = (PIMAGE_NT_HEADERS)((int)Pdos->e_lfanew + (int)Pdos);

 IMAGE_OPTIONAL_HEADER32 Popt = Pnt->OptionalHeader;

 IMAGE_EXPORT_DIRECTORY * Export;
 Export = (IMAGE_EXPORT_DIRECTORY*)(Popt.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + (ULONG_PTR)Pdos);

 DWORD * AllAddress;
 DWORD * AllName;
 USHORT * AllOrg;

 AllAddress = (DWORD*)((int)Export->AddressOfFunctions + (int)Pdos);//函数地址数组
 AllName = (DWORD*)((int)Export->AddressOfNames + (int)Pdos);//函数名称数组
 AllOrg = (USHORT *)((int)Export->AddressOfNameOrdinals + (int)Pdos);//序号数组

 int OneAddress;
 char * OneName;
 USHORT OneOrg;
 char * Buf = new char[500];
 int ListId = NULL;

 for (int i = 0; i < (int)Export->NumberOfNames; i++)
 {

 OneName = (char*)((BYTE*)Pdos + AllName[i]);
 OneOrg = (USHORT)AllOrg[i];
 OneAddress = (int)((int)Pdos + AllAddress[OneOrg]);

 printf("Name: %s, Org :%d,Address :%x\n", OneName, OneOrg, OneAddress);
 }

 return 0;
}

时间: 2025-01-18 16:38:13

PE结构学习02-导出表的相关文章

手写PE结构解析工具

PE格式是 Windows下最常用的可执行文件格式,理解PE文件格式不仅可以了解操作系统的加载流程,还可以更好的理解操作系统对进程和内存相关的管理知识,而有些技术必须建立在了解PE文件格式的基础上,如文件加密与解密,病毒分析,外挂技术等,在PE文件中我们最需要关注,PE结构,导入表,导出表,重定位表,下面将具体介绍PE的关键结构,并使用C语言编程获取到这些结构数据. 参考文献: [琢石成器 Win32汇编语言程序设计 - 罗云彬] 整理学习笔记,精简内容,翻译汇编代码C语言化 在任何一款操作系统

PE结构、SEH相关知识学习笔记

原文:http://www.pediy.com/kssd/index.html -- 病毒技术 -- 病毒知识 -- Anti Virus专题 PE结构的学习 原文中用fasm自己构造了一个pe,这里贴一个用masm的,其实是使用WriteFile API将编写的PE数据写成文件~也没啥好说的,PE结构在这里没有仔细介绍,需要可以另外查询,剩下要说的的基本都在代码注释里了 参考:点击打开链接(PEDIY技术之新思路(二)_用'高级'编译器MASM实现自定义PE文件结构) Pe.asm: REMO

编写自定义PE结构的程序(如何手写一个PE,高级编译器都是编译好的PE头部,例如MASM,TASM等,NASM,FASM是低级编译器.可以自定义结构)

正在学PE结构...感谢个位大哥的文章和资料...这里先说声谢谢 一般高级编译器都是编译好的PE头部,例如MASM,TASM等一直都说NASM,FASM是低级编译器.可以自定义结构但是苦于无人发布相关文章说明..我这里就简单的用NASM写一下由于刚学PE结构许多东西都不太懂希望个位大侠指点如何打造一个迷你的PE结构..我暂只只能作到617字节下面随着学习的深入...还有更迷你的PE出现... 代码可以直接编译..编译参数:nasmw -fbin MsgBoxA.asm -o MsgBoxA.ex

PE文件结构与函数导出表——详解与实例

PE文件结构与函数导出表--详解与实例 随着windows系统从Xp升级到Win7.Win8, 从32位升级到64位,PE文件结构在整体未变的情况下发生了一些小的变动,一方面是推荐的程序装载地址未采用,另一方面,导出函数序号不再是简单的升序,而是一定程度上的进行了乱序.本文首先对PE文件结构进行了详尽的解说,接着介绍了如何得出函数导出表,整个过程采用SysWoW64目录下的wininet.dll实例进行说明.在介绍过程中,明确指出了Win7.Win8等新系统相对Xp带来的区别. 文章链接:htt

设计模式学习02—工厂模式

1.动机与定义 我们在程序中使用一个对象时,需要new一下,如果需要设置其他值就再初始化一下.比如我要使用一个按钮,手动new一个矩形按钮,然后初始化一些值,如显示文字,背景色等. // 矩形按钮 IButton btn = new RecButton(); // 初始化其他值 btn.setText("提交"); btn.setBackgroundColor("#00aaff"); // 其他初始化省略 // 圆形按钮 IButton btn2 = new Rou

Java学习02

昨天学了一天Java,今天来回忆总结一下. Java是一门面向对象的语言,与C++有很多地方都很相似. Java的特点: 1.取消了指针,用引用代替 2.有垃圾自动回收机制,程序员不需要手动管理内存 3.跨平台性(JVM) 昨天主要从最基础的开始学,学习了变量,操作符,语句结构.下面用程序来回顾一下. 1 /* 2 测试4种进制 3 1.二进制 4 2.十进制 5 3.八进制 0开头 6 4.十六进制 0x开头 7 */ 8 9 //当class声明为public时文件名必须为类名一样 10 p

ThinkPhp学习02

原文:ThinkPhp学习02 一.什么是MVC                M -Model 编写model类 对数据进行操作 V -View  编写html文件,页面呈现 C -Controller 编写类文件(UserAction.class.php)二.ThinkPHP的MVC特点        三.ThinkPHP的MVC对应的目录    M 项目目录/应用目录/Lib/Model V 项目目录/应用目录/Tpl C 项目目录/应用目录/Lib/Action四.url访问C     

2014年7月17日学习笔记--PHP的循环结构学习

今天重新开始学习PHP, 为了学习PHP买了书,但书是一本大部头的书,不好带一直没有好好学习,我决定把书拆了分章来看,这样也方便带 也可以很快完成任务. 今天在linux mint 17上安装了lnmp 环境 和brackets工具,来学PHP,小的例子用vim来完成的. 记录一下自己美化的九九乘法表 代码如下: <?php     for($i=1;$i<=9;$i++){         for($j=1;$j<=9;$j++){             if($i>=$j){

RabbitMQ (消息队列)专题学习02 Hello World

一.概述 RabbitMQ可以当做一个消息代理,它的核心原理非常简单:即接收和发送消息,可以把它想象成一个邮局:我们把信件放入邮箱,邮递员就会把信件投递到你的收件人处,RabbitMQ就是一个邮箱.邮局.投递员功能综合体,整个过程就是:邮箱接收信件,邮局转发信件,投递员投递信件到达收件人处. RabbitMQ和邮局的主要区别就是RabbitMQ接收.存储和发送的是二进制数据----消息. 在专题学习一中我们已经简单提到了一些概念,在此我们更为深入的学习下RabbitMQ相关的专有名词. 1.生产