PE文件格式基础

2025-8-24 95 8/24

PE文件格式基础

总览

  • PE文件结构:

    核心 [DOS头部→NT头部→节表→各个节],重点关注NT头部(控制程序执行)、节表(载荷隐藏关键)、导入表(免杀篡改核心)

    将PE文件当作一本书,而每一本书中都包含了不同的数据

  • PE Bear工具:

    轻量PE分析工具,核心用途是快速查看PE结构、节信息、导入导出表、验证载荷隐藏是否成功、免杀篡改是否生效

  • EXE和DLL的区别:

    本质 [是否可独立执行],重点关注DLL的“无入口独立加载”特性(适配DLL注入、DLL后门),以及两者在节表、导入表上的细微差异。

  • PE编译流程:

    核心 [源码→编译→汇编→链接],重点关注“链接阶段”(控制导入表生成、节表命名/属性),通过修改编译/链接参数,规避杀软对PE特征的检测。

  • 关联:PE结构是载荷隐藏、导入表篡改、无导入表PE构建的基础;EXE/DLL差异决定注入/后门的方式;编译流程优化是入门级免杀的关键一步

学习内容

模块1:PE文件格式核心认知

  • 1.1 什么是PE文件

    Windows可识别、能运行的"可执行文件",如常见的.exe,.dll

    PE文件的结构决定了它能否绕过杀软检测

  • 1.2 PE文件整体结构拆解

    结构:DOS头→NT头→节表→各个节

  • 1.3 核心结构作用

    1、DOS头:PE结构最前面的"伪装头",早期为了兼容DOS系统,现在基本没用。红队利用点,修改DOS头字段,伪装成正常PE文件。核心字段:e_magic(标识是否为PE文件,固定为“MZ”)、e_lfanew(指向NT头的偏移量,找不到这个系统就认不出PE文件)

    2、NT头:PE文件的“大脑”,控制程序如何运行,包含文件头(IMAGE_FILE_HEADER)和可选头(IMAGE_OPTIONAL_HEADER)

    • 文件头:核心字段---Machine(目标CPU框架,32/64位)、NumberOfSections(节的数量,可增加节来隐藏载荷)、TimeDateStamp(时间戳,修改可规避针对“新建/新落地PE文件”的检测)

    • 可选头:核心字段---AddressOfEntryPoit(程序入口点,可修改入口点让程序先执行恶意载荷再执行正常代码)、ImageBase(程序加载到内存的基地址,注入时要用到)、SectionAlignment(内存中节的对齐方式)、FileAlignment(磁盘中节的对齐方式)、DataDirectory(数据目录,包含导入表、导出表的偏移量,篡改导入表必须改这)

    3、节表:PE文件的“目录”,记录了每个节的名称、大小、在磁盘/内存中的位置、属性(可读/写/执行)。红队利用点,通过节表控制每个节的属性,如把载荷藏在自定义节中,设置合理属性规避免杀;修改节名称,如把恶意节伪装成".text"".data",假装是正常代码/数据节。

    4、各个节:PE文件的“身体”,存放具体内容。重点关注三个常用节以及自定义节。

    • .text节:存放程序核心代码,属性默认“可读可执行”,杀软重点检测区

    • .dara节:存放程序的数据(变量、常量),属性默认“可读可写”,可将Shellcode藏这里,杀软对数据节的检测相对宽松

    • .rsrc节:存放程序资源(图标、字符串、对话框),属性默认“可读”,可将Shellcode加密后藏这里,运行时再解密提取。

    • 自定义节:可通过编译链接,新增一个自定义节(如".payload"),专门放恶意载荷,设置属性"可读可写可执行"

  • 1.4 导入表和导出表

    导入表(IAT)是PE文件的"依赖清单",记录着程序运行需要调用的Windows API,杀软常检测PE文件导入的API组合(如导入CreateRemoteThread、WriteProcessMemory,就是注入的典型特征),可通过"篡改导入表" "构建无导入表PE"来进行规避

    导出表(EAT)是PR文件对外提供的"接口清单",主要用于DLL文件,EXE很少用;

  • 1.5 红队视角:PE结构与免杀、载荷隐藏的关联

模块2:PE Bear工具实操

  • 2.1 工具安装与基础界面

    Releases · hasherezade/pe-bear

  • 2.2 核心实操1:查看PE整体结构(快速定位NT头部、节表、导入导出表)

    PE文件格式基础

DOS Header(DOS 头部)

DOS stub(DOS 存根):一段 16 位的 DOS 程序,在现代 Windows 中基本不执行,仅用于兼容。

