逆向工程- 壳的介绍与利用
写在最前面:本篇文章主要用于记录逆向工程中有关于壳的知识,同时会对其进行实践。
什么是壳?
简单地讲,壳就是对核进行了一次包装。对于植物而言,瓜子、花生的外面都包有一层壳,它有硬度,能对里面的种子起到保护的作用。对于软件而言,壳的作用也类似,在一个程序的外面包裹一层外壳,可以起到对软件保护的作用。
根据壳的作用,可以分为两类:压缩壳
和加密壳。
- 压缩壳:顾名思义就是对软件进行压缩,使其体积减小,在软件被执行的时候对其进行解压缩,解压缩后的程序与加壳前的程序结构相同。压缩壳的作用主要是减小可执行程序的体积。
- 加密壳:就是对软件进行保护,它也是在软件被执行后或执行时进行解密,解密后的程序可能与加壳前的程序结构是不相同的。加密壳的作用主要保护可执行程序的安全,使其关键代码不被逆向或者不被破解等.
其中,加密壳又可以根据其保护强度分为:PE加密壳
和虚拟指令壳
。
- PE加密壳:软件加壳后 PE 格式的布局发生了变化,在解密后 PE 格式的布局也与原来的 PE 布局不再相同
- 虚拟指令壳:常称为虚拟机的壳,它将软件中的二进制代码中的指令进行模拟,也就是说原来的指令不见了,取而代之的是另外的一套指令系统,由于指令系统发生了变化,因此保护强度更高。
注:下面的示例一般以压缩壳和PE加密壳为主,虚拟指令壳不会涉及。
壳的基本原理
先给出一个简单的壳执行的示意图:
如图所示,加壳后的文件多了一个节表:Pack
,其中存储的就是解密的代码或者加壳后的数据。由于壳要首先取得控制权,因此程序的入口地址会指向壳的添加的节区(当然不是绝对的,也可能入口不变,而是修改入口处的代码),当壳的代码执行完成后,再跳回到原来的入口点进行执行。
用压缩壳举例说明。如果是压缩壳,那么整个 PE 文件会被压缩,然后将解压缩的代码放入新的节中。而在执行的时候,解压缩的代码会被先执行,在内存中完成解压缩的动作,解压缩完成后,会跳转到解压缩后的原程序的入口点开始执行。
同样的,如果是加密壳,会将PE文件的某一段进行加密,而后将解密的代码放到新的节中,在程序执行时,解密的代码会先被执行,在内存中完成加密的动作,之后跳转到解密后的源程序的入口地址处。
总结:壳就是对原PE文件进行保护操作,而后在程序执行时跳转到添加的节区处,执行添加的代码以实现文件的恢复,如:压缩后的解压、加密后的解密、导入表隐藏后的导入表填充等。从而使得攻击者无法从PE文件本身中得到某些信息。
加壳与脱壳
前面我们介绍了壳的基本原理以及压缩与加密两个功能。在实际的使用中,并不需要我们为了实现某个功能而重新编写代码、修改PE文件,而是使用一系列专门的加壳脱壳工具。
脱壳工具
加壳是为了保护软件不被逆向,脱壳工具的目的则是把软件的保护外壳解除掉,然后对软件进行逆向。
脱壳工具一般分为专用的和通用的脱壳机,通用脱壳机是根据外壳的类型或模拟执行进行脱壳,通用脱壳机能脱的壳较多,但是效果不好,专用脱壳机只能针对某一个壳(甚至是某一个壳的具体版本)进行脱壳,虽然它只能脱单一的一种壳,但是由于它的针对性特别强,因此脱壳的效果较好。
一次简单的加密壳模拟
首先来看一下需要加壳的可执行文件。
如图所示,就是一个简单的弹窗程序。
确定加解密方案
我们要对其进行加壳,首先要先确定加密和解密的方案,这里采取一种简单的异或进行,加密前后文件的区别如下。
如图所示,只是加密了前两个字节,加密密钥为0xCC。
增加PACK节
通过PEditor工具进行,增加前后的文件对比如下:
如图所示,增加了PACK节,RVA是4000h。注意:这个文件的FOA和RVA是一样的。
修改节表属性
因为我们要对text节的代码进行解密,所以其属性要加上“可写”。具体修改如下:
注意:PACK节也要修改属性,改为可执行、可读。修改方法与上同。
修改程序入口地址
要将原程序的入口地址改为解密程序的地址,也就是PACK节的起始地址,具体如下:
添加解密代码
要在PACK节里添加解密代码,使得程序可以正常运行。这一步在OD里进行。
代码解释:
注意:在OD里改完需要进行保存偶~
测试验证
写在最后:本篇文章只是对于壳进行了简单的介绍与实践,关于壳的知识还有很多,脱壳、加壳的工具也有很多,需要继续学习。