1.导出表的定义
导出表大多存在于DLL中,目的就是用来导出其他exe运行的函数。不管exe或者DLL的本质都是PE文件。
2.准备工作
写一个DLL文件并简单调用一下。
2.1主要代码
2.1.1   .C文件
[C++] 纯文本查看 复制代码
DLLIMPORT int Add(int a,int b){        return a+b;}DLLIMPORT int Sub(int a,int b){        return a-b;}DLLIMPORT int Mul(int a,int b){        return a*b;}DLLIMPORT int Div(int a,int b){        return a/b;}

DLLIMPORT关键字可以用来修饰某个函数或者时变量就会被导出。
2.1.2   .H文件
[C++] 纯文本查看 复制代码
DLLIMPORT int Add(int a,int b);DLLIMPORT int Sub(int a,int b);DLLIMPORT int Mul(int a,int b);DLLIMPORT int Div(int a,int b);

2.1.3   测试代码
[C++] 纯文本查看 复制代码
#include<Windows.h>#include<stdio.h>#include<stdlib.h>int main(){        typedef int(* FUNT)(int,int);        //定义函数指针        HINSTANCE Hint = LoadLibrary("test.dll");        调用先前写好的DLL                if(Hint==NULL)        {                printf("DLL调用失败");        //测试        return 0;        }        FUNT ADD =(FUNT)GetProcAddress(Hint,"Add");        FUNT SUB =(FUNT)GetProcAddress(Hint,"Sub");        FUNT MUL =(FUNT)GetProcAddress(Hint,"Mul");        FUNT DIV =(FUNT)GetProcAddress(Hint,"Div");                int a=20,b=10;                printf("和为%d\n",ADD(a,b));        printf("差为%d\n",SUB(a,b));        printf("积为%d\n",MUL(a,b));        printf("商为%d\n",DIV(a,b));                FreeLibrary(Hint);        //释放        return 0;}

2.1.4  结果
PE导出表分析
2.2导出函数定义声明
[C#] 纯文本查看 复制代码
> EXPORTS    Add @1    Div @2    Mul @3    Sub @4

3.导出表的位置
导出表位于扩展PE头的DIRECTORY DataDirectory[10]里,该数组有10个成员,第一个就是导出表,即DIRECTORY DataDirectory[0]。
[C++] 纯文本查看 复制代码
> typedef struct _IMAGE_DATA_DIRECTORY>  {> DWORD   VirtualAddress;        //导出表开始的地址       **注意是RVA的值**> RVADWORD   Size;                //导出表大小> }> IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

关于PE文件结构前面提到很多,这里不再赘述,直接用StudyPE+工具找出,如图:
PE导出表分析
选中区域就是数组里的内容,
前四个字节就是导出表的位置:0x00006000是RVA(内存偏移地址)的值,要转化成FOA(文件偏移地址)才能分析;
这里简单说一下,RVA转FOA的步骤:
1.判断RVA是否位于PE头中,如果在,那么RVA==FOA;
2.判断RVA的值在哪一个区段中,求出RVA与该区段开始地址的差值;
3.FOA=节.PointerToRawData(节区在文件中开始地址)+差值

我们来手动算一下,
PE导出表分析
1.节表开始的位置在0x00000178,则RVA不属于PE头

2.观察可知RVA介于.edata和.idata区段之间,

(PE导出表分析
差值为:0x00006000-0x00006000=0x0

3.FOA=0x2000+0x0=0x2000
接着四个字节就是导出表的大小:0x00000069;
4.导出表的结构
现在我们找到了导出表的文件地址,贴上导出表的数据结构和对应的二进制代码:
PE导出表分析
> [C] 纯文本查看 复制代码
typedef struct _IMAGE_EXPORT_DIRECTORY {    **0x00**        DWORD   Characteristics;    //用不到    **0x04**           DWORD   TimeDateStamp;      //时间戳.  编译的时间. 把秒转为时间.可以知道DLL的编译时间.此处和标准PE头的第二个成员一样    **0x08**         WORD    MajorVersion;    **0x0a**       WORD    MinorVersion;    **0x0c**         DWORD   Name;           //指向该导出表文件名的字符串,也就是这个DLL的名称    存储的RVA 地址,需要转换    **0x10**       DWORD   Base;           // 导出函数的起始序号   **0x14**        DWORD   NumberOfFunctions;     //所有的导出函数的个数    **0x18**       DWORD   NumberOfNames;         //以名字导出的函数的个数    **0x1c**       DWORD   AddressOfFunctions;     // 导出的函数地址的 地址表  RVA 即函数地址表     **0x20**      DWORD   AddressOfNames;         // 导出的函数名称表的  RVA      即函数名称表   **0x24**        DWORD   AddressOfNameOrdinals;  // 导出函数序号表的RVA   即函数序号表} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

直接从名字开始分析:导出表文件名所在的地址是:0x6050
差值:0x00006050-0x00006000=0x00000050;
FOA=0x00002000+0x00000050=**0x00002050**;
PE导出表分析
字符串以00结尾,可知该DLL的名字是test.dll;
**导出函数的起始序号(01)稍后分析;**
**导出函数的个数**在0x14位,为4个;
**以名字导出的函数**的个数在0x18位,为4个(说明DLL没有隐藏函数名字,转用序号调用);
导出函数有4个,所以导出函数的地址有4个,是连续的;
                               **函数地址表**
起始序号——>下标函数地址(FOA)函数名 (此表中函数名为二进制代码推出)01——>0
华山资源网 Design By www.eoogi.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
华山资源网 Design By www.eoogi.com

稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!

昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。

这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。

而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?