逆向工程 | PE头重要概念清单

1 byte = 8 bit
WORD: 2 byte (16 bit)
DWORD: 4 byte (32 bit)

VA (Virtual Address): 进程虚拟内存的绝对地址
RVA (Relative Virtual Address): 进程虚拟内存位置相对于某个基准位置 (ImageBase) 的相对地址

RVA + ImageBase = VA

在下面介绍的PE头中,所有字段均没有用到VA,涉及地址的地方全都用RVA。对RVA的使用体现了Portable的理念

DOS头 (40h bytes, i.e. 6410 bytes, "MZ" - 40h)

struct _IMAGE_DOS_HEADER{
    0X00 WORD e_magic;      //※Magic DOS signature MZ(4Dh 5Ah):MZ标记:用于标记是否是可执行文件
    0X02 WORD e_cblp;     //Bytes on last page of file
    0X04 WORD e_cp;       //Pages in file
    0X06 WORD e_crlc;     //Relocations
    0X08 WORD e_cparhdr;  //Size of header in paragraphs
    0X0A WORD e_minalloc; //Minimun extra paragraphs needs
    0X0C WORD e_maxalloc; //Maximun extra paragraphs needs
    0X0E WORD e_ss;       //intial(relative)SS value
    0X10 WORD e_sp;       //intial SP value
    0X12 WORD e_csum;     //Checksum
    0X14 WORD e_ip;       //intial IP value
    0X16 WORD e_cs;       //intial(relative)CS value
    0X18 WORD e_lfarlc;   //File Address of relocation table
    0X1A WORD e_ovno;     //Overlay number
    0x1C WORD e_res[4];   //Reserved words
    0x24 WORD e_oemid;    //OEM identifier(for e_oeminfo)
    0x26 WORD e_oeminfo;  //OEM information;e_oemid specific
    0x28 WORD e_res2[10]; //Reserved words
    0x3C DWORD e_lfanew;    //※Offset to start of PE header:定位PE文件,PE头相对于文件的偏移量
};
  • WORD e_magic: DOS签名(signature, 4D5A,即"MZ")
  • WORD e_lfanew: 指示NT头的偏移

DOS存根 (40h - "PE\0\0")

NT头

typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;        // PE Signature: 50450000 ("PE"00)
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADER32, *PIMAGE_NT_HEADER32;

NT头:文件头 (File Header) (2010 bytes)

struct _IMAGE_FILE_HEADER{
    0x00 WORD Machine;                  //※程序执行的CPU平台:0X0:任何平台,0X14C:intel i386及后续处理器
    0x02 WORD NumberOfSections;         //※PE文件中区块数量
    0x04 DWORD TimeDateStamp;           //时间戳:连接器产生此文件的时间距1969/12/31-16:00P:00的总秒数
    0x08 DWORD PointerToSymbolTable;  //COFF符号表格的偏移位置。此字段只对COFF除错信息有用
    0x0c DWORD NumberOfSymbols;       //COFF符号表格中的符号个数。该值和上一个值在release版本的程序里为0
    0x10 WORD SizeOfOptionalHeader;   //IMAGE_OPTIONAL_HEADER结构的大小(字节数):32位默认E0H,64位默认F0H(可修改)
    0x12 WORD Characteristics;          //※描述文件属性,eg:
                                        //单属性(只有1bit为1):#define IMAGE_FILE_DLL 0x2000  //File is a DLL.
                                        //组合属性(多个bit为1,单属性或运算):0X010F 可执行文件
};
  • WORD Machine:标识CPU类型的Machine码,Intel x86为14C
  • WORD NumberOfSections:节区 (Section) 数量2
  • WORD SizeOfOptionalHeader:指示IMAGE_OPTIONAL_HEADER32的大小
  • WORD Characteristics:标识文件的属性和运行信息,记住,0002h为可执行文件,2000h为DLL文件

NT头:可选头 (Optional Header) (32位默认E0h bytes,64位默认F0h bytes)

