-
-
PE结构学习之理论基础
-
发表于:
2017-4-26 08:09
20395
-
学习PE结构的相关知识已经有有一段时间,近几日开始尝试写一个简单的压缩壳,意在加深对PE结构中常用字段的理解,以及对数据目录表的理解。欲将收集到的资料,加上自己的理解与加工,整理出来,分享,大家共同交流。
part.1 PE结构简介
资源来源:
http://bbs.pediy.com/thread-203563.htm
鉴于PE的解析的帖子以及教程非常多,我这里只是介绍一下学习的过程与思路,具体的内容还是需要自己去记忆与理解。
首先上一张,我认为概括的比较直观的图,结合PEtool或者其他的PE解析工具以及压缩包中的PDF文件,首先将pe的每个字段所在位置,整体分布,由一个宏观的把握。个人感觉PE字段的命名有一定的规律,了解了文件偏移,虚拟地址,相对虚拟地址这些概念之后,一部分字段就可以猜测出含义,部分没有规律的,可以百度之。
以上的知识梳理过后,我们有了一个对于PE的宏观印象,如下图:
当然,也要注意在这个示意图中,没有显示出文件对齐与内存对齐。
Part2.PE文件的拉伸
就本人的经历而言,对于一些知识如果不加以利用,看看具有由哪些用处的话,很快就会遗忘掉。这里,我们写一个简单的小例子,简单模拟一下PE文件加载进内存的操作。这部分知识参考滴水公开的视频,不过海哥使用的是C语言的函数对PE文件进行读写操作,而我改成了使用系统API来实现。
大体思路与流程如下:
● 读取PE文件;
● 按照文件大小开辟空间A,全部初始化为0,然后将PE文件的内容写入开辟的新空间A中;
● 按照SizeOfImage这个参数开辟空间B,全部初始化为0;
● 将内存中的PE从A的开始部分往B拷贝SizeOfHeaders大小;
● 然后开始循环,把每个区段,写入到Misc这个位置,写入SizeOfRawData大小,一直拷贝完所有区段,
注意事项:
遇到RVA需要转化成原先的偏移,然后再加上现在的基址得到现在的地址
主要代码:
函数readpefile:将PE文件读取到内存中
函数filebuffertoimagebuffer:在内存中将pe的内容,进行拉伸
这里也只是模拟加载的部分步骤,剩下的部分暂且不去讨论,今后补全了这部分知识,再发出来讨论。
总结,只是演示功能,为了省事,所以不少本来应该作为参数传出的变量,本人直接定义为全局的。(我才不会说是因为指针与引用使用不熟练呢)
Part.3 PE还原
大体思路与流程如下:
● 利用最后一个区段的SizeOfRawData加上最后一个区段的文件偏移PointerToRawData得到文件的大小
● 开辟一个空间C,先将空间B的PE头拷贝过来
● 然后循环遍历区段表,将所有区段按照区段的属性拷贝到空间C中
● 然后将空间C写入到一个新的文件中
这个过程就是Part2的逆过程。
主要代码:
imagebuffertonewfilebuffer:将拉伸后的PE文件还原到PE初始的状态
new_memerytofile:将还原过的PE写回到一个新文件中
代码写的很渣,基本是怎么方便怎么来的,但是在附件中也展示出来,有需要的小伙伴可以参考改进
这部分知识,对于今后写壳的时候,有着启发性的作用,熟练的掌握了PE的结构,以及对于PE文件的读写操作,内存中的拷贝操作,这都是写壳所必备的知识,应当熟练掌握。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!