吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4848|回复: 11
收起左侧

[原创] PE 文件解析2-获取PE头、区段、数据目录

[复制链接]
appsion 发表于 2020-10-31 10:43
本帖最后由 appsion 于 2020-10-31 12:33 编辑

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


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


2.png

概念:
        TLS:
              Thread Local Storage,   线程本地存储,用来保存变量或回调函数.

        IAT:
             Import Address Table, 导入地址表, 由于导入函数就是被程序调用但其执行代码又不在程序中的函数,这些函数的代码位于一个或者多个DLL 中.当PE 文件被装入内存的时候,Windows 装载器才将DLL 装入,并将调用导入函数的指令和函数实际所处的地址联系起来(动态连接),这操作就需要导入表完成.其中导入地址表就指示函数实际地址.



结构体: IMAGE_DATA_DIRECTORY
说明: 数据目录
头文件: winnt.h
参考文档: https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_data_directory
[Asm] 纯文本查看 复制代码
typedef struct _IMAGE_DATA_DIRECTORY
 {
        DWORD VirtualAddress;
        DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

参数说明: 仅供参考, 详细说明请参考原文.
        VirtualAddress:
                数据目录相对虚拟地址(RVA)
        Size:
                表的大小

VirtualAddress成员如下:
Offset (PE/PE32+)Description
96/112Export table address and size
104/120Import table address and size
112/128Resource table address and size
120/136Exception table address and size
128/144Certificate table address and size
136/152Base relocation table address and size
144/160Debugging information starting address and size
152/168Architecture-specific data address and size
160/176Global pointer register relative virtual address
168/184Thread local storage (TLS) table address and size
176/192Load configuration table address and size
184/200Bound import table address and size
192/208Import address table address and size
200/216Delay import descriptor address and size
208/224The CLR header address and size
216/232Reserved




2.1 获取PE头信息


IMAGE_FILE_HEADER.Machine                                                                 // 处理器类型

IMAGE_OPTIONAL_HEADER.MajorLinkerVersion                                     // 链接器版本号
IMAGE_OPTIONAL_HEADER.MinorLinkerVersion

IMAGE_OPTIONAL_HEADER.MajorOperatingSystemVersion                  // 系统版本号
IMAGE_OPTIONAL_HEADER.MinorOperatingSystemVersion

IMAGE_OPTIONAL_HEADER.Subsystem                                                 // 子系统名称

IMAGE_OPTIONAL_HEADER.MajorSubsystemVersion                           // 子系统版本号
IMAGE_OPTIONAL_HEADER.MinorSubsystemVersion

IMAGE_FILE_HEADER.TimeDateStamp                                                  // 映像时间

IMAGE_FILE_HEADER.Characteristics                                                    // 映像特征

IMAGE_OPTIONAL_HEADER.Magic                                                      // 映像类型

IMAGE_OPTIONAL_HEADER.MajorImageVersion                                // 映像版本号
IMAGE_OPTIONAL_HEADERMinorImageVersion

IMAGE_OPTIONAL_HEADER.ImageBase                                              // 映像基址

IMAGE_OPTIONAL_HEADER.BaseOfCode                                           // 代码基址

IMAGE_OPTIONAL_HEADER.BaseOfData                                            // 数据基址

IMAGE_OPTIONAL_HEADER.AddressOfEntryPoint                             // 入口点相对地址

ImageBase + AddressOfEntryPoint                                                    // 入口点实际地址

IMAGE_OPTIONAL_HEADER.SizeOfImage                                         // 映像内存大小

IMAGE_OPTIONAL_HEADER.CheckSum                                            // 映像校验合

IMAGE_OPTIONAL_HEADER.DllCharacteristics                                 // 映像的DLL特性

IMAGE_OPTIONAL_HEADER.SizeOfHeaders                                    // 文件头大小

IMAGE_FILE_HEADER.NumberOfSections                                       // 节表数量

IMAGE_OPTIONAL_HEADER.SectionAlignment                              // 节表内存对齐

IMAGE_OPTIONAL_HEADER.FileAlignment                                    // 文件对齐

IMAGE_FILE_HEADER.PointerToSymbolTable                                // 符号表偏移地址

IMAGE_FILE_HEADER.NumberOfSymbols                                     // 符号表数量

IMAGE_OPTIONAL_HEADER.SectionAlignment                            // 节表(区段)对齐

IMAGE_OPTIONAL_HEADER.FileAlignment                                  // 文件对齐

IMAGE_OPTIONAL_HEADER.DataDirectory                                 // 数据目录

IMAGE_NT_HEADERS.OptionalHeader.NumberOfRvaAndSizes             // 数据目录数量

IMAGE_OPTIONAL_HEADER.DataDirectory                                // 数据目录表


2.2 获取区段信息
[Asm] 纯文本查看 复制代码
// 节表数量
IMAGE_FILE_HEADER.NumberOfSections
// 节表头
IMAGE_SECTION_HEADER *SectionHead = (IMAGE_SECTION_HEADER *)(DataBuff + DosHead->e_lfanew + sizeof(IMAGE_NT_HEADERS));

for (size_t i = 0; i < IMAGE_FILE_HEADER.NumberOfSections; i++)
{
        IMAGE_SECTION_HEADER Section = SectionHead[i];

        // 节表名称
        // Section.Name

        // 节表的RVA
        // Section.VirtualAddress

        // 节表的虚拟大小
        // Section.Misc.VirtualSize

        // 节表的Raw
        // Section.PointerToRawData

        // 节表的Raw的数据大小
        // Section.SizeOfRawData

        // 特征
        // Section.Characteristics

}



2.3 获取数据目录

// NT头
IMAGE_NT_HEADERS * NTHead = GetNTHead(DataBuff);

// 数据目录数量
DataDirectoryCount = NTHead->OptionalHeader.NumberOfRvaAndSizes;

// 数据目录头
IMAGE_DATA_DIRECTORY *DirectoryHead = NTHead->OptionalHeader.DataDirectory;

// 数据目录说明
IMAGE_DIRECTORY_ENTRY_EXPORT0导出表
IMAGE_DIRECTORY_ENTRY_IMPORT1导入表
IMAGE_DIRECTORY_ENTRY_RESOURCE2资源表
IMAGE_DIRECTORY_ENTRY_EXCEPTION3异常表
IMAGE_DIRECTORY_ENTRY_SECURITY4安全证书表
IMAGE_DIRECTORY_ENTRY_BASERELOC5基址重定位表
IMAGE_DIRECTORY_ENTRY_DEBUG6调试表
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE7版权信息
IMAGE_DIRECTORY_ENTRY_GLOBALPTR8全局指针
IMAGE_DIRECTORY_ENTRY_TLS9TLS表
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG10加载配置表
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT11绑定导入表
IMAGE_DIRECTORY_ENTRY_IAT12IAT表
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT13延迟导入表
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR14COM描述符表
15保留


获取数据目录
[Asm] 纯文本查看 复制代码
for (size_t i = 0; i < DataDirectoryCount; i++)
{
        // 获取数据目录标题
        switch (i)
        {
                case 0: Caption = "导出表"; break;
                case 1: Caption = "导入表"; break;
                case 2: Caption = "资源表"; break;
                case 3: Caption = "异常表"; break;
                case 4: Caption = "安全证书表"; break;
                case 5: Caption = "基址重定位表"; break;
                case 6: Caption = "调试表"; break;
                case 7: Caption = "版权信息"; break;
                case 8: Caption = "全局指针"; break;
                case 9: Caption = "TLS表"; break;
                case 10: Caption = "加载配置表"; break;
                case 11: Caption = "绑定导入表"; break;
                case 12: Caption = "IAT表"; break;
                case 13: Caption = "延迟导入表"; break;
                case 14: Caption = "COM描述符表"; break;
                case 15: Caption = "保留"; break;
                default:        break;
        }

        // 表的RVA
        // DataDirectoryHead[i].VirtualAddress

        // 表的大小
        // DataDirectoryHead[i].Size

        // 节表数量
        int SECTIONCount = IMAGE_FILE_HEADER.NumberOfSections;
        
        // 节表头
        IMAGE_SECTION_HEADER *SectionHead = (IMAGE_SECTION_HEADER *)(DataBuff + DosHead->e_lfanew + sizeof(IMAGE_NT_HEADERS));


        // 表的FOA
        // 注: 获取表的FOA需要以下几步
                //1. 判断表的RVA所在节表中的哪一个.
                //2. 表的FOA = 表的RVA - 节表的RVA + 节表FOA
        DWORD DataDirectoryFOA = RVAToRaw(SectionHead, SectionCount, DataDirectoryHead[i].VirtualAddress);
}



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;
}

