PE 文件学习笔记【2】分析PE文件

1、 DOS头部

所有的PE文件都是以一个64字节的DOS头开始,所以刚好是四行,每行16个字节

怎么看这个呢?这里说一个结构体就明白了。

最左边是文件头的偏移量。) 
IMAGE_DOS_HEADER STRUCT 
{ 
+0h WORD    e_magic        //   MZ(4Dh 5Ah)     DOS可执行文件标记 
+2h     WORD    e_cblp            
+4h WORD    e_cp                         
+6h WORD    e_crlc                      
+8h WORD    e_cparhdr      
+0ah    WORD    e_minalloc       
+0ch    WORD    e_maxalloc  
+0eh    WORD    e_ss           
+10h    WORD    e_sp       
+12h    WORD    e_csum      
+14h    WORD    e_ip        
+16h    WORD    e_cs        
+18h    WORD    e_lfarlc       
+1ah    WORD    e_ovno          
+1ch    WORD    e_res[4]        
+24h    WORD    e_oemid         
+26h    WORD    e_oeminfo    
+29h    WORD    e_res2[10]  
+3ch    DWORD   e_lfanew     //  RVA     指向PE文件头 
} IMAGE_DOS_HEADER ENDS

 需要关注的点是结构体的第一个和第二个元素。

(1)e_magic:DOS头的标记位,值为4D5Ah。ASCII为”MZ“,判断一个文件是否为PE文件是会用

(2)e_lfanew:这是一个RVA,代表了PE文件头到基址的偏移量,我们可以用它来找到PE文件头的位置

2、PE头文件

IMAGE_NT_HEADERS STRUCT 
{
+0h       DWORD    Signature  
+4h       IMAGE_FILE_HEADER    FileHeader 
+18h      IMAGE_OPTIONAL_HEADER32   OptionalHeader   
} IMAGE_NT_HEADERS ENDS

(1)在一个PE文件中Signature字段被设置为4550h,ASCII码为”PE00“。如上图所示 

IMAGE_FILE_HEADER  结构体

struct IMAGE_FILE_HEADER
{
    WORD Machine; //运行平台
    WORD NumberOfSections; //区块表的个数
    DWORD TimeDataStamp;//文件创建时间,是从1970年至今的秒数
    DWORD PointerToSymbolicTable;//指向符号表的指针
    DWORD NumberOfSymbols;//符号表的数目
    WORD SizeOfOptionalHeader;//IMAGE_NT_HEADERS结构中OptionHeader成员的大小,对于win32平台这个值通常是0x00e0
    WORD Characteristics;//文件的属性值
}

(2)IMAGE_FILE_HEADER  结构体

    1)Machine字段,表示目标CPU 的类型。

      几个常见的及其标识如下: 

机器              标识     

Intel I386        014ch

MIPS R3000        0162h

Alpha AXP         0184h

Power PC          01F0h

MIPS R4000        0184h

根据以上信息我们知道这个PE文件要运行在Intel I386机器上。(我们上图为0x014C

2)NumberOfSection,标识区块的数目,关于区块后面会详细讲。(我们上图为0x0005

3)TimeDateStamp(我们上图为0x5D084DBD

这个字段没啥好说的,指的就是PE文件创建的事件,这个时间是指从1970年1月1日到创建该文件的所有的秒数。

4)PointerToSymbolTable。这个字段用的比较少,(我们上图为0x00000000

5)NumberOfSymbol。这个字段也用得很少,(我们上图为0x00000000

6)SizeOfOptionalHeader:(我们上图为0x00E0)

紧跟着IMAGE_FILE_HEADER后面的数据大小,这也是一个数据结构,它叫做IMAGE_OPTIONAL_HEADER,其大小依赖于是64位还是32位文件。32位文件值通常是00E0h,对于64位值通常为00F0h。

