铁甲2.01与JDpack1.01脱壳综述
铁甲和JDpack是由中国人姜东开发的加壳软件。随着版本的升级程序的易用
性得到了用户的信赖,尽管加壳技术并不成熟。比方说他自身的加密,铁甲2.01
软件,只要把系统时间调到2001年7月1日以前,就能正常使用。
通过对由他们加壳的程序的跟踪发现,在铁甲和JDpack加壳的程序上存在着
对调试工具的防范措施,但是使用的技术很简单。两个软件原理基本相同,但是
代码和方法可能有所不同,下面以铁甲2.01来说一下。
===============================================================================
使用铁甲加壳windows自带的notepad.exe,然后调试分析:
启动trw2000,然后载入notepad.exe,程序被拦截到TRW2000领域,开始使用
F8键继续跟踪,一直跟踪到如下代码:
0167:0040D04B 32C3 XOR
AL,BL
0167:0040D04D 8806 MOV
[ESI],AL
0167:0040D04F 889D00244000 MOV
[EBP+00402400],BL
0167:0040D055 46
INC ESI //--下命令G 40D058
0167:0040D056
E2EB LOOP 0040D043
//---循环
0167:0040D058 9C
PUSHF //---光标跳到这里,代码发生变化
0167:0040D059 46
INC ESI
0167:0040D05A B074
MOV AL,74
0167:0040D05C
7501 JNZ 0040D05F
0167:0040D05E 07 POP
ES
0167:0040D05F F8
CLC
0167:0040D060 5D
POP EBP
0167:0040D061 684A0A0A81
PUSH DWORD 810A0A4A
0167:0040D066 347D
XOR AL,7D
======================变化后的代码================================
0167:0040D04B 32C3 XOR
AL,BL
0167:0040D04D 8806
MOV [ESI],AL
0167:0040D04F 889D00244000
MOV [EBP+00402400],BL
0167:0040D055 46
INC ESI
0167:0040D056 E2EB
LOOP 0040D043
0167:0040D058
9C PUSHF //---光标在这里
0167:0040D059 58 POP
EAX
0167:0040D05A F6C401
TEST AH,01
0167:0040D05D 7406
JZ 0040D065 //--R FL Z跳过,否则
0167:0040D05F
FFA535224000 JMP NEAR [EBP+00402235] //执行这个非法
0167:0040D065 8BB549224000 MOV ESI,[EBP+00402249]
//跳到这里
===================================================================
F10开始继续跟踪,应该经过如下代码段3次,不要理会,当过了 CALL 0040D3F4
3次后,要小心了,因为程序的反跟踪代码就在这里开始第一次检查:
0167:0040D0A9 F3A4 REP MOVSB
0167:0040D0AB 8BB529224000 MOV ESI,[EBP+00402229]
0167:0040D0B1 8BB84D224000 MOV EDI,[EAX+0040224D]
0167:0040D0B7 03FA ADD
EDI,EDX
0167:0040D0B9 57
PUSH EDI
0167:0040D0BA 56
PUSH ESI
0167:0040D0BB E834030000
CALL 0040D3F4 //循环3次后,F10仔细跟踪
0167:0040D0C0
5E POP ESI
0167:0040D0C1 5F POP
EDI
0167:0040D0C2 58
POP EAX
0167:0040D0C3 5E
POP ESI
======================================================================
过来以后,发现一段代码:
0167:0040D1B6 EB00
JMP SHORT 0040D1B8
0167:0040D1B8 83C602
ADD ESI,BYTE +02
0167:0040D1BB
E2B8 LOOP 0040D175
0167:0040D1BD EB9E JMP
SHORT 0040D15D
0167:0040D1BF E8FE010000 CALL
0040D3C2 //--ANTI-Debug ,F8跟进去
0167:0040D1C4 8B9505244000 MOV
EDX,[EBP+00402405]
0167:0040D1CA 8BB539224000
MOV ESI,[EBP+00402239]
0167:0040D1D0 03F2
ADD ESI,EDX
==========================
F8跟进去到了这里,典型的ANTI-Debug的基本模式:
0167:0040D3BF C20400
RET 04
0167:0040D3C2 8CC8
MOV EAX,CS
0167:0040D3C4
50 PUSH EAX
0167:0040D3C5 0F014C24FE SIDT [ESP-02] //----利用IDT来检测,F8继续
0167:0040D3CA 5E POP
ESI
0167:0040D3CB 83C618
ADD ESI,BYTE +18
0167:0040D3CE 8B4E04
MOV ECX,[ESI+04]
0167:0040D3D1 668B0E
MOV CX,[ESI]
0167:0040D3D4
8B560C MOV EDX,[ESI+0C]
0167:0040D3D7 668B5608 MOV
DX,[ESI+08]
0167:0040D3DB 8B4614 MOV
EAX,[ESI+14]
0167:0040D3DE 668B4610
MOV AX,[ESI+10]
0167:0040D3E2 2BC2
SUB EAX,EDX
0167:0040D3E4 2BD1
SUB EDX,ECX //--注意这里EAX=10
0167:0040D3E6 2BC2 SUB
EAX,EDX //--为使结果为0,可以使用命令R修改EDX=10
0167:0040D3E8 7409
JZ 0040D3F3 //结果为0就跳走,不为0就蓝屏
// 如果不修改EDX,可以在这里R FL Z,让程序
// 躲避过第一次检测
0167:0040D3EA 8B44241C MOV
EAX,[ESP+1C]
0167:0040D3EE 03C2
ADD EAX,EDX
0167:0040D3F0 FFD0
CALL EAX
0167:0040D3F2 C3
RET
0167:0040D3F3
C3 RET
0167:0040D3F4
60 PUSHA
===========================================================================================
好了躲过了第一次检测,程序还有第二次检测,同样是调用CALL 0040D3C2,所以F8继续跟踪
到以下代码:
0167:0040D240 53 PUSH
EBX
0167:0040D241 FFB541224000 PUSH DWORD
[EBP+00402241]
0167:0040D247 FF9580234000 CALL
NEAR [EBP+00402380]
0167:0040D24D 8907
MOV [EDI],EAX
0167:0040D24F 83854522400004
ADD DWORD [EBP+00402245],BYTE +04 //从这里G 0040D266
0167:0040D256
EBAB JMP SHORT 0040D203
0167:0040D258 83C614 ADD
ESI,BYTE +14
0167:0040D25B 8B9505244000 MOV
EDX,[EBP+00402405]
0167:0040D261 E96CFFFFFF JMP
0040D1D2
0167:0040D266 E857010000 CALL
0040D3C2 //跳到检测口,F8跟进去,如同上一个检测处理
0167:0040D26B 83BD7D22400001
CMP DWORD [EBP+0040227D],BYTE +01
0167:0040D272 7505
JNZ 0040D279
0167:0040D274
E9F9000000 JMP 0040D372
0167:0040D279
8DB5A5224000 LEA ESI,[EBP+004022A5]
======================
处理好第二个以后,程序出口到了代码:
0167:0040D266 E857010000
CALL 0040D3C2 //检测成功,程序执行下一行
0167:0040D26B 83BD7D22400001
CMP DWORD [EBP+0040227D],BYTE +01 // 与01比较,
0167:0040D272
7505 JNZ 0040D279
// 程序不能跳,跳了就非法
0167:0040D274 E9F9000000 JMP
0040D372 //----跳到程序的OEP入口---->>>>>
0167:0040D279 8DB5A5224000
LEA ESI,[EBP+004022A5]
0167:0040D27F 56
PUSH ESI
0167:0040D280
FF9588234000 CALL NEAR [EBP+00402388]
0167:0040D286
83F800 CMP EAX,BYTE +00
0167:0040D289 7408 JZ
0040D293
0167:0040D28B 8985A1224000 MOV
[EBP+004022A1],EAX
0167:0040D291 EB07
JMP SHORT 0040D29A
=======================
成功的到达程序OEP入口处: 典型的 JMP EAX
0167:0040D370 EB00
JMP SHORT 0040D372
0167:0040D372 8B9505244000 MOV EDX,[EBP+00402405]
//---跳到这里
0167:0040D378 8B8535224000 MOV
EAX,[EBP+00402235]
0167:0040D37E 03C2
ADD EAX,EDX
0167:0040D380 5D
POP EBP
0167:0040D381 FFE0
JMP EAX //----程序的正确入口!
这里pedump出解压的文件
0167:0040D383 55
PUSH EBP
0167:0040D384 8BEC
MOV EBP,ESP
0167:0040D386 50
PUSH EAX
=======================================================================================
完成脱壳了。在JMP EXA上F10一次,程序直接从NOTEPAD.hmjd跳到NOTEPAD.text,代码如下:
0167:004010C0
25322E3264 AND EAX,64322E32
0167:004010C5
0000 ADD [EAX],AL
0167:004010C7 000D0A000055 ADD [5500000A],CL
0167:004010CD 8BEC MOV
EBP,ESP
0167:004010CF 83EC44 SUB
ESP,BYTE +44
0167:004010D2 56
PUSH ESI
0167:004010D3 FF15E4634000
CALL `KERNEL32!GetCommandLineA`
0167:004010D9 8BF0
MOV ESI,EAX
0167:004010DB
8A00 MOV AL,[EAX]
0167:004010DD 3C22 CMP
AL,22
0167:004010DF 751B
JNZ 004010FC
0167:004010E1 56
PUSH ESI
0167:004010E2 FF15F4644000
CALL `USER32!CharNextA`
呵呵,验证无误,OK,该休息了,脱壳到了0:19分。
=================================================================================
在本机器上Jdpe 2.01的入口是10CC,用TRW2000脱出后,就可以修复ITA,完成脱壳和修
复工作。
接着看了看JDpack的壳,大致情形一样,但是我没有跟到他的ANTI-Debug,在这里要说的
是跟踪的时候注意几个循环和跳转的处理,比较累了,得休息了,明天继续研究写个jdpack
的脱壳过程。
CrackerABC 2002/07/31
================================================================================
JDPack 1.01脱壳
由于没有跟踪到JDPack的Anti-Debug代码,加上迷惑处很多,所以就直接使用trw2000来
动态脱壳。
首先使用冲击波检测到程序入口为40DC50,所以在TRW2000中下断点BPX
40DC50,然后运
行被加壳的程序,成功拦截以后,PEDUMP出解压文件。
然后,启动加壳后的程序,然后启动ImportREC,从程序进程中选择被加壳的程序,然后
手动输入入口点DC50,自动搜索ITA表内容,然后获取输入表,发现所有的函数都有效,直接
修复脱壳出来的程序,运行,完全正常。
这里要提一点:如果在中断后,使用suspend命令挂起TRW2000,然后使用Procdump来脱
出文件,则文件可以直接运行,但是,无法反编译后看到字串。如果尝试使用ImportREC来
修复ITA,程序就会非法,还得去分析非法原因,所以不如直接使用TRW2000脱壳出来修复来
的快和好。而且脱出来的程序也就大了4K左右。