首先声明,不要被这个题目所迷惑,我所谓的流行只是我以为他应该要流行,并不是说一定就是现在所流行的技术,再者,我很菜,错误之处,请各位海涵.
         我并不太清楚壳的历史,因为关于它的特殊性再加上我所能了解的信息也非常局限性,在我看来第一款壳应该就是upx,但是或许事实并不是这样,因为地下壳是那么的多.而我并不知道第一款加密或者意想加密的壳是哪个,一是因为加密这个定义比较模糊,二是我根本不收集壳并研究.加壳的中心思想我想不外乎只有两点,一是尽可能的隐藏所能隐藏的东西,二是尽最大能力的拖延脱壳者的时间,让脱壳者那颗并没有无限大的忍耐度的心再也受不了为止.

IAT加密与解密的早期战场:
         早期的壳大多于只加密这个东东,因为他便利,加密起来也简单.正如我所说我并不研究壳,所以很有可能我的思路是错误的.
        一种简单的加密思路是将被加密程序的IAT数据保存于壳内,然后新建立一个IAT导入表,里面只导入壳需要使用到的函数,比如很多壳都喜欢只导入LoadLibrary和GetProcAddress两个函数,这样其他函数可以再通过这两个函数来动态定位.关于后来例如Asprotect这样的每个dll导入一个函数的做法完全是为了更好的兼容性.将这些数据保存于壳内后,壳在Loader执行的时候就手动加载每一个dll填充每一个函数,这是一种非常简单的加密手段,目的正如我上面所说的,隐藏信息.
         我想应该是这种方法很快就不够用了,因为他脱起来也较简单,等壳装载完毕后,直接用REC就可以修复.这导致了新加密方法的使用.
         新的IAT加密方法和上面的加密方法基本上差不多,但是在最后填充函数地址的时候,也就是在壳加载了函数所在DLL和获得函数地址之后并不直接填充到IAT跳转描述表里面,而是保存起来,然后将跳转描述表里面相应位置填充为指向壳的一段代码,这段代码负责动态解密跳转到真正的函数地址.形成一个代理模式.这种方法仍然是现在流行的方法,大部分的加密壳都是基于这个原理的,只不过实现手段上不同而已.有的壳是直接跳转到壳里,然后立马又跳回真正的函数地址,我很能理解这样做的原因,因为我知道写一个复杂的代码连接引擎并不是很容易.大部分壳这个过程是动态的,也就是在loader的时候动态生成跳转代码的,这有一个很致命的缺点,因为这样或多或少的会形成一个magic jmp,因为一般并不是所有函数都能被代理,所以必须还得考虑兼容性的问题,所以很多壳只代理了一部分函数,其他函数也只是获取地址然后填充,这样一个简单的过程,但是他们又不注意将需要代理的函数在加壳时给予区分,而是在loader里面判断是否加密,所以导致magic jmp,这样把所有信息行为都暴露给脱壳者是很不划算的.
         还有一种较上面方法好一点的就是他们模拟了一些代码,也就是一些函数在壳里自己实现,来增加脱壳者修复的难度,但是从某个角度来说,这样的用处并不大.当然我们所考虑的情况都是再不使用SDK的情况下.
         我不得不说关于IAT加密并不会留住加密和解密的步伐,因为一般程序只有少量的导入数据,而且大部分函数都要直接跳转到真正的函数入口,而写壳的不可能将所有的函数都模拟起来,实际上模拟起来也并不难修复.所以注定这个早期的战场迟早会被淡化,加壳和脱壳会寻找新的火拼点.
CODE现在流行和将来流行的火拼点:
         很早我就意思到加壳迟早会回归到这上面来,早期没有人过多于将精力放在这上面是因为处理代码远比处理IAT难度要大,要复杂,要考虑得多. 代码处理流行的技术在我了解的有以下几种主要方式.
         1.VM
         2.代码变形
         3.代码乱序
         4.代码寄生
         5.花指令
         6.代码抽取