7)Characteristics:(我们上图为0x010E

文件属性,普通EXE文件这个字段值为010fh,DLL文件这个字段一般是0210h。

(3)IMAGE_OPTIONAL_HEADER 结构体

typedef struct _IMAGE_OPTIONAL_HEADER
{
    //
    // Standard fields.  
    //
+18h    WORD    Magic;                   // 标志字, ROM 映像(0107h),普通可执行文件(010Bh)
+1Ah    BYTE    MajorLinkerVersion;      // 链接程序的主版本号
+1Bh    BYTE    MinorLinkerVersion;      // 链接程序的次版本号
+1Ch    DWORD   SizeOfCode;              // 所有含代码的节的总大小
+20h    DWORD   SizeOfInitializedData;   // 所有含已初始化数据的节的总大小
+24h    DWORD   SizeOfUninitializedData; // 所有含未初始化数据的节的大小
+28h    DWORD   AddressOfEntryPoint;     // 程序执行入口RVA
+2Ch    DWORD   BaseOfCode;              // 代码的区块的起始RVA
+30h    DWORD   BaseOfData;              // 数据的区块的起始RVA
    //
    // NT additional fields.    以下是属于NT结构增加的领域。
    //
+34h    DWORD   ImageBase;               // 程序的首选装载地址
+38h    DWORD   SectionAlignment;        // 内存中的区块的对齐大小
+3Ch    DWORD   FileAlignment;           // 文件中的区块的对齐大小
+40h    WORD    MajorOperatingSystemVersion;  // 要求操作系统最低版本号的主版本号
+42h    WORD    MinorOperatingSystemVersion;  // 要求操作系统最低版本号的副版本号
+44h    WORD    MajorImageVersion;       // 可运行于操作系统的主版本号
+46h    WORD    MinorImageVersion;       // 可运行于操作系统的次版本号
+48h    WORD    MajorSubsystemVersion;   // 要求最低子系统版本的主版本号
+4Ah    WORD    MinorSubsystemVersion;   // 要求最低子系统版本的次版本号
+4Ch    DWORD   Win32VersionValue;       // 莫须有字段,不被病毒利用的话一般为0
+50h    DWORD   SizeOfImage;             // 映像装入内存后的总尺寸
+54h    DWORD   SizeOfHeaders;           // 所有头 + 区块表的尺寸大小
+58h    DWORD   CheckSum;                // 映像的校检和
+5Ch    WORD    Subsystem;               // 可执行文件期望的子系统
+5Eh    WORD    DllCharacteristics;      // DllMain()函数何时被调用,默认为 0
+60h    DWORD   SizeOfStackReserve;      // 初始化时的栈大小
+64h    DWORD   SizeOfStackCommit;       // 初始化时实际提交的栈大小
+68h    DWORD   SizeOfHeapReserve;       // 初始化时保留的堆大小
+6Ch    DWORD   SizeOfHeapCommit;        // 初始化时实际提交的堆大小
+70h    DWORD   LoaderFlags;             // 与调试有关,默认为 0 
+74h    DWORD   NumberOfRvaAndSizes;     // 下边数据目录的项数,这个字段自Windows NT 发布以来一直是16
+78h    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; // 数据目录表
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

从上文中可以知道,可选头大小为0x00E0。

重要的数据,再次画出来

 总共31个,重要的有:

AddressOfEntryPoint: 也就是上文提到的OEP,程序源入口点(0x000010C0)。

ImageBase: 默认加载基址,(0x00400000)

SectionAlignment:  内存当中的块对齐数,一般为0x1000 (0x00001000)

FileAlignment:磁盘当中块对齐数,一般为0x200 (0x00001000)

SizeOfHeaders:所有头部大小 也就是DOS头 文件头 以及区块头的总大小 ,文件主体相对文件其实的偏移。(0x00001000)

IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]:数据目录表,保存了各种表的RVA及大小。

IMAGE_DATA_DIRECTORY STRUCT
{VirtualAddress DWORD     ;数据的起始RVA
isize DWORD     ;数据块的长度
}IMAGE_DATA_DIRECTORY ENDS

数据目录列表的含义如下:

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值