目 录
目 录 1
摘 要 2
ABSTRACT 3
第一章 绪论 4
一.研究背景与意义 4
第二章 程序的分析与实现 5
一. 前提 5
1. PE格式简介 5
二. 加壳主程序 8
1. 加壳的概念 8
2. PE格式的判断 10
3. 文件读入内存 12
4. 读取附加数据 14
5. 处理输入表 15
6. 处理重定位表 18
7. 压缩文件 21
8. 处理资源数据 23
9. 合并节 28
三. 外壳部分的编写 29
1. 外壳工作流程概述 29
2. 外壳第一段 30
3. 外壳第二段 35
四. 将外壳部分添加至原程序 40
第三章 结论 46
参考文献 47
致 谢 48
1. 加壳的概念
对程序文件加密时有一个方面是必须要考虑的,那就是防止解密者对程序文件的非法修改和反编译。要实现这种保护,最常用的方法之一就是给编译好的程序文件加上一个外壳。所谓的外壳就是附加在原程序上,通过windows装载器载入内存后,先于原程序执行,得到控制权,执行过程中对原程序进行解密、还原,还原完成后再把控制权交给原程序,执行原来的代码部分。加上外壳后,原程序代码在磁盘文件中一般是加密后的形式存在的,只在执行时在内存还原,这样就可以比较有效的防止破解者对程序文件的非法修改,同时也可以防止程序被静态反编译。
对程序的加壳一般是选用一些现成的加壳软件,如tElock,Asprotect,Aspack,UPX等。不同的外壳所侧重的方面不一样,有的侧重于压缩,有的侧重于加密。为了更好地保护软件,一般可以来用tElock,Aspuroct等侧重于加密的加先软件。使用现成的加壳软件虽然很方便,却存在着一些不可避免的缺点:越是先进、优秀的加壳软件有时反而会越不安全。为什么呢?因为加壳软件越优秀、用它加密的软件越多,研究它的人也会越多,其中必定有一些高手会分析出这些外壳所用的关键技术,并将其公开,有时甚至会针对这些加壳软件而写出专门的脱壳机。一旦一个加壳软件被写出脱壳机,那么用它加密的软件的保密性就可想而知了。所以写一个自己专用的加完软件还是有一定意义的。
本设计编写了一个简单的加壳程序。在这个加壳程序中要实现的主要功能有:对程序的压缩、对资源的处理、对输入表的处理、区块的融合和额外数据的保留等。
本设计的加壳工具有两部分组成,第一部分是主体程序,主要是将原PE文件读入内存,然后对PE文件各个部分加工,主要是各区块数据压缩,将输入表、重定位变形,最后将外壳部分与处理好的主体文件拼合。第二部分就是外壳部分,这部分主要是加壳后程序执行时候的引导段,它模拟PE加载器处理输入表、重定位表,最后跳到原程序。
最终装配成一个完整的程序结构,如图所示。
目标程序新增了一个区块.lgj,这部分就是“壳”。区块.text,.data等是原始数据的代码数据,不过现在是以压缩的形式保存的。另外,为了简化,本设计没处理输入表,其所在区块仍以明文形式存在。
在“.lgj”区块里,以ShellStart为分界,之前的部分以非压缩的方式存在,之后的部分是以压缩的方式存在的。新程序的入口点指向外壳ShellStart0开始的部分,外壳执行时先执行这部分,这部分主要功能是将ShellStart开始的真正的外壳代码在内存中解压缩,并初始化一些数据。初始化完成后转移到ShellStart继续执行。ShellStart开始的代码是外壳的真正部分,它的主要功能是还原原始程序(.text,.data等区块数据),另一个重要的功能是阻止破解者的跟踪、脱壳。所以一般来说这段代码比较长,里面还有各种反调试器,反DUMP的代码。将它以压缩的方式存储一方面可以减小文件尺寸,另一方面也有利于程序的安全性。
2. PE格式的判断
由于处理的程序对象是PE格式,所以对文件进行处理前必须先判断文件是否符合PE格式。
检验的方法是:先看文件头部第一个字的值是否等于IMAGE_DOS_SIGNATURE,也就是字符串“MZ”,如果是,则表示DOS MZ header有效。其次根据e_lfanew字段找到PE header,检查比较PE 头部的第一个字的值是否等于IMAGE_NT_SIGNATURE,也就是“PE”。如果前后两个值都匹配,那么就认为该文件是一个有效的PE文件,最后再检查一下FileHeader结构中的characteristics字段的值,判断是EXE文件还是DLL文件。