免费评分

参与人数 3吾爱币 +9 热心值 +3 收起 理由
Hmily + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
vip11699 + 1 + 1 谢谢@Thanks!
0xdada + 1 + 1 谢谢@Thanks!

查看全部评分

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

 楼主| appsion 发表于 2020-11-1 09:03
lthink 发表于 2020-10-31 16:48
学PE看看这套就行
https://www.52pojie.cn/forum.php?mod=viewthread&tid=1174321
节表定位方式严谨的写 ...

好的谢谢, 先做记录以后更新
lthink 发表于 2020-10-31 16:48
学PE看看这套就行
https://www.52pojie.cn/forum.php?mod=viewthread&tid=1174321
节表定位方式严谨的写法是选项头地址+选项头的大小,视频中都有详细说明

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
JFF + 1 + 1 热心回复!

查看全部评分

0xdada 发表于 2020-10-31 17:14
感谢大佬,水滴逆向的课的作业一直做不出来,一来就是好东西
头像被屏蔽
KatharsisKing 发表于 2020-11-1 08:23
提示: 作者被禁止或删除 内容自动屏蔽
cptw 发表于 2020-11-1 09:08
谢谢分享,
winooxx 发表于 2020-11-1 14:08
感谢楼主的分享!
平凡的无序 发表于 2020-11-1 15:26
看看,学习一下
归来仍是英雄 发表于 2020-11-1 19:31
感谢大佬分享,
iijjjyonu 发表于 2020-11-2 10:29
谢了,有空慢慢看下
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-12-26 13:54

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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