PE文件格式详解,第二讲,NT头文件格式,以及文件头格式

时间:2022-09-05 23:47:20

        PE文件格式详解,第二讲,NT头文件格式,以及文件头格式

作者:IBinary
出处:http://www.cnblogs.com/iBinary/
版权所有,欢迎保留原文链接进行转载:)

PS:本篇博客默认你已经有了汇编基础,所以会使用32位汇编编写最小PE进行讲解

今天详解NT 头格式,以及文件头格式,以及作用, 关于DOS头文件格式,以及DOSStub昨天的博客已经写过了.主要是分散讲解.便于理解.

一丶最小PE的生成,以及标准PE的生成

ps: (如果直接学习NT头,文件头,请不用看这个生成PE,直接看下面讲解即可)

1.标准PE的生成

为了便于学习PE文件格式,所以这里写出一个最小PE,还有一个最小的标准PE,让大家理解.

32位汇编编写.(汇编是能编写最小PE的)

首先我们先写一段基本的汇编代码,然后一层一层的优化

32位汇编代码:

.
.model flat,stdcall
option casemap:none include windows.inc
include user32.inc
include kernel32.inc      ;包含各种lib库以及头文件
includelib user32.lib
includelib kernel32.lib .data
g_szHello db "Hello",0dh,0ah,00    ;定义Hello字符串
.code
start:
invoke MessageBoxA,NULL,offset g_szHello ,NULL,MB_OK ;弹出信息框
invoke ExitProcess,0    ;退出程序
end start

很简单的汇编代码

看下EXE的大小,以及内容

PE文件格式详解,第二讲,NT头文件格式,以及文件头格式2.50KB有点大了.

可以继续优化,但是比如手动敲命令行了.注意,这里使用的masm32的link连接器

首先我们要去掉分区,因为这里的EXE主要是分区太多.所以去掉.

怎么去掉? 只需要把上面的汇编代码修改一下即可.

修改为:

.
.model flat,stdcall
option casemap:none include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib .code
g_szHello db "Hello",0dh,0ah,00 ;将数据段的数据,放到代码区中
start:
invoke MessageBoxA,NULL,offset g_szHello ,NULL,MB_OK
invoke ExitProcess,
end start

很简单,就是把.data去掉即可.

这个就是标准PE了,看下文件大小.

PE文件格式详解,第二讲,NT头文件格式,以及文件头格式注意一下,这里我使用的是RadAsm集成开发环境,

编译器是Masm32的link连接器. 如果使用VC6.0以及以上的,文件会变的很大,可能会有16.KB,28.KB,不利于大家学习.如果不会配置RadAsm集成开发环境,请参考以前的帖子.自己配置一下即可.

2.最小PE的生成

区合并和内存对齐优化,生成最小PE(不通用)

首先我们要知道PE中的区在哪里,以及怎么使内存对齐缩小,不至于让PE很大.

首先看下我们的标准PE格式的二进制.(使用Winhex,或者010 Editor都可以)

PE文件格式详解,第二讲,NT头文件格式,以及文件头格式

可以看出,生成的时候默认会为我们生成.const常量区,那么我们可以让它和代码区合并吗?

注意,如果是别的程序,是不可以合并的,因为常量区很有用,但是如果生成最小PE那么你需要合并,

最后一个Hello的位置,则是代码区

手工连接,使其合并分区,变为最小PE

命令行参数

PE文件格式详解,第二讲,NT头文件格式,以及文件头格式PE文件格式详解,第二讲,NT头文件格式,以及文件头格式

/ALIGN:内存对齐(2的倍数即可,默认是4096)

/MERGE: 区 = 区  (合并分区)

例如link加上 写成下面这样

/ALIGN:4 /MERGE:.rdata=.text

手工编译连接看下.

PE文件格式详解,第二讲,NT头文件格式,以及文件头格式

不过这样写还要另外加选项,不能保证她是否是能运行,不通用,所以使用标准pe讲解

