【破文标题】企业报表处理软件(2005版)免光盘破解

来源:互联网 发布:js合并对象数组 编辑:程序博客网 时间:2024/04/29 17:19

【破文标题】企业报表处理软件(2005版)免光盘破解
【破文作者】gc801
【作者邮箱】
gc801@qq.com
【作者主页】http://free4.e-168.cn/f1club
【破解工具】OllyDbg,PEiD,W32Dasm,Hiew
【破解平台】Win9x/NT/2000/XP
【软件名称】企业报表处理软件(2005版)
【软件大小】50.6m
【原版下载】CDFACE.exe
【保护方式】光盘保护
【软件简介】没有什么好说的,用过的都知道。
------------------------------------------------------------------------
【破解过程】所需工具在
http://www.pediy.com/tools.htm均有下载。
破解之前先熟悉一下汇编中常用的东西:
CMP 比较          
JNZ 不等于就跳转   机器码:75
JE  等于就跳转     机器码:74
JMP 无条件跳转     机器码:EB

今天我们就是靠它们来实现破解的。简单吧。

做破解的都知道一件事,先查壳。当然我也不例外。可惜今天查壳无用,用PEID查壳显示“[代码未能识别] [重叠] *”,核心扫描显示“Borland Delphi 4.0 - 5.0 [重叠]”,跟了一下,发现要脱这个壳不容易,随便脱了一下,程序不能运行,所兴干脆放弃脱壳,直接载入跟踪,还好,这个软件一开始就检测光盘了。

虽然PEID没能帮我脱掉壳(费话,它也不是脱壳工具),但是它帮了我一个大忙,找到了OEP入口点(用Generic OEP finder插件)。是0055A0AA,我们就把断点下到这里。

OD载入CDFACE,CTRL+G,找到0055A0AA,把断点下在0055A0AA,F9运行。程序在0055A0AA处断下来了,我们先按F8初步跟踪。所幸的是程序加密并不严密,直接就被跟踪了出来。

0055A0AA    55                  push ebp
0055A0AB    8BEC                mov ebp,esp
0055A0AD    83C4 F8             add esp,-8
0055A0B0    60                  pushad
0055A0B1    C745 FC 00000000    mov dword ptr ss:[ebp-4],0
0055A0B8    E8 00000000         call CDFace.0055A0BD
0055A0BD    5B                  pop ebx
0055A0BE    81EB 1E114000       sub ebx,CDFace.0040111E
0055A0C4    55                  push ebp
0055A0C5    8D83 AC114000       lea eax,dword ptr ds:[ebx+4011AC]
0055A0CB    50                  push eax
0055A0CC    8D83 61104000       lea eax,dword ptr ds:[ebx+401061]
0055A0D2    50                  push eax
0055A0D3    64:FF35 00000000    push dword ptr fs:[0]
0055A0DA    64:8925 00000000    mov dword ptr fs:[0],esp
0055A0E1    8B7D 0C             mov edi,dword ptr ss:[ebp+C]
0055A0E4    B9 FFFFFFFF         mov ecx,-1
0055A0E9    32C0                xor al,al
0055A0EB    FC                  cld
0055A0EC    F2:AE               repne scas byte ptr es:[edi]
0055A0EE    8BCF                mov ecx,edi
0055A0F0    2B4D 0C             sub ecx,dword ptr ss:[ebp+C]
0055A0F3    894D F8             mov dword ptr ss:[ebp-8],ecx
0055A0F6    8B75 08             mov esi,dword ptr ss:[ebp+8]
0055A0F9    0376 3C             add esi,dword ptr ds:[esi+3C]
0055A0FC    8B76 78             mov esi,dword ptr ds:[esi+78]
0055A0FF    0375 08             add esi,dword ptr ss:[ebp+8]
0055A102    8B5E 20             mov ebx,dword ptr ds:[esi+20]
0055A105    035D 08             add ebx,dword ptr ss:[ebp+8]
0055A108    33D2                xor edx,edx
0055A10A    56                  push esi                                            ;在这里有一个循环这是开始,我们不要跟着它绕了,
0055A10B    8B3B                mov edi,dword ptr ds:[ebx]
0055A10D    037D 08             add edi,dword ptr ss:[ebp+8]
0055A110    8B75 0C             mov esi,dword ptr ss:[ebp+C]
0055A113    8B4D F8             mov ecx,dword ptr ss:[ebp-8]
0055A116    F3:A6               repe cmps byte ptr es:[edi],byte ptr ds:[esi]
0055A118    75 03               jnz short CDFace.0055A11D                          ;不满足条件继续转悠。
0055A11A    5E                  pop esi
0055A11B    EB 0C               jmp short CDFace.0055A129                          ; 满足条件以后就跳走。我们要跟着它走,跳到它想跳的地方
0055A11D    5E                  pop esi                                            ; kernel32.7C880DD8
0055A11E    83C3 04             add ebx,4
0055A121    42                  inc edx
0055A122    3B56 18             cmp edx,dword ptr ds:[esi+18]
0055A125  ^ 72 E3               jb short CDFace.0055A10A                            ;这里是循环结束。
0055A127    EB 22               jmp short CDFace.0055A14B
0055A129    2B5E 20             sub ebx,dword ptr ds:[esi+20]                       ;满足条件以后跳到这,所以我们就在这里按F4程序运行到这
0055A12C    2B5D 08             sub ebx,dword ptr ss:[ebp+8]                        ;就可以不反复循环,跟着它转了。
0055A12F    D1EB                shr ebx,1                                           ;跳出来以后继续F8跟
0055A131    035E 24             add ebx,dword ptr ds:[esi+24]
0055A134    035D 08             add ebx,dword ptr ss:[ebp+8]
0055A137    0FB703              movzx eax,word ptr ds:[ebx]
0055A13A    C1E0 02             shl eax,2
0055A13D    0346 1C             add eax,dword ptr ds:[esi+1C]
0055A140    0345 08             add eax,dword ptr ss:[ebp+8]
0055A143    8B00                mov eax,dword ptr ds:[eax]
0055A145    0345 08             add eax,dword ptr ss:[ebp+8]
0055A148    8945 FC             mov dword ptr ss:[ebp-4],eax
0055A14B    64:8F05 00000000    pop dword ptr fs:[0]
0055A152    83C4 0C             add esp,0C
0055A155    61                  popad
0055A156    8B45 FC             mov eax,dword ptr ss:[ebp-4]
0055A159    C9                  leave
0055A15A    C2 0800             retn 8


