每一种操作系统它最重要的格式就是它的可执行文件格式,
因为操作系统就是为了支持这些文件而生成的,内核里面有很多机制,也是配合这种文件格式设计的。
换句话说,这种文件格式也是适合操作系统设计的。
比如: PE 它是 windows 下的文件格式,是 MZ 打头的(4D5A)只有两个字节,后面很大一片就是对这个结构体的管理,
比如:声音在什么位置,图像在什么位置,文字在什么位置,在前面这一片都是有记录的,
也就是说,前面开头不只是标志而已,前面这一片是一个结构体。
 
PE(Portable Execute)文件是Windows下可执行文件的总称,常见的有DLL,EXE,OCX,SYS等
 
1.pe文件的两种状态
pe文件,例如.exe文件,在磁盘中和内存中的状态是不同的;
 
例如:用winhex打开一个测试程序crackme.exe;
直接打开,和在内存中打开,比较两种状态的区别;
 
1)直接打开
运行winhex    ->file    ->open    ->选择crackme.exe
 
2)在内存中打开
运行winhex    ->运行crackme.exe使程序加载到内存    ->tools->    open Memory    ->找到crackme.exe
 
3)比较pe文件两种状态下的区别
1】开头部分
磁盘中:
内存中:
可以看到:
    两种状态下开头部分都一样;
    磁盘中的pe文件总是以00000000开头,而内存中的不一定;
 
2】分节处
磁盘中:
内存中:
可以看到:
    pe文件从某处开始,有一堆补0的地方,也就是留出来的空隙;
    空隙结束后,内存和磁盘中的内容一样;
    但内存中空隙比磁盘中的多,如上图,磁盘中空隙结束后到600;而内存中到1000;
 
4)结论
pe文件有两种状态:磁盘文件和内存映像;
pe文件被加载到内存中时可能被拉伸,但绝大多数数据还是一样的;
 
2.关于pe文件的分节
pe文件在磁盘和在内存中都是分为一段一段的;
段与段之间是空白区,用0填充;
这种机制就是分节,每一段数据就是一个节;
 
1)为什么要分节
1】节省硬盘空间;
任何一个exe程序都有一个独立的4gb的虚拟内存空间;(2的32次方为4gb,也就是寻址范围32位)
2g是给我们写的应用程序用的,还有2g是给操作系统用的;
因此不涉及到内存比硬盘贵的问题,因为是虚拟内存;
 
关于硬盘对齐和内存对齐:
    pe文件用对齐的方式保存;
    对齐可以提高读写速度;
    以前硬盘比较贵,一些老的编译器为了节省硬盘,可能存储方式为硬盘的对齐小于内存对齐;
    例如:硬盘对齐200h,内存对齐1000h时,pe文件可能是这样的:
    这样的pe结构在执行时会有一段拉伸过程;
 
因为硬盘水平发展的成本降低;可能也有一些新编译器编译出来的exe文件,硬盘中和内存中的对齐是一样的;
可以减少运算时间,相当于用空间换时间;
 
2】节省内存
解决应用程序多开的问题;
应用程序中有一些只读的数据,
无论开多少次这些数据都是一样的;
如果每开一次相同的程序,只读数据都要加载一次,会造成不必要的内存浪费;
分节机制可以将只读数据和可读写数据分开,多开时只复制一份可读写数据的节,而保存只读数据的节不复制;
 
例如:开5次exe
 
3.节表和pe头
节表(块表):
    PE文件分了很多个节,那每个节在文件中从哪里开始?有多大?在内存中从哪里开始,有多大?这些信息都保持在节表中;
 
pe头:
    对pe文件做概要性描述;
 
4.手动找头pe头文件
用winhex打开crackme.exe
 
1)doc头
pe结构最开始是dos头,根据dos头的结构和结构中数据的类型,对造上图填入对应的数据
注意:windows中数据是从高到低排列的,要注意顺序
struct _IMAGE_DOS_HEADER {
    0x00 WORD e_magic;            //5a4d    
    0x02 WORD e_cblp;             //0050               
    0x04 WORD e_cp;               //0002                 
    0x06 WORD e_crlc;             //0000   
    0x08 WORD e_cparhdr;          //0004  
    0x0a WORD e_minalloc;         //000f   
    0x0c WORD e_maxalloc;         //ffff   
    0x0e WORD e_ss;               //0000 
    0x10 WORD e_sp;               //00b8 
    0x12 WORD e_csum;             //0000   
    0x14 WORD e_ip;               //0000 
    0x16 WORD e_cs;               //0000 
    0x18 WORD e_lfarlc;           //0040 
    0x1a WORD e_ovno;             //001a   
    0x1c WORD e_res[4];           //0000,0000,0000,0000 
    0x24 WORD e_oemid;            //0000    
    0x26 WORD e_oeminfo;          //0000  
    0x28 WORD e_res2[10];         //0000,0000,0000,0000,0000,0000,0000,0000,0000,0000   
    0x3c DWORD e_lfanew;          //00000100
};
可以用petool来对比看是否找错
dos头的作用:
    当解析一个pe文件时,首先一定要解析头两个字节是否是5a4d;
    需要通过dos头去找真正的pe头部;
 
