目标程序:木马克星 5.51(引擎版本号 0515)
加壳类型:ASProtect 2.1x SKE -> Alexey Solodovnikov
使用工具:OllyDbg 1.10 (OD),PEiD 0.94,StudPE 2.3
文章作者:looyoo //2006.7.7.


特别声明:此前已在看雪或一蓑烟雨发过 ASProtect 2.1x 脱壳帖的弟兄,皆为吾师,一并致谢!


七月流火,酷暑难当。昨晚忽得一夜喜雨,感觉舒坦了许多。为了打发世界杯决赛前的无聊,我捣鼓起了“驳壳”的干活,但无奈壳王的霸气,累战累败。为加快“围猎”的步伐起见,我用“自加自脱”的办法,放弃所有附加选项来加壳目标程序,集中火力打歼灭战,使脱壳变为只是处理“CALL xxxxxxx -> JMP DWORD PTR DS:[??????]”的单一问题,因为这里才是我累战累败的麦城。这样做能使我们以清醒的头脑面对关键的问题,避免“强弩之末”效应。我拿来试练的目标程序是一款剪贴板,加壳、调试、补丁、转储、修改,一切按部就班。几个回合下来,竟然也见到了晴天日出,我成功了!是简单而导致明了?是功到垂成?抑或是幸遇软蛋?都有可能,但将复杂分割成简单再各个击破,是成功的一大法门。推倒重来吧,让模糊变得清晰,让偶然成为有章可循,如何?所幸仍然成功了。感觉有了点门道,于是想用文字记录下来。但该目标程序就一个问题、一个补丁,是否过于简单呢?我于是想加个附加选项,比如加密“IAT”,但无论我怎么设置,无论加壳后怎样清楚明白的显示,在 OD下都只有那个“CALL xxxxxx”问题,一头雾水,看来我还得为加壳去听讲座。万幸中的不幸,此时我家的电脑又偏偏不能上网,不然也用不着为了个目标程序而这样折腾。翻箱倒柜了半天后,总算在“库存”中找到了一款名为“木马克星 5.51”的程序(向作者致歉!),PEiD 下显示“ ASProtect 2.1x SKE -> Alexey Solodovnikov”,正合我意,就把它送上流水线吧,窃喜!^_^

我的操作流程分为两步:1.获取信息;2.解剖剥离。

1.获取信息:

