百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

WindowsPE文件格式入门01.PE头(pe文件是啥)

cac55 2025-04-05 17:09 36 浏览 0 评论

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表示不重要的无用数据

作业

相关推荐

unetbootin中文版:能够将Linux系统装进U盘的U盘启动盘制作工具

unetbootin中文版是一款能够将Linux操作系统装进U盘或移动硬盘的U盘启动盘制作工具,制作好的U盘启动盘能够用于电脑的维护和系统还原等操作,使用起来非常地不错。该软件不会基于操作系统使用特定...

实用之选,实用之改:DELL 戴尔 灵越14CR-4528B 小改作业

昨天发布了一篇三脚架,今天有时间也写写早就准备写的DELL戴尔灵越14CR-4528B作业吧。话说上个笔记本还是2006年底买的华硕A6JE,电脑挺不错的,在家上上网也够用了,就是转轴设计缺陷,容...

教你如何制作一个启动U盘,从此电脑不用找专人做系统

在电脑使用中,老是遇到卡顿,蓝屏,重启等很多故障,大多都是因为自己日常使用习惯而造成的,很多用户在下载软件的时候不知不觉中都被安装许多乱七八糟的软件,当电脑乱七八糟的东西过多的时候我们就重新来装一个系...

8、Deepin操作系统启动盘(系统盘)制作

1、在Deepin官网https://www.deepin.org/zh/download/下载原版Deepin操作系统2、同时在Deepin官网https://www.deepin.org/zh/d...

电脑死机怎么办,电脑如何使用U盘重装系统

电脑死机是我们最常遇到的系统故障,遇到死机时通常重启就可以解决,不过系统损坏引起的死机就只能重装系统,那么电脑死机如何重装系统呢?下面来看看电脑死机怎么办如何使用U盘重装系统_小白一键重装系统官网。 ...

bootmgr is compressed无法启动系统

bootmgriscompressedPressCtrlAltDeltorestart,电脑启动后无法正常开机出现了这样的字样,就是说明你的C盘驱动被压缩解决方法:1、使用系统光盘或者...

新手教程!如何分辨BIOS启动列表(菜单)中的各种启动项

在BIOS启动菜单中识别各类启动项,是新手安装系统或调整启动顺序的必备技能。下面用最直观的方式,为你梳理常见启动项及其含义,帮助你快速上手:一、传统存储设备启动项1.Floppy(软盘驱动器)对应...

带回家的MINI客厅电脑,自学成才,分享U盘装系统教程

刚好老家新装修了房子,客厅买了个大电视,本来是想在客厅弄台主机,接电视玩,大屏幕玩的才爽,但是台式机箱太占地方了。网上逛了一圈,发现有专门的客厅电脑,就搞了一个,外形不错,放客厅很有档次,主要是主机太...

电脑基础知识:BIOS简介及其与Windows操作系统的关系

什么是BIOS?BIOS,全称BasicInputOutputSystem,即“基本输入输出系统”,是一段固化在电脑主板芯片上的底层固件程序。它类似于一款极简化的操作系统,负责电脑开机时的硬件初...

win 7 系统注册表文件丢失或损坏,求不重做系统的解决办法!

粉丝问题解答:win7系统注册表文件丢失或损坏,求不重做系统的解决办法!解决方法:你只需要有启动盘即可,不需要其他的。之所以要求启动盘,是因为下面要对系统文件进行还原覆盖,所以不能用原系统启动。用...

UEFI怎么装Win7 小编呕血解难点!

自从广开言路之后,小编就被你们害苦了,这不,一条评论又让小编彻夜难眠。另外某些小伙伴坐不上沙发后提出要上墙的需求,其实呢只要大家提出的问题具有普遍性、有难度、而且适合小编做微信内容的话,都有机会将你们...

固态攻坚战——ASUS 华硕k45v换固态、拆机清灰教程

作者:蘑菇爱上我现在固态白菜价固态对于电脑体验的提升还是很大的对于固态存储芯片的问题没什么好说的有钱mlc,没钱tlc,不需要考虑什么寿命的问题,我用了一年多的m600,写入才3TB品牌很重要,主控...

MBR启动报错?Win10不重装一样能好!

Win10一遇到启动故障,很多小伙伴可能就会抓瞎,这可怎么弄,我不会修复啊!其实大可不必惊慌,就像这种最常见的Winload启动错误,多半都是MBR分区表丢失造成的(UEFI分区模式的几乎没有这种故障...

从零开始:硬盘手动装系统全攻略

手动安装操作系统是计算机技术必备的基本技能。对于初学者来说,可能会感到有些挑战。但通过掌握硬盘手动装系统方法,你可以亲身体验整个安装过程,进而更好地理解操作系统的工作原理。本文将详细介绍硬盘手动装系统...

电脑开机后显示File:BCD错误0xc000000f

WIN7\WIN8\WIN101、一个win864位PE。这个64位PE的相关文件,路径在boot\BOOT.WIM实机测试,开机后显示File:\EFI\Microsoft\Boot\BCD,...

取消回复欢迎 发表评论: