对Crunch v1.1主程序文件的脱壳方法
【声明】
我写文章以交流为主,希望大家在转载时能保持文章的完整性。
【前言】
Crunch v1.1的主程序文件的注册方法采用了和Armadilo的方法类似,由于其自身有多处反跟踪的代码,所以如果不处理。。。。。
样例文件: Crunch.EXE (Crunch v1.1的主程序文件)
加壳方式: Crunch v1.1
目标: 手动脱壳
作者: ljttt
写作日期: 2001-xx-xx (有感于某制假企业)
1、启动ICEDUMP,并启动ProcDump 1.6.2,选择Option/Rebuild new import table,单击Bhrama Server。这样我们将来手动脱壳时可以借助ProcDump的自动脱壳功能。这样很方便、快洁。
2、Ctrl-D进入SoftICE,设断点
bpint 3
3、用PEditor 1.5打开Crunch.EXE,单击break'n'enter。这时将在第一条指令处中断进入SoftICE。可以看到如下提示:
015F:0066C000 CC
INT 3
015F:0066C001 E800000000 CALL
0066C006
015F:0066C006 5D
POP EBP
在命令窗口提示如下:
You have to enter "eb eip 55" before you continue !
现在我按照提示输入
eb eip 55
这样修改了入口处的 CC (int 3)。现在显示如下,可以继续跟踪了。
015F:0066C000 55
PUSH EBP
015F:0066C001 E800000000 CALL
0066C006
015F:0066C006 5D
POP EBP
4、继续到如下代码处:(特征是第一个 REPZ MOVSB 指令)
015F:0066C0D9 BFE4000000 MOV
EDI,000000E4
015F:0066C0DE 03FD
ADD EDI,EBP
015F:0066C0E0 8BC8
MOV ECX,EAX
015F:0066C0E2 F3A4
REPZ MOVSB <--在该指令执行完后,以下将得到SMC方法还原后的正确代码
015F:0066C0E4 8B07
MOV EAX,[EDI] <--现在还是加密的代码
015F:0066C0E6 D581
AAD
015F:0066C0E8 C2A614 RET
14A6
5、在 REPZ MOVSB 执行后,我们可以看到如下的代码:
015F:0066C0D9 BFE4000000 MOV
EDI,000000E4
015F:0066C0DE 03FD
ADD EDI,EBP
015F:0066C0E0 8BC8
MOV ECX,EAX
015F:0066C0E2 F3A4
REPZ MOVSB
015F:0066C0E4 8BD5
MOV EDX,EBP <--这是还原后的正确代码了,可以继续跟踪了
015F:0066C0E6 81C2A6140000 ADD
EDX,000014A6
015F:0066C0EC 52
PUSH EDX
6、继续跟踪到如下代码处:(特征是 CALL EDX 后紧跟着两个 INT 3 指令)
015F:0066C11C 5A
POP EDX
015F:0066C11D 90
NOP
015F:0066C11E FFD2
CALL EDX <--在此处我们要停下,其中有反跟踪的代码,我们要跳过这段代码
015F:0066C120 CC
INT 3
015F:0066C121 CC
INT 3
015F:0066C122 E85E140000 CALL
0066D585
7、在 CALL EDX 处我们要停下,下指令跳过反跟踪代码(关于这段反跟踪代码的分析我已在《对Crunch v1.1加壳程序的手动脱壳的一点分析》一文中说明)
r eip eip+E
r esi 10
8、好了,现在我们又可以继续跟踪了,到如下代码处:(特征是 JG 0066C19F 指令)
015F:0066C1A6 83C701 ADD
EDI,01
015F:0066C1A9 4B
DEC EBX
015F:0066C1AA 83FB00 CMP
EBX,00
015F:0066C1AD 7FF0
JG 0066C19F <--现在程序又要用到SMC的方法来还原代码了。
015F:0066C1AF 90
NOP
<--现在这里还是加密的代码
015F:0066C1B0 EBCD
JMP 0066C17F
015F:0066C1B2 90
NOP
9、我们来看看SMC方法还原的正确代码:
015F:0066C1A6 83C701 ADD
EDI,01
015F:0066C1A9 4B
DEC EBX
015F:0066C1AA 83FB00 CMP
EBX,00
015F:0066C1AD 7FF0
JG 0066C19F <--该指令后的代码现在是还原后的正确代码了,可以比较以上的代码看看
015F:0066C1AF B942000000 MOV
ECX,00000042
015F:0066C1B4 59
POP ECX
10、继续跟踪到如下代码处:(特征是 SUB ECX,00000042 指令)
015F:0066C216 83F900 CMP
ECX,00
015F:0066C219 75EB
JNZ 0066C206
015F:0066C21B 59
POP ECX
015F:0066C21C 81E942000000 SUB
ECX,00000042
015F:0066C222 51
PUSH ECX
015F:0066C223 E8C3110000 CALL
0066D3EB <--内有反跟踪的代码,所以在此处我们要按F8键进入
015F:0066C228 33C0
XOR EAX,EAX
11、在 CALL 0066D3EB 处我们按进入,可以看到如下代码:(这里的反跟踪代码说明见我写的《对Crunch v1.1加壳程序的手动脱壳的一点分析》一文)
015F:0066D3EB 8BDD
MOV EBX,EBP
015F:0066D3ED 8B85483C0000 MOV
EAX,[EBP+00003C48]
015F:0066D3F3 8B8D86330000 MOV
ECX,[EBP+00003386]
015F:0066D3F9 C1E908 SHR
ECX,08
015F:0066D3FC 33D2
XOR EDX,EDX
015F:0066D3FE B902000000 MOV
ECX,00000002
015F:0066D403 F7F1
DIV ECX
015F:0066D405 0BD2
OR EDX,EDX
015F:0066D407 7502
JNZ 0066D40B <--在此处我们要停下!
015F:0066D409 EB72
JMP 0066D47D
015F:0066D40B 8BDD
MOV EBX,EBP
12、在 JNZ 006D40B 处停下,我们不能让其跳转,所以我们可下指令
方法一:修改跳转方向
r fl z
方法二:NOP掉跳转指令
eb eip 90
eb eip+1 90
13、按F12返回到主程序代码段中,继续跟踪如下代码处:(特征是 CALL EBX 后紧跟一条 NOP 指令)
015F:0066C273 BB76060000 MOV
EBX,00000676
015F:0066C278 03DD
ADD EBX,EBP
015F:0066C27A 899D643C0000 MOV
[EBP+00003C64],EBX
015F:0066C280 BB050A0000 MOV
EBX,00000A05
015F:0066C285 03DD
ADD EBX,EBP
015F:0066C287 FFD3
CALL EBX <--内有反跟踪代码,在此处我们要停下,想办法跳过它
015F:0066C289 90
NOP
015F:0066C28A 60
PUSHAD
015F:0066C28B BB85230000 MOV
EBX,00002385
14、在 CALL EBX 处停下,下指令跳过反跟踪(其中的反跟踪代码说明见我写的《Crunch v1.1中的一段有趣的检测跟踪代码》一文)
r eip eip+2
15、好了,到此主程序中的反跟踪代码大部分被我们跳过了,有没有一种登山的感觉,但是现在还只是过了一小段路程,我们继续!
如果你有过对Crunch加壳的程序的脱壳经验,一定会发现大部分类似,现在我们来看看Crunch.EXE主程序和他们的不同。这也是我们以下要进行的步骤的一个原理说明吧:
首先,Crunch.EXE自身用Crunch v1.1的方法加了壳,(其中我们在跟踪时已经知道了有大量的反跟踪代码,如果不小心掉了进去,呵呵!接受一次被超度的感觉吧!)。
然后,Crunch.EXE建立一个临时文件,其中的代码是由主程序在内存中还原得到的(此文件也用Crunch v1.1加了壳)。然后通过此文件建立一个子进程。进行注册分析。
此时,主程序Crunch.EXE进入一个的循环中,等待子进程(临时文件创建)的注册过程结束,当子进程退出后,主程序Crunch.EXE退出循环。并删除此临时文件。最后,主程序进入主界面。
因此,我们要在主程序进入主界面之前,DUMP得到我们想要的脱壳文件。由于子进程中也有反跟踪代码,所以我们必须也要跳过其中的反跟踪代码,否则前功尽弃。开始我想过很多办法,比如在临时文件刚刚保存还未创建进程的时候得到完整的加壳文件来进行单独的脱壳,然后在下次跟踪时用我脱壳后没有反跟踪代码的文件替换掉临时文件,但是发现单独运行临时文件竟然无法工作,(看来作者早有防范)可见主程序Crunch.EXE需要和子进程有信息通讯,必须要同时工作,我们也只有在主程序中运行的情况下对子进程进行分析跳过其中的反跟踪代码。不过这把我一下难住了。由于WINDOWS的多任务特点,我们无法在单步跟踪时知道何时子进程开始执行第一条指令。我跟踪的情况并非在CreatProcess函数执行后,也不在ResumeThread函数执行后。不过还是让我想出了办法。Yeah!
16、继续跟踪来到如下代码处:
015F:0066C473 50
PUSH EAX
015F:0066C474 FFB50D240000 PUSH
DWORD PTR [EBP+0000240D] <--数据缓冲区地址,我跟踪时为 920000
015F:0066C47A FFB505240000 PUSH
DWORD PTR [EBP+00002405]
015F:0066C480 FF951E210000 CALL
[EBP+0000211E]
<--即 CALL WriteFile
015F:0066C486 FFB505240000 PUSH
DWORD PTR [EBP+00002405]
015F:0066C48C FF9522210000 CALL
[EBP+00002122]
015F:0066C492 6800800000 PUSH
00008000
015F:0066C497 6A00
PUSH 00
015F:0066C499 FFB50D240000 PUSH
DWORD PTR [EBP+0000240D]
015F:0066C49F FF9512210000 CALL
[EBP+00002112]
17、在 CALL [EBP+0000211E] 处停下,我们要做些准备工作。我跟踪时 [EBP+0000240D] = 920000 ,这就是即将被保存到临时文件中的数据。
我们要修改其中第一条指令为 CC 。临时文件的 Entry Point = 31C00,(这个值可以通过显示 920000 的内容,分析 PE 结构知道,也可以在无调试环境下用ProcDump来DUMP出临时文件得到。方法很多,可以自己去分析。)所以第一条指令位于
920000+31C00 处。
下指令
eb 920000+31C00 CC
18、下指令
I3HERE ON
19、继续跟踪到如下代码处:(特征是 JMP EBX 后紧跟一条指令 MOV EAX,[EBP+00003536])
015F:0066C52D 83C304 ADD
EBX,04
015F:0066C530 FF33
PUSH DWORD PTR [EBX]
015F:0066C532 FFD0
CALL EAX
015F:0066C534 BBCC0C0000 MOV
EBX,00000CCC
015F:0066C539 03DD
ADD EBX,EBP
015F:0066C53B FFE3
JMP EBX
<--在此处停下
015F:0066C53D 8B8536350000 MOV
EAX,[EBP+00003536] <--在此处设下断点
015F:0066C543 83C014 ADD
EAX,14
015F:0066C546 B914000000 MOV
ECX,00000014
015F:0066C54B 33D2
XOR EDX,EDX
015F:0066C54D 8034101A XOR
BYTE PTR [EDX+EAX],1A
015F:0066C551 42
INC EDX
015F:0066C552 49
DEC ECX
015F:0066C553 83F900 CMP
ECX,00
20、在 JMP EBX 处时我们暂时停下,在 MOV EAX,[EBP+00003536] 处设下断点
bpx 0066C53D
此处断点将在子进程结束后中断。现在子进程还并未真正运行。在 JMP EBX 后将进入了一个循环。我们不需要浪费时间,按F5键继续。
21、程序将中断在子进程第一条指令处:
015F:0047FFFF FFCC
DEC ESP
015F:00480001 E800000000 CALL
00480006
015F:00480006 5D
POP EBP
015F:00480007 83ED06 SUB
EBP,06
015F:0048000A 8BC5
MOV EAX,EBP
22、还原原来的代码,下指令
r eip eip-1
e eip 55 <--由于原来的第一条指令代码为 55
23、现在我们的跟踪步骤和前面对主程序Crunch.EXE类似了。重复第 4 - 14 步中的方法来反跟踪。这里就不多说了,只是把一些特征代码列出。方法比较。
㈠请对比步骤4:
特征一: REPZ MOVSB
015F:004800E2 F3A4
REPZ MOVSB <--特征
015F:004800E4 8B07
MOV EAX,[EDI] <--未还原前的加密代码
015F:004800E6 D581
AAD
015F:004800E8 C29D14 RET
149D
015F:004800EB 0E
PUSH CS
以下是还原后的代码
015F:004800E2 F3A4
REPZ MOVSB <--特征
015F:004800E4 8BD5
MOV EDX,EBP <--还原后的正确代码
015F:004800E6 81C29D140000 ADD
EDX,0000149D
015F:004800EC 52
PUSH EDX
015F:004800ED 33C0
XOR EAX,EAX
㈡请对比步骤6:
特征二: CALL EDX 后紧跟 INT 3
015F:0048011D 90
NOP
015F:0048011E FFD2
CALL EDX <--特征,要跳过这里的反跟踪
015F:00480120 CC
INT 3
015F:00480121 CC
INT 3
015F:00480122 E855140000 CALL
0048157C
㈢请对比步骤8:
特征三: JG 0048019F
015F:004801AA 83FB00 CMP
EBX,00
015F:004801AD 7FF0
JG 0048019F <--特征
015F:004801AF 90
NOP
<--未还原前的加密代码
015F:004801B0 EBCD
JMP 0048017F
015F:004801B2 90
NOP
以下是还原后的代码
015F:004801AA 83FB00 CMP
EBX,00
015F:004801AD 7FF0
JG 0048019F <--特征
015F:004801AF B942000000 MOV
ECX,00000042 <--还原后的正确代码
015F:004801B4 59
POP ECX
015F:004801B5 57
PUSH EDI
㈣请对比步骤10:
特征四: SUB ECX,00000042
015F:0048021B 59
POP ECX
015F:0048021C 81E942000000 SUB
ECX,00000042
015F:00480222 51
PUSH ECX
015F:00480223 E8BA110000 CALL
004813E2 <--要跳过这里的反跟踪
要跳过的地方
015F:004813FA F7F1
DIV ECX
015F:004813FC 0BD2
OR EDX,EDX
015F:004813FE 7502
JNZ 00481402 <--NOP掉
015F:00481400 EB72
JMP 00481474
㈤请对比步骤13:
特征五: CALL EBX 后紧跟 NOP
015F:00480285 03DD
ADD EBX,EBP
015F:00480287 FFD3
CALL EBX <--要跳过此处的反跟踪
015F:00480289 90
NOP
015F:0048028A 60
PUSHAD
24、跳过了以上这些反跟踪的部分后,按F5键让子进程进行注册分析。这时将回到WINDOWS中,单击 CONTINUE 键将进入程序主界面。(如果你想分析注册码,可以试试了)这时将中断在我们在主程序中留下的一个断点
CALL 0066C53D。显示如下:
015F:0066C534 BBCC0C0000 MOV
EBX,00000CCC
015F:0066C539 03DD
ADD EBX,EBP
015F:0066C53B FFE3
JMP EBX
015F:0066C53D 8B8536350000 MOV
EAX,[EBP+00003536] <--在此处中断
015F:0066C543 83C014 ADD
EAX,14
015F:0066C546 B914000000 MOV
ECX,00000014
015F:0066C54B 33D2
XOR EDX,EDX
015F:0066C54D 8034101A XOR
BYTE PTR [EDX+EAX],1A
25、我们继续跟踪到如下代码处:(特征是 JMP EAX 后紧跟 JMP [EBP+00003C6C])
015F:0066C9DB 83850124000014 ADD
DWORD PTR [EBP+00002401],14
015F:0066C9E2 FF8D55330000 DEC
DWORD PTR [EBP+00003355]
015F:0066C9E8 6683BD5533000000 CMP WORD
PTR [EBP+00003355],00
015F:0066C9F0 0F85FAFDFFFF JNZ
0066C7F0
015F:0066C9F6 B83C160000 MOV
EAX,0000163C
015F:0066C9FB 03C5
ADD EAX,EBP
015F:0066C9FD FFE0
JMP EAX
<--此处有大量的代码
015F:0066C9FF FFA56C3C0000 JMP
[EBP+00003C6C] <--这里是关键!
015F:0066CA05 8CD8
MOV AX,DS
015F:0066CA07 A804
TEST AL,04
26、我们可以在 JMP EAX 处停下,直接在 JMP [EBP+00003C6C] 处设下断点,或者把光标移动到此处按F7键,快速到此。(如果你想了解各个细节可以继续慢慢跟踪。)然后继续跟踪到如下代码处:
特征是 MOV EAX,[EBP+00002415] 加 ADD [EBP+00003382],EAX 后跟一条 JMP [EBP+00003C5C]
指令
015F:00670094 BB810A0000 MOV
EBX,00000A81
015F:00670099 03DD
ADD EBX,EBP
015F:0067009B FFD3
CALL EBX
015F:0067009D 64678F060000 POP
DWORD PTR FS:[0000]
015F:006700A3 83C408 ADD
ESP,08
015F:006700A6 8B8515240000 MOV
EAX,[EBP+00002415]
015F:006700AC 018582330000 ADD
[EBP+00003382],EAX
015F:006700B2 FFA55C3C0000 JMP
[EBP+00003C5C] <--在这里将跳转到最后一段代码处
015F:006700B8 C3
RET
27、在 JMP [EBP+00003C5C] 处按F10键将来到如下代码处:
015F:0066C0E4 61
POPAD
015F:0066C0E5 5D
POP EBP
015F:0066C0E6 8B8582330000 MOV
EAX,[EBP+00003382]
015F:0066C0EC 5D
POP EBP
015F:0066C0ED FFE0
JMP EAX
<--EAX=OEP,这里将跳转到程序真正的入口处了!
28、在 JMP EAX 处我们要停下来,这里将到了我们来DUMP文件的时候到了。(这里我使用的是ICEDUMP 6.0168的命令使用方法)
/bhrama ProcDump32 - Dumper Server
这时程序将回到WINDOWS,过一段时间,如果成功,将出现文件保存对话框让你选择想保存的文件名。存完将回到SoftICE,好!我们按F5结束工作。
【后记】
用这种方法脱壳很累,写这篇文章也很累。不过再累也得把方法留下来,让自己以后能够对该程序的加壳方法温故知新。
Crunch.EXE v1.1
在脱壳后,还需要修改一处代码使之成为注册版。
004043C8: 8D45EC
lea eax,dword ptr [ebp-14]
004043CB: BA02000000
mov edx,00000002
004043D0: E81BA40D00
call 004DE7F0
004043D5: 59
pop ecx
004043D6: 84C9
test cl,cl
004043D8: 7409
jz 004043E3
<--修改此处的代码为NOP,即 7409=9090
004043DA: C605F4054E0001 mov byte ptr
[004E05F4],01
004043E1: EB07
jmp 004043EA
004043E3: C605F4054E0000 mov byte ptr
[004E05F4],00
004043EA: FF4E1C
dec dword ptr [esi+1C]
004043ED: 8D45FC
lea eax,dword ptr [ebp-04]
004043F0: BA02000000
mov edx,00000002
004043F5: E8F6A30D00
call 004DE7F0
【补充】
最新下载了Crunch v1.2 。发现脱壳方法与上类似,就不写了。
不过注意在跟踪
- 标 题:对Crunch v1.1主程序文件的脱壳方法 ---ljtt
- 作 者:ljtt
- 时 间:2000-11-30 17:32:15
- 链 接:http://bbs.pediy.com