上面的程序段有一个循环,我们根据判断,程序继续运行会在0055A11B   /EB 0C               jmp short CDFace.0055A129跳出,跳到,0055A129,所以我们就在0055A129上按F4,程序就运行到了这里。
(经验需要积累,并不是一下子就学会了的。至于为什么要跳出,你想想就会明白了。这是个循环,程序判断当不满足一个条件时0055A118   /75 03  jnz short CDFace.0055A11D,跳到这句的后面,继续循环,所以,明显的最终会满足这个条件而不跳到它后面,而是不跳转继续执行到0055A11B   /EB 0C               jmp short CDFace.0055A129,所以我们假设满足这个条件它不跳走,那当然是执行中间这句0055A11B   /EB 0C               jmp short CDFace.0055A129了)
这里说得可能麻烦了一些,越说越糊涂,我做个例子你就会明白了。
假设有这样一段程序:
/***************程序开始
For x=1 to 100
 ……假设这里是一些操作
 if x=100 then Goto Next
 x=x+1
Loop
:Next
……
/***************程序结束
上面那段程序应该很清楚了吧,X是一个变量,如果X<100,它就在这里执行这个循环,如果X=100就会跳出循环。我们为了节约时间,当然让它一下子就跳到:Next执行,而且这时候的条件也已经成立了,就是X=100,在OD中,F4的作用就是运行到该句,在上面那个例子中也就是相当于直接执行到:Next。

上面我们讲的是如何绕过循环,如果你不这么做,一步一步老老实实的F8跟也是可以跟到这里的。不过要按好多下,手都酸了。

在0055A129这句上按F4,程序继续运行。
0055A129    2B5E 20             sub ebx,dword ptr ds:[esi+20]
继续按F8跟。

最后有个Retu,程序返回到
0055A4F6    0BC0                or eax,eax
0055A4F8    75 05               jnz short CDFace.0055A4FF

继续跟。它会在0055A4F8跳走,跳到0055A4FF
还是跟吧。还没开始判断光盘呢。

继续按F8跟你会发现,程序在穷举光盘,从你运行程序的驱动器号开始,一直到T盘。嘿嘿,有门了。
cmp eax,5就是判断驱动器是不是光驱。我们不管它,我们要跟到它提示错误时为止。


我们一直跟到这段程序的最后处:
0055A4FF  ………………………………
//……前面省略N多,都是在穷举光盘。
0055A883    83F8 05             cmp eax,5                                         ;判断是否为光驱
0055A886    75 1B               jnz short CDFace.0055A8A3                         ;不是跳到出错信息处
0055A888    8D83 E4134000       lea eax,dword ptr ds:[ebx+4013E4]
0055A88E    8D8B 51134000       lea ecx,dword ptr ds:[ebx+401351]
0055A894    50                  push eax
0055A895    51                  push ecx
0055A896    FF93 D2114000       call dword ptr ds:[ebx+4011D2]                    ;没有研究它在干什么,判断是不是在根目录运行?(猜的)
0055A89C    83F8 FF             cmp eax,-1                                        ;比较
0055A89F    74 02               je short CDFace.0055A8A3                          ;跳到出错信息处
0055A8A1    EB 19               jmp short CDFace.0055A8BC                         ;明显就是正确的出口,我们要跟着它走才不会挂。
0055A8A3    8D8B 93134000       lea ecx,dword ptr ds:[ebx+401393]                 ;这里其实就是出错信息开始的位置,无论如何不能到这里。
0055A8A9    8D83 9C134000       lea eax,dword ptr ds:[ebx+40139C]    ;装入出错字符
0055A8AF    6A 20               push 20
0055A8B1    51                  push ecx
0055A8B2    50                  push eax
0055A8B3    6A 00               push 0
0055A8B5    FF93 CE114000       call dword ptr ds:[ebx+4011CE]                     ; user32.MessageBoxA 提示必须在光盘运行。
0055A8BB    C3                  retn

编过程序的都应该知道MessageBox是什么了。就是那个信息提示窗口。
程序运行到这里,就提示错误了,看到了没。程序退出了,没办法跟了。
嗯。我们把断点下到0055A883。CTRL+F2重新载入。按F9,第一次断到EOP处,再按F9,就断在我们刚下的断点上0055A883了。
(为什么要把断点下在这里?从程序上面分析,这里的下面一句就是跳到失败处的嘛。)

嗯,我们看,现在断点这里EAX的值是0000001,不等于5噢,也就是下面的JNZ就要成立了。我们要么让EAX=5(这是不可能的,因为不是光盘嘛),要么让JNZ不跳,它现在不是不等于就跳吗?我不让它跳,我让它等于就跳,嘿嘿。(怎么可能等于呢,只有在光盘运行才能等于,也就是说,更改条件后,在光盘反而不能运行了。嘎嘎。当然也可以让它在光盘运行,我们这里做最简单的。)

嗯,按上面说的做,把JNZ改为JE,等于就跳到失败处。在0055A886 jnz short CDFace.0055A8A3上面双击,把JNZ改成JE。(改为JG在光盘也可以运行)
好了,不跳了。继续F8。

嗯?~!!!!到0055A89F   /74 02               je short CDFace.0055A8A3处又要跳到失败处了,我们再改,不让它跳,这回,我们把JE改成JNZ或者是不让它跳到失败处,让它跳到继续运行处。
(这里可以有2种选择,可以JE改JNZ或者不跳到失败处,而跳到成功处。成功处在哪里,分析这里你就会发现,成功处就是“0055A8A1   /EB 19               jmp short CDFace.0055A8BC”这一句。)

我们采用第2种方案,让它跳到成功处。je short CDFace.0055A8A3改成je short CDFace.0055A8A1。它不就跳到正确出口处了吗?你想改成je short CDFace.0055A8BC也行啊,不过改的东西多一些,我们的改法只改一个字节,多美。

本来以为改造已经成功了,保存修改运行一看,还有错误。看来后面还有判断。那我们继续跟。

0055A8A1   /EB 19               jmp short CDFace.0055A8BC
跳至:
0055A8BC  - E9 AF53EFFF         jmp CDFace.0044FC70

跟到0044FC70。

0044FC70  /.  55                push ebp                                          ;初始化,任何过程开始都是这个,保存现场
0044FC71  |.  8BEC              mov ebp,esp
0044FC73  |.  33C9              xor ecx,ecx
0044FC75  |.  51                push ecx
0044FC76  |.  51                push ecx
0044FC77  |.  51                push ecx
0044FC78  |.  51                push ecx
0044FC79  |.  51                push ecx
0044FC7A  |.  51                push ecx
0044FC7B  |.  51                push ecx
0044FC7C  |.  53                push ebx
0044FC7D  |.  B8 78FA4400       mov eax,CDFace.0044FA78
0044FC82  |.  E8 D964FBFF       call CDFace.00406160
0044FC87  |.  8B1D A80D4500     mov ebx,dword ptr ds:[450DA8]                      ;  CDFace.004517CC
0044FC8D  |.  33C0              xor eax,eax
0044FC8F  |.  55                push ebp
0044FC90  |.  68 83FD4400       push CDFace.0044FD83
0044FC95  |.  64:FF30           push dword ptr fs:[eax]
0044FC98  |.  64:8920           mov dword ptr fs:[eax],esp
0044FC9B  |.  8D55 EC           lea edx,dword ptr ss:[ebp-14]
0044FC9E  |.  8B03              mov eax,dword ptr ds:[ebx]
0044FCA0  |.  E8 F71BFFFF       call CDFace.0044189C
0044FCA5  |.  8B45 EC           mov eax,dword ptr ss:[ebp-14]
0044FCA8  |.  8D55 F0           lea edx,dword ptr ss:[ebp-10]
0044FCAB  |.  E8 6C84FBFF       call CDFace.0040811C
0044FCB0  |.  8B55 F0           mov edx,dword ptr ss:[ebp-10]
0044FCB3  |.  B8 F01C4500       mov eax,CDFace.00451CF0
0044FCB8  |.  B9 98FD4400       mov ecx,CDFace.0044FD98
0044FCBD  |.  E8 BE40FBFF       call CDFace.00403D80
0044FCC2  |.  A1 F01C4500       mov eax,dword ptr ds:[451CF0]
0044FCC7  |.  E8 2C42FBFF       call CDFace.00403EF8
0044FCCC  |.  50                push eax                                           ; /RootPathName
0044FCCD  |.  E8 BA65FBFF       call <jmp.&kernel32.GetDriveTypeA>                 ; /GetDriveTypeA取得驱动器类型
0044FCD2  |.  83F8 05           cmp eax,5                                          ;比较是否光驱
0044FCD5      74 31             je short CDFace.0044FD08                           ;如果是光驱就跳到继续执行处
0044FCD7  |.  8D55 E8           lea edx,dword ptr ss:[ebp-18]                      ;不是就要出错了。
0044FCDA  |.  B8 01000000       mov eax,1
0044FCDF  |.  E8 CC2BFBFF       call CDFace.004028B0
0044FCE4  |.  8B45 E8           mov eax,dword ptr ss:[ebp-18]
0044FCE7  |.  BA A4FD4400       mov edx,CDFace.0044FDA4                            ;  ASCII "/AutoRun.inf"
0044FCEC  |.  E8 5341FBFF       call CDFace.00403E44
0044FCF1  |.  74 15             je short CDFace.0044FD08
0044FCF3  |.  6A 10             push 10
0044FCF5  |.  B9 B4FD4400       mov ecx,CDFace.0044FDB4
0044FCFA  |.  BA BCFD4400       mov edx,CDFace.0044FDBC
0044FCFF  |.  8B03              mov eax,dword ptr ds:[ebx]
0044FD01  |.  E8 2618FFFF       call CDFace.0044152C
0044FD06  |.  EB 60             jmp short CDFace.0044FD68
0044FD08  |>  8B03              mov eax,dword ptr ds:[ebx]
0044FD0A  |.  E8 2D16FFFF       call CDFace.0044133C
0044FD0F  |.  8B03              mov eax,dword ptr ds:[ebx]
0044FD11  |.  BA E8FD4400       mov edx,CDFace.0044FDE8
0044FD16  |.  E8 3D12FFFF       call CDFace.00440F58
0044FD1B  |.  8B0D C00C4500     mov ecx,dword ptr ds:[450CC0]                      ;  CDFace.00451CE8
0044FD21  |.  8B03              mov eax,dword ptr ds:[ebx]
0044FD23  |.  8B15 F8F04400     mov edx,dword ptr ds:[44F0F8]                      ;  CDFace.0044F144
0044FD29  |.  E8 2616FFFF       call CDFace.00441354
0044FD2E  |.  8B03              mov eax,dword ptr ds:[ebx]
0044FD30  |.  8B40 38           mov eax,dword ptr ds:[eax+38]
0044FD33  |.  8B48 08           mov ecx,dword ptr ds:[eax+8]
0044FD36  |.  8D45 E4           lea eax,dword ptr ss:[ebp-1C]
0044FD39  |.  BA 00FE4400       mov edx,CDFace.0044FE00                            ;  ASCII "MUTEX_"
0044FD3E  |.  E8 3D40FBFF       call CDFace.00403D80
0044FD43  |.  8B45 E4           mov eax,dword ptr ss:[ebp-1C]
0044FD46  |.  E8 AD41FBFF       call CDFace.00403EF8
0044FD4B  |.  50                push eax                                           ; /MutexName
0044FD4C  |.  6A FF             push -1                                            ; |InitialOwner = TRUE
0044FD4E  |.  6A 00             push 0                                             ; |pSecurity = NULL
0044FD50  |.  E8 AF64FBFF       call <jmp.&kernel32.CreateMutexA>                  ; /CreateMutexA
0044FD55  |.  E8 4A65FBFF       call <jmp.&kernel32.GetLastError>                  ; [GetLastError
0044FD5A  |.  3D B7000000       cmp eax,0B7
0044FD5F  |.  74 07             je short CDFace.0044FD68
0044FD61  |.  8B03              mov eax,dword ptr ds:[ebx]
0044FD63  |.  E8 6C16FFFF       call CDFace.004413D4
0044FD68  |>  33C0              xor eax,eax
0044FD6A  |.  5A                pop edx
0044FD6B  |.  59                pop ecx
0044FD6C  |.  59                pop ecx
0044FD6D  |.  64:8910           mov dword ptr fs:[eax],edx
0044FD70  |.  68 8AFD4400       push CDFace.0044FD8A
0044FD75  |>  8D45 E4           lea eax,dword ptr ss:[ebp-1C]
0044FD78  |.  BA 04000000       mov edx,4
0044FD7D  |.  E8 563DFBFF       call CDFace.00403AD8
0044FD82  /.  C3                retn

仔细分析这一段,我们发现,程序又判断驱动器是不是光驱,是光驱就继续,不是光驱就提示出错
0044FCCD  |.  E8 BA65FBFF       call <jmp.&kernel32.GetDriveTypeA>                 ; /GetDriveTypeA
0044FCD2  |.  83F8 05           cmp eax,5                      ;判断是不是光驱
0044FCD5      74 31             je short CDFace.0044FD08       ;如果是就跳到成功处。修改这里,JE改JMP,无论如何都跳。
0044FCD7  |.  8D55 E8           lea edx,dword ptr ss:[ebp-18]
0044FCDA  |.  B8 01000000       mov eax,1
0044FCDF  |.  E8 CC2BFBFF       call CDFace.004028B0

改完之后再一运行,已经可以了。

------------------------------------------------------------------------
【破解总结】幸运的是程序加密并不严谨,一开始就引入判断光驱的过程,只用了不长时间破解。反而在脱壳上下了不少工夫,结果无功而返。

总结一下。改了三个地方:
0055A886    75 1B               jnz short CDFace.0055A8A3
    //offset 00154886h    JNZ改JE,75改74。如果想让程序在光盘也能运行应该改为JG,机器码是7F。
0055A89F    74 02               je short CDFace.0055A8A3
    //offset 0015489fh    JE改JNZ或改跳转,我们选 的是改跳转,7402改7400  
0044FCD5    74 31               je short CDFace.0044FD08
    //offset 0004f0d5h    JE改JMP,74改EB。  


需要注意的是在HIEW中修改和在OD中修改不同,OD中已经让程序运行在内存之中,而HIEW是静态修改的,程序并没有运行。所以修改的偏移位置并不相同。
借助于W32Dasm我们可以知道偏移位置。具体方法是用W32Dasm反汇编程序,查找0055A886,最下端中间显示的Offset就是在HIEW中显示的偏移位置。其他都相同,这里不再详述。我上面已经把Offset标注出来了。

最后需要说明的是,这次破解并非常规的破解,常规的破解应该先脱壳,然后下函数断点或者其它断点是正规方法。这次没有用常规方法就成功,主要原因是程序加密不严谨,给了破解者可乘之机,一开始就进行检测了。如果遇到严谨的加密方法,没有脱壳就开始破解,可能要跟上几天才能得出结果。
------------------------------------------------------------------------
【版权声明】本文纯属技术交流, 转载请注明作者信息并保持文章的完整, 谢谢!
------------------------------------------------------------------------

原创粉丝点击