当前位置: 首页 > ds >正文

免杀对抗--PE文件结构

前言

欢迎来到我的博客

个人主页:北岭敲键盘的荒漠猫-CSDN博客

本文整理windows执行文件PE的结构

帮助大家更好的了解Windows的免杀对抗

理解PE

PE就是Windows的可执行程序,常见的后缀有exe,dll,sys等。

我们所说的PE文件结构可以这么理解。

PE文件就是一大坨二进制数据,我们学习PE文件结构实际上就是去分辨哪个区域的二进制数据是做什么的。

图解PE文件

这个结构要从下往上看哈。

PE文件查看工具

前面说了,学PE文件结构实际上就是学PE文件这一大坨的二进制数据中,哪部分是做什么内容。

010 Editor

如果要看程序的二进制数据可以用010 editor查看。

打开010直接拖进去就行了。

010还有各种插件,用来辅助识别常见的后缀的各个区块

studyPE

有这样一个情况,我们拿一个PE文件就010打开,看里面一坨一坨的二进制,那肯定是相当麻烦,所以就可以用一些辅助工具直接帮我们分析。

studyPE是一个比较推荐的工具。

用起来也比较简单,我们直接把exe,dll之类的拖进去就可以了。

可以很方便的看到PE的文件结构。

winnt.h简介

C语言点进去,在里面能看见PE的全部结构。

PE文件结构

DOS部首

作用:

兼容早期MS-DOS系统,确保PE文件在DOS环境下运行时能显示提示信息(如“此程序不能在DOS模式下运行”)。

总大小不确定

DOS MZ头

全部结构如下:

typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE headerWORD   e_magic;                     // Magic numberWORD   e_cblp;                      // Bytes on last page of fileWORD   e_cp;                        // Pages in fileWORD   e_crlc;                      // RelocationsWORD   e_cparhdr;                   // Size of header in paragraphsWORD   e_minalloc;                  // Minimum extra paragraphs neededWORD   e_maxalloc;                  // Maximum extra paragraphs neededWORD   e_ss;                        // Initial (relative) SS valueWORD   e_sp;                        // Initial SP valueWORD   e_csum;                      // ChecksumWORD   e_ip;                        // Initial IP valueWORD   e_cs;                        // Initial (relative) CS valueWORD   e_lfarlc;                    // File address of relocation tableWORD   e_ovno;                      // Overlay numberWORD   e_res[4];                    // Reserved wordsWORD   e_oemid;                     // OEM identifier (for e_oeminfo)WORD   e_oeminfo;                   // OEM information; e_oemid specificWORD   e_res2[10];                  // Reserved wordsLONG   e_lfanew;                    // File address of new exe header} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

字节长度:64字节

粉色区域部分,一行16字节,四行,共64字节。

关键结构如下:

e_magic

占用2字节

固定值0x5A4D(ASCII为"MZ"),标识DOS可执行文件

e_lfanew