二丶NT头

首先看下NT头和文件头的结构体.

NT头:

typedef struct _IMAGE_NT_HEADERS {
DWORD Signature;              //4个字节的PE标志
IMAGE_FILE_HEADER FileHeader;      //文件头
IMAGE_OPTIONAL_HEADER32 OptionalHeader;//可选头
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

NT 头第一个成员,对应的是PE位置,4个字节.

内存分布图:

PE文件格式详解,第二讲,NT头文件格式,以及文件头格式

在这里,建议大家使用010编辑器,可以使用自定义PE模版,解析PE各个位置内容.

PE文件格式详解,第二讲,NT头文件格式,以及文件头格式

下面模版自动点击则可以解析

三丶文件头

文件头结构体:

typedef struct _IMAGE_FILE_HEADER {
WORD Machine;                   //机器型号,作用是区别这个exe是哪个CPU可以跑的.重要.
WORD NumberOfSections;             //节的数量 (可以理解为汇编中区的个数)现在我们有两个,一个.rdata 一个.text
DWORD TimeDateStamp;               //程序的编译时间,参考用,没有实际作用
DWORD PointerToSymbolTable;          //符号表地址 我们使用的PDB文件(里面有函数吗什么的)都存放在这个表中,不过微软是单独生成的PDB文件,所以这个字段没用,主要是给别人用
DWORD NumberOfSymbols;             //符号表大小
WORD SizeOfOptionalHeader;          //可选头大小,这个字段很重要.因为要通过这个字段,才知道可选头是多大,而不懂PE的人求选项头都是用sizeof()求出来的.所以真正的选项头大小要靠这个字段
WORD Characteristics;            //文件属性,描述文件信息的.
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

上面只是简单的写了下各个成员的作用.

在这里需要注意的是   可选头大小,文件属性,以及机器型号.  其余的自己看看.

1.机器型号:

机器型号,在PE中的定义,在VC++6.0中已经给出了.

代码:

#define IMAGE_FILE_MACHINE_UNKNOWN           0
#define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386.
#define IMAGE_FILE_MACHINE_R3000 0x0162 // MIPS little-endian, 0x160 big-endian
#define IMAGE_FILE_MACHINE_R4000 0x0166 // MIPS little-endian
#define IMAGE_FILE_MACHINE_R10000 0x0168 // MIPS little-endian
#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 // MIPS little-endian WCE v2
#define IMAGE_FILE_MACHINE_ALPHA 0x0184 // Alpha_AXP
#define IMAGE_FILE_MACHINE_POWERPC 0x01F0 // IBM PowerPC Little-Endian
#define IMAGE_FILE_MACHINE_SH3 0x01a2 // SH3 little-endian
#define IMAGE_FILE_MACHINE_SH3E 0x01a4 // SH3E little-endian
#define IMAGE_FILE_MACHINE_SH4 0x01a6 // SH4 little-endian
#define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian
#define IMAGE_FILE_MACHINE_THUMB 0x01c2
#define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64
#define IMAGE_FILE_MACHINE_MIPS16 0x0266 // MIPS
#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 // MIPS
#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 // MIPS
#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64

看下PE中怎么存储的.

PE文件格式详解,第二讲,NT头文件格式,以及文件头格式

按照小尾方式,则是 0x014C ,那么对应上面的宏则是386的程序(看注释),而我们的汇编编译出来的标准PE也正是标准PE,如果学习PE,自己可以去看下PE存储

2.可选头大小

PE文件格式详解,第二讲,NT头文件格式,以及文件头格式

这个地方是我计算偏移得出,根据结构体的类型大小,可以自己计算偏移得出.

可以看出,可选头的大小是0x00E0 大小,换算成10进制就可以知道,E0是224字节大小,所以根据这个,可以计算出可选头大小

3.文件属性

文件属性紧跟在E0 00 后面,它是0F 01

文件属性是按照位来的.

什么意思?

先看下宏定义:

#define IMAGE_FILE_RELOCS_STRIPPED           0x0001  // Relocation info stripped from file.
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references).
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file.
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file.
#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 // Agressively trim working set
#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 // App can handle >2gb addresses
#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed.
#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine.
#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file
#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 // If Image is on removable media, copy and run from the swap file.
#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 // If Image is on Net, copy and run from the swap file.
#define IMAGE_FILE_SYSTEM 0x1000 // System File.
#define IMAGE_FILE_DLL 0x2000 // File is a DLL.
#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 // File should only be run on a UP machine
#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed.

首先按照小尾方式查看.

0x010f

那么先看第一个1,不看后面的,找百位为1的那么就是 0x100 在上面则可以找到对应的宏,它的注释是:

32 bit word machine. 代表了他是一个32位程序
那么看个位是F,那么就找F,但是需要注意,他因为是位运算,所以是 | 连接起来了,那么F 代表了
0x0001  | 0x0002 | 0x0004 | 0x0008  那么分别就对应前4个宏
那么最终想要表示的结果是
32 bit word machine.
Relocation info stripped from file.
File is executable  (i.e. no unresolved externel references)
Line nunbers stripped from file
Local symbols stripped from file.

翻译过来就是 这是一个32位程序,是一个可执行程序....
那么训练一下,我随便写一个
0x2102
那么 按照 个 十 百 千 位去寻找
先找千位   0x2000 // File is a DLL.                                 说明这是一个DLL文件
再找百位   0x100  // 32 bit word machine.                            说明是一个32位可执行程序
再找十位   十位为零,则没有.
再找个位   0x0002 // File is executable (i.e. no unresolved externel references).     说明是一个可执行程序
那么总结一下,说明了这个文件是一个 DLL文件,是一个32位程序,是一个可执行程序 总的来说很简单,主要是熟练运用,在不使用工具的前提下,明白各个位置代表的作用 作者:IBinary
出处:http://www.cnblogs.com/iBinary/
版权所有,欢迎保留原文链接进行转载:)

