• 标 题:ASProtect 1.23RC4之System Cleaner 4.91d脱壳修复and破解
  • 作 者:David
  • 时 间:2004-2-01 周日, 下午10:12
  • 链 接:http://bbs.pediy.com

【脱文作者】 weiyi75[Dfcg]

【作者邮箱】 weiyi75@sohu.com

【作者主页】 Dfcg官方大本营

【使用工具】 Ollydbg1.09d,ImportREC1.6F

【破解平台】 Win2000/XP

【软件名称】 System Cleaner 4.91d

【下载地址】 http://218.63.244.68:1010/ckkd/attachment.php?aid=253

【软件简介】 提供了三种简单有效的减肥方式。执行清除的速度很快,如果你不想清理某文件也可以设定
System  Cleaner  2000把文件先放到一个目录暂存,或是执行ZIP把文件压缩起来。有定时的功能,可以让
你订定大扫 除的时间 ,或是定时清理你的硬盘。

【软件大小】 1.01M

【加壳方式】 ASProtect 1.23 RC4 - 1.3.08.24 -> Alexey Solodovnikov

【破解声明】 我是一只小菜鸟,偶得一点心得,愿与大家分享:)

--------------------------------------------------------------------------------

【破解内容】

   前言,在我开始尝试脱这个程序的程序的时候,我dump下来的文件都是错误的,因为我在错误的地方dump程序,并因此常常导致脱壳后的程序崩溃。百思不解,后来看了Jeffzhang的动画,知道了这个程序不能在入口处脱壳,不然即使修复Iat和补上代码也不能运行。本文没有用AsprDbgr1b辅助修复IAT,全部IAT修复用ImportREC 1.6F,锻炼一下手动修复的能力。又经过jwh51指点破解过程,jwh51和Jeffzhang兄真是脱壳高手,吾望尘莫及,吾水平不行,克隆能力还是不错的。

好,脱壳开始。

OD异常设置不忽略内存异常,其余全部忽略,载入程序,用插件隐藏OD。

00401000 >  68 01B05F00     PUSH SystemCl.005FB001   //停在这里,F9运行。
00401005    E8 01000000     CALL SystemCl.0040100B
0040100A    C3              RETN
0040100B    C3              RETN
0040100C    0F39            ???                                      ; 未知命令
0040100E    44              INC ESP
0040100F    15 2F5BD708     ADC EAX,8D75B2F
00401014    58              POP EAX
00401015    A3 026254BC     MOV DWORD PTR DS:[BC546202],EAX
0040101A    8C4F DE         MOV WORD PTR DS:[EDI-22],CS
0040101D    1084D6 77A87E09 ADC BYTE PTR DS:[ESI+EDX*8+97EA877],AL
00401024    B5 D4           MOV CH,0D4
00401026    CF              IRETD
00401027    2F              DAS
00401028    B4 7C           MOV AH,7C
0040102A    23D8            AND EBX,EAX

.....................................................................


内存异常。

00C341E4    3100            XOR DWORD PTR DS:[EAX],EAX
00C341E6    EB 01           JMP SHORT 00C341E9
00C341E8    68 648F0500     PUSH 58F64
00C341ED    0000            ADD BYTE PTR DS:[EAX],AL
00C341EF    00EB            ADD BL,CH
00C341F1    02E8            ADD CH,AL
00C341F3    0158 68         ADD DWORD PTR DS:[EAX+68],EBX
00C341F6    6C              INS BYTE PTR ES:[EDI],DX                 ; I/O 命令
00C341F7    AF              SCAS DWORD PTR ES:[EDI]
00C341F8    C2 0068         RETN 6800
00C341FB    54              PUSH ESP
00C341FC    42              INC EDX
00C341FD    C3              RETN

.....................................................................


继续Shift+F9 27次忽略异常到最后一次异常处。

