逆向学习-PE文件格式
从DOS头到节区头是PE头部分,其下的节区合称PE体。文件中使用偏移(offset),内存中使用VA(Virtual Address,虚拟地址)来表示位置。文件加载到内存时,情况就会发生变化(节区的大小、位置等)。文件的内容一般可分为代码(.text)、数据(.data)、资源(,rsrc)节,分别保存。
VA指的是进程虚拟内存的绝对地址,RVA(Relative Virtuall Address,相对虚拟地址)指从某个基准位置(ImageBase)开始的相对地址。
VA与RVA满足:RVA+ImageBase=VA PE头内部信息大多以RVA形式存在。
DOS头
IMAGE_DOS_HEADER结构体大小为64字节。
其中有2个重要成员:e_magic与e_lfanew。(分别在结构体的开头和结尾)
e_magic: DOS签名(signature, 4D5A=>ASCII值“MZ”)
e_lfanew: 指示NT头的偏移(根据不同文件拥有可变值)。
NT头
IMAGE_NT_HEADERS结构体由3个成员组成,第一个成员为签名(Signature)结构体,其值为50450000h(“PE”00)。另外两个成员分别为文件头(File Header)与可选头(Optional Header)结构体。IMAGE_NT_HEADERS结构体的大小为F8。
文件头
typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
IMAGE_FILE_HEADER结构体有4种重要成员。
1.Machine,每个cpu都有唯一的Machine码。
2.NumberOfSections 用来指出文件中存在的节区数量,要与实际节区数相同。
3.SizeOfOptionalHeader 用来指出IMAGE_OPTIONAL_HEADER32结构体的长度。(32位和64位是不同的)
4.Characteristics 用于标识文件的属性,文件是否是可运行的形态、是否为DLL文件等信息,以bit OR形式组合起来。 0x0002代表可执行文件,0x2000代表DLL文件。
可选头
typedef struct _IMAGE_OPTIONAL_HEADER {
WORD Magic; 10B 32位PE 20B 64位PE 107 ROM映像
BYTE MajorLinkerVersion; 链接器版本号
BYTE MinorLinkerVersion; 链接器副版本号
DWORD SizeOfCode; 所有代码节的总和 该大小是基于文件对齐后的大小
DWORD SizeOfInitializedData; 所有含已初始化数据的节的总大小
DWORD SizeOfUninitializedData; 所有含未初始化数据的节的大小
DWORD AddressOfEntryPoint; 程序执行入口RVA
DWORD BaseOfCode; 代码节的起始RVA
DWORD BaseOfData; 数据节的起始RVA
DWORD ImageBase; 程序的优先装载地址
DWORD SectionAlignment; 内存中节的对齐粒度
DWORD FileAlignment; 文件中节的对齐粒度
WORD MajorOperatingSystemVersion; 操作系统主版本号
WORD MinorOperatingSystemVersion; 操作系统副版本号
WORD MajorImageVersion; PE文件映像的版本号
WORD MinorImageVersion;
WORD MajorSubsystemVersion; 子系统的版本号
WORD MinorSubsystemVersion;
DWORD Win32VersionValue; 未用 必须设置0
DWORD SizeOfImage; 内存中整个PE文件的映像尺寸
DWORD SizeOfHeaders; 所有节表按照文件对齐粒度后的大小
DWORD CheckSum; 校验和
WORD Subsystem; 指定使用界面的子系统
WORD DllCharacteristics; DALL文件属性
DWORD SizeOfStackReserve; 初始化时保留的栈的大小
DWORD SizeOfStackCommit; 初始化时实际提交的栈的大小
DWORD SizeOfHeapReserve; 初始化时保留的堆的大小
DWORD SizeOfHeapCommit; 初始化时实际提交的堆的大小
DWORD LoaderFlags; 加载标志 未用
DWORD NumberOfRvaAndSizes; 下面的数据目录结构的数量
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
重要成员
1.Magic 32位时,值为10B,64位时,值为20B。
2.AddressOfEntryPoint 持有EP的RVA值,指出程序最先执行的代码起始地址。
3.ImageBase 进程虚拟内存的范围是0~FFFFFFFF(32位)。ImageBase指出文件的优先装入地址。EXE、DLL文件被装载到用户内存的0~7FFFFFFF中,SYS加载到80000000~FFFFFFFF。一般而言,EXE的ImageBase的值为00400000,DLL文件的ImageBase的值为10000000.文件载入后的地址为ImageBase+AddressOfEntryPoint。
4.SectionAlignment,FileAlignment FileAlignment指定了节区在磁盘文件中的最小单位,SectionAlignment指定了节区在内存中的最小单位。磁盘文件或内存的节区大小必定为他们的值的整数倍。
5.SizeOfImage 指定了PE Image在虚拟内存中所占空间的大小。一般而言,文件的大小与加载到内存中的大小是不同的。
6.SizeOfHeader 指出整个PE头的大小。该值必须是FileAlignment的整数倍。第一节区所在位置与SizeHeaders距文件开始偏移的量相同。
7.Subsystem 区分系统驱动文件和普通的可执行文件。
8.NumberOfRvaAndSizes 用来指定DataDirectory数组的个数。
9.DataDirectory 是由IMAGE_DATA_DIRECTORY结构体组成的数组。
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 导出表
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 导入表
#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 资源目录
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 异常目录
#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 安全目录
#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 重定位基本表
#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 调试目录
#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 描术字串
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 机器值
#define IMAGE_DIRECTORY_ENTRY_TLS 9 TLS目录
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 载入配值目录
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 绑定输入表
#define IMAGE_DIRECTORY_ENTRY_IAT 12 导入地址表
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 延迟载入描述
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 COM信息
节区头
VirtualSize 内存中节区所占大小
VirtualAddress 内存中节区起始地址(RVA) 不带有任何值,由SectionAlignment确定
SizeOfRawData 磁盘文件中节区所占大小
PointerToRawData 磁盘文件中节区起始位置 不带有任何值,由FileAlignment确定
Characteristics 节区属性(bit OR)
RVA to RAW
RAW = RVA - VirtualAddress + PointerToRawData
IAT(Import Address Table,导入地址表)
IMAGE_IMPORT_DESCRIPTOR
记录着PE文件要导入哪些库文件。
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics;
DWORD OriginalFirstThunk; //INT(Import Name Table) address (RVA)
};
DWORD TimeDateStamp;
DWORD ForwarderChain;
DWORD Name; //library name string address (RVA)
DWORD FirstThunk; //IAT(Import Address Table) address (RVA)
} IMAGE_IMPORT_DESCRIPTOR;
typedef struct _IMAGE_IMPORT_BY_NAME {
WORD Hint; //ordinal
BYTE Name[1]; //function name string
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
重要成员:
OriginalFirstThunk INT的地址(RVA)
Name 库名称字符串的地址(RVA)
FirstThunk IAT的地址(RVA)
导入函数输入至IAT的顺序:
1.读取IID的Name成员,获取库名称字符串("kernel32.dll")
2.装载相应库——————> LoadLibrary("kernel32.dll")
3.读取IID的OriginalFirstThunk成员,获取INT地址
4.逐一读取INT中数组的值,获取相应IMAGE_IMPORT_BY_NAME地址(RVA)
5.使用IMAGE_IMPORT_BY_NAME的Hint(ordinal) 或Name项,获取相应函数的起始地址。 GetProcAddress("GetCurrentThreadId")
6.读取IID的FirstThunk(IAT)成员,获得IAT地址
7.将上面获得的函数地址输入相应IAT数组值。
8.重复以上补助4~7,直到INT结束(遇到NULL时)
EAT
IMAGE_EXPORT_DIRECTORY
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics; // 未使用,总为0 DWORD TimeDateStamp; // 文件创建时间戳
WORD MajorVersion; // 未使用,总为0 WORD MinorVersion; // 未使用,总为0
DWORD Name; // 指向一个代表此 DLL名字的 ASCII字符串的 RVA
DWORD Base; // 函数的起始序号
DWORD NumberOfFunctions; // 导出函数的总数 DWORD NumberOfNames; // 以名称方式导出的函数的总数 DWORD AddressOfFunctions; // 指向输出函数地址的RVA
DWORD AddressOfNames; // 指向输出函数名字的RVA
DWORD AddressOfNameOrdinals; // 指向输出函数序号的RVA} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
重要成员:
NumberOfFunctions 实际Export函数的个数
NumberOfNames Export中具名的函数个数
AddressOfFunctions Export函数地址数组
AddressOfName 函数名称地址数组
AddressOfNameOrdinals Ordinal地址数组
GetProcAddress()操作原理:
(1)利用AddressOfNames成员转到“函数名称数组”。
(2)“函数名称数组”中存储着字符串地址。通过比较字符串,查找指定的函数名称(此时数组的索引称为name_index)。
(3)利用AddressOfNameOrdinals成员,转到ordinal数组。
(4)在ordinal数组中通过name_index查找相应ordinal值。
(5)利用AddressOfFunctions成员转到“函数地址数字”(EAT)
(6)在“函数地址数组”中将刚刚求得的ordinal用作数组索引,获得指定函数的起始地址。
逆向学习-PE文件格式的更多相关文章
- C++PE文件格式解析类(轻松制作自己的PE文件解析器)
PE是Portable Executable File Format(可移植的运行体)简写,它是眼下Windows平台上的主流可运行文件格式. PE文件里包括的内容非常多,详细我就不在这解释了,有兴趣 ...
- PE文件格式详解,第二讲,NT头文件格式,以及文件头格式
PE文件格式详解,第二讲,NT头文件格式,以及文件头格式 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) PS:本篇博客 ...
- Reverse Core 第二部分 - 13章 - PE文件格式
@date: 2016/11/24 @author: dlive PE (portable executable) ,它是微软在Unix平台的COFF(Common Object File For ...
- PE文件格式偏移参考
在进行PE文件格式病毒分析的时候,经常要使用到PE文件格式的解析,尤其是对LoadPE形式的病毒的分析,经常要查看PE文件格式的偏移,特地从博客<PE文件格式的偏移参考>中转载收录一份,之 ...
- 深入理解 Win32 PE 文件格式
深入理解 Win32 PE 文件格式 Matt Pietrek 这篇文章假定你熟悉C++和Win32. 概述 理解可移植可执行文件格式(PE)可以更好地了解操作系统.如果你知道DLL和EXE中都有些什 ...
- 深入学习PE文件(转)
PE文件是Win32的原生文件格式.每一个Win32可执行文件都遵循PE文件格式.对PE文件格式的了解可以加深你对Win32系统的深入理解. 一. 基本结构. 上图便是PE文件的基本结构.(注意:DO ...
- PE文件格式分析
PE文件格式分析 PE 的意思是 Portable Executable(可移植的执行体).它是 Win32环境自身所带的执行文件格式.它的一些特性继承自Unix的Coff(common object ...
- 深入理解 Win32 PE 文件格式 Matt Pietrek(慢慢体会)
这篇文章假定你熟悉C++和Win32. 概述 理解可移植可执行文件格式(PE)可以更好地了解操作系统.如果你知道DLL和EXE中都有些什么东西,那么你就是一个知识渊博的程序员.这一系列文章的第一部分, ...
- PE文件格式详解(六)
0x00 前言 前面两篇讲到了输出表的内容以及涉及如何在hexWorkShop中找到输出表及输入DLL,感觉有几个地方还是没有理解好,比如由数据目录表DataDirectory[16]找到输出表表后以 ...
随机推荐
- 聊聊Unity2018的LWRP和混合光照
0x00 前言 在这篇文章中,我们选择了过去几周Unity官方社区交流群以及UUG社区群中比较有代表性的几个问题,总结在这里和大家进行分享.主要涵盖了** Scripting.Assetsbundle ...
- iOS开发之Masonry框架源码解析
Masonry是iOS在控件布局中经常使用的一个轻量级框架,Masonry让NSLayoutConstraint使用起来更为简洁.Masonry简化了NSLayoutConstraint的使用方式,让 ...
- Java基础——多线程(持续更新中)
如何建立一个执行路径呢? 通过查询API文档 java.lang.Thread类 该类的描述中有创建线程的两种方式 1.继承Thread类 (1).将类声明为 Thread 的子类 (2).该子类应重 ...
- python的进程与线程(一)
摘要: 源地址:https://www.cnblogs.com/yuanchenqi/articles/6248025.html 如有侵权,立即删除 操作系统 学习进程和线程的知识,先了解一下底层操作 ...
- cassandra 堆外内存管理
为什么需要堆外内存呢 单有一些大内存对象的时候,JVM进行垃圾回收时需要收集所有的这些对象的内存也.增加了GC压力.因此需要使用堆外内存. java 分配堆外内存 org.apache.cassand ...
- Identity Server 4 - Hybrid Flow - MVC客户端身份验证
预备知识 可能需要看一点点预备知识 OAuth 2.0 不完全简介: https://www.cnblogs.com/cgzl/p/9221488.html OpenID Connect 不完全简介: ...
- 【Java】几道让你拿offer的知识点
前言 只有光头才能变强 之前在刷博客的时候,发现一些写得比较好的博客都会默默收藏起来.最近在查阅补漏,有的知识点比较重要的,但是在之前的博客中还没有写到,于是趁着闲整理一下. 文本的知识点: Inte ...
- 【带着canvas去流浪(4)】绘制散点图
目录 一. 任务说明 二. 重点提示 三. 示例代码 四.散点hover交互效果的实现 4.1 基本算法 4.2 参考代码 4.3 Demo中的小问题 示例代码托管在:http://www.githu ...
- QT5.6.0 VS2013 Win764位系统QT环境搭建过程
QT5.6.0 VS2013 Win764位系统QT环境搭建过程 没用过QT自己跟同事要了安装包,按照同事指导方法操作安装部署开发环境结果遇到好多问题,错误网上搜遍了所有帖子也没有找到合适的解决方案. ...
- oracle非正常退出后重启实例
sqlplus /nolog 回车 conn / as sysdba 回车 startup 回车(如果被告知已启动,应先执行 shutdown immediate 回车)