还有一种早期我用过的代码移位技术我这里并没有列为主要技术,因为它是这里面最容易被还原的技术,但是可以用来和上面的技术组合,将是很不错的.
         首先我们来看看VM,我不知道这技术是什么时候开始被使用的,但是很显然的,他将成为现在和将来壳所发展的趋势,尤其是在cpu执行速度越来越快的今天.我这里并不想教你怎样写一个VM,但是我会或多或少的给你一些建议.
         首先让我来阐述一下VM的工作原理,VM就是我们平常说的虚拟技术,他是将原来的代码变成OPCODE,然后写一个虚拟机来解释执行OPCODE来完成原来代码的功能.核心原理也逃不出文章一开始我所说的两点.但是到如今使用也不多的原因是因为实现难度比较大,因为写好一个虚拟机引擎并不容易,你将必须有非常好的构架,否则你将不容易成功.你必须增加OPCODE的灵活性来代替你翻译代码为OPCODE的工作量,你不得不仔细而反复的看intel的开发手册,而你还得考虑虚拟引擎工作环境,你需要考虑线程安全,重入等问题.而你还得考虑虚拟引擎堆栈管理,等一系列技术问题,不过还好这些也并不是多么复杂而且不为人知.
         代码变形并不是一种多么必不可少的技术,如果只用代码变形,那么将没有什么难度可言,之所以介绍它是因为他和其他技术组合,效果非常令人满意,很显然,代码变形就是将code转化为多种实现方式,以迷惑脱壳者,或者说这种技术更用于迷惑破解者,因为他们对脱壳者带来的影响并不大,我们简单来看看代码变形是如何操作的,比如mov eax,eax那么可以变形成push eax,pop eax,然后实际运用中不会这么乏味,他们会随机选取多种设定好的变换方式,然后穿插花指令,那么效果非常不错,然后这种技术运用也不太多,因为他的实现难度和效果并不成正比,加上变形当前阶段下很不好高度随机化,不过我已经想到了一种提高随机性的方法.只是还没有去验证.
         代码乱序是一种我很推荐的,而且在将来会流行的技术,因为他的实现难度和效果是成正比的,而且兼容性也不会太差,代码乱序就是将一段代码的顺序打乱,然后分成小片,一片有一条或者多条指令,中间使用jmp或者其他跳转方式转移到下一条指令,这种方法很明显的有不少优点,比起VM来,他需要考虑的更少,实现起来更方便,然后如果加上花指令,代码变形你将发现,不管你是动态分析也好,静态分析也罢,你已经被带到一个痛苦的边缘,况且他的还原工具还很不好写.然后这种方法至今我没有看到太多,这或多或少有些遗憾,不过我想未来肯定会流行起来,当然不排除会出写一些飞跃的技术,很有可能是硬件带来的质的飞跃,导致这些技术纷纷落后将不再使用.
         代码寄生这种我尚未尝试过的模型,只是我一天睡觉前偶尔意思到的,我很少在睡觉前想这些东西,但是那是一次意外,其实代码寄生的实现难度是比较大的,但是他的优势也是很明显的,况且如果这种技术被应用到病毒或者其他方面大概也会有所作为,大概思路就是将一段代码的执行,全部寄生到目标代码的各个部位,你可以找函数和函数之间的空隙,你甚至可以将目标代码的代码变形,然后和寄生代码穿插,这种模型理论上是完全可以实现的,但是我现在尚没有时间来验证,不过我已经有这个计划.
         花指令是现在非常流行而且几乎所有加密壳都得使用的技术,花指令大概分两种,一种是行为花指令,也就是某种意义上的代码变形,一种是空间花指令,也就是只站用代码空间,不会被执行到的,但是却可以让反编译引擎产生幻觉的东西.我想大家对于这个都已经是非常了解了,所以不再多说.
         关于代码抽取,这种方法的大概思路是将壳的代码抽取出来然后放到壳里面,然后修改被抽取地方代码的流程,当运行到代码处的时候就到壳里执行这些代码,这些技术流行的原因是因为他处理起来简单,效率上影响又不大,而且很容易和其他技术相结合.
         大概的现在和未来短时间内人们使用的加壳技术的代码处理上差不多就只有上面几种或者是上面集中的高级版本或者变形版本等等,但是核心大概也不会差得有多远.