PE文件格式详解,第二讲,NT头文件格式,以及文件头格式的更多相关文章

  1. PE文件格式详解,第一讲,DOS头文件格式

    PE文件格式详解,第一讲,DOS头文件格式 今天讲解PE文件格式的DOS头文件格式 首先我们要理解,什么是文件格式,我们常说的EXE可执行程序,就是一个文件格式,那么我们要了解它里面到底存了什么内容 ...

  2. PE文件格式详解,第三讲,可选头文件格式,以及节表

    PE文件格式详解,第三讲,可选头文件格式,以及节表 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 一丶可选头结构以及作 ...

  3. 第二讲,NT头文件格式,以及文件头格式

    今天详解NT 头格式,以及文件头格式,以及作用, 关于DOS头文件格式,以及DOSStub昨天的博客已经写过了.主要是分散讲解.便于理解. 一丶最小PE的生成,以及标准PE的生成 ps: (如果直接学 ...

  4. Git应用详解第二讲:Git删除、修改、撤销操作

    前言 前情提要:Git应用详解第一讲:Git分区,配置与日志 在第一讲中我们对Git进行了简单的入门介绍,相信聪明的你已经了解Git的基本使用了. 这一讲我们来进一步深入学习Git应用,着重介绍Git ...

  5. Android学习之基础知识十三 — 四大组件之服务详解第二讲(完整版的下载示例)

    上一讲学习了很多关于服务的使用技巧,但是当在真正的项目里需要用到服务的时候,可能还会有一些棘手的问题让你不知所措.接下来就来综合运用一下,尝试实现一下在服务中经常会使用到的功能——下载. 在这一讲我们 ...

  6. PE文件结构详解(二)可执行文件头

    在PE文件结构详解(一)基本概念里,解释了一些PE文件的一些基本概念,从这篇开始,将详细讲解PE文件中的重要结构. 了解一个文件的格式,最应该首先了解的就是这个文件的文件头的含义,因为几乎所有的文件格 ...

  7. PE文件格式详解(七)

    PE文件格式详解(七)   Ox00 前言 前面好几篇在讲输入表,今天要讲的是输出表和地址的是地址重定位.有了前面的基础,其实对于怎么找输出表地址重定位的表已经非常熟悉了.   0x01 输出表结构 ...

  8. BMP文件格式详解

    BMP文件格式详解(BMP file format) BMP文件格式,又称为Bitmap(位图)或是DIB(Device-Independent Device,设备无关位图),是Windows系统中广 ...

  9. OpenGL学习--05--纹理立方体--BMP文件格式详解(转载)

    http://blog.csdn.net/o_sun_o/article/details/8351037 BMP文件格式详解 BMP文件格式详解(BMP file format) BMP文件格式,又称 ...

随机推荐

  1. SVG学习备忘录

    最近在写一个基于SVG的前端流程图\拓扑图图形框架. 一些容易忽略的问题备忘如下: 1.JS添加SVG元素需要使用document.createElementNS("http://www.w ...

  2. commandline (命令行)登录mysql

    mysql登录在命令行登录的时候是通过mysql的里面的程序的录的 其登录格式有两种:(在oracle上看到的是列出这两种,不要既有全参数名又有缩写参数名.) 1.全参数名登录释例 mysql --h ...

  3. 无废话Android之android下junit测试框架配置、保存文件到手机内存、android下文件访问的权限、保存文件到SD卡、获取SD卡大小、使用SharedPreferences进行数据存储、使用Pull解析器操作XML文件、android下操作sqlite数据库和事务(2)

    1.android下junit测试框架配置 单元测试需要在手机中进行安装测试 (1).在清单文件中manifest节点下配置如下节点 <instrumentation android:name= ...

  4. ZLL主机接口的信息处理流程

    主机接口的信息处理流程 在我们翻译的文档中是用电脑端来模拟主机的,电脑代替网关发送主机接口命令的环节是在zll_controller.c中实现的,(在下载的文件中已经提供了其对应的可执行文件zllCm ...

  5. 前端开发工程师:网易web前端课程,价值1499元【无水印版】

    这套网上的朋友购买分享给我的,特此分享~ 让大家都受益 早日成为强大的web前端开发工程师!!赶紧回复下载吧 下载地址:http://fu83.cn/thread-172-1-1.html

  6. 3ds max学习笔记(十二)-- (弯曲:实例旋转楼梯)

    一般来讲,弯曲以不扭曲为原则: 新建一个圆柱体,在修改器列表中点击[弯曲]即可: 参数如下: 角度的正负表示的是方向的不同, 方向基本不更改,若要更改则90,-90: 限制:物体(或组)哪些受弯曲的影 ...

  7. 菜鸟Vue学习笔记(一)

    我今年刚参加工作,作为一个后台Java开发人员,公司让我开发前端,并且使用Vue框架,我边学习边记录. Vue框架是JS的封装框架,使用了MVVM模式,即model—view—viewmodel模式, ...

  8. C&plus;&plus;笔记(2017&sol;2&sol;9)

    this指针 this指针作用就是指向成员函数所作用的对象. 非静态成员函数中可以直接使用this来代表指向该函数作用的对象的指针. 静态成员函数中不能使用this指针. 静态成员 static 定义 ...

  9. LeetCode题解之Rotate String

    1.题目描述 2.问题分析 直接旋转字符串A,然后做比较即可. 3.代码 bool rotateString(string A, string B) { if( A.size() != B.size( ...

  10. hadoop2&period;6&period;0的eclipse插件编译和设置

    编译hadoop2.6.0的eclipse插件 下载源码: git clone https://github.com/winghc/hadoop2x-eclipse-plugin.git 编译源码: ...