指向NT头的偏移地址(位于DOS头偏移0x3C

用于指向PE文件头的位置。

因为DOS stub的大小不确定。

而需要知到下一个PE文件头的位置,就需要使用这个记录下PE文件的位置。

这四个字节要倒着读,即00 00 01 08也就是108

所以DOS stub之后的PE部分的开头就是108位置。

DOS stub

大小:不确定

直观理解:

实际上就是DOS跟win16位系统执行的程序。

当本现代程序出现在了老版系统中的时候就会执行这些老版的程序,报出错误,告诉老系统这个程序是新版程序,不能在他的系统中执行。

避免了出现不可预见的错误。

PE文件头

宏观图标

代码层面

主要三部分。

Signature

大小:固定4字节

作用:标识PE文件头的初始部分。

描述:

可以通过MZ头后的e_lfanew找到这个部分。

FileHeader

大小:固定20字节

结构包括如下部分

Machine

大小:2字节

作用:描述这个程序可以执行在哪个平台上。

0:代表任意都可以

64平台:86 64

NumberOfSections

大小:2字节

作用:

描述程序有几个区块(节表),区块可以理解为程序的分类箱。.text箱子存放代码,.rsrc箱子存放图片等资源,.data存放变量等。他们的权限又不同,比如.text中的代码肯定是要有执行权限的,但是给.rsrc一个执行权限那就有点搬石头打自己脚了。

2字节,图中倒着读代表了7个区块。

TimeDateStamp

大小:4字节

作用:

记录程序的创建时间戳。

PE文件采用小端存储,真实我们要的时间戳是68 3D 50 F8

转化为十进制1748848888

转化为真实时间:2025/06/02 15:21:28

PointerToSymbolTable

大小:4字节

作用:COFF 符号表的 RVA 偏移量,如果 COFF 符号表不存在,则该值为 0

不怎么用,没啥必要。

这里位00 00 00 00就是没有

NumberOfSymbols

大小:4字节

作用:COFF 符号表中的符号个数

跟上面一样用处不大,这里也是0

SizeOfOptionalHeader

大小:2字节

作用:标识_IMAGE_OPTIONAL_HEADER的大小

F0转化为10进制为240

一般来说,32位是E0(224),64位是F0(240)。

Characteristics

大小:2字节

作用:描述文件属性

读取方法:

把16进制转化为2进制,这里是0022转化为0000 0000 0010 0010

对照着这个图比对1的位置

在1,5处为1,所以这个文件属性对应数据位为1,5的属性

1:文件可执行

5:应用程序可处理大于2GB的地址

OptionalHeader

大小:由SizeOfOptionalHeader标识,本程序为240字节。

代码层面

Magic

大小:2字节

作用:描述这个程序是32位还是64位

32位:10BH

64位:20BH

ROM映射文件:107H

这个程序是020B是64位的。

节表

IMAGE_SECTION_HEADERS

情况:

由多个IMAGE_SECTION_HEADER构成。

大小:

一个IMAGE_SECTION_HEADER40字节,有多个。

数量:

由FileHeader中的NumberOfSections决定。

一个IMAGE_SECTION_HEADER的结构:

typedef struct _IMAGE_SECTION_HEADER {BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];union {DWORD   PhysicalAddress;DWORD   VirtualSize;} Misc;DWORD   VirtualAddress;DWORD   SizeOfRawData;DWORD   PointerToRawData;DWORD   PointerToRelocations;DWORD   PointerToLinenumbers;WORD    NumberOfRelocations;WORD    NumberOfLinenumbers;DWORD   Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
功能简介

1. 基础信息字段

字段名数据类型功能描述
NameBYTE[8]节名称(ASCII字符串),长度≤8字节,不足则用0填充(如.text.data) 。
MiscUnion联合体,包含两个等效成员:<br> • VirtualSize:节在内存中的实际大小(未对齐)<br> • PhysicalAddress(极少用) 。
VirtualAddressDWORD节加载到内存后的 相对虚拟地址(RVA) ,需按SectionAlignment对齐 。

2. 文件与内存布局字段

字段名数据类型功能描述
SizeOfRawDataDWORD节在磁盘文件中的实际大小,需按FileAlignment对齐 。
PointerToRawDataDWORD节在磁盘文件中的起始偏移量,用于定位原始数据 。
PointerToRelocationsDWORD重定位表在文件中的偏移(仅OBJ文件有效,PE文件中通常为0) 。
PointerToLinenumbersDWORD行号表在文件中的偏移(仅调试信息有效) 。
NumberOfRelocationsWORD重定位条目数量(仅OBJ文件有效) 。
NumberOfLinenumbersWORD行号条目数量(仅调试信息有效) 。

3. 属性标志字段

字段名数据类型功能描述
CharacteristicsDWORD节属性标志位,通过位运算组合(如可执行/可读/可写)
Characteristics运算

这是一个区块,最后四字节是节表属性。

 十六进制:60 00 00 20

换算二进制为:

110 0000 0000 0000 0000 0000 0010 0000

按照1的位数对照表格判断

6和30,31为1

分别代表途中的信息

已初始化数据,可读可写但是不可执行。(毕竟区块名为text就是文本嘛)

节数据

描述:

可以理解为节表就是书本的目录,节数据就是指定的一章节的具体内容。

定位节数据:

既然这个关系跟书本很像,那么我们要寻找节数据就需要通过目录寻找。

节表中的SizeOfRawData跟PointerToRawData分别代表了节数据的大小跟初始位置。

这个节表中

SizeOfRawData

值为2A600

PointerToRawData

值为400

所以这个节数据的位置就是初始偏移量在400位置,大小是2A600

http://www.xdnf.cn/news/13083.html

相关文章:

  • 汽车车载软件平台化项目规模颗粒度选择的一些探讨
  • 【学习笔记】TLS
  • 贝叶斯医学分析中“先验”的如何进行选择(文献解读)
  • Java【基础篇0】
  • java中装饰模式
  • Go内存池设计与实现:减少GC压力
  • ASM,LVM,扫描并扩容步骤-linux
  • 什么是双脉冲测试?
  • 【C++】第十一节—一文详解vector(使用+杨辉三角+深度剖析+模拟实现+细节详细补充)
  • 为什么要引入内联函数?
  • Python Selenium登录网易邮箱
  • FastAPI实战起步:从Python环境到你的第一个“Hello World”API接口
  • day 18进行聚类,进而推断出每个簇的实际含义
  • token和md5
  • Spring Boot 完全指南:快速构建企业级应用
  • vue中Echarts的使用
  • 【评测】Qwen3-Embedding模型初体验
  • frida Hook入门
  • [FreeRTOS]1.FreeRTOS基础知识
  • Java处理字符数组转换为开始日期和结束日期
  • 【学习笔记】深入理解Java虚拟机学习笔记——第3章 垃圾收集器与内存分配策略
  • LLMs之MCP:《Evaluation Report on MCP Servers》翻译与解读
  • 『uniapp』自定义隐私政策弹窗 调整颜色和多语言国际化支持超链接 演示本地插件的使用,和一般性的插件自定义(保姆级图文)
  • CppCon 2015 学习:Live Lock-Free or Deadlock
  • AI架构师修炼之道
  • Linux系统编程中的_GNU_SOURCE宏
  • Promise 基础:异步编程的救星
  • 使用idea开发工具创建javaweb项目工程
  • CQF预备知识:Python相关库 -- 傅里叶变换 scipy.fft
  • 第十八章 归档与备份