dos头中有两个重要的数据:
    第一个 e_magic    ->可执行文件是5a4d,对应mz;
    最后一个 e_lfanew    ->pe头的地址;
 
2)标准pe头
通过dos头最后一个字段的值找pe头部,也就是nt头:
    00000100:对应的前两个字节是50 45,即asci的pe
 
从dos头到pe头之间的数据是长度不确定的垃圾数据;
这段空间可以自由发挥,将自己的代码放上去之类的;
 
dos头紧接着的是nt头;
nt头结构:
struct _IMAGE_NT_HEADERS {
0x00 DWORD Signature;
0x04 _IMAGE_FILE_HEADER FileHeader;
0x18 _IMAGE_OPTIONAL_HEADER OptionalHeader;
};
nt头中包括两个内容:pe头和可选pe头;
 
Signature    ->pe标记,有4个字节,也就是50 45 00 00;
 
紧接pe标记的是标准pe头FileHeader,根据其结构从pe标记往后开始查找它的值:
struct _IMAGE_FILE_HEADER {
0x00 WORD Machine;                    //014c
0x02 WORD NumberOfSections;           //0006
0x04 DWORD TimeDateStamp;             //0ad92429   
0x08 DWORD PointerToSymbolTable;      //00000000  
0x0c DWORD NumberOfSymbols;           //00000000
0x10 WORD SizeOfOptionalHeader;       //00e0 
0x12 WORD Characteristics;            //818e
};
petools对比是否找错:
 
3)可选pe头
可选pe头虽然名字叫可选,但它其实很重要,甚至比标准pe头还重要;
标准pe头紧接的就是可选pe头,结构如下:
struct _IMAGE_OPTIONAL_HEADER {
0x00 WORD Magic;
0x02 BYTE MajorLinkerVersion;
0x03 BYTE MinorLinkerVersion;
0x04 DWORD SizeOfCode;
0x08 DWORD SizeOfInitializedData;
0x0c DWORD SizeOfUninitializedData;
0x10 DWORD AddressOfEntryPoint;
0x14 DWORD BaseOfCode;
0x18 DWORD BaseOfData;
0x1c DWORD ImageBase;
0x20 DWORD SectionAlignment;
0x24 DWORD FileAlignment;
0x28 WORD MajorOperatingSystemVersion;
0x2a WORD MinorOperatingSystemVersion;
0x2c WORD MajorImageVersion;
0x2e WORD MinorImageVersion;
0x30 WORD MajorSubsystemVersion;
0x32 WORD MinorSubsystemVersion;
0x34 DWORD Win32VersionValue;
0x38 DWORD SizeOfImage;
0x3c DWORD SizeOfHeaders;
0x40 DWORD CheckSum;
0x44 WORD Subsystem;
0x46 WORD DllCharacteristics;
0x48 DWORD SizeOfStackReserve;
0x4c DWORD SizeOfStackCommit;
0x50 DWORD SizeOfHeapReserve;
0x54 DWORD SizeOfHeapCommit;
0x58 DWORD LoaderFlags;
0x5c DWORD NumberOfRvaAndSizes;
0x60 _IMAGE_DATA_DIRECTORY DataDirectory[16];
};
 
 
 

