WindowsPE文件格式入门01.PE头
https://www.bpsend.net/thread-288-1-2.html
portable excute 可移植,可执行的文件(exe dll)
能够解析的文件,其内部都是有格式的,不是随随便便放的,都是按照某种规律放的,可执行文件也是如此,他有自己的格式,exe 和 dll 的格式是一样的
微软由dos 到 windows 文件格式发生了改变,所以要出新的文件格式,因此微软要求文件要兼容 dos 系统,其次要兼容其他的所有操作系统
IMAGE_FILE_MACHINE_AM33 希望兼容所有的cpu
因此PE的文件格式里面有很多字段时 windows 系统用不到的,有些是给已经被淘汰的 dos系统用的,还有一些是给其他系统用的,所以不是每个字段都非常有用,我们只需要关注在 windows 上的用的,即windows会检查的一些字段
PE头
IMAGE_DOS_HEADER IMAGE_NT_HEADERS IMAGE_FILE_HEADER IMAGE_OPTIONAL_HEADER IMAGE_DATA_DIRECTORY[1] //柔性数组 IMAGE_SECTION_HEADER[] //描述整个数据.解析这个表可以拿到所有数据
用于解析的PE文件

PE文件代码
.586
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
.data
g_szText db "pe for pe teach",0
g_szCaption db "tiptip",0
.code
start:
invoke MessageBox, NULL, offset g_szText, offset g_szCaption, MB_OK
invoke ExitProcess,eax
end start

我们自己编译
ml /c /coff pe.asm
link /subsystem:windows pe.obj

在winhex查看

此时可以发现0很多,这是因为文件生成的时候有对齐值我们可以通过修改对齐值来修改其大小




还可以更小,就是把数据节合并(因为数据段里面也存在对齐)



继续合并


此时已经达到了编译器的最小大小了
DOS头 IMAGE_DOS_HEADER: 00000000--0000003F
IMAGE_DOS_HEADER 结构体
// DOS头结构体: _IMAE_DOS_HEADER
typedef struct _IMAE_DOS_HEADER { //DOS .EXE header 偏移
WORD e_magic; //幻数 Magic number; 0x00
// 中间部分成员是为了兼容16位操作系统...可修改可忽略...
LONG e_lfanew; //File address of new exe header 0x3C
} IMAGE_DOS-HEADER, *PIMAGE_DOS_HEADER;

该结构体中两个重要字段(不可更改),分别是 e_magic,和 e_lfanew字段:
第一个字段 e_magic:该字段WORD类型,2字节 ,存储字符是“MZ”,对应PE文件的开头,是PE文件的标识符。该标识符在Winnt.h头文件中有一个宏定义,定义如下所示:
#define IMAGE_DOS_SIGNATURE 0x4D5A // MZ
#define IMAGE_OS2_SIGNATURE 0x4E45 // NE
#define IMAGE_OS2_SIGNATURE_LE 0x4C45 // LE最后一个字段 e_lfanew:该字段LONG类型,4字节,对应PE文件的0x3C处 :表示NT头在文件中的偏移,即32位及以上系统文件头在文件中真正的偏移,这个值可以修改,但是修改的话要把整个IMAGE_NT_HEADERS 结构体移到 该值对应的偏移值处
IMAGE_DOS_HEADER 到 IMAGE_NT_HEADERS 中间有一部分数据 叫做 stub code 也叫残留代码,残留数据,这个里面是跑在16位 dos系统里面的代码,起一个提示作用

NT头 IMAGE_NT_HEADERS
偏移值 : IMAGE_DOS_HEADER 中e_lfanew值 -- IMAGE_DOS_HEADER 中e_lfanew值 + 0x98
IMAGE_NT_HEADERS 结构体
// NT头结构体: _IMAGE_NT_HEADERS
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature; // 签名 32位文件格式的头部标识,不可修改
IMAGE_FILE_HEADER FileHeader; // 文件头
IMAGE_OPTIONAL_HEADER32 OptionalHeader; // 选项头
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
DWORD Signature
- 宏定义: #define IMAGE_NT_SIGNATURE 0x50450000 // PE00