NT Headers(NT 头部):PE 文件的核心控制区

  • Signature:固定为 PE\0\0(0x50450000),标识这是一个 NT 可执行文件。

  • File Header(文件头):

    包含架构(Machine)、节数量(NumberOfSections)、时间戳(TimeDateStamp)等。红队重点:修改 TimeDateStamp 可规避 “新建文件” 检测;NumberOfSections 可用于判断是否有新增的隐藏节。

  • Optional Header(可选头):

    包含入口点(AddressOfEntryPoint)、镜像基址(ImageBase)、数据目录(DataDirectory)等。

    红队重点:AddressOfEntryPoint 是修改程序执行流程的关键;DataDirectory 指向导入表、导出表等核心数据结构。

  • 2.3 核心实操2:分析节信息(节名称、大小、属性,判断载荷隐藏位置是否合理)

    Shellcode写入.date区段,未写入前原始地址2400,原始大小200,写入后原始地址2400,原始大小400,区段增大写入Shellcode成功

  • 2.4 红队实操:用PE Bear验证“载荷隐藏效果”

    PE Bear只用于“分析和验证”,不能修改PE文件;实战中,先用PE Bear分析正常PE文件的结构特征(比如正常EXE的节名称、导入API),再按照这个特征修改恶意PE文件,伪装成正常文件,提升免杀率。

模块3:EXE与DLL的本质区别

  • 3.1 直观差异:能否独立运行

    EXE可以,双击就能运行 ,有独立入口点(EntryPoint),运行时直接执行入口代码

    DLL不可以,必须被其他EXE/DLL加载才能运行,无独立入口点,入口是DllMain(被加载时触发)

  • 3.2 结构差异:头部、节表、导入表的细微不同

  • 3.3 红队应用场景:EXE用于独立远控/Loader,DLL用于注入/后门

  • 3.4 实操对比:用PE Bear查看同一源码生成的EXE与DLL,标注差异点

模块4:PE编译与链接全过程

  • 4.1 编译核心流程拆解(源码→预编译→汇编→目标文件→链接→PE文件)

  • 4.2 红队重点:链接阶段的关键配置(控制导入表、节表属性,基础免杀优化)

  • 4.3 实操演示:用VS/MinGW编译生成PE文件,修改链接参数规避基础检测

    1. 修改节名称:默认节名称是.text、.data、.rsrc,杀软对这些名称的特征很敏感,可修改为自定义名称(比如.text改成“.code”,.data改成“.dat”),但注意不要过于明显(比如不要改成“.payload”)。

      • VS操作:项目属性 → 链接器 → 命令行,添加参数:/SECTION:.code,ERW /SECTION:.dat,RW(修改节名称和属性)。

    2. 修改时间戳:PE文件的时间戳(NT头部中的TimeDateStamp)默认是编译时间,杀软会检测“新建PE文件+恶意特征”的组合,可修改时间戳为任意正常时间(比如系统文件的时间戳)。

    3. 隐藏导入表:通过链接参数,减少导入表中的API数量,或隐藏敏感API(比如注入相关的API),后续中级课程会讲“无导入表PE”,这里先掌握基础:减少不必要的API导入。

      • 删除源码中不必要的头文件和函数调用,避免导入多余的API(比如不需要界面,就不要导入user32.dll的API)。

    4. 控制节属性:将存放载荷的节,设置为“可读可写”(避免设置为“可读可写可执行”,过于明显),运行时再通过代码修改节属性为“可执行”

  • 4.4 红队避坑:编译参数错误导致的PE特征异常

      1. 编译架构要匹配:目标机是32位,就编译32位PE;是64位,就编译64位PE,否则无法运行(注入时会失败)。

      1. 不要使用默认编译参数:默认参数生成的PE文件,特征太明显,容易被杀软检测到,一定要修改节名称、时间戳等参数。

      1. 编译后用PE Bear验证:确认节名称、时间戳、导入表是否修改成功,避免参数设置错误导致PE文件异常。

额外

  1. Windows 系统(x86/x64 架构)采用「小端序(Little Endian)」存储数据

所谓的小端序就是多字节数据,低位字节存在内存低地址,高位字节存在内存高地址

比如一个 16 位的数值 0x5A4D(对应字符 MZ),拆成两个字节是:

  • 高位字节:0x5A(对应字母 Z)

  • 低位字节:0x4D(对应字母 M)

按小端序存储时,内存中会先存低位字节 0x4D,再存高位字节 0x5A → 所以你在十六进制视图里看到的是 4D 5A,但 PE-Bear 解析后显示的是 0x5A4D(完整数值)。

如果后续要手动构造PE文件字段要记住这样的小端序规则,按照低位字节先写入的顺序。

- THE END -
0

非特殊说明,本博所有文章均为博主原创。

共有 0 条评论