吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4246|回复: 13
收起左侧

[原创] PE 文件解析3-数据目录[导出表]

[复制链接]
appsion 发表于 2020-11-1 09:45
本帖最后由 appsion 于 2020-11-1 11:28 编辑

PE 文件解析3-数据目录[导出表]

新手学习PE文件解析记录,  持续更新. 部分参考来源于网络, 无法逐一标注, 如果侵权,请及时联系. 如有错误请指正,误喷.



上文链接: https://www.52pojie.cn/thread-1294381-1-1.html


301.png

结构体: IMAGE_EXPORT_DIRECTORY
说明: 导出表信息
头文件: winnt.h
帮助文档: 仅存在于头文件, 没有帮助文档
[Asm] 纯文本查看 复制代码
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
                描述
        TimeDateStamp
                创建时间
        MajorVersion
                主版本号
        MinorVersion
                次版本号
        Name
                DLL库文件名的RVA.
        Base
                导出函数的起始序号.
        NumberOfFunctions
                导出函数的函数总数量.
        NumberOfNames
                按名称导出的函数数量
        AddressOfFunctions
                指向输出函数地址的RVA
        AddressOfNames
                指向输出函数名称的RVA
        AddressOfNameOrdinals
                指向输出函数序号的RVA


3.1 获取导出表信息
[Asm] 纯文本查看 复制代码
// 参数说明
//    DataBuff:文件指针
//    ExportRVA:导出表的RVA
void ExportDllInfo(char *DataBuff, DWORD ExportRVA)
{
        // 获取节表
        int SectionCount = 0;
        IMAGE_SECTION_HEADER *SectionHead = GetSectionHead(DataBuff, SectionCount);

        // 获取导出表FOA
        DWORD ExportFOA = RVAToRaw(SectionHead, SectionCount, ExportRVA);

        // 获取导出表
        IMAGE_EXPORT_DIRECTORY *Export = (IMAGE_EXPORT_DIRECTORY*)(DataBuff + ExportFOA);

        // 导出表名称RVA
        DWORD DllName_RVA = Export->Name;

        // 导出表名称FOA
        DWORD DllName_FOA = RVAToRaw(SectionHead, SectionCount, DllName_RVA);

        // 导出表名称
        char *DllName = (char *)(DataBuff + DllName_FOA);

        // 导出表创建时间
        // Export->TimeDateStamp

        // 导出表主版本
        // Export->MajorVersion
        
        // 导出表次版本
        // Export->MinorVersion

        // 导出函数起始序号
        // Export->Base

        // 导出函数总数量
        // Export->NumberOfFunctions

        // 按名称导出的函数数量
        // Export->NumberOfNames

        // 导出函数地址FOA
        DWORD ExportFunction_FOA = RVAToRaw(SectionHead, SectionCount, Export->AddressOfFunctions);

        // 导出函数名称FOA
        DWORD ExportName_FOA = RVAToRaw(SectionHead, SectionCount, Export->AddressOfNames);

        // 函数序号FOA
        DWORD ExportOrdinal_FOA = RVAToRaw(SectionHead, SectionCount, Export->AddressOfNameOrdinals);
}



3.2 获取导出函数信息, 方式有二种, 按名称导出, 按序号导出.

1. 按名称导出
[Asm] 纯文本查看 复制代码
for (size_t i = 0; i < Export->NumberOfNames; i++)
{
        // 名称RVA
        DWORD Name_RVA = ((DWORD*)(DataBuff + ExportName_FOA))[i];

        // 序号
        WORD Ordinal = ((WORD*)(DataBuff + ExportOrdinal_FOA))[i];
}


2. 按序号导出
[Asm] 纯文本查看 复制代码

// 获取导出函数名称RVA与序号
std::map<WORD, DWORD> NameOrdinal;
std::map<WORD, DWORD>::iterator Find_NameOrdinal;
for (size_t i = 0; i < Export->NumberOfNames; i++)
{
        WORD Ordinal = ((WORD*)(DataBuff + ExportOrdinal_FOA))[i];
        DWORD Name_RVA = ((DWORD*)(DataBuff + ExportName_FOA))[i];
        NameOrdinal.insert(std::pair<WORD, DWORD>(Ordinal, Name_RVA));
}

// 实际导出数量, 注: 部分 FunctionRVA 为0;
int RealFunctionCount = 0;
for (size_t i = 0; i < Export->NumberOfFunctions; i++)
{
        // FunctionRVA
        DWORD FunctionRVA = ((DWORD*)(DataBuff + ExportFunction_FOA))[i];
        if (!FunctionRVA) continue;

        // FunctionID
        // 注: 
                //1. Export->Base 为导出函数的起始序号
                //2. 函数序号不是按递增方式排列
        WORD Ordinal = Export->Base + i;

        Find_NameOrdinal = NameOrdinal.find(i);
        if (Find_NameOrdinal != NameOrdinal.end())
        {
                // 导出函数名称RVA
                DWORD Name_RVA = Find_NameOrdinal->second;

                // 导出函数名称FOA
                DWORD Name_FOA = RVAToRaw(SectionHead, SectionCount, Find_NameOrdinal->second);

                // 导出函数名称
                char *Name = DataBuff + Name_FOA;
        }
        RealFunctionCount++;
}


RVA 转 FOA
[Asm] 纯文本查看 复制代码
DWORD RVAToRaw(IMAGE_SECTION_HEADER *SectionHead, int SECTIONCount, DWORD m_RVA)
{
        // 遍历节表
        for (size_t i = 0; i < SECTIONCount; i++)
        {
                IMAGE_SECTION_HEADER section = ((IMAGE_SECTION_HEADER*)SectionHead)[i];

                // 判断 RVA 所在的节表
                if (m_RVA >= section.VirtualAddress && m_RVA <= (section.VirtualAddress + section.SizeOfRawData))
                {
                        // 获取偏移差
                        m_RVA = m_RVA - section.VirtualAddress;
                        m_RVA = m_RVA + section.PointerToRawData;
                        return m_RVA;
                }
        }
        return 0;
}


免费评分

参与人数 6吾爱币 +9 热心值 +5 收起 理由
yiyunde + 1 热心回复!
Hmily + 5 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
zjun777 + 1 用心讨论,共获提升!
fengbolee + 1 + 1 用心讨论,共获提升!
茗箩寰霁 + 1 + 1 用心讨论,共获提升!
huangxw + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

霏映 发表于 2020-11-1 11:08
不错,下来试试
954464133 发表于 2020-11-2 10:39
lvcaolhx 发表于 2020-11-2 10:59
wobzhidao 发表于 2020-11-3 08:19
这个软件确实不错的啊
雪痕 发表于 2020-11-3 12:54
学习学习
rbj520 发表于 2020-11-3 20:14
謝謝樓主分享
碎步流年 发表于 2020-11-5 13:52
看着不错,试试
miaoj29 发表于 2020-11-10 15:47
谢谢分享,,,,辛苦辛苦
tsecond 发表于 2020-11-13 09:12
看着熟悉的C代码就是舒服!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 17:53

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表