OD 加载目标程序,Shift+F9 直至显示程序界面,记下按键次数并留意 CPU 窗口数据。重新加载目标程序,Shift+F9 到最后一次异常,Alt+M 到内存窗口,记下 Data 的值 589000,在 401000 上设断,Shift+F9 至 OEP:588a6c,Ctrl+B 搜索 FF 25,得到 IAT 内的一个地址 5a3348 及壳调用位置(CALL xxxxxxx//004012B4    E8 47EDBA00     CALL 00FB0000) 00FB0000,IAT 还需要精确定位,留到下一步顺便解决吧。

第一步所得相关信息为:

OEP   588a6c
Data  589000
TAT   5a3294~5a3d08(由第二步获取)
CALL  00fb0000

2.解剖剥离:

OD 加载目标程序,Shift+F9 直至“00DBEA55  MOV BYTE PTR DS:[ECX],0B6”,也可以在此前任何位置,搜索字符“85”,并双击返回到 CPU 窗口,在两个“85”之间的第二个 CALL (00DBEC09   CALL 00DB7818)上设断,Shift+F9 运行至此,撤销断点,F7 步入该 CALL,进入新界面后,向下滚屏至第一个返回点 00DB7989    RETN,设断,向上找到最近的一个 CALL//00DB795A  CALL 00DB75B8,F4 至此,F7 步入后,向下滚屏至 00DB75F2  CMP ESI,EAX,(CMP,JNZ,JMP 成组出现)设断,F9 运行,注意寄存器窗口 eax,esi,edi 的值的变化,F9 连续按键过程中,esi 相继出现三个参数 8c,9d,91,其中 9d 与 eax 的数据相同,不管它。当 esi 出现 91 时,edi 中的函数名随按键动作相应变化(每变化一次相对应的在数据窗口的 IAT 内增加一个函数名称),而 8c 则不然,据此判断 8c 被加密,而 91 未加密。至此,补丁参数已经确定,IAT 起始及终止地址这时也可从数据窗口读取,即:5a3294~5a3d08(命令槽口 d 5a3348,其中 5a3348 在第 1 步得知)。
再重新加载目标程序,Shift+F9 直接运行至 00DB75F2  CMP ESI,EAX,设断,F9 运行,在寄存器 esi 中刚出现 8c 时开始第一次补丁。先用 OllyHelper 申请一块内存空间,我这里是 010B0000,修改 00DB75F4  JNZ SHORT 00DB7654 为 00DB75F4  JMP 010B0000,去断点,F8 至 010B0000 后,粘贴补丁:

010B0000  - 0F84 F375D0FF   JE 00DB75F9
010B0006    81FE 91000000   CMP ESI,91----------------------------------91 为未加密参数
010B000C  - 0F84 4276D0FF   JE 00DB7654
010B0012    BE 91000000     MOV ESI,91
010B0017  - E9 3876D0FF     JMP 00DB7654
----------------
0F 84 F3 75 D0 FF 81 FE 91 00 00 00 0F 84 42 76 D0 FF BE 91 00 00 00 E9 38 76 D0 FF

然后 F9 运行,IAT 随即被解密,可从命令槽口 d 5a3294,再在数据窗口观察验证。接下来,撤销 00DB75F4 处的更改(切记!),补丁是否撤销无碍,Shift+F9 至最后一次异常 00DBFAA5    C700 EFCA5C85   MOV DWORD PTR DS:[EAX],855CCAEF,Ctrl+B 搜索“89,45,F0,B8,00,07,00,00”,在 00DB7190   CALL 00D9254C 设断,Shift+F9 至此,撤销断点,沿用前面申请到的内存空间,改 CALL 00D9254C 为 JMP 010B0037 后,转到(注意不是运行到...)该内存空间,粘贴补丁:

010B0000    BA 00104000     MOV EDX,Iparmor.<ModuleEntryPoint>-----------新建 EIP 后 F9 运行//也可以 F8 运行,一步步地观察修改过程
010B0005    803A E8         CMP BYTE PTR DS:[EDX],0E8
010B0008    75 12           JNZ SHORT 010B001C
010B000A    8B42 01         MOV EAX,DWORD PTR DS:[EDX+1]
010B000D    03C2            ADD EAX,EDX
010B000F    83C0 05         ADD EAX,5
010B0012    3D 0000FB00     CMP EAX,0FB0000------------------------------来自 CALL xxxxxxx
010B0017    75 03           JNZ SHORT 010B001C
010B0019    EB 0C           JMP SHORT 010B0027
010B001B    90              NOP
010B001C    42              INC EDX
010B001D    81FA 00905800   CMP EDX,589000-------------------------------Data 起点
010B0023  ^ 72 E0           JB SHORT 010B0005
010B0025  - EB FE           JMP SHORT 010B0025
010B0027    8915 00010B01   MOV DWORD PTR DS:[10B0100],EDX---------------[10B0100] 要作相应修改,下同。
010B002D    60              PUSHAD
010B002E    FFE2            JMP EDX
010B0030    90              NOP
010B0031    90              NOP
010B0032    90              NOP
010B0033    90              NOP
010B0034    90              NOP
010B0035    90              NOP
010B0036    90              NOP
010B0037    60              PUSHAD
010B0038    B8 94325A00     MOV EAX,5A3294-------------------------------IAT 起点
010B003D    90              NOP
010B003E    3910            CMP DWORD PTR DS:[EAX],EDX
010B0040    75 20           JNZ SHORT 010B0062
010B0042    8B0D 00010B01   MOV ECX,DWORD PTR DS:[10B0100]
010B0048    C701 FF250000   MOV DWORD PTR DS:[ECX],25FF
010B004E    8941 02         MOV DWORD PTR DS:[ECX+2],EAX
010B0051    61              POPAD
010B0052    90              NOP
010B0053    8B15 00010B01   MOV EDX,DWORD PTR DS:[10B0100]
010B0059    90              NOP
010B005A    90              NOP
010B005B    90              NOP
010B005C  ^ EB BE           JMP SHORT 010B001C
010B005E    90              NOP
010B005F    90              NOP
010B0060    90              NOP
010B0061    90              NOP
010B0062    83C0 04         ADD EAX,4
010B0065    3D 083D5A00     CMP EAX,5A3D08-------------------------------IAT 终点
010B006A  ^ 7E D2           JLE SHORT 010B003E
010B006C  ^ EB E3           JMP SHORT 010B0051
----------------------------
BA 00 10 40 00 80 3A E8 75 12 8B 42 01 03 C2 83 C0 05 3D 00 00 FB 00 75 03 EB 0C 90 42 81 FA 00
90 58 00 72 E0 EB FE 89 15 00 01 0B 01 60 FF E2 90 90 90 90 90 90 90 60 B8 94 32 5A 00 90 39 10
75 20 8B 0D 00 01 0B 01 C7 01 FF 25 00 00 89 41 02 61 90 8B 15 00 01 0B 01 90 90 90 EB BE 90 90
90 90 83 C0 04 3D 08 3D 5A 00 7E D2 EB E3

修改那几个已标注的数据后,在补丁的第一行新建 EIP,F9 运行,这时“CALL xxxxxxx” 变成了“JMP DWORD PTR DS:[??????]”格式,可以搜索一下“CALL 0FB0000”看看是否还有遗漏,确认无遗漏后转储进程为可执行文件,PEiD 检测该文件,提示为无效 PE 文件,别急,用 StudPE 修改 RVA 后再检测,提示为 Borland Delphi 4.0 - 5.0,显然已是有效 PE 文件了,但点击后仍然不能运行。OD 加载,F9 运行,主窗口变得一片空白,堆栈提示 0012F984   0040DFF4  RETURN to 1.0040DFF4 from 1.0040A708,找到 0040A708  JMP 00FF0000,显然 JMP 00FF0000 地址已经随壳而去,改为 JMP 0040a76d(见六楼附注),保存更改到可执行文件,点击运行,正常!解剖剥离手术到此结束。
希望我这一夜汗水对后来的弟兄有所帮助。
(主程序脱壳前 1038 KB,脱壳后 2308 KB)

一点体会:

   1.判断 IAT 是否加密,只要在 00DB75F2  CMP ESI,EAX 设断,F9 运行,观察寄存器 esi,edi 的联动反应即可。加密时,esi 的值不变,则 edi 的函数名也不变(若不存在该现象,则 IAT 未加密);未加密时,esi 的值不变,但 edi 中的函数名却会随 F9 的键击而变。这比通过数据窗口判断来得简单;
   2.第一个补丁在加密参数刚出现时即操作,第二个补丁粘贴完成后要先新建 EIP,然后再 F9 运行,请后来的弟兄注意;
   3.搜索“85”字符可以在 F9 初次运行后即执行,因为设断后 Shift+F9 运行自然会中断在指定位置,没有必要紧盯着寻找“0B6”之类。确定第二个补丁位置时,运行到最后一次异常即可搜索“89,45,F0,B8,00,07,00,00”,并定位在紧接其下的 CALL 处,其他的繁琐操作似乎均可略去;
   4.脱壳后若不能运行,且 PEiD 检测显示为无效 PE 文件时不要放弃,用 PE 工具修改一下文件头或许就柳暗花明了。

本文旨在与菜鸟交流,谬误之处,请能者赐教!转载请注明作者并保持文章的完整, 谢谢! 

(更多代码请见附件) mmkx5.51.rar