PE文件结构(四) 输出表

PE文件结构(四)


參考

书:《加密与解密》

视频:小甲鱼 解密系列 视频


输出表


一般来说输出表存在于dll中。输出表提供了 文件里函数的名字跟这些函数的地址, PE装载器通过输出表来改动IAT。

IMAGE_OPTIONAL_HEADER中的 DataDirectory[0] 提供了输出表的RVA。输出表是以一个IMAGE_EXPORT_DIRECTORY结构 開始的。


IMAGE_EXPORT_DIRECTORY结构:

typedef struct _IMAGE_EXPORT_DIRECTORY {
    DWORD   Characteristics;         //未使用
    DWORD   TimeDateStamp;           //文件生成的时间
    WORD    MajorVersion;            //主版本。一般为0
    WORD    MinorVersion;            //次版本,一般为0
    DWORD   Name;                    //指向dll名的RVA
    DWORD   Base;                    // 基数,一般为 1 (就是从1数起)
    DWORD   NumberOfFunctions;       // AddressOfFunctions指向的数组的元素的个数
    DWORD   NumberOfNames;           // AddressOfNames 指向的数组的元素的个数
    DWORD   AddressOfFunctions;     // 函数地址数组ENT的RVA
    DWORD   AddressOfNames;         // 函数名字数组EAT的RVA 
    DWORD   AddressOfNameOrdinals;  // 输出序列号数组的RVA,这个数组是以WORD为单位的,用来函数名字数组连接函数地址数组的
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;


输出表主要就是来给PE载入器改动IAT的,即查找函数的入口地址。PE载入器查找函数的地址有两种方法,从序号查找,从函数名查找。


1. 从序号查找函数入口地址

    PE载入器通过INT知道了序号。直接用这个序号 去找 函数地址数组EAT就能够了。


2. 从函数名查找函数入口地址

    通过函数名,查找函数名数组ENT,找到这个函数名在数组中的序号 n(从0数起),然后取输出序列号数组的第n个值(从0数起)。

然后 以这个值为序号的的函数地址数组EAT的值就是这个函数的入口地址。


即 ENT[  输出序列号数组[n]  ] 


实例分析:


比如找user32.dll 中AdjustWindowRect 这个函数。


先查看user32.dll的二进制文件。它的IMAGE_OPTIONAL_HEADER结构为:


图片1



从中能够知道:

Name: RVA 55C0h          文件偏移值:49C0h  
Base: 1
NumberOfFunctions: 02DCh  
NumberOfNmae:02DCh
AddressOfFunctions:  RVA 3928h         文件偏移值:2D28h
AddressOfNames:  RVA 4498h             文件偏移值:3898h
AddressOfNameOrdinals: RVA 5008h        文件偏移值:4408h


查看ENT数组所指向的字符串。能够知道AdjustWindowRect是第2个元素。

所以。查看AddressOfNameOrdinals所指向的输出序列号数组的第2个元素,能够发现值为 1。


图片2



再查看EAT中序号为1的元素(即第2个元素)值为021140h,这个就是AdjustWindowRect函数的RVA。


图片3






















版权声明:本文博客原创文章,博客,未经同意,不得转载。

原文地址:https://www.cnblogs.com/yxwkf/p/4690505.html