00C33A2C    3100            XOR DWORD PTR DS:[EAX],EAX  //到这里就可以用Loadpe脱壳了。
00C33A2E    64:8F05 0000000>POP DWORD PTR FS:[0]
00C33A35    58              POP EAX
00C33A36    833D B07EC300 0>CMP DWORD PTR DS:[C37EB0],0
00C33A3D    74 14           JE SHORT 00C33A53
00C33A3F    6A 0C           PUSH 0C
00C33A41    B9 B07EC300     MOV ECX,0C37EB0
00C33A46    8D45 F8         LEA EAX,DWORD PTR SS:[EBP-8]
00C33A49    BA 04000000     MOV EDX,4
00C33A4E    E8 EDD0FFFF     CALL 00C30B40
00C33A53    FF75 FC         PUSH DWORD PTR SS:[EBP-4]
00C33A56    FF75 F8         PUSH DWORD PTR SS:[EBP-8]
00C33A59    8B45 F4         MOV EAX,DWORD PTR SS:[EBP-C]
00C33A5C    8338 00         CMP DWORD PTR DS:[EAX],0
00C33A5F    74 02           JE SHORT 00C33A63
00C33A61    FF30            PUSH DWORD PTR DS:[EAX]
00C33A63    FF75 F0         PUSH DWORD PTR SS:[EBP-10]
00C33A66    FF75 EC         PUSH DWORD PTR SS:[EBP-14]
00C33A69    C3              RETN   //按F2在RET那里设置一个断点,然后再次按Shift+F9 

.......................................................................

 
我们会在停在RET这一行,清除断点。

 
接着按ALT+M打开内存镜像。在第一个块上下内存访问断点。
 
内存镜像

地址       大小       Owner      Section    Contains      类型   访问      初始访问  映射为

 
00400000   00001000   SystemCl              PE header     Imag   R         RWE
00401000   00164000   SystemCl              code          Imag   R         RWE  //在此处上下内
存访问断点

 
按F9运行,程序到达这里。

00407278  - FF25 2C235700   JMP DWORD PTR DS:[57232C]  //这里 
0040727E    8BC0            MOV EAX,EAX
00407280  - FF25 28235700   JMP DWORD PTR DS:[572328]
00407286    8BC0            MOV EAX,EAX
00407288  - FF25 24235700   JMP DWORD PTR DS:[572324]
0040728E    8BC0            MOV EAX,EAX
00407290  - FF25 20235700   JMP DWORD PTR DS:[572320]
00407296    8BC0            MOV EAX,EAX
00407298    50              PUSH EAX
00407299    6A 40           PUSH 40
0040729B    E8 E0FFFFFF     CALL SystemCl.00407280
004072A0    C3              RETN

.......................................................................

 
如果我们按一次F8我们将回到壳的代码中,按Ctrl+F9返回到程序领空。

 
0040734D    A3 68E65600     MOV DWORD PTR DS:[56E668],EAX            ; SystemCl.00400000
00407352    A1 68E65600     MOV EAX,DWORD PTR DS:[56E668]
00407357    A3 D8505600     MOV DWORD PTR DS:[5650D8],EAX
0040735C    33C0            XOR EAX,EAX
0040735E    A3 DC505600     MOV DWORD PTR DS:[5650DC],EAX
00407363    33C0            XOR EAX,EAX
00407365    A3 E0505600     MOV DWORD PTR DS:[5650E0],EAX
0040736A    E8 C1FFFFFF     CALL SystemCl.00407330
0040736F    BA D4505600     MOV EDX,SystemCl.005650D4
00407374    8BC3            MOV EAX,EBX    //这里的EAX里面的值要记录下来,EAX=564344,仿真Oep时
要用到。

00407376    E8 75D8FFFF     CALL SystemCl.00404BF0
0040737B    5B              POP EBX
0040737C    C3              RETN

.......................................................................

这些是什么东西??这个问题花了我一些时间但在调试了更多的别的程序之后,我认为这是对GetModuleHandleA的调用代码的一部分。

地址0040734D并不是OEP,我们按F8单步执行,直到RET,返回(ret)后我们来到这里:  

