PE文件解析 基础篇
PE文件解析 基础篇
来源 https://bbs.pediy.com/thread-247114.htm
前言
- 之前学习了PE格式,为了更好的理解,决定写一个类似LoadPE的小工具。
- 编译器是VS2015,采用MFC框架。
- 此系列文章采用边介绍知识点,边写代码的形式,以免变的无聊丧失兴趣。
- PE知识请参照《加密与解密》第10章
PE文件格式
1.PE文件基本概念
- PE文件是windows系统中遵循PE结构的文件,比如以.exe .dll为后缀名的文件 以及系统驱动文件。(PE结构框架看下图)

- PE文件从磁盘当中像内存中的映射,不是简单的“1对1”的关系,而是“拉长”了。具体的位置表现在块。 但是磁盘上的数据结构与在内存中的结构是一致的。
- 无论PE文件在磁盘中还是在内存中,都少不了地址的概念,理解一下几个概念至关重要。
- 存了张图 比较好的解释了各部分的关系

|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
(最左边是文件头的偏移量。) IMAGE_DOS_HEADER STRUCT { +0h WORD e_magic // MZ(4Dh 5Ah) DOS可执行文件标记 +2h WORD e_cblp +4h WORD e_cp +6h WORD e_crlc +8h WORD e_cparhdr +0ah WORD e_minalloc +0ch WORD e_maxalloc +0eh WORD e_ss +10h WORD e_sp +12h WORD e_csum +14h WORD e_ip +16h WORD e_cs +18h WORD e_lfarlc +1ah WORD e_ovno +1ch WORD e_res[4] +24h WORD e_oemid +26h WORD e_oeminfo +29h WORD e_res2[10] +3ch DWORD e_lfanew // RVA 指向PE文件头 } IMAGE_DOS_HEADER ENDS |

3.PE文件头
|
1
2
3
4
5
6
|
IMAGE_NT_HEADERS STRUCT {+0h DWORD Signature +4h IMAGE_FILE_HEADER FileHeader +18h IMAGE_OPTIONAL_HEADER32 OptionalHeader } IMAGE_NT_HEADERS ENDS |
- Signature 字段
- IMAGE_FILE_HEADER 结构体
|
1
2
3
4
5
6
7
8
9
10
|
struct IMAGE_FILE_HEADER{ WORD Machine; //运行平台 WORD NumberOfSections; //区块表的个数 DWORD TimeDataStamp;//文件创建时间,是从1970年至今的秒数 DWORD PointerToSymbolicTable;//指向符号表的指针 DWORD NumberOfSymbols;//符号表的数目 WORD SizeOfOptionalHeader;//IMAGE_NT_HEADERS结构中OptionHeader成员的大小,对于win32平台这个值通常是0x00e0 WORD Characteristics;//文件的属性值} |

- IMAGE_OPTIONAL_HEADER 结构体
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
typedef struct _IMAGE_OPTIONAL_HEADER{ // // Standard fields. //+18h WORD Magic; // 标志字, ROM 映像(0107h),普通可执行文件(010Bh)+1Ah BYTE MajorLinkerVersion; // 链接程序的主版本号+1Bh BYTE MinorLinkerVersion; // 链接程序的次版本号+1Ch DWORD SizeOfCode; // 所有含代码的节的总大小+20h DWORD SizeOfInitializedData; // 所有含已初始化数据的节的总大小+24h DWORD SizeOfUninitializedData; // 所有含未初始化数据的节的大小+28h DWORD AddressOfEntryPoint; // 程序执行入口RVA+2Ch DWORD BaseOfCode; // 代码的区块的起始RVA+30h DWORD BaseOfData; // 数据的区块的起始RVA // // NT additional fields. 以下是属于NT结构增加的领域。 //+34h DWORD ImageBase; // 程序的首选装载地址+38h DWORD SectionAlignment; // 内存中的区块的对齐大小+3Ch DWORD FileAlignment; // 文件中的区块的对齐大小+40h WORD MajorOperatingSystemVersion; // 要求操作系统最低版本号的主版本号+42h WORD MinorOperatingSystemVersion; // 要求操作系统最低版本号的副版本号+44h WORD MajorImageVersion; // 可运行于操作系统的主版本号+46h WORD MinorImageVersion; // 可运行于操作系统的次版本号+48h WORD MajorSubsystemVersion; // 要求最低子系统版本的主版本号+4Ah WORD MinorSubsystemVersion; // 要求最低子系统版本的次版本号+4Ch DWORD Win32VersionValue; // 莫须有字段,不被病毒利用的话一般为0+50h DWORD SizeOfImage; // 映像装入内存后的总尺寸+54h DWORD SizeOfHeaders; // 所有头 + 区块表的尺寸大小+58h DWORD CheckSum; // 映像的校检和+5Ch WORD Subsystem; // 可执行文件期望的子系统+5Eh WORD DllCharacteristics; // DllMain()函数何时被调用,默认为 0+60h DWORD SizeOfStackReserve; // 初始化时的栈大小+64h DWORD SizeOfStackCommit; // 初始化时实际提交的栈大小+68h DWORD SizeOfHeapReserve; // 初始化时保留的堆大小+6Ch DWORD SizeOfHeapCommit; // 初始化时实际提交的堆大小+70h DWORD LoaderFlags; // 与调试有关,默认为 0 +74h DWORD NumberOfRvaAndSizes; // 下边数据目录的项数,这个字段自Windows NT 发布以来一直是16+78h IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; // 数据目录表} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; |
|
1
2
3
4
|
IMAGE_DATA_DIRECTORY STRUCT VirtualAddress DWORD ? ; 数据的起始RVA Size DWORD ? ; 数据块的长度IMAGE_DATA_DIRECTORY ENDS |

4.写代码操作一下
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
//打开文件m_hFile = CreateFile( m_DeleFileName,GENERIC_READ,NULL,NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,NULL);DWORD dwSize = GetFileSize(m_hFile, NULL);PBYTE pBuf = new BYTE[dwSize]{};//读取ReadFile(m_hFile,pBuf,dwSize,&dwSize,NULL);//判断是否为PE文件m_pDos = PIMAGE_DOS_HEADER(pBuf);if (m_pDos->e_magic!=IMAGE_DOS_SIGNATURE){ MessageBox(L"不是有效的PE文件 \n"); CloseHandle(m_hFile); m_hFile = NULL; return;}m_pNTHeader = PIMAGE_NT_HEADERS(pBuf+m_pDos->e_lfanew);if (m_pNTHeader->Signature!= IMAGE_NT_SIGNATURE){ MessageBox(L"不是有效的PE文件 \n"); CloseHandle(m_hFile); m_hFile = NULL; return;}//读取文件头信息m_pFileHeader = &(m_pNTHeader->FileHeader);m_NumberOfSections.Format(L"%X",m_pFileHeader->NumberOfSections);m_TimeDateStamp.Format(L"%p", m_pFileHeader->TimeDateStamp);m_SizeOfOptionalHeader.Format(L"%X", m_pFileHeader->SizeOfOptionalHeader);//拓展头信息m_pOptionalHeader = &(m_pNTHeader->OptionalHeader);m_AddressOfEntryPoint.Format(L"%X",m_pOptionalHeader->AddressOfEntryPoint);m_SizeOfHeaders.Format(L"%X", m_pOptionalHeader->SizeOfHeaders);m_ImageBase.Format(L"%X", m_pOptionalHeader->ImageBase);m_SizeOfImage.Format(L"%X", m_pOptionalHeader->ImageBase);m_BaseOfCode.Format(L"%X", m_pOptionalHeader->BaseOfCode);m_DllCharacteristics.Format(L"%X", m_pOptionalHeader->DllCharacteristics);m_BaseOfData.Format(L"%X", m_pOptionalHeader->BaseOfData);m_NumberOfRvaAndSizes.Format(L"%X", m_pOptionalHeader->NumberOfRvaAndSizes);m_SectionAlignment.Format(L"%X", m_pOptionalHeader->SectionAlignment);m_FileAlignment.Format(L"%X", m_pOptionalHeader->FileAlignment);m_CheckSum.Format(L"%X", m_pOptionalHeader->CheckSum);m_Magic.Format(L"%X", m_pOptionalHeader->CheckSum);m_Subsystem.Format(L"%X", m_pOptionalHeader->Subsystem); |

============== End
PE文件解析 基础篇的更多相关文章
- [系统安全] 十六.PE文件逆向基础知识(PE解析、PE编辑工具和PE修改)
[系统安全] 十六.PE文件逆向基础知识(PE解析.PE编辑工具和PE修改) 文章来源:https://masterxsec.github.io/2017/05/02/PE%E6%96%87%E4%B ...
- C++PE文件格式解析类(轻松制作自己的PE文件解析器)
PE是Portable Executable File Format(可移植的运行体)简写,它是眼下Windows平台上的主流可运行文件格式. PE文件里包括的内容非常多,详细我就不在这解释了,有兴趣 ...
- [WebKit内核] JavaScript引擎深度解析--基础篇(一)字节码生成及语法树的构建详情分析
[WebKit内核] JavaScript引擎深度解析--基础篇(一)字节码生成及语法树的构建详情分析 标签: webkit内核JavaScriptCore 2015-03-26 23:26 2285 ...
- [WebKit内核] JavaScriptCore深度解析--基础篇(一)字节码生成及语法树的构建
看到HorkeyChen写的文章<[WebKit] JavaScriptCore解析--基础篇(三)从脚本代码到JIT编译的代码实现>,写的很好,深受启发.想补充一些Horkey没有写到的 ...
- C语言读取写入CSV文件 [一]基础篇
本系列文章目录 [一] 基础篇 [二] 进阶篇--写入CSV [三] 进阶篇--读取CSV 什么是CSV? CSV 是一种以纯文本形式存储的表格数据,具体介绍如下(来自维基百科): 逗号分隔值(Com ...
- PE文件解析器的编写(二)——PE文件头的解析
之前在学习PE文件格式的时候,是通过自己查看各个结构,自己一步步计算各个成员在结构中的偏移,然后在计算出其在文件中的偏移,从而找到各个结构的值,但是在使用C语言编写这个工具的时候,就比这个方便的多,只 ...
- [WebKit] JavaScriptCore解析--基础篇 (一)JSC与WebCore
先看一下官方的基本介绍,短短几句就塞满了关键字. SquirrelFish,正式名称是JavaScriptCore,包括register-based(基于寄存器的虚拟机), direct-thread ...
- Python数据类型解析(基础篇)
Python语言的类型 数字类型 字符串类型 元组类型 列表类型 文件类型 字典类型 1.数字类型 Python有三种数字类型:整数,浮点数,复数 Python中的整 ...
- 3D游戏常用技巧Normal Mapping (法线贴图)原理解析——基础篇
http://www.cnblogs.com/wangchengfeng/p/3470310.html
随机推荐
- python 中的特殊方法,纠正自己笨笨的记忆
1. __new__ 和 __init__ 的区别 python 2.x 老式类(默认继承type) class A: pass 老式类中没有__new__类方法(也就是说定义也不会执行,它不是老式类 ...
- Qt-网易云音乐界面实现-4 实现推荐列表和我的音乐列表,重要在QListWidget美化
来标记下这次我么实现的部分 这次我们来是试下这部分功能,来对比一下,左边是原生,右面是我写的,按着模仿的海可以哈,就有有的资源不是一样了,因为我连抠图都懒得扣了了 好了,现在就是我的是先过程了,主要教 ...
- 对最近java基础学习的一次小结
开头想了3分钟,不知道起什么名字好,首先内容有点泛,但也都是基础知识. 对之前所学的java基础知识做了个小结,因为我是跟着网上找的黑马的基础视频看跟着学的,10天的课程硬生生给我看了这么久,也是佛了 ...
- 使用Xshell远程访问tensorboard
在使用tensorflow时,由于本地资源的限制,一般在远程服务器上训练模型,而服务器没有图形界面,那么在训练过程中如何实时地访问tensorboard可视化数据呢? 如果服务器和本地电脑连接在同一个 ...
- 网格系统-bootStrap4常用CSS笔记
.row 定义一行 .col 均分列数,最多一行12列.每列左右间隙各15px .col-{1到12} 定义在所有屏幕下的列宽 .col-{sm|md|lg|xl}-{1到12} 定义在指定屏幕下该列 ...
- Hyperledger Fabric服务器配置及修改Docker容器卷宗存储根目录/位置
Hyperledger Fabric节点服务器对存储空间的消耗还是比较大的,在我实际生产体验的过程中,每一条请求数据大概仅2K左右,但实际占用空间远不止这点,每个节点都会对Block及链进行保存维护, ...
- spring study
Dependency Injection The Inversion of Control(IoC) is a general concept, and it can be expressed in ...
- 前端_JQuery
使用参考:http://jquery.cuishifeng.cn/ 目录 jQuery是什么 jQuery对象 寻找元素(选择器和筛选器) 选择器 表单属性选择器 筛选器 操作元素(属性.css.文档 ...
- Django_rest_framework_Serializer
序列化Serializer 序列化用于对用户请求数据进行验证和数据进行序列化(为了解决queryset序列化问题). 那什么是序列化呢?序列化就是把对象转换成字符串,反序列化就是把字符串转换成对象 m ...
- Scrum立会报告+燃尽图(十二月五日总第三十六次):Final阶段分配任务
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2284 项目地址:https://git.coding.net/zhang ...
