总览
-
PE文件结构:
将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 工具安装与基础界面
-
2.2 核心实操1:查看PE整体结构(快速定位NT头部、节表、导入导出表)

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文件,修改链接参数规避基础检测
-
修改节名称:默认节名称是.text、.data、.rsrc,杀软对这些名称的特征很敏感,可修改为自定义名称(比如.text改成“.code”,.data改成“.dat”),但注意不要过于明显(比如不要改成“.payload”)。
-
VS操作:项目属性 → 链接器 → 命令行,添加参数:/SECTION:.code,ERW /SECTION:.dat,RW(修改节名称和属性)。
-
-
修改时间戳:PE文件的时间戳(NT头部中的TimeDateStamp)默认是编译时间,杀软会检测“新建PE文件+恶意特征”的组合,可修改时间戳为任意正常时间(比如系统文件的时间戳)。
-
隐藏导入表:通过链接参数,减少导入表中的API数量,或隐藏敏感API(比如注入相关的API),后续中级课程会讲“无导入表PE”,这里先掌握基础:减少不必要的API导入。
-
删除源码中不必要的头文件和函数调用,避免导入多余的API(比如不需要界面,就不要导入user32.dll的API)。
-
-
控制节属性:将存放载荷的节,设置为“可读可写”(避免设置为“可读可写可执行”,过于明显),运行时再通过代码修改节属性为“可执行”
-
-
4.4 红队避坑:编译参数错误导致的PE特征异常
-
-
编译架构要匹配:目标机是32位,就编译32位PE;是64位,就编译64位PE,否则无法运行(注入时会失败)。
-
-
-
不要使用默认编译参数:默认参数生成的PE文件,特征太明显,容易被杀软检测到,一定要修改节名称、时间戳等参数。
-
-
-
编译后用PE Bear验证:确认节名称、时间戳、导入表是否修改成功,避免参数设置错误导致PE文件异常。
-
-
额外
-
Windows 系统(x86/x64 架构)采用「小端序(Little Endian)」存储数据
所谓的小端序就是多字节数据,低位字节存在内存低地址,高位字节存在内存高地址。
比如一个 16 位的数值 0x5A4D(对应字符 MZ),拆成两个字节是:
-
高位字节:
0x5A(对应字母 Z) -
低位字节:
0x4D(对应字母 M)
按小端序存储时,内存中会先存低位字节 0x4D,再存高位字节 0x5A → 所以你在十六进制视图里看到的是 4D 5A,但 PE-Bear 解析后显示的是 0x5A4D(完整数值)。
如果后续要手动构造PE文件字段要记住这样的小端序规则,按照低位字节先写入的顺序。
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:https://www.oneblanks.xyz/pe%e6%96%87%e4%bb%b6%e6%a0%bc%e5%bc%8f%e5%9f%ba%e7%a1%80/
共有 0 条评论