00564A64    FF15 A4D15600   CALL DWORD PTR DS:[56D1A4]  这里是临时OEP
00564A6A    E8 4903EAFF     CALL SystemCl.00404DB8
00564A6F    90              NOP
00564A70    0000            ADD BYTE PTR DS:[EAX],AL
00564A72    0000            ADD BYTE PTR DS:[EAX],AL
00564A74    0000            ADD BYTE PTR DS:[EAX],AL
00564A76    0000            ADD BYTE PTR DS:[EAX],AL

................................................................. 

但哪里才是OEP ?                                                 

如果你往上看,你会发现这样的代码:      

00564A4F    001C43          ADD BYTE PTR DS:[EBX+EAX*2],BL
00564A52    56              PUSH ESI
00564A53    0000            ADD BYTE PTR DS:[EAX],AL
00564A55    0000            ADD BYTE PTR DS:[EAX],AL
00564A57    0000            ADD BYTE PTR DS:[EAX],AL
00564A59    0000            ADD BYTE PTR DS:[EAX],AL
00564A5B    0000            ADD BYTE PTR DS:[EAX],AL
00564A5D    0000            ADD BYTE PTR DS:[EAX],AL
00564A5F    E8 D828EAFF     CALL SystemCl.0040733C

真正的OEP是 :   

00564A54                                                      

你可能会问\"为什么 ?\"...                                           
ASPR使用了一种叫做 \"Steal-Bytes\"的技术:                            
asrp隐藏了PE文件OEP开始处的字节,并把这些字节从原始PE文件中擦除.. 

=====================                                                
关于stolen bytes                                                     
=====================                                                

稍微说明一下:                                                    

每一种编译工具例如 : VC++ , Delphi , Borland , etc..                
在OEP有一个唯一的/相同的PE头                              
其中的一些是这样的:                                             

Push EBP                                                             
MOV Ebp,Esp                                                          
Add ESP , -010                                                       
Mov EAX, SOME_VALUE                                                  

(共11bytes)                                                   

或者:                                                                 

Push EBP                                                             
MOV Ebp,Esp                                                          
Add ESP , -010                                                       
Push EBX                                                             
Push ESi                                                             
Push EDi                                                             
Mov EAX, SOME_VALUE                                                  

(共14 bytes)     

这个程序被抽掉多少字节,11个,因为

00564A4F    001C43          ADD BYTE PTR DS:[EBX+EAX*2],BL
00564A52    56              PUSH ESI
00564A53    0000            ADD BYTE PTR DS:[EAX],AL  //这里往下一共12个字节,被抽掉的字节会用
00补充,故Oep判断为564a54
00564A55    0000            ADD BYTE PTR DS:[EAX],AL
00564A57    0000            ADD BYTE PTR DS:[EAX],AL
00564A59    0000            ADD BYTE PTR DS:[EAX],AL
00564A5B    0000            ADD BYTE PTR DS:[EAX],AL
00564A5D    0000            ADD BYTE PTR DS:[EAX],AL
00564A5F    E8 D828EAFF     CALL SystemCl.0040733C

用Peid扫描一下脱壳的文件,Borland Delphi 6.0 - 7.0,我们仿真入口点11个字节。

Push EBP                  //固定格式                                            
Mov EBP,ESP               //固定格式                                                
Add ESP,-010              //ADD ESP 的值一般 Delphi 程序都是-010
Mov eax, 00564344         //这里EAX的值就是刚才记录下来的。

将仿真入口码先记录下来。

ok,现在剩下的工作就是修复IAT了。    

先关闭OD,打开单独的程序。                                                     

在improved ImpRec 1.6 Final中选取进程,然后  

Oep处的1000别修改  

点击: 自动搜索IAT (IAT AutoSearch) 

RVA   0017221C  大小为0C8  //太小了

修改RVA的大小(Size of the RVA )为1000         

然后点击获取输入表(GetImports)     

点击显示非法函数(Show Invalid)  
                                                      
在无效地址列表(invalid list)中点击右键选择\"Trace Level 1\" 修复。    

还有452个指针要手动修复。

然后用ASProtect 1.22再减轻一下压力,注意不能用1.2x和1.3版的插件修复,也修复不了。                     
还有441个指针要手动修复。

