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头的更多相关文章

  1. PE文件格式学习之PE头移位

    以前刚开始学网络安全,是从免杀开始的.记得那时候杀毒软件还很弱.金山江民瑞星还存在. 那会什么原理也不懂,就一直瞎鼓捣.(后来转入渗透行列了) 这段时间一直在学PE格式,突然想起来以前很古老的PE文件 ...

  2. 【网络爬虫入门01】应用Requests和BeautifulSoup联手打造的第一条网络爬虫

    [网络爬虫入门01]应用Requests和BeautifulSoup联手打造的第一条网络爬虫 广东职业技术学院 欧浩源 2017-10-14  1.引言 在数据量爆发式增长的大数据时代,网络与用户的沟 ...

  3. Windows Pe 第三章 PE头文件(下)

    3.5  数据结构字段详解 3.5.1  PE头IMAGE_NT_HEADER的字段 1.IMAGE_NT_HEADER.Signature +0000h,双字.PE文件标识,被定义为00004550 ...

  4. Windows Pe 第三章 PE头文件(中)

    这一章的上半部分大体介绍了下PE文件头,下半部分是详细介绍里面的内容,这一章一定要多读几遍,好好记记基础概念和知识,方便之后的学习. 简单回忆一下: 3.4  PE文件头部解析 3.4.1 DOS M ...

  5. Windows Pe 第三章 PE头文件(上)

    第三章  PE头文件 本章是全书重点,所以要好好理解,概念比较多,但是非常重要. PE头文件记录了PE文件中所有的数据的组织方式,它类似于一本书的目录,通过目录我们可以快速定位到某个具体的章节:通过P ...

  6. PE文件学习系列三-PE头详解

    合肥程序员群:49313181.    合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入) Q  Q:408365330     E-Mail:egojit@qq.com 最近比较忙 ...

  7. PE头的应用---插入代码到EXE或DLL文件中

    三.代码实现(DELPHI版本),采用第三种方式实现代码插入. 1. 定义两个类,一个用来实现在内存中建立输入表:一个用来实现对PE头的代码插入. DelphiCode: const MAX_SECT ...

  8. 不用搭环境的10分钟AngularJS指令简易入门01(含例子)

    不用搭环境的10分钟AngularJS指令简易入门01(含例子) `#不用搭环境系列AngularJS教程01,前端新手也可以轻松入坑~阅读本文大概需要10分钟~` AngularJS的指令是一大特色 ...

  9. 【爬虫入门01】我第一只由Reuests和BeautifulSoup4供养的Spider

    [爬虫入门01]我第一只由Reuests和BeautifulSoup4供养的Spider 广东职业技术学院  欧浩源 1.引言  网络爬虫可以完成传统搜索引擎不能做的事情,利用爬虫程序在网络上取得数据 ...

  10. JavaScript基础入门 - 01

    JavaScript入门 - 01 准备工作 在正式的学习JavaScript之前,我们先来学习一些小工具,帮助我们更好的学习和理解后面的内容. js代码位置 首先是如何编写JavaScript代码, ...

随机推荐

  1. 目标检测 | Spatially Sparse Convolution

    Spatially Sparse Convolution 导言 为什么需要稀疏化? 在3D表示中,除了点云(Point Cloud)和网格模型(Mesh),我们常常还会使用到一种称为体素(Voxel) ...

  2. CF2018C Tree Pruning

    分析 好像官方题解是反向求解的,这里提供一个正向求解的思路,即直接求出最后所有叶节点到根的距离相同为 \(x\) 时需要删除的结点数 \(ans_x\) . 如果我们最后到根的相同距离为 \(x\), ...

  3. python实现监控站点目录,记录每天更新内容,并写入操作日志,以便查找病毒恶意修改

    问题描述:站点需要追溯代码的修改时间,以便尽早发现病毒恶意修改迹象,及时处理 运行环境:linux服务器,宝塔面板 示例代码:一.读取txt的文件路径,依次遍历所有目录下面的文件,并记录文件信息 pa ...

  4. 复杂任务分解:Tree of Thought

    像搭乐高一样玩转AI思考 今天要带大家解锁一个让AI从"单细胞生物"进化成"八爪鱼思考者"的神技--Tree of Thought(思维树).准备好了吗?我们要 ...

  5. 自己修改的一款Typora学术主题Academic-zh-vq

    这款typora主题是在Academic-Zh主题的基础上修改而来的. 主题衍生路径: 官方Academic主题-->zh-academic主题-->Academic-Zh主题--> ...

  6. vue2打包部署到nginx,解决路由history模式下页面空白问题

    项目使用的是vue2,脚手架vue-cli 4. 需求:之前项目路由使用的是hash,现在要求调整为history模式,但是整个过程非常坎坷,遇到了页面空白问题.现在就具体讲一下这个问题. 首先,直接 ...

  7. golng切片实现分页

    前言 实现切片分页,主要是根据选择页码和每页显示数量,计算了切片的开始.结束索引地址 package main import "math" func main() { slice1 ...

  8. vue学习一(指令3.v-on,v-for)

    3.1.v-on 绑定事件  可以简写为@ ,按键修饰符    v-on:keyup    =    @keyup 事件修饰符:v-on提供了事件修饰符 修饰符是由点开头的指令后缀来表示的       ...

  9. Pydantic多态模型:用鉴别器构建类型安全的API接口

    title: Pydantic多态模型:用鉴别器构建类型安全的API接口 date: 2025/3/20 updated: 2025/3/20 author: cmdragon excerpt: Py ...

  10. 从零开始开发一个 MCP Server!

    大家好!我是韩老师. 最近,在 AI 开发领域,MCP (Model Context Protocol) 是越来越火了! 前几天,我我也开发了一款 Code Runner MCP Server: Co ...