初来贵地.献析文一篇. 请高手勿笑 .
我不知道有这么个地方, 以后请大家多指教.
我写的不怎么好的地方,请大家指正.
我不怎么懂脱壳,请不要大家找我脱壳。。。
作者:牛博威
Email:advice107@sina.com
qq: 343538175
加壳软件一种可以对别的程序进行修改但是不影响其使用的工具软件。程序员经常利用加壳软件对自己的软件进行加壳,以加密或者压缩自己的软件。加壳后的软件一般来说难以被逆向分析,因此,脱壳软件应运而生。从某种角度来说,了解加壳和脱壳技术的原理是很有必要的。
下面我以Def为例说明其加壳原理,同时,我们改造Def使其具有针对自身的脱壳功能。
Def是一款源码开放的小型加壳软件,精炼易懂,便于学习。其源代码和程序可以去http://protools.cjb.net下载。
首先根据其源代码分析其加壳原理。它的加壳流程主要如下:
1、 以文件内存映象方式打开被加壳文件,并判断是否是有效的PE文件且不是Dll文件;
2、 遍历所有节表,根据节表名判断是否是输入表,资源节表或者其他节表,如果不是,定位到该节区,根据本节区大小对该节区的内容进行简单的异或加密,加密方式如下:
_encrypt: ;加密该节区
xor byte ptr[esi],al ;进行异或加密
inc esi ;esi指向节区下一个字节
dec eax ;判断是否到节区尾部,同时也是下一次异或操作的变量
jne _encrypt
然后把节表名称修改为.def,对未进行加密的节表,添加未加密标志,具体见下文;
3、 为被加壳文件添加自解密部分,用于被加壳文件运行时候自行解密。这一段可以参考源代码中的_loader部分。这段自解密代码被添加到文件节表的后面,同时修改文件的入口地址为此处的偏移地址。添加自解密部分的代码如下:
mov esi,offset _loader ; 初始化_loader的偏移地址
mov ecx,_loader_size ; 初始化loader部分的大小
rep movsb ; 把loader部分拷贝到被加壳文件的节表尾部
;其实这里最好判断一下是否有足够空间放置本段代码
4、 最后关闭文件内存映象;
根据上面的流程分析,再仔细研究一下其代码,相信你可以很快明白它的具体工作方式。下面我们来修改def,使其具有脱壳功能。
Def手工脱壳很简单,我以脱去Def自身的壳为例,说明其脱壳流程:
1、 用Trw载入Def;
2、 F10单步运行至xxxx:400244 push dword ptr 00401000 处,其中00401000为Def原来的入口地址。下命令Suspend,将进程挂起,F5回到windows界面;
3、 打开Peditor,点task,选择被挂起的Def进程,点右键dump(full),保存为unDef;
4、 用Peditor修改unDef文件的入口地址为00001000,注意这里是00401000减去00400000得到的。
好了,这样unDef就是Def的脱壳文件。我们现在要修改Def为自身的脱壳程序,也就是要对unDef进行处理。
首先,脱壳程序应该可以判断一个文件是否被Def加壳,利用Def的判断方式,判断第一个节表名称是否为.def便可以。故此,修改:
:00401091 813A2E646566 cmp dword ptr [edx], 6665642E ;.def ?
:00401097 0F858B000000 je 00401128
为:
:00401091 813A2E646566 cmp dword ptr [edx], 6665642E
:00401097 0F848B000000 jne 00401128 ;如果第一个节表名不为.def则跳出
;请注意这里最好不要改成jmp
现在就可以对加壳文件进行脱壳了,由于def采用了简单的异或加密,因此解密部分不需要修改。找个加壳文件实验一下,竟然发生异常。为什么这样呢?因为Def并不是把所有的节表都加密,对于引入表,资源节表等,def是不处理的。但我们的unDef会把所有的节表都进行解密,因此当然会发生错误。也许你会问,在程序中不是有call _is_encryptable(也就是:004010A7 call 004011A0)用来判断是否应该被加密么?不错,虽然如此,但是仔细再看一下_is_encryptable这个函数,它通过节表名来判断节表的修改合法性,而被加壳的文件所有节表名称都被改成了.def。因此,对这个函数来说加壳文件中所有的节表都应该被修改。
难道我们就没有办法判断了么?当然不是,仔细研究一下加壳文件的引导部分,也就是Def源代码中的_loader部分,在程序自身解密的时候有cmp byte ptr [esi+07], 00,其中esi指向节表头,如果[edx+07]=0 则跳过解密部分,否则进行解密。这样一来,我们修改unDef的解密部分。从VA=004010A7开始,修改后如下:
:004010A7 807A0700 cmp byte ptr [edx+07], 00 ;判断节区修改标志
:004010AB 90 nop ;保证文件后面的内容不变
:004010AC 90 nop
:004010AD 90 nop
:004010AE 740F je 004010BF ;如果不该解密,便跳过解密部分
到这里,就可以把所有加密部分恢复。但是脱壳文件仍然无法运行,因为我们还没有把文件的入口地址修改过来。看一下def如何修改入口地址,你可以很容易编写恢复入口地址的代码,如下:
:004010D6 50 &nbs