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

    技术2022-05-11  128

    【破文标题】企业报表处理软件(2005版)免光盘破解【破文作者】gc801【作者邮箱】****【作者主页】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 不等于就跳转   机器码:75JE  等于就跳转     机器码:74JMP 无条件跳转     机器码: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 ebp0055A0AB    8BEC                mov ebp,esp0055A0AD    83C4 F8             add esp,-80055A0B0    60                  pushad0055A0B1    C745 FC 00000000    mov dword ptr ss:[ebp-4],00055A0B8    E8 00000000         call CDFace.0055A0BD0055A0BD    5B                  pop ebx0055A0BE    81EB 1E114000       sub ebx,CDFace.0040111E0055A0C4    55                  push ebp0055A0C5    8D83 AC114000       lea eax,dword ptr ds:[ebx+4011AC]0055A0CB    50                  push eax0055A0CC    8D83 61104000       lea eax,dword ptr ds:[ebx+401061]0055A0D2    50                  push eax0055A0D3    64:FF35 00000000    push dword ptr fs:[0]0055A0DA    64:8925 00000000    mov dword ptr fs:[0],esp0055A0E1    8B7D 0C             mov edi,dword ptr ss:[ebp+C]0055A0E4    B9 FFFFFFFF         mov ecx,-10055A0E9    32C0                xor al,al0055A0EB    FC                  cld0055A0EC    F2:AE               repne scas byte ptr es:[edi]0055A0EE    8BCF                mov ecx,edi0055A0F0    2B4D 0C             sub ecx,dword ptr ss:[ebp+C]0055A0F3    894D F8             mov dword ptr ss:[ebp-8],ecx0055A0F6    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,edx0055A10A    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 esi0055A11B    EB 0C               jmp short CDFace.0055A129                          ; 满足条件以后就跳走。我们要跟着它走,跳到它想跳的地方0055A11D    5E                  pop esi                                            ; kernel32.7C880DD80055A11E    83C3 04             add ebx,40055A121    42                  inc edx0055A122    3B56 18             cmp edx,dword ptr ds:[esi+18]0055A125  ^ 72 E3               jb short CDFace.0055A10A                            ;这里是循环结束。0055A127    EB 22               jmp short CDFace.0055A14B0055A129    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,20055A13D    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],eax0055A14B    64:8F05 00000000    pop dword ptr fs:[0]0055A152    83C4 0C             add esp,0C0055A155    61                  popad0055A156    8B45 FC             mov eax,dword ptr ss:[ebp-4]0055A159    C9                  leave0055A15A    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+1Loop: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,eax0055A4F8    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 eax0055A895    51                  push ecx0055A896    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 200055A8B1    51                  push ecx0055A8B2    50                  push eax0055A8B3    6A 00               push 00055A8B5    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,esp0044FC73  |.  33C9              xor ecx,ecx0044FC75  |.  51                push ecx0044FC76  |.  51                push ecx0044FC77  |.  51                push ecx0044FC78  |.  51                push ecx0044FC79  |.  51                push ecx0044FC7A  |.  51                push ecx0044FC7B  |.  51                push ecx0044FC7C  |.  53                push ebx0044FC7D  |.  B8 78FA4400       mov eax,CDFace.0044FA780044FC82  |.  E8 D964FBFF       call CDFace.004061600044FC87  |.  8B1D A80D4500     mov ebx,dword ptr ds:[450DA8]                      ;  CDFace.004517CC0044FC8D  |.  33C0              xor eax,eax0044FC8F  |.  55                push ebp0044FC90  |.  68 83FD4400       push CDFace.0044FD830044FC95  |.  64:FF30           push dword ptr fs:[eax]0044FC98  |.  64:8920           mov dword ptr fs:[eax],esp0044FC9B  |.  8D55 EC           lea edx,dword ptr ss:[ebp-14]0044FC9E  |.  8B03              mov eax,dword ptr ds:[ebx]0044FCA0  |.  E8 F71BFFFF       call CDFace.0044189C0044FCA5  |.  8B45 EC           mov eax,dword ptr ss:[ebp-14]0044FCA8  |.  8D55 F0           lea edx,dword ptr ss:[ebp-10]0044FCAB  |.  E8 6C84FBFF       call CDFace.0040811C0044FCB0  |.  8B55 F0           mov edx,dword ptr ss:[ebp-10]0044FCB3  |.  B8 F01C4500       mov eax,CDFace.00451CF00044FCB8  |.  B9 98FD4400       mov ecx,CDFace.0044FD980044FCBD  |.  E8 BE40FBFF       call CDFace.00403D800044FCC2  |.  A1 F01C4500       mov eax,dword ptr ds:[451CF0]0044FCC7  |.  E8 2C42FBFF       call CDFace.00403EF80044FCCC  |.  50                push eax                                           ; /RootPathName0044FCCD  |.  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,10044FCDF  |.  E8 CC2BFBFF       call CDFace.004028B00044FCE4  |.  8B45 E8           mov eax,dword ptr ss:[ebp-18]0044FCE7  |.  BA A4FD4400       mov edx,CDFace.0044FDA4                            ;  ASCII "/AutoRun.inf"0044FCEC  |.  E8 5341FBFF       call CDFace.00403E440044FCF1  |.  74 15             je short CDFace.0044FD080044FCF3  |.  6A 10             push 100044FCF5  |.  B9 B4FD4400       mov ecx,CDFace.0044FDB40044FCFA  |.  BA BCFD4400       mov edx,CDFace.0044FDBC0044FCFF  |.  8B03              mov eax,dword ptr ds:[ebx]0044FD01  |.  E8 2618FFFF       call CDFace.0044152C0044FD06  |.  EB 60             jmp short CDFace.0044FD680044FD08  |>  8B03              mov eax,dword ptr ds:[ebx]0044FD0A  |.  E8 2D16FFFF       call CDFace.0044133C0044FD0F  |.  8B03              mov eax,dword ptr ds:[ebx]0044FD11  |.  BA E8FD4400       mov edx,CDFace.0044FDE80044FD16  |.  E8 3D12FFFF       call CDFace.00440F580044FD1B  |.  8B0D C00C4500     mov ecx,dword ptr ds:[450CC0]                      ;  CDFace.00451CE80044FD21  |.  8B03              mov eax,dword ptr ds:[ebx]0044FD23  |.  8B15 F8F04400     mov edx,dword ptr ds:[44F0F8]                      ;  CDFace.0044F1440044FD29  |.  E8 2616FFFF       call CDFace.004413540044FD2E  |.  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.00403D800044FD43  |.  8B45 E4           mov eax,dword ptr ss:[ebp-1C]0044FD46  |.  E8 AD41FBFF       call CDFace.00403EF80044FD4B  |.  50                push eax                                           ; /MutexName0044FD4C  |.  6A FF             push -1                                            ; |InitialOwner = TRUE0044FD4E  |.  6A 00             push 0                                             ; |pSecurity = NULL0044FD50  |.  E8 AF64FBFF       call <jmp.&kernel32.CreateMutexA>                  ; /CreateMutexA0044FD55  |.  E8 4A65FBFF       call <jmp.&kernel32.GetLastError>                  ; [GetLastError0044FD5A  |.  3D B7000000       cmp eax,0B70044FD5F  |.  74 07             je short CDFace.0044FD680044FD61  |.  8B03              mov eax,dword ptr ds:[ebx]0044FD63  |.  E8 6C16FFFF       call CDFace.004413D40044FD68  |>  33C0              xor eax,eax0044FD6A  |.  5A                pop edx0044FD6B  |.  59                pop ecx0044FD6C  |.  59                pop ecx0044FD6D  |.  64:8910           mov dword ptr fs:[eax],edx0044FD70  |.  68 8AFD4400       push CDFace.0044FD8A0044FD75  |>  8D45 E4           lea eax,dword ptr ss:[ebp-1C]0044FD78  |.  BA 04000000       mov edx,40044FD7D  |.  E8 563DFBFF       call CDFace.00403AD80044FD82  /.  C3                retn

    仔细分析这一段,我们发现,程序又判断驱动器是不是光驱,是光驱就继续,不是光驱就提示出错0044FCCD  |.  E8 BA65FBFF       call <jmp.&kernel32.GetDriveTypeA>                 ; /GetDriveTypeA0044FCD2  |.  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,10044FCDF  |.  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标注出来了。

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


    最新回复(0)