加壳技术
什么是壳
壳是一种概念上的东西,我们的程序如果直接运行,可能会面临各种问题,例如我们需要防止程序被简单地反编译甚至被篡改.壳最初就是用于实现保护的这样的一种特殊程序.
相当于在我们原本的程序外加了一个特殊的壳程序,来保护我们原本的程序,壳在后面的发展中功能逐渐变化,也就出现了不同种类的壳.
大致有压缩壳,加密壳,VM壳的分类.
压缩壳主要用于较小软件的大小;加密壳用于保护软件,例如对数据/代码进行加密,以防止简单的静态分析破解等;VM壳利用了虚拟机技术,可以有效保护代码,但是牺牲了效率,所以往往出现在关键代码部分.
CTF中,可以使用DIE(Detect It Eazy)等软件对二进制程序进行检测,一般可以查出是否加壳.
压缩壳
压缩壳的侧重点就是减小软件体积大小,加密保护并不是其重点.
常见的压缩壳有UPX,aspack,fsg,Aspack Scrambler,ExeStealth, n Protector,V2Packer,WWPack32,XComp0.98, BeRoEXEPacker,dePACK,ExeShield Protector,KByS,NsPacK,tElock, Nspack PECompect Petite winUpack
UPX
加壳
该项目开源,并且几乎不带有任何反调试或保护策略.
可以在UPX官网下载UPX程序进行加壳/脱壳.
官网:
使用方法:
upx [-命令] [-选项] [-o 目标文件] 源文件..
1 | whh@whh-virtual-machine:~/do$ ./upx |
脱壳
静态脱壳:
UPX本身提供脱壳器,使用参数-d即可脱壳.
但是UPX是基于加壳后可执行文件内存储的标识来查找并操作的,由于UPX开源,任何人可以修改这些标识,所以会导致官方的UPX脱壳失败,此时需要手动脱壳.
动态脱壳:
可执行文件被操作系统载入后,寄存器中会放一些操作系统预先填充好的值,栈数据也会被设置,壳程序需要保留这些程序(状态),以免被壳段代码不经意间破坏.
一般,由于栈中原来的数据不应被更改,简单的壳程序一般将其压栈,x86的pushad指令
就可以将所有的寄存器一次性压栈,UPX也是这样,称为保护现场
.载入程序可以发现最开始为pushad
,就可以执行该指令后再设置硬件断点,中断到一个长跳转后继续单步执行,找到原程序的入口(OEP
,即原始入口点),然后Dump出来即还原.
或者如果没有发现pushad,则单步执行,单步执行为了防止跳过OEP,然后跳过UPX壳程序的循环代码,直到找到OEP,此时同样Dump即可.