每一种操作系统它最重要的格式就是它的可执行文件格式,
因为操作系统就是为了支持这些文件而生成的,内核里面有很多机制,也是配合这种文件格式设计的。
换句话说,这种文件格式也是适合操作系统设计的。
比如: 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. Linux Centos下软件的安装与卸载方法

    转载于: http://blog.csdn.net/zolalad/article/details/11368879 Linux下软件的安装与卸载   第一章   linux下安装软件,如何知道软件安 ...

  2. python-day3(正式学习)

    执行python的两种方式 交互式 优点:运行一句执行一句,方便修改 缺点:关闭即消失,无法保存 命令行式 优点:能一直保存 缺点:代码全部写完才可以调试bug 以后尽量使用pycharm和jupyt ...

  3. 统计学习方法 | 感知机 | python实现

    感知机是二类分类的线性分类模型,利用随机梯度下降法对基于误分类的损失函数进行极小化. 书中算法可以将所有样本和系数向量写成增广向量的形式,并将所有负样本乘以-1,统一形式,方便计算. (1)训练数据集 ...

  4. 【背包问题】PACKING

    题目描述 It was bound to happen.  Modernisation has reached the North Pole.  Faced with escalating costs ...

  5. pb相关小技巧或用法

    1.动态post window lwlw = w_main lw.dynamic post event ue_all(ls_no,ls_table) 2.打开隐藏窗口 IF NOT IsValid(w ...

  6. html5手机网页开发,中文输入法下软键盘遮挡输入框

    安卓手机解决办法 微信UI框架weui中给出了解决方法:weui框架http://weui.github.io/weui/example.js // .container 设置了 overflow 属 ...

  7. Windows 下 nvm, node, npm 的下载、安装与配置

    主要解决的问题 下载安装完 nvm 和 node 后,缺失 npm 文件 执行 jasmine 等命令时提示「不是内部或外部命令...」及全局变量的设置 下载与安装 一.nvm github 下载地址 ...

  8. css三大特性及权重说明

    一.三大特性简述 层叠性: 后来的覆盖前面的 (长江后浪推前浪) 继承性: 子标签会继承父标签的某些样式 (跟文字有关的一般都会继承) 优先级: 设计到一个算法“css特殊性(Specificity) ...

  9. CentOS7中使用yum安装Nginx的详细步骤

    1.添加源 rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarc ...

  10. redis写入性能测试

    import timeit import redis def clock(func): def clocked(*args, **kwargs): t0 = timeit.default_timer( ...