现在的问题是,这441个指针是有用的吗?ImpRec 1.6会告诉你

点击show invalid并右键单击选择其中的一个,让我们来修复它 : 
                                      
001722E8<- 右键单击选择Deasm\HexView查看:  

ImpRec 1.6提示你,read error!好,够了,只要有这个提示的一律可以安全的Cut。

如果这个指针有效,里面会显示汇编指令。

找了一会,发现001724D8处的指针是唯一一个没识别的指针。

右键单击选择Deasm\HexView查看,究竟它是Kernel32.dll中的哪个函数呢,按Page Down两次,看到

00C31D6E    call 00C25158    // = kernel32.dll/00D9/FindResourceA

第一个看到的Api函数就是要修复的指针。

呵呵,修复它吧,双击00C31D6E这行,填入Api函数FindResourceA。

最后面几百个靠一块的指针一眼看出全是垃圾,用Deasm\HexView验证一下。

现在点击show invalid,将剩下440个垃圾指针全部Cut掉,提示所有指针修复完成,爽啊!

Btw:我是除了未部几百个垃圾指针,其余20多个指针一个个验证的。

将Oep填入00164A54,然后修复脱壳文件。

补上抽掉的11个字节。

换Od上场,载入修复的文件,补上我们刚才分析的代码,保存文件,正常运行。

脱壳后发现和原版一样有随机NAG提示和30天限制,想半法去掉它的30天时间限制。各位脱壳爱好都也可能发现脱Aspr经常有这种现象,有一种解决方案是脱壳后再把NAG窗口想法NOP掉,其实没必要这么做,在脱壳过程中就可以解决这个问题,以前有在SoftICE下的操作方案,这里就谈谈OD下的操作方案.

例子就用这个systemClean,这里主要说一下如何解决时间过期问题:

1.用OD载入加壳的主程序,F9运行,异常后按SHIFT+F9共23次,为什么是23次,因为总共有27次异常,我们要提前4-5次中断,所以是23次,这个是前辈的经验,要多看些脱文才能完全理解。

 
2.接着按ALT+M打开内存镜像。在第一个块上下内存访问断点。
 
内存镜像

地址       大小       Owner      Section    Contains      类型   访问      初始访问  映射为
 
00400000   00001000   SystemCl              PE header     Imag   R         RWE
00401000   00164000   SystemCl              code          Imag   R         RWE  //在此处上下内
存访问断点,按SHIFT+F9,代码来到了这里:

00563EB0    55                    PUSH    EBP
00563EB1    8BEC                  MOV     EBPESP
00563EB3    A1 2CD75600           MOV     EAXDWORD PTR DS:[56D72C]  //注意这一行
00563EB8    8B55 08               MOV     EDXDWORD PTR SS:[EBP+8]
00563EBB    8910                  MOV     DWORD PTR DS:[EAX], EDX
00563EBD    5D                    POP     EBP
00563EBE    C2 0400               RETN    4

注意以上代码的第三行mov eax dword ptr[56d72c];

[56d72c]中的值为566578,

我们输入命令:dd 566578 看看内存:

00566578  0049D74C  SystemCl.0049D74C  ,存放的是注册名的地址,改成自己的.
0056657C  FFFFFFFF                                 ,这一行是试用天数.
00566580  FFFFFFFF                                 ,这一行是剩下的天数.
00566584  00000000
00566588  00000001
0056658C  00000002

前三行就是我们要改的东西了.

用OD打开脱壳后的文件,把两个时间的地址全改为FF(共8个字节),然后在文件后面的某个空白处输入你的大名,我选择了在56DFB4处,

输入例如:Crack By weiyi75[Dfcg] Thank Jwh51[Dfcg]

在566578处改为 B4 DF 56 00 ,也就是我们大名的地点,保存.再运行看看.呵呵,时间限制没有了,在关于对话框中出现了Licensed to 你的大名。
 

感谢:某老外,Jeffzhang,Jwh51提供技术指点。 

-------------------------------------------------------------------------------- 

【版权声明】 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