关于pe结构的更多相关文章

  1. 【PE结构】由浅入深PE基础学习-菜鸟手动查询导出表、相对虚拟地址(RVA)与文件偏移地址转换(FOA)

    0 前言 此篇文章想写如何通过工具手查导出表.PE文件代码编程过程中的原理.文笔不是很好,内容也是查阅了很多的资料后整合出来的.希望借此加深对PE文件格式的理解,也希望可以对看雪论坛有所贡献.因为了解 ...

  2. PE结构学习笔记--关于AddressOfEntryPoint位置在文件中怎么确定问题

    第一次学习PE结构,也不知道有没有更好的办法. 1.AddressOfEntryPoint 这个成员在OptionalHeader里面,OptionalHeader的类型是一个IMAGE_OPTION ...

  3. OD 实验(五) - 对 PE 结构的简单分析

    载入程序,按 Alt+M 查看内存空间 双击进入程序的 PE 头 这些为 DOS 环境下才会运行的 这个执行 PE 的地址,PE 结构的偏移地址为 C0 找到这个地址 以 PE 开头 SizeOfCo ...

  4. 仿LordPE获取PE结构

    乍一看LordPE一个小工具一般般,真的动手做起来才知道技术含量高的很. 当前只是获取到PE结构并打印,仅此而已. PE.h #pragma once #include <stdio.h> ...

  5. 编写自定义PE结构的程序(如何手写一个PE,高级编译器都是编译好的PE头部,例如MASM,TASM等,NASM,FASM是低级编译器.可以自定义结构)

    正在学PE结构...感谢个位大哥的文章和资料...这里先说声谢谢 一般高级编译器都是编译好的PE头部,例如MASM,TASM等一直都说NASM,FASM是低级编译器.可以自定义结构但是苦于无人发布相关 ...

  6. 手写PE结构解析工具

    PE格式是 Windows下最常用的可执行文件格式,理解PE文件格式不仅可以了解操作系统的加载流程,还可以更好的理解操作系统对进程和内存相关的管理知识,而有些技术必须建立在了解PE文件格式的基础上,如 ...

  7. 【转】pe结构详解

    (一)基本概念 PE(Portable Execute)文件是Windows下可执行文件的总称,常见的有DLL,EXE,OCX,SYS等, 事实上,一个文件是否是PE文件与其扩展名无关,PE文件可以是 ...

  8. Win32汇编-编写PE结构解析工具

    汇编语言(assembly language)是一种用于电子计算机.微处理器.微控制器或其他可编程器件的低级语言,亦称为符号语言.在汇编语言中,用助记符(Mnemonics)代替机器指令的操作码,用地 ...

  9. 羽夏笔记——PE结构(不包含.Net)

    写在前面   本笔记是由本人独自整理出来的,图片来源于网络.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章有帮助你 ...

随机推荐

  1. SSM+pagehelper分页

    1.maven依赖 <dependency> <groupId>com.github.jsqlparser</groupId> <artifactId> ...

  2. PHP的四种运行方式

    一丶cgi协议模式 cgi模式通用网关接口(Common Gateway Interface),它允许web服务器通过特定的协议与应用程序通信,调用原理大概为:用户请求->Web服务器接收请求- ...

  3. python 安装virtualenv和wxPython

    有人说 Virtualenv.Fabric 和 PIP 是 Pythoneer 的三大神器 上一节说过了怎么安装PIP,下面继续安装virtualenv 安装wxPython时比较简单 sudo pi ...

  4. python 基础例子 双色球 查询天气 查询电话

    # 随机生成双色球import random# 随机数 1-16之间# r = random.randint(1,16)# print(r)phone_numbers_str = "匪警[1 ...

  5. 请定义一个函数quadratic(a, b, c),接收3个参数,返回一元二次方程 ax^2+bx+c=0ax 2 +bx+c=0 的两个解。

    #!/usr/bin/python # 导入math包 import math def quadratic(a, b, c): if not isinstance(a, (int, float))an ...

  6. MySQL8.0哪些新特性你最期待

    1.数据字典全部采用InnoDB引擎存储,支持DDL原子性.crash safe,metadata管理更完善 2.快速在线加新列(腾讯互娱DBA团队贡献) 3.并行redo log,并提升redo l ...

  7. command not found 的解决&&解释

    ln -s /opt/platform/calico/calicoctl /usr/local/sbin/calicoctl ln -s /opt/platform/nginx/sbin/nginxl ...

  8. MySQL 聚合函数(一)聚合(组合)函数概述

    MySQL版本:5.7+ 本节介绍对值的集合进行操作的组合(聚合)函数.翻译自:Aggregate (GROUP BY) Function Descriptions 一.MySQL 5.7中的聚合函数 ...

  9. django+mysql(1)

    报错误:mysqlclient 1.3.13 or newer is required; you have 0.9.3 第一种: django降到2.1.4版本就OK了 第二种(仍使用django 2 ...

  10. python+vsCode 环境搭建

    先安装python环境和vscode Python下载链接:https://www.python.org/vscode下载地址:https://code.visualstudio.com/ 安装这两个 ...