struct _IMAGE_OPTIONAL_HEADER{
    0x00 WORD Magic;                    //※幻数(魔数),0x0107:ROM image,0x010B:32位PE,0X020B:64位PE 
    0x02 BYTE MajorLinkerVersion;     //连接器主版本号
    0x03 BYTE MinorLinkerVersion;     //连接器副版本号
    0x04 DWORD SizeOfCode;              //所有代码段的总和大小,注意:必须是FileAlignment的整数倍,存在但没用
    0x08 DWORD SizeOfInitializedData;   //已经初始化数据的大小,注意:必须是FileAlignment的整数倍,存在但没用
    0x0c DWORD SizeOfUninitializedData; //未经初始化数据的大小,注意:必须是FileAlignment的整数倍,存在但没用
    0x10 DWORD AddressOfEntryPoint;     //※程序入口地址OEP,这是一个RVA(Relative Virtual Address),通常会落在.textsection,此字段对于DLLs/EXEs都适用。
    0x14 DWORD BaseOfCode;              //代码段起始地址(代码基址),(代码的开始和程序无必然联系)
    0x18 DWORD BaseOfData;              //数据段起始地址(数据基址)
    0x1c DWORD ImageBase;               //※内存镜像基址(默认装入起始地址),默认为4000H
    0x20 DWORD SectionAlignment;        //※内存对齐:一旦映像到内存中,每一个section保证从一个「此值之倍数」的虚拟地址开始
    0x24 DWORD FileAlignment;           //※文件对齐:最初是200H,现在是1000H
    0x28 WORD MajorOperatingSystemVersion;    //所需操作系统主版本号
    0x2a WORD MinorOperatingSystemVersion;    //所需操作系统副版本号
    0x2c WORD MajorImageVersion;              //自定义主版本号,使用连接器的参数设置,eg:LINK /VERSION:2.0 myobj.obj
    0x2e WORD MinorImageVersion;              //自定义副版本号,使用连接器的参数设置
    0x30 WORD MajorSubsystemVersion;          //所需子系统主版本号,典型数值4.0(Windows 4.0/即Windows 95)
    0x32 WORD MinorSubsystemVersion;          //所需子系统副版本号
    0x34 DWORD Win32VersionValue;             //总是0
    0x38 DWORD SizeOfImage;         //※PE文件在内存中映像总大小,sizeof(ImageBuffer),SectionAlignment的倍数
    0x3c DWORD SizeOfHeaders;       //※DOS头(64B)+PE标记(4B)+标准PE头(20B)+可选PE头+节表的总大小,按照文件对齐(FileAlignment的倍数)
    0x40 DWORD CheckSum;            //PE文件CRC校验和,判断文件是否被修改
    0x44 WORD Subsystem;          //用户界面使用的子系统类型
    0x46 WORD DllCharacteristics;   //总是0
    0x48 DWORD SizeOfStackReserve;  //默认线程初始化栈的保留大小
    0x4c DWORD SizeOfStackCommit;   //初始化时实际提交的线程栈大小
    0x50 DWORD SizeOfHeapReserve;   //默认保留给初始化的process heap的虚拟内存大小
    0x54 DWORD SizeOfHeapCommit;    //初始化时实际提交的process heap大小
    0x58 DWORD LoaderFlags;       //总是0
    0x5c DWORD NumberOfRvaAndSizes; //目录项数目:总为0X00000010H(16)
    0x60 _IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];//#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
};
  • WORD Magic:为IMAGE_OPTIONAL_HEADER32时,Magic为10B;为IMAGE_OPTIONAL_HEADER64时,为20B
  • DWORD AddressOfEntryPoint:持有Entry Point的RVA值,指示程序最先执行的代码起始地址
  • DWORD ImageBase
  • DWORD SectionAlignment, FileAlignmentFileAlignment指定了节区在磁盘文件中的最小单位,而SectionAlignment指定了节区在内存中的最小单位
  • DWORD SizeOfImage:指定PE文件加载到内存后,PE Image在虚拟内存中所占空间大小(一般来讲,文件的大小和加载到内存中的大小是不同的)
  • DWORD SizeOfHeaders:指出整个PE头的大小
  • WORD Subsystem:用于区分驱动文件和普通的可执行文件(1表示系统驱动,2表示GUI文件,在窗口打开,3表示CUI文件,在控制台执行)
  • DWORD NumberOfRvaAndSizes:指定DataDirectory数组的个数

节区头

  • DWORD VirtualSize:内存中节区所占大小
  • DWORD VirtualAddress:内存中节区起始地址 (RVA)
  • DWORD SizeOfRawData:磁盘文件中节区所占大小
  • DWORD PointerToRawData:磁盘文件中节区起始位置
  • DWORD Characteristics:节区属性

Image:映像。PE文件加载到内存时,文件不会原封不动地加载,而要根据节区头中定义的节区起始地址、节区大小等加载。因此,磁盘文件中的PE与内存中的PE具有不同形态。将装载到内存中的形态成为“映像”加以区别,使用这一术语能够很好地区分二者。

加载PE文件时,每个节区都要完成RVA到RAW的映射: 根据

RAW - Pointer To Raw Data = RVA - Virtual Address

得:

RAW = RVA - Virtual Address + Pointer To Raw Data

Reference

PE文件学习笔记(一):DOS头与PE头解析

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 1.check 介绍 PE文件可选头结构如下,其中有个成员是checksum ,其在编译以后生成一个校验和,所有驱...
    看点书阅读 1,481评论 0 0
  • ELF&PE 文件结构分析 说简单点,ELF 对应于UNIX 下的文件,而PE 则是Windows 的可执行文件,...
    刀背藏身阅读 11,991评论 1 27
  • VOL1 在遥远的外太空,有一颗叫做“B16”的小行星。从前在这个星球上只有一个小王子和一朵小玫瑰花,在宇宙无限漫...
    大写的7菇凉阅读 1,192评论 5 5
  • 1.我怎么会如此的幸运 最近特别累,脚开始肿起来,又开始疼,还好徐飞在,我还有救 2.我怎么会如此的幸运 今天看一...
    花猫和喵阅读 239评论 1 0
  • 工作:小歇的一周,工作强度不大。 学习:无 运动:周三私教课,周二迪士尼暴走一天,周六宁波游乐园暴走一天。 作息:...
    笨笨1106阅读 154评论 0 0