PE文件格式实验
更新时间:2024-02-26 20:58:02 阅读量: 综合文库 文档下载
PE文件格式分析实验
使用工具LordPE/PEview、winhex
选择一个exe或者DLL文件
阶段一:(本次实验)
1. DOS头部查看、对应DOS头结构进行数据逐项分析 2. PE头部查看、对应PE头结构进行数据逐项分析
3. Exe文件和DLL文件均是PE格式,他们的区别在哪里?
4. Section表结构的查看(是否可以增加一个新的section表?对齐边界是多少?) 5. PE文件section查看、对应section 块表结构进行数据分析 6. VA、RVA、RA计算
7. 问题:你查看的PE文件DOS、PE头部的空隙是多大? 8. 问题:你查看的PE文件在那个section的空隙最大/最小?
9. 问题:如果手工增加一个section,要修改哪些字段,请手工试验。(提高:你的新块表
增加是否引起原文件的对齐位置的改变?) 10. 问题(提高):一个section的属性字节如何设置,请在上一个问题基础上实验。
本次实验要求对照以上要求,自行选择文件进行分析,撰写报告。
阶段二:(后一阶段的工作) 1. 资源查看、修改
2. 编写PE文件分析程序 3. 编写PE病毒程序
附录1PE格式详细讲解(一)
前几天发了一个PE信息查看器的小工具,本来想用那个获取邀请码的,可是觉得几率不是太大,于是再献上一篇教程,既是为了自己能获得邀请码,也是帮助那些想学习PE格式的人,让知识来源于网络再回归网络。
N年没写文章了,不知道句子还能不能写通顺,最近正在看《软件加密技术内幕》,刚看完PE结构那部分内容,所以想起来写篇教程作为读书笔记,既可加强记忆又可帮助别人,何乐而不为呢。
好了,废话少说好戏正式上场,PE是英文Portable Executable(可移植的执行体)的缩写,从缩写可以看出它是跨平台的,即使在非intel的CPU上也能正常运行的。它是 Win32环境自身所带的执行体文件格式。其实不光是EXE文件是PE格式,其它的一些重要文件,例如动态链接库文件(DLL),驱动文件(SYS)等也是PE格式的,所以学好PE格式是非常重要的,以下我把这类文件统称为PE文件。学习PE文件结构不仅可以使我们知道可执行文件是怎样运行的,也可以使我们了解一下windows操作系统的一些工作机制,精通PE是成为计算机高手的必经之路。
其实说白了PE文件格式就是一种文件组织的方式,里面对一些重要信息的存放做了一些规定,比如文件要运行,我们就得先知道入口地址,可是我们从哪去得到入口地址呢,我们必须把保存有入口地址信息
的有关数据放在固定的位置,这样不管是哪个文件我们就能从那个固定位置取得入口地址,而这固定位置就是PE标准所规定的。现在我们就来正式学习这套标准,我觉得从整体到部分是个很好的学习方法,先从整体把握全局,然后再重点各个击破,逐渐深入,下面我就以这个思路来介绍PE文件格式,方便大家快速掌握。它总体上由五大部分组成: 1.DOS MZ header(DOS头) 2.DOS stub 3.PE header(PE头) 4.section table(节表) 5.section(各个节)
所有的PE文件必须以一个DOS MZ header开始,其实它是一个IMAGE_DOS_HEADER类型的结构,这个结构的定义我们可以在WINNT.H头文件找到,此结构中有两个重要的成员是我们必须知道的,第一个e_magic,它是一个DWORD类型的变量,这个变量只有一个用处,就是当我们要判断一个文件是不是PE文件时,我们首先需要把这个变量的值与IMAGE_DOS_SIGNATURE比较,相等就完成了判断的第一步,当然后面我们还得判断一个标志,不等的话就说明当前文件不是PE文件。第二个成员就是非常重要的了,可以说只要它一出错我想这个文件就坏了,它就是e_lfanew,这是一个LONG类型的变量,里面存放了PE头在这个文件中的偏移量,它是定位PE头的关键数据,知道这两个成员的意义后DOS头学习基本就完成了。接下来的DOS stub实际上是个EXE,当当前系统不支持PE文件结构时它能输出一个错误提示“This program requires Windows”,不是很重要。接下来是重头戏PE头,PE头是一个IMAGE_NT_HEADERS类型的结构,下面是这个结构在WINNT.H中的定义: typedef struct _IMAGE_NT_HEADERS { DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader; } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
它有三个数据成员,Signature是一个标志变量,这个就是当我们判断一个文件是否是PE文件时第二步需要判断的,若这个值等于\时就是一个PE文件,当然我们也可以像上面一样直接与IMAGE_NT_SIGNATURE这个常量比较,其实是等效的,因为IMAGE_NT_SIGNATURE是一个宏定义,它的实际值就是\。第二个成员是一个IMAGE_FILE_HEADER类型的对象,通常我们叫它文件头,这个结构在头文件中的定义是: typedef struct _IMAGE_FILE_HEADER { WORD Machine;
WORD NumberOfSections; DWORD TimeDateStamp; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
可以看出它有7个成员,下面我就对其中比较重要的成员做一说明,NumberOfSections这个成员保存了节的数目,至于节是什么东东,后面再说,在这只要知道它的数目保存在文件头的NumberOfSections中就可以了,当我们要遍历节时需要访问这个对象。PointerToSymbolTable,NumberOfSymbols这两个成员在调试时用的着,这里不做过多说明。SizeOfOptionalHeader这个成员保存了PE头中OptionalHeader这个成员的大小,最后一个成员是一个关于文件的标记,即这个文件是EXE还是DLL文件。总的来说文件头中包含了PE文件的物理分布的有关信息,比较重要的就是第二个成员了。接下来我们来学习PE头的第三个成员
OptionalHeader,这是PE文件结构中最重要的一个部分,因为大部分重要的数据结构都得通过它去定位,可以说它保存了PE文件逻辑分布的信息,但是这部分也是学习PE结构过程中的一个难点,因为层次结构比较多,我们定位一个结构需要抽丝剥茧般一层层进行下去,在此过程还得保持头脑清醒,对变量类型还得有比较深层次的理解。好了,我们还是那个原则,开始不要先涉入过深,先对这个成员有个总体的印象,它是一个IMAGE_OPTIONAL_HEADER32类型的对象,这个结构的定义是: typedef struct _IMAGE_OPTIONAL_HEADER { //
// Standard fields. //
WORD Magic;
BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; DWORD BaseOfData; //
// NT additional fields. //
DWORD ImageBase; DWORD SectionAlignment; DWORD FileAlignment;
WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD CheckSum; WORD Subsystem; WORD DllCharacteristics; DWORD SizeOfStackReserve; DWORD SizeOfStackCommit; DWORD SizeOfHeapReserve; DWORD SizeOfHeapCommit; DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
从这个结构的长度就可看出,它保存的信息不少,肯定很重要,在正式学习这个结构的成员前,我们还要理解一个重要的术语--RVA,RVA 代表相对虚拟地址。它是一个DWORD类型的数据,那RVA到底是什么呢?简单的说它是一个偏移量,这个偏移量是虚拟空间中相对于参考点的偏移,它的值就是偏移的大小,值得一说的是这个值只有当PE文件被PE文件装载器载入内存时才有作用,否则的话我们不能用这个值去直接定位与它相关的数据结构。如果在PE文件没有被PE装载器载入内存,而我们又想在PE文件中直接定位相关数据该怎么办呢,我们需要把这个值转换成文件偏移量,也就是相对于文件开头的偏移量,我们可以用RVAToOffset这个函数去完成地址的相关转换,至于这个函数的实现可以从网上找到。好了,准备工作做好了,下面我们就进入正题吧。由于这个结构成员较多,有些也不是很常用,还有有些我也不是很明白,所以就不说了,下面我就对一些比较常用的一一进行介绍吧。还希望大家不要像我一样一知半解的,要有宁可错杀一千,不可放过一个的学习精神。
AddressOfEntryPoint:
PE装载器准备运行的PE文件的第一个指令的RVA。若您要改变整个执行的流程,可以将该值指定到新的RVA,这样新RVA处的指令首先被执行。ImageBase PE文件的优先装载地址。比如,如果该值是400000h,PE装载器将尝试把文件装到虚拟地址空间的400000h处。字眼\优先\表示若该地址区域已被其他模块占用,那PE装载器会选用其他空闲地址。
SectionAlignment:
内存中节对齐的粒度。例如,如果该值是4096 (1000h),那么每节的起始地址必须是4096的倍数。若第一节从401000h开始且大小是10个字节,则下一节必定从402000h开始,即使401000h和402000h之间还有很多空间没被使用。
FileAlignment:
文件中节对齐的粒度。例如,如果该值是(200h),,那么每节的起始地址必须是512的倍数。若第一节从文件偏移量200h开始且大小是10个字节,则下一节必定位于偏移量400h: 即使偏移量512和1024之间还有很多空间没被使用/定义。
MajorSubsystemVersion MinorSubsystemVersion :
win32子系统版本。若PE文件是专门为Win32设计的,该子系统版本必定是4.0否则对话框不会有3维立体感。
SizeOfImage:
内存中整个PE映像体的尺寸。它是所有头和节经过节对齐处理后的大小。
SizeOfHeaders:
所有头+节表的大小,也就等于文件尺寸减去文件中所有节的尺寸。可以以此值作为PE文件第一节的文件偏移量。
Subsystem:
NT用来识别PE文件属于哪个子系统。 对于大多数Win32程序,只有两类
值: Windows GUI 和 Windows CUI (控制台)。
DataDirectory:
一IMAGE_DATA_DIRECTORY 结构数组。每个结构给出一个重要数据结构的RVA,比如引入地址表等。 可以告诉大家这个成员是PE结构的重中之重了,在这先给大家提个醒,让大家多看它两眼,加深对它的印象。
好了,到此为止,这个PE文件结构在总体划分上就只剩下节表和节没有介绍了,现在我就来说说节表和节吧,在正式介绍它之前,我先说一点它话,当然绝对是有助于你理解节表的,书大家都看过是吧,现在你想一想我们拿到一本新书时,做的第一件事是什么呢?首先我们翻开的是书的目录,然后从书的目录中去搜寻我们感兴趣的东西。可以打个形象的比喻,节表就相当于书的目录,而书中的各个章节就相当于PE文件结构中的节,通过目录我们能很快找到书中我们感兴趣的内容,同样通过节表我们很快能找到PE文件中的各个节。好了,有了定性的认识后我们还得继续升华,还得定量的学习它,这才是科学的学习方法。节表从数据结构的角度来说它是一个结构数组,所谓结构数组就是这个数组的每个成员都是同一种结构类型的变量。它们不光在逻辑上是连续的,在存储介质中也是连续的。同样我们也可在WINNT.H中找到这个结构的定义:
typedef struct _IMAGE_SECTION_HEADER { BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; union {
DWORD PhysicalAddress; DWORD VirtualSize; } Misc;
DWORD VirtualAddress; DWORD SizeOfRawData; DWORD PointerToRawData; DWORD PointerToRelocations; DWORD PointerToLinenumbers; WORD NumberOfRelocations; WORD NumberOfLinenumbers; DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
这个结构总共包含了10个成员变量,由于有些并不是很重要,所以我就对其中比较重要的做个介绍,如果你是那种追根究底的人,你自己完全可以继续查阅相关资料,了解一下其它成员的实际意义,不过要在你对我介绍的都掌握之后,学习把握主次是很重的,舍本逐末只会捡了芝麻丢了西瓜。好了,现在开始介绍吧。
Name[IMAGE_SIZEOF_SHORT_NAME]:
这个成员是一个字节型的数组,很明显它保存的是一个名字,我想你能猜到了吧,这就是节的名字,不过要注意一下,这个数组的上限是8,最多只能保存8个字符,还有就是它不是一个ASCIIZ字符串,因为它不是以null结尾的。
VirtualAddress:
本节的RVA(相对虚拟地址)。PE装载器将节映射至内存时会读取本值,因此如果域值是1000h,而PE文件装在地址400000h处,那么本节就被载到401000h。
这个很重要,定位节时需要它。
SizeOfRawData:
经过文件对齐处理后节尺寸,PE装载器提取本域值了解需映射入内存的节字节数。(译者注: 假设一个文件的文件对齐尺寸是0x200,如果前面的 VirtualSize域指示本节长度是0x388字节,则本域值为0x400,表示本节是0x400字节长)。
PointerToRawData:
这是节基于文件的偏移量,PE装载器通过本域值找到节数据在文件中的位置。
Characteristics:
包含标记以指示节属性,比如节是否含有可执行代码、初始化数据、未初始数据,是否可写、可读等。
基本上比较重要的成员都介绍了,我想你看了这么久肯定有点迷糊了,介绍了这么久的节表,那到底什么是节呢?还专门为它建立一个目录好像很重要似的。确实,可以说节才是PE内容的真正载体, 节其实我们可以想象成块,这样更形象点,因为一节就是一块数据,而且这块数据拥有共同的属性,比如是代码还是数据,是只读的还是读写的。学习节要牢牢记住几个字---共同的属性。就是说多个数据只要是具有共同属性我们就能把它放在同一节中,而不用去考虑这些数据是不是在逻辑上有什么关联。真正以数据之间逻辑关联建立的目录是PE头的第三个成员OptionalHeader,我们已经稍微了解了下了。
好了,对PE文件结构的总体构造已经介绍完了,但学习PE文件结构的任务还远远没有完成,因为还有导入表,象DLL还有导出表,还有到底怎么去定位PE中的重要结构等都没有介绍。我只能对你说,不要着急,一口吃不成胖子,学习决非一日之寒,尤其是计算机的学习,它是一个系统的认知过程,知识有很强的连贯性。所以对于决心学好的计算机的人,我有一句良言相赠----找准目标,持之以恒,绝不放弃。上面介绍的内容我参考了《软件加密技术内幕》这本书,由于我也是第一次真正接触PE,所以有些概念理解的不是很准确,希望大家多多包含,有时间大家可以看看原版。当然这只是这个PE教程的第一部分,如果大家不拿鸡蛋砸我的话,我还会写出后续部分。我的知识来自网络,所以我也要回馈网络,虽然现在水平还不是很高,但尽力了就行了。
附上PE信息查看器的下载地址,可以用这个小工具辅助学习,效果更好。 http://bbs.pediy.com/showthread.php?t=97970
附录2纯手工添加一个PE节
http://www.pediy.com/kssd/ 第三章系统篇 PE格式区块
作 者ID: yulongying 时 间: 2011-03-03
最近在公司时间比较闲暇,所以一直都在论坛闲逛,前段时间看了dncwbc一篇文章 《再写手工打造可执行程序》
http://bbs.pediy.com/showthread.php?t=130261
还写了一篇读后感 《再写手工打造可执行程序 读后感 》
http://bbs.pediy.com/showthread.php?t=130261
含金量比较低,但是对于新手还是有价值的,这里在前两篇文章基础上,探讨下怎么手动添加一个以0填充的section,其实原理都是一样,含金量也是比较低 呵呵 高手莫笑! 要修改的一共有以下几处
1、PE头结构中的 NumberOfSections +1 = 3+1=4
2、然后就是optional header中的SizeOfImage(加载到内存中的总大小)之前是(1+3)*1000=4000,这里再解释下此表达式1代表就是文件头 3代表pe文件中使用了3个section,1000就是SectionAlignment了;现在应该是(1+4)*1000=5000
3、在之前的.text .rdata .data三个sectionheader后面的空白文件段添加添加一个section header,对此section header分别域进行填充 section name 8个字节:.hawk 加载到内存中的大小 4个字节:1000
VA:最后一个section的VA+1000=3000+1000=4000 在文件中的大小还是:200
文件偏移:最后一个section文件便宜+其大小=800+200=A00
PointerToRelocations PointerToLinenumbers NumberOfRelocations NumberOfLinenumbers 依然均为0 Characteristics 我随便填了40 00 00 40
4、从 新增的section起始便宜A00一直填充0到BFF(大小为200h)
补充: 1、
添加一个section header我们发现是在file header与sections之间对齐之后产生的空隙中,如果不存在空隙或者空隙控件不够40(之前笔误写了40h 谢谢jsjnwms提醒)此方法就不使用了,应该就比较麻烦了,难道要重组pe?这里还请高手解答。
2、我们pe fileheader总大小dncwbc那篇文章计算过了原话:“我们的PE文件头总大小为:
64 + 112 + 4 + 20 + 224 = 424,3个节表头的总大小 3 * 40 =120。424 + 120 = 544 byte 转化成十六进制为220h”,现在我们已经添加过一个section header 现在应该为544+40=584 转化成十六进制为248h经过file alignment 200h对齐之后还是400,在这里不需要修改,如果对齐之后有变化那这块也需要修改。
上面仅仅是一个做为菜鸟的见解,如有遗漏之处还请各位多多抛砖指引哈。
上传的文件跟《再写手工打造可执行程序读后感》中的文件用UE简单对比以下就知道那些改动了。 上传的附件
正在阅读:
PE文件格式实验02-26
无言的爱作文700字06-28
晚饭不吃,饿治百病05-05
和书中人物密语作文600字06-18
铸造操作规程05-11
软件工程导论试题集04-27
2013-2014年高一上学期期末考试试题(语文)06-02
宝宝2岁第3个月发育指南08-15
信息技术与高中化学教学的整合之道11-30
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 实验
- 格式
- 文件
- 11.第二外语(俄语) 考试大纲
- 初中八年级数学下册第一章《三角形的证明》1.4《角平分线》教案3
- 中小学声乐教学有效途径的方法探究讲座心得
- 动物学复习题-刘凌云
- 代沟的责任在于子女 反方辩论
- 钜丰金业-新手如何炒黄金?
- 0-7、第七章 利润及利润分配
- 互联网金融产业对传统商业银行的影响
- 自己动手编写串口动态库(超详细)
- 江苏省东台市富安中学届九年级政史第16周双休日自主学习试题精选
- 血检作业
- 公文处理中常见错别字及语法、标点
- 最新教科版(六三制)小学语文三年级上册《古诗三首》优秀教案第
- 汽轮发电机交流励磁机励SD271-88
- 最新苏科版七年级上期中联考数学试卷(含答案)
- 中日两国渔船的性能和发展情况的比较研究
- 六年级15—16学年上册英语(北京版)u6单元测试(附答案)
- 生物化学复习资料
- 聘书的作用
- 2016-2017年广东省深圳市南山区九年级(上)数学期末试卷