文件头 IMAGE_FILE_HEADER:描述磁盘上PE文件的相关信息。
- 重要字段不可修改:
// 文件头结构体 20B: _IMAGE_FILE_HEADER
typedef struct _IMAGE_FILE_HEADER {
WORD Machine; // 表示CPU平台,不可修改:
// 32位IMAGE_FILE_MACHINE_I386, 0x014c
// 64位IMAGE_FILE_MACHINE_AMD64, 0x8664
WORD NumberOfSections; // 表示节表数量,用于遍历节表,判断从PE中拷贝什么数据到内存中:
//.text/.rdata/.data...每个2行半
// 遍历节表经验:根据此处的个数拿对应的节表数据
DWORD TimeDateStamp; // 时间戳:链接器填写的文件生成的时间,作用不大(可修改)
DWORD PointerToSymbolTable; // 符号表位置(无用)
DWORD NumberOfSymbols; // 符号表个数:windows的符号表信息一般由PDB放置在文件后端(无用)
WORD SizeOfOptionalHeader; // 选项头大小:用于定位节表位置=选项头地址+选项头大小(不可随便修改)
WORD Characteristics; // 文件属性,指应用程序是一个什么程序(不可随便修改)
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;重要字段:7.DWORD AddressOfEntryPoint;10.DWORD ImageBase
IMAGE_OPTIONAL_HEADER 结构体
typedef struct _IMAGE_OPTIONAL_HEADER {
WORD Magic; // 32位PE: IMAGE_NT_OPTIONAL_HDR32_MAGIC , 0x10b.
// 以 _IMAGE_OPTIONAL_HEADER 结构体解析
// 64位PE: IMAGE_NT_OPTIONAL_HDR64_MAGIC , 0x20b.
// 以 _IMAGE_OPTIONAL_HEADER64 结构体解析
BYTE MajorLinkerVersion; // 主链接器版本号 (无用)
BYTE MinorLinkerVersion; // 副链接器版本号 (无用)
//系统分配内存不看着3个值,但是对于调试器有影响(影响反汇编所用内存大小,OD是机器码个数*2,字节数是通过SizeOfCode 得到)
DWORD SizeOfCode; // 代码所占空间大小 (没啥用)
DWORD SizeOfInitializedData; // 已初始化数据所占空间大小 (没啥用)
DWORD SizeOfUninitializedData;// 未初始化数据所占空间大小 (没啥用)
DWORD AddressOfEntryPoint; // *oep:原本的程序入口点(实际为偏移,+模块基址=实际入口点)
// ep: 被加工后的入口点
//这个值可以修改,但是修改过后必须跳转到在该偏移处跳转到真正入口
DWORD BaseOfCode; // 代码基址 (无用)
DWORD BaseOfData; // 数据基址 (无用)
DWORD ImageBase; // *建议装载地址:exe映射加载到内存中的首地址= PE 0处,即实例句柄hInstance
// 一般而言,exe文件可遵从装载地址建议,但dll文件无法满足
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
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;选项头 IMAGE_OPTIONAL_HEADER:以供操作系统加载PE文件使用,32位必选。
- 1.WORD Machine; 2.WORD NumberOfSections;
- 6.WORD SizeOfOptionalHeader; 7.WORD Characteristics.
AddressOfEntryPoint EP
OEP 程序入口点 - Old Entry Point
如果 EP 没有被修改的话 OEP = EP ,但是很多时候为了隐藏程序入口点 通常会修改 EP 的值
例如 原本 AddressOfEntryPoint 的值为1000 可以改成 1100 ,那么模块基址 + 1100 的地方就成了程序入口点 再到 该地址 执行跳转指令 ,可以挑战转到 偏移 为 1000 处或者 跳转到其他地方在跳回 偏移 1000处
CC表示不重要的无用数据

作业
WindowsPE文件格式入门01.PE头的更多相关文章
- PE文件格式学习之PE头移位
以前刚开始学网络安全,是从免杀开始的.记得那时候杀毒软件还很弱.金山江民瑞星还存在. 那会什么原理也不懂,就一直瞎鼓捣.(后来转入渗透行列了) 这段时间一直在学PE格式,突然想起来以前很古老的PE文件 ...
- 【网络爬虫入门01】应用Requests和BeautifulSoup联手打造的第一条网络爬虫
[网络爬虫入门01]应用Requests和BeautifulSoup联手打造的第一条网络爬虫 广东职业技术学院 欧浩源 2017-10-14 1.引言 在数据量爆发式增长的大数据时代,网络与用户的沟 ...
- Windows Pe 第三章 PE头文件(下)
3.5 数据结构字段详解 3.5.1 PE头IMAGE_NT_HEADER的字段 1.IMAGE_NT_HEADER.Signature +0000h,双字.PE文件标识,被定义为00004550 ...
- Windows Pe 第三章 PE头文件(中)
这一章的上半部分大体介绍了下PE文件头,下半部分是详细介绍里面的内容,这一章一定要多读几遍,好好记记基础概念和知识,方便之后的学习. 简单回忆一下: 3.4 PE文件头部解析 3.4.1 DOS M ...
- Windows Pe 第三章 PE头文件(上)
第三章 PE头文件 本章是全书重点,所以要好好理解,概念比较多,但是非常重要. PE头文件记录了PE文件中所有的数据的组织方式,它类似于一本书的目录,通过目录我们可以快速定位到某个具体的章节:通过P ...
- PE文件学习系列三-PE头详解
合肥程序员群:49313181. 合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入) Q Q:408365330 E-Mail:egojit@qq.com 最近比较忙 ...
- PE头的应用---插入代码到EXE或DLL文件中
三.代码实现(DELPHI版本),采用第三种方式实现代码插入. 1. 定义两个类,一个用来实现在内存中建立输入表:一个用来实现对PE头的代码插入. DelphiCode: const MAX_SECT ...
- 不用搭环境的10分钟AngularJS指令简易入门01(含例子)
不用搭环境的10分钟AngularJS指令简易入门01(含例子) `#不用搭环境系列AngularJS教程01,前端新手也可以轻松入坑~阅读本文大概需要10分钟~` AngularJS的指令是一大特色 ...
- 【爬虫入门01】我第一只由Reuests和BeautifulSoup4供养的Spider
[爬虫入门01]我第一只由Reuests和BeautifulSoup4供养的Spider 广东职业技术学院 欧浩源 1.引言 网络爬虫可以完成传统搜索引擎不能做的事情,利用爬虫程序在网络上取得数据 ...
- JavaScript基础入门 - 01
JavaScript入门 - 01 准备工作 在正式的学习JavaScript之前,我们先来学习一些小工具,帮助我们更好的学习和理解后面的内容. js代码位置 首先是如何编写JavaScript代码, ...
随机推荐
- P5355 [Ynoi Easy Round 2017] 由乃的玉米田
莫队 + bitset + 根号分支 乘法似乎是简单的,我们可以直接莫队扫描然后枚举较小数 时间 \((n + m) \sqrt n\). 加法是一个经典 idea, 莫队套 bitset,然后利用 ...
- csharp入门经典
C#简介 .NET Framework是Microsoft为开发应用程序而创建的一个具有革命意义的平台,它有运行在其他操作系统上的版本 .NET Framework的设计方式确保它可以用于各种语言,包 ...
- deepseek:封装一个axios
封装一个包含上传和下载文件功能的 axios 实例,可以提高代码的复用性和可维护性.以下是一个完整的封装示例,支持文件上传.下载.以及常规的 GET/POST 请求. 封装代码 import axio ...
- xss学习及xss-lab解题记录
什么是XSS(跨站脚本攻击) SQL注入是服务端将用户输入的数据当成SQL代码去执行 XSS可以理解为服务端把用户输入的数据当成前端代码去执行 前端代码->主要是js代码 两个关键条件: 第一个 ...
- 质数测试——Fermat素数测试和MillerRabin素数测试
质数测试 今天我来填坑了,之前我在数学基础算法--质数篇这篇文章中提到我要单独讲一下MillerRabin算法,最近已经有许多粉丝在催了,所以我马不停蹄的来出这篇文章了,顺便把Fermat素数测试也讲 ...
- docker Get "https://registry-1.docker.io/v2/": x509: certificate is valid for
前言 docker 在进行 build 时,报错:Get "https://registry-1.docker.io/v2/": x509: certificate is vali ...
- 手把手教你下载b站视频并生成音频字幕
1.下载b站视频: 可以直接使用https://bilibili.iiilab.com/ 贴进去网址就能下载了 2.提取音频 可以使用 ffmpeg 将音频文件提取出来(ffmpeg直接去官网下载即可 ...
- 本地项目上传到gitee
前置条件:本地已经装好了GIt和GITEE有远程地址 检查本地装好了GIT:鼠标右键 检查准备好了远程:地址 本地项目拷贝到目录 D:\tmp2024-02-19\code 本地项目所在文件夹打开gi ...
- 密码加密|jsencrypt|md5|加密解密的两种方式
一.md5 npm install md5 二.JSEncrypt 2.1 介绍 JSEncrypt属于RSA加密,RSA加密算法是一种非对称加密算法: 2.2 使用 安装: npm install ...
- [每日算法 - 华为机试] LeetCode1160. 拼写单词
题目入口 力扣https://leetcode.cn/problems/find-words-that-can-be-formed-by-characters/ 题目概述 给你一份『词汇表』(字符串数 ...