Anti加壳与脱壳的暗中较量:
         曾经在哪儿看过说是没有Anti的壳不算是一款成功的壳,我也比较赞同这个观点,至少当前来说,但是可以预见的是,这种观点会随着技术的进步被淡化,甚至抛弃.
         我对Anti很不在行,也不花太多时间于研究Anti技术,所以我也只能模糊的说一些关于Anti方面的认识.
         早期的壳我想大多Anti都依赖于那几个检测调试器的系统函数,后来的Anti开始有了些变化,加壳者开始使用各种不同的方法来针对性的探测是否有调试器存在,比如CreateFile,查找窗口类,标题,什么的,这些已经过事的技术现在已经越来越感觉他的无助了,因此有人开始研究主要调试器的一些信息,或者漏洞,一旦发现则用之,这种短时性的针对性很强的Anti很显然也会在短时间内从壳中消失掉.几乎同时利用多线程技术,和seh异常技术,来拖延或者检测调试器的手段和使用越来越多,虽然无法从根本上不被调试,但是总比没有要好得多.而且一种新Anti的出现,往往脱壳者耗费在这上面的时间也并不少.然而到如今也没有出现多么通用性或者有效性的Anti,可以预见的是未来短时间内也不可能出现这样的Anti更何况在这种调试手段日益增多的情况下.
充分发挥各种构架的优势:
         我在上一篇中提到过关于构架的优势,有些构架有天生抗Anti的优势,这就是为什么EncryptPE刚出来的时候很少有人愿意去研究的目的,因为调试手段的缺乏使脱壳者们都失去了耐心.机遇调试机智的构架拥有天生抗Anti的优势,但是这种优势也并不是功不可破,但如果发挥到极限,也可以浪费不少时间.
硬件的地位将重要起来:
         这两年加密狗或者加密卡等等之一系列的流行说明硬件将扮演一个越来越重要的地位,由于物理隔离(我想并不是所有破解或者脱壳者都愿意去弄个狗什么的的,他们更愿意研究其他的)等的诸多缘故,这些使用了硬件技术的不管是好与不好的壳都被研究得较于其他的壳少,而且随着硬件当前的发展趋势,研究起来的难度也越来越大.从另一个方面表现出来就是他的有效性越来越高,加之成本开始低廉起来,很显然将成为主要地位.前提是上尉出现一种可行的全软的终极方案,但这种方案很显然将在不久的将来出现,至少现在已经有它们的皱型.
网络决定一切?
         这两年网络的天翻地覆是大家有目共睹的,各个行业都开始网络化,自然加壳技术也不会忘记这种越来越有效的手段.或者不久一种终极方案就要出现了,尽可能的让服务器来完成工作,然后通知客户端,但是这种已经脱离了加壳意义的加密手段或者保护手段,并不是我想说的重点,但是很显然他们将为重视.不过在加壳技术上,可以通过把一部分代码保存在服务端上,然后等到授权或者运行时再向服务端请求数据,这种模型在加密狗上似乎已经普遍实现,但是全软的我似乎还没看到,但是他们仍然是一种可行的方案.
resource更加让脱壳着头疼:
         对资源的加密不流行的原因从某种意义上来说是因为本身对于资源的处理就比较让人头疼,他的乱七八糟的树型结构饶来饶去的实在不太一目了然,但是很显然的,他仍然是可以被加密的,从加密手段上来说,大概有资源移位,但是和代码移位一样,实际效果并不好,也有资源重组,也就是修改资源树目录,然后把资源分散开来,让现在工具缺乏的情况下,使得资源修复够折腾人,然后和IAT一样,由于资源也是小量的,所以依然可以手工在短时间内修复.还有一种加密模型就是hook所有有关资源的系统api然后动态供给资源,但是也许你会发现,在兼容性和加密强度两难的情况下,这个并不是你想要的.
其他加密手段:
         对于PE其他部分,例如导出表啊,重定位信息啊,由于他们在PE里面时有时无,并且也并没有多么高明的加密手段,所以注定了并不会有所作为,所以这里将不再阐述.