导出表介绍与应用

导出表的定义

typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD Name;
DWORD Base;
DWORD NumberOfFunctions;
DWORD NumberOfNames;
DWORD AddressOfFunctions; // RVA from base of image
DWORD AddressOfNames; // RVA from base of image
DWORD AddressOfNameOrdinals; // RVA from base of image
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

Characteristics:现在没有用到,一般为0。

TimeDateStamp:导出表生成的时间戳,由连接器生成。

MajorVersion,MinorVersion:看名字是版本,实际貌似没有用,都是0。

Name:模块的名字。

Base:序号的基数,按序号导出函数的序号值从Base开始递增。

NumberOfFunctions:所有导出函数的数量。

NumberOfNames:按名字导出函数的数量。

AddressOfFunctions:一个RVA,指向一个DWORD数组,数组中的每一项是一个导出函数的RVA,顺序与导出序号相同。

AddressOfNames:一个RVA,依然指向一个DWORD数组,数组中的每一项仍然是一个RVA,指向一个表示函数名字。

AddressOfNameOrdinals:一个RVA,还是指向一个WORD数组,数组中的每一项与AddressOfNames中的每一项对应,表示该名字的函数在AddressOfFunctions中的序号。

反正我看图也是没看太明白。

我用个例子我来解释

节点分布

节点遍历信息

文件中的字节码

导出表在紧跟导入表信息的后面。

从节点信息我们可以知道,文件中的偏移是从800开始,内存的偏移是从2000开始。

文件中的偏移=文件中的地址 – RVA内存偏移 + FOA文件偏移(这里是800)

如name文件偏移=HEX:90 21 00 00=2190-2000+800=990偏移,以/0结束。ansi就是winresult.dll。

接着往下是nBase,类推。不在详述。就很好理解导出表的结构了。

导出表的应用

1,导出函数的覆盖

还是用回之前的那个例子。如果我们要吧导出函数AnimateClose跟AnimateOpen调换。只需要把函数的虚拟地址修改调换即可。

导出函数从00002168=2168-2000+800=968开始。数量为4个,

HEX对应

83 11 00 00

82 12 00 00

22 10 00 00

23 13 00 00

我们可以对这4个HEX中第二组跟第三组进行调换。就可对导出函数进行互换。

注意:用这种方法需要清楚所调用的函数的参数必须相同。

这种用途,可以在不知道EXE源码的情况下。对DLL进行修改。从而让EXE的功能造成变动。

2,函数地址内的指令硬编码

这个是在函数内的地址对函数的功能代码做修改,可以做到功能修改。替换原来函数的功能。

导出私有函数

就是在导出函数中没有公开。私有的函数。默认我们是调用不了的。

修改步骤为:把导出表整体结构搬迁到一个空闲空间中。

然后NumberOfFunctions; NumberOfNames;分别加1,

增加函数名TOPXY,修改因搬迁而变动的地址。

PE头数据目录因搬迁而变动的地址

具体的导出表修改后如下。可跟上面的对比,(这里未包含PE头数据目录的导出表的修改信息)

发表评论

邮箱地址不会被公开。 必填项已用*标注