手写PE文件(一)
DOS Header(IMAGE_DOS_HEADER)->64 Byte
DOS头部
DOS Stub 112字节
"PE"00(Signature) 4个字节
IMAGE_FILE_HEADER 20个字节
PE文件头 IMAGE_OPTIONAL_HEADER32 96个字节
数据目录表 16*8=128个字节
IMAGE_SECTION_HEADER 40个字节
块表 IMAGE_SECTION_HEADER 40个字节
IMAGE_SECTION_HEADER 40个字节
.text 512个字节
块 .rdata 512个字节
.data 512个字节
COFF 行号
调试信息 COFF符号表
Code View调试信息
1这部分可以使读者对PE文件整体结构有一个大概了解。
2方便审查自己的构造进度 本次构造的PE文件总共有3个块,他们分别用来存放可执行代
码,输入表信息,以及全局变量,接触过PE文件的朋友对区块的概念应该不陌生,我们知道windows下的很多应用程序的文件对齐制度,也就是大名鼎鼎的FileAlignment字段的值最多200个字节,也就是十进制的512字节,对于不足512个字节的,要填充00补完512个字节,对于超过512个字节,要多分配512个字节
本例中的PE文件头64+112+4+20+224+40*3=544个字节但是显然要填充到1024个字节,整个文件体积就是512*2(PE文件头)+512*3(块)=2560个字节,这也就是我们构造的PE文件总的大小
提前搞清一些字段与区段的偏移量也是比较重要的,
1 PE文件头开始位置B0
2 IMAGE_OPTIONAL_HEADER32开始处000000C8h
3 数据目录表开始处 00000128h
4 块表开始处 000001A8h
5 .text区段开始处 00000400
6 .rdata区段开始处 00000600
7 .data区段开始处 00000800
二:重点字段的介绍
1 DOS头部
1-1 DOS Header
1-1-1 e_magic[WORD]-->4D5A(DOS可执行文件头标记)
1-1-19 e_lfanew[WORD]->BO OO OO OO (指定PE文件头的偏移量64+112)
2 PE文件头
2-1 "PE"00
2-1-1 Signature[DWORD]-->50450000(PE文件头标记)
注释:此处的值总为0000h
2-2 IMAGE_FILE_HEADER
2-2-1 Machine[DWORD]--->4C 01(可执行文件的目标CPU类型)
注释:次PE文件运行于哪个CUP下,其标志就为相应的值
interl i386 14C h MIPS R3000 162h
MIPS R4000 166h Alpha AXP 184h
Power PC 1F0h
2-2-2 NumberOfSections[WORD]--->03 00区段数目
注释:此值取决于PE文件的区块数目,本程序为3个区段
2-2-3 SizeOfOptionalHeader[WORD]--->E0 00(PE 可选头大小)
注释:此值表示PE可选头的大小
2-2-7 Characteristics[WORD]--->OF O1(文件属性)
注释: 此值为文件的执行属性,EXE文件的属性一般为010Fh,DLL文件般
为0210h
2-3 IMAGE_OPTIONAL_HEADER
2-3-1 Magic[WORD]--->OB 01(*标记字)
注释:此处是一个标记字,用于描述PE文件的映像类型,ROM映像0107h,普通可
执行映像010Bh,PE32+则是020Bh。
2-3-7 AddressOfEntryPoint[DWORD]--->00 10 00 00(*程序执行入口)
注释:通俗的讲就是指向可执行代码区块(.text)的首地址
2-3-10 ImageBase[DWORD]--->00 00 40 00(*程序默认装入基地址)
2-3-11 SectionAlignment[DWORD]-内存中的对齐大小,也叫做块粒度,其默认值是CPU页大小
2-3-12 FileAlignment[DWORD]--->00 02 00 00(*文件区中区块对齐值)
注释: 磁盘上的PE文件的区块对齐大小,这个值必须是2的幂,并且最小是200h
2-3-17 MajorSubsystemVersion[WORD]--->04 00(*运行所需最低子系统主版本号)
注释:要求最低的子系统主版本号,一般情况下为4
2-3-18 MinorSubsystemVersion[WORD]--->00 00(*运行所需最低子系统次版本号)
注释:要求最低的子系统次版本号,一般情况下都为0
2-3-20 SizeOfImage[DWORD]--->00 40 00 00(映像装入内存后总尺寸)
注释:指的是装入文件从Image Base到最后一个区块大小
2-3-21 SizeOfHeaders [DWORD]--->00 04 00 00(*DOS头 PE头,区块表的总大小)
注释:指的是DOS头,PE头与区块表的总大小,并且所有这些项目都是出现在PE文件中任何代码和数据之前,此值遵循文件对齐制度
2-3-23 Subsystem[WORD]--->03 00(*文件子系统)
注释:标明可执行文件所期望的子系统
2-3-30 NumberOfRvaAndSizes[DWORD]--->10 00 00 00(数据目录表的项数,默认值16)
注释:数据目录的项数,这个自动从NT系统发布以来就是16
2-4 数据目录表
2-4-2 Import Table
注释:输入表
2-4-2-1 VirtualAddress[DWORD]--->10 20 00 00(*数据块起始RAV)
注释:输入表的起始地址,要去除IAT所占空间,直接从第一个IID开始
2-4-2-2 Size[DWORD]--->3C 00 00 00 (*数据块大小)
注释:从第一个IID到最后一个IMAGE_IMPORT_BY_NAME的总长度
3 块表
3-1 IMAGE_SECTION_HEADER(1.text)
3-1-1 Name[BYTE]--->2E 74 65 78 74 00 00 00(*8个字节的块名)
注释:此区块的名称,限制在8个字节内
3-1-2 VirtualSize[DWORD]--->26 00 00 00(被实际使用的区块大小)
注释:此区块包含数据的大小
3-1-10 Characteristics[DWORD]--->20 00 00 60(该区块的读写执行属性)
*----------------------------------------------------------------*
| 字段值 | 用 途 |
-----------------------------------------------------------------
| 00000020h | 包含代码,常与10000000h一起设置 |
-----------------------------------------------------------------
| 00000040h | 包含已初始化数据 |
-----------------------------------------------------------------
| 00000080h | 包含未初始化数据 |
-----------------------------------------------------------------
| 02000000h | 可以被丢弃 |
-----------------------------------------------------------------
| 10000000h | 共享块 |
-----------------------------------------------------------------
| 20000000h | 可执行 |
-----------------------------------------------------------------
| 40000000h | 可读 |
-----------------------------------------------------------------
| 80000000h | 可写 |
-----------------------------------------------------------------
4 块
4-1 .text(*此区段是一段汇编代码的16进制形式,功能是弹出一个MessageBox提示框)
6A 00 68 00 30 40 00 68 07 30 40 00 6A 00 E8 07 00 00 00 6A 00 E8 06 00 00 00 FF 25 08 20 40 00 FF 25 00 20 40 00
4-2 .rdata (该区块包含输入表)
4-2-1 IMAGE_THUNK_DATA32(IAT1)
注释:其实IMAGE_THUNK_DATA32是一个联合体,可以同时代表IAT和INT
4-2-1-1 AddressOfData[DWORD]--->76 20 00 00(*指向IMAGE_IMPORT_BY_NAME的RVA)
注释:作为IAT时我们就使用它的成员AddressOfData成员,用来存放指向IMAGE_IMPORT_BY_NAME的RVA,当程序装入内存后,只与IAT交换信息,输入表的其他部分就不再需要了。[由于本例子中两个API引自两个不同DLL中,所以要补充00 00 00 00结束]
4-2-3 IMAGE_IMPORT_DESCRIPTOR(IID 1)
注释:这里稍微复杂些,它的作用是使用INT指定某个DLL文件中的API函数,并配合IAT指向相关API的地址
4-2-3-1 OriginalFirstThunk[DWORD]--->4C 20 00 00(*指向输入名称表INT的RVA)
注释:这里指定某个DLL中API函数
4-2-3-4 Name[DWORD]--->6A 20 00 00(指向DLL名字的RVA与指针)
注释:这里指定某个系统DLL
4-2-3-5 FirstThunk[DWORD]--->08 20 00 00(指向输入地址表的IAT的RVA)
注释:这里指定相关的IAT,并由IAT在IMAGE_IMPORT_BY_NAME中获得相应API的地址
4-2-4 IMAGE_IMPORT_DESCRIPTOR(IID 2)
4-2-4-1 OriginalFirstThunk [DWORD]--->54 20 00 00(*指向输入名称表INT的RVA)
4-2-4-4 Name [DWORD]--->84 20 00 00(*指向DLL名字的RVA与指针)
4-2-4-5 FirstThunk [DWORD]--->00 20 00 00(*指向输入地址表IAT的RVA)
[填充20个00h空字节做结尾标记]
4-2-5 IMAGE_THUNK_DATA32(INT 1)
4-2-5-1 ForwarderString [DWORD]--->5C 20 00 00
注释:直接指向相关API函数
【由于本例子中两个API函数引自两个不同的DLL中,所以要补充00 00 00 00结束】
4-2-7 IMAGE_IMPORT_BY_NAME(1)
4-2-7-2 Name[BYTE]--->4D 65 73 73 61 67 65 42 6F 78 41(MessageBoxA的16进制码)
注释:相关API函数的16进制码
【后面跟输出函数的DLL名称16进制码00 75 73 65 72 33 32 2E 64 6C 6C 00 00 user32.dll】注释:相关系统的API函数罗列完毕后,通常在最后一个AIP后面加00,并跟着DLL名称的16进制数据
三 PE文件结构字段清单
1 DOS头部
1-1 DOS Header
1-1-1 e_magic [WORD]---> 4D 5A(*DOS可执行文件头标记)
1-1-2 e_cblp [WORD]---> 00 00(文件最后页的字节数)
1-1-3 e_cp[WORD]--->00 00(文件页数)
1-1-4 e_crlc[WORD]--->00 00(重定位元素个数)
1-1-5 e_cparhdr[WORD]--->00 00(以段落为单位的头部大小)
1-1-6 e_minalloc[WORD]--->00 00(所需的最小附加段)
1-1-7 e_maxalloc[WORD]--->00 00(所需的最大附加段)
1-1-8 e_ss[WORD]--->00 00(初始的堆栈段(ss)相对偏移量)
1-1-9 e_sp[WORD]--->00 00(初始的堆栈指针(SP)值)
1-1-10 e_csum[WORD]--->00 00(校验和)
1-1-11 e_ip[WORD]--->00 00(初始的指令指针(IP)值)
1-1-12 e_cs[WORD]--->00 00(初始的代码段(CS)的偏移量)
1-1-13 e_lfarlc[WORD]--->00 00(重定位表在文件中的偏移量)
1-1-14 e_ovno[WORD]--->00 00(覆盖号)
1-1-15 e_res[WORD]--->00 00(保留字,一般都为确保对齐而保留)
1-1-16 e_oemid[WORD]--->00 00(OEM标识符,相对于e_oemid)
1-1-17 e_oeminfo[WORD]--->00 00(OEM信息,即OEM细节)
1-1-18 e_res[WORD]--->00 00(保留字,一般为对齐而保留)
1-1-19 e_lfanew[DWORD]--->B0 00 00 00(指向PE文件头的偏移量,BO=64+112)
2 PE文件头
2-1 PE 00
2-1-1 Signature[DWORD]--->50 45 00 00(*PE文件头标记)
2-2 IMAGE_FILE_HEADER
2-2-1 Machine[WORD]--->4C 01(可执行文件的目标CPU类型)
2-2-2NumberOfSections[WORD]--->03 00区块数目
2-2-3TimeDateStamp [DWORD]--->00 00 00 00(文件创建时间和日期)
2-2-4 PointerToSymbolTable[DWORD]---->00 00 00 00(指向符号表,用于调试)
2-2-5 NumberOfSymbols[DWORD]--->(符号表中的符号个数,用于调试) 00 00 00 00
2-2-6 SizeOfOptionalHeader[WORD]--->E0 00(PE头IMAGE_OPTIONAL_HEADER32)大小
2-2-7 Characteristics [WORD]--->OF O1 (*文件属性)
2-3 IMAGE_OPTIONAL_HEADER32
手写PE文件(一)的更多相关文章
- 手写PE文件(二)
[文章标题]: 纯手工编写的PE可执行程序 [文章作者]: Kinney [作者邮箱]: mohen_ng@sina.cn [下载地址]: 自己搜索下载 [使用工具]: C32 [操作平台]: win ...
- 010Edit手写PE
前言PE结构DOS头IMAGE_DOS_HEADERPE头介绍总大小[248字节]结构体含义标记(4字节)0x4550文件头(20字节)扩展头(224字节)为程序添加ExitProcess函数 前言 ...
- UI进阶之--网易彩票手写plist文件,动态创建控制器与tableViewcell
点击右上角设置按钮 点击按钮后发生的事件:1. 控制器的跳转,进入新的控制器.view, 2. 跳转的时候对将要跳转的目标控制的子控件进行了布局.---通过手写plist文件的方式加载 为按钮注册单击 ...
- 手写PE结构解析工具
PE格式是 Windows下最常用的可执行文件格式,理解PE文件格式不仅可以了解操作系统的加载流程,还可以更好的理解操作系统对进程和内存相关的管理知识,而有些技术必须建立在了解PE文件格式的基础上,如 ...
- 手写JAVA虚拟机(三)——搜索class文件并读出内容
查看手写JAVA虚拟机系列可以进我的博客园主页查看. 前面我们介绍了准备工作以及命令行的编写.既然我们的任务实现命令行中的java命令,同时我们知道java命令是将class文件(字节码)转换成机器码 ...
- 手写简单PE
环境工具:Windows 10 010Editor 目标程序功能: 调用MessageBoxA弹出消息框. 1.构造DOS头 typedef struct _IMAGE_DOS_HEADER { // ...
- 编写自定义PE结构的程序(如何手写一个PE,高级编译器都是编译好的PE头部,例如MASM,TASM等,NASM,FASM是低级编译器.可以自定义结构)
正在学PE结构...感谢个位大哥的文章和资料...这里先说声谢谢 一般高级编译器都是编译好的PE头部,例如MASM,TASM等一直都说NASM,FASM是低级编译器.可以自定义结构但是苦于无人发布相关 ...
- SpringBoot项目里,让TKmybatis支持可以手写sql的Mapper.xml文件
SpringBoot项目通常配合TKMybatis或MyBatis-Plus来做数据的持久化. 对于单表的增删改查,TKMybatis优雅简洁,无需像传统mybatis那样在mapper.xml文件里 ...
- 【转】机器学习教程 十四-利用tensorflow做手写数字识别
模式识别领域应用机器学习的场景非常多,手写识别就是其中一种,最简单的数字识别是一个多类分类问题,我们借这个多类分类问题来介绍一下google最新开源的tensorflow框架,后面深度学习的内容都会基 ...
随机推荐
- 解决dropdownlist postback 在 iphone UIwebview 失效的问题
原因: IPhone UIWebView 的 用户代理 User Agent 在ASP.NET 4.0环境下是不识别的:所以ASP.NET提供了一个默认的,低级的不包括javascript的页面版本 ...
- Python学习教程(learning Python)--2.2 Python下的变量基础
变量的基本概念,变量可以这样去理解,变量是一个值,这个值存储在计算机的内存里.以 网购为例,您在选购傻商品的时候,是在不同页面里选不同的商品,选好一件点击“放入购物车”,选完了再点击去结帐,这些商品的 ...
- [转]判断程序是否运行在 Windows x64 系统下
以下功能代码判断是否运行在 Windows x64 下.本例使用 Windows API 函数 IsWow64Process,具体请参考MSDN文档:http://msdn.microsoft.com ...
- Lex+YACC详解
1. 简介 只要你在Unix环境中写过程序,你必定会邂逅神秘的Lex&YACC,就如GNU/Linux用户所熟知的Flex&Bison,这里的Flex就是由Vern Paxon实现的一 ...
- poj 2777 Count Color
题目连接 http://poj.org/problem?id=2777 Count Color Description Chosen Problem Solving and Program desig ...
- 怎么解决/bin/sh: arm-linux-gcc: not found make
1.arm-linux-gcc 环境变量没有设,所以找不到这个编译器 在/etc/profile里添加arm-linux-gcc的存放路径 sudo -s gedit /etc/profile 编 ...
- LD_PRELOAD
下面的helloworld会在屏幕上打印出什么内容? 1 2 3 4 5 6 #include <stdio.h> int main(int argc, char* argv[], cha ...
- ListView usage in ERP-DEV
ListView Learning Note how to add double click event to listviewitem in ListView. refer link in stac ...
- FPGA入门1
FPGA入门知识介绍 近几年来,由于现场可编程门阵列(FPGA)的使用非常灵活,又可以无限次的编程,已受到越来越多的电子编程者的喜爱,很多朋友都想学习一些FPGA入门知识准备进行这个行业,现在关 ...
- 1.总结---tr()和QTextCodec对象
1. 关于Qt 中的tr()函数-------http://tscsh.blog.163.com/blog/static/200320103201310213312518/ 在论坛中漂,经常遇到有人遇 ...