·汉化新世纪 ·汉化新世纪论坛 ·百家争鸣 ·论坛集萃 ·汉化问答 ·软件介绍
文章首页 >> 汉化教学 >> 编程知识 >> 汉化提高课─解除软件自检验    Creative Commons License,创作共用协议(中文版)  署名 非商业性使用 禁止演绎

汉化提高课─解除软件自检验

作者: 飞鹰 来源:汉化教学 时间:2003-07-26 点击:10170

汉化提高课─解除软件自检验

作者:汉化新世纪成员飞鹰

在汉化一个软件之前,我想首先摆在我们汉化人之前的就有两大难题:一是软件被加了壳,二是软件自身有自检验;如果我们无法很好的处理这两个难题的话, 将不能进行软件的汉化。就此,我以我多年的汉化经验写了两篇《汉化提高课》文章,一篇是关于软件脱壳的,一篇(此篇)是关于解除软件自检验的,衷心希望各位汉化爱好者能在阅读完这两篇文章之后,汉化技术会有进一步的提高,我写这两篇文章的目的也就达到了。

什么是自检验?自检验是软件作者给软件加保护的一种方式,它是通过检查程序的完整性来防止其它人修改软件。这种完整性检查就是针对程序的某一部分或全部计算出一个值来,然后和预期的值相比较。如果不同,则说明程序被人修改过了,这有可能是感染了病毒,也可能是被破解了;可让程序在这种情况下拒绝运行。

软件的自检验要如何才能解除呢?我们可以通过一些动态调试器(如Softice、Trw2000、OllyDbg等),跟踪软件的执行过程来判断出软件的自检验处(如果你的汇编高手的话,你还可以分析出自检验的算法),之后修改软件让其跳过这段自检验代码的检验就可以达到解除软件自检验的目的了。俗话说:欲成其事,先利其器;那么我们要先选择一种动态调试软件才能进行下面的工作,用Softice、Trw2000来调试是完全可行的,加上这两个调试器的功能相当强大,但我想大多数汉化人一看到这种调试器就头痛,那还会有心情再把此篇文章看一去;为了让大家能能掌握一些跟踪调试软件的方法,也为了让我这篇文章不白写,我就选用最近调试器中的新成员 OllyDbg 来进行下面的工作吧!

OllyDbg 是一个32位汇编级的直观的分析调试器,它在源代码不可得或者你用编译器遇到问题的时候特别有用,现在最高版本是1.06,它的界面如图一所示,界面上共分为四个窗口,左上角是汇编区,右上角是寄存器区,左下角是内存区,右下角是入栈出栈区。OllyDbg 不像Softice、Trw2000那样在运行时需要占用整个系统的全部资源,它在运行时可以一边调试、一边进行其它工作(比如听MP3);并且,它的调试环境是友好的图形界面,需要什么命令你都可以在菜单中选择,不必再记任何命令,如何你想调试速度更快的话,你可能需要记一些 OllyDbg 常用的快捷键。选择好顺手的兵器(OllyDbg 1.06)后,下面我们就开始学习解除软件自检验的方法。

(图一)

1、自检验保护软件 CpuIdle 5.9:这个软件是应我们 汉化新世纪成员-五哥 的要求,进行的调试修改。首先,我们知道 CpuIdle 5.9 被UPX1.20加了壳,脱壳后(脱壳方法可以参看我写的另一篇文章《汉化提高课─UPXPR 的脱壳方法》)再次启动软件,你就会发现软件运行不起来,没有任何的错误提示就退出。下面我们启动 OllyDbg 来进行跟踪分析,操作步骤:选择“File”主菜单中的“Open”项目(快捷键为F3)载入软件-->稍等片刻后出现如图一所示的界面,之后按 F8 键(也可以选择“Debug”主菜单中的“Step over”项目)进行单步调试-->一直按 F8 键来到 0048BB4C 处后(指令为JNZ SHORT CPUIDLE5.0048BB7D),此时再按 F8 键将跳转到 0048BB7D 处,其中从 0048BAE9至0048BB78 之间的指令将不会被执行到,从 0048BB7D 处按 F8 键往后走不到几条指令 OllyDbg 将会中止跟踪过程。所以,我们就可以断定 0048BB4C 处正是软件自检验的检测处;如果此处跳转的话,程序将退出运行;如果此处不跳转的话,程序将会启动继续执行-->知道了软件自检验的检测处是 0048BB4C 后,选择“Debug”主菜单中的“Restart”项目(快捷键为Ctrl+F2)重新载入该软件,当跟踪到 0048BB4C 处时,在左上角的汇编区中单击鼠标右键选择“Copy to executable file”-->在进入的新窗口中单击鼠标右键选择“Assemble”项目把指令 JNZ SHORT CPUIDLE5.0048BB7D 改为 NOP(注意要选中该对话框中的“Fill with NOP's”选项)(注:NOP指令为空指令,即不执行任何操作),单击“Assemble”按钮修改成功,之后关闭新打开这个窗口时 OllyDbg 会询问你“文件已经被修改,是否要保存?”,单击“是”按钮后你修改的地方就被永久的保存到 EXE 文件中去了(免去再用 16 进制修改一次的麻烦)。关闭 OllyDbg 后,再次启动新保存的 CpuIdle 5.9,你会发现软件已经可以正常运行了。下面是调试该软件时在 OllyDbg 左上角的汇编区中显示出来的内容。其中,‘//’是我自己加入的注释,方便大家理解;‘;’是 OllyDbg 自动分析出来的字符。

0048B9FC >/$ 55            PUSH EBP                         //载入软件后首先停在这里
0048B9FD |. 8BEC           MOV EBP,ESP
0048B9FF |. 83C4 E0        ADD ESP,-20
0048BA02 |. 33C0           XOR EAX,EAX
0048BA04 |. 8945 E0        MOV DWORD PTR SS:[EBP-20],EAX
0048BA07 |. 8945 E4        MOV DWORD PTR SS:[EBP-1C],EAX
0048BA0A |. 8945 EC        MOV DWORD PTR SS:[EBP-14],EAX
0048BA0D |. 8945 E8        MOV DWORD PTR SS:[EBP-18],EAX
0048BA10 |. B8 A4B74800    MOV EAX,CPUIDLE5.0048B7A4
0048BA15 |. E8 2EB2F7FF    CALL CPUIDLE5.00406C48
0048BA1A |. 33C0           XOR EAX,EAX
0048BA1C |. 55             PUSH EBP
0048BA1D |. 68 A3BB4800    PUSH CPUIDLE5.0048BBA3
0048BA22 |. 64:FF30        PUSH DWORD PTR FS:[EAX]
0048BA25 |. 64:8920        MOV DWORD PTR FS:[EAX],ESP
0048BA28 |. 8D55 E8        LEA EDX,DWORD PTR SS:[EBP-18]
0048BA2B |. 33C0           XOR EAX,EAX
0048BA2D |. E8 6A70F7FF    CALL CPUIDLE5.00402A9C
0048BA32 |. 8B45 E8        MOV EAX,DWORD PTR SS:[EBP-18]
0048BA35 |. 8D55 EC        LEA EDX,DWORD PTR SS:[EBP-14]
0048BA38 |. E8 2FD8F7FF    CALL CPUIDLE5.0040926C
0048BA3D |. 8B55 EC        MOV EDX,DWORD PTR SS:[EBP-14]
0048BA40 |. A1 C0D54800    MOV EAX,DWORD PTR DS:[48D5C0]
0048BA45 |. E8 3A8EF7FF    CALL CPUIDLE5.00404884
0048BA4A |. A1 C0D54800    MOV EAX,DWORD PTR DS:[48D5C0]
0048BA4F |. 8B00           MOV EAX,DWORD PTR DS:[EAX]
0048BA51 |. E8 9290F7FF    CALL CPUIDLE5.00404AE8
0048BA56 |. 8B15 C0D54800  MOV EDX,DWORD PTR DS:[48D5C0]   ; CPUIDLE5.0048CFAC
0048BA5C |. 8B12           MOV EDX,DWORD PTR DS:[EDX]
0048BA5E |. 807C02 FF 5C   CMP BYTE PTR DS:[EDX+EAX-1],5C
0048BA63 |. 74 14          JE SHORT CPUIDLE5.0048BA79
0048BA65 |. A1 C0D54800    MOV EAX,DWORD PTR DS:[48D5C0]
0048BA6A |. BA B8BB4800    MOV EDX,CPUIDLE5.0048BBB8
0048BA6F |. E8 7C90F7FF    CALL CPUIDLE5.00404AF0
0048BA74 |. A1 C0D54800    MOV EAX,DWORD PTR DS:[48D5C0]
0048BA79 |> A1 C0D54800    MOV EAX,DWORD PTR DS:[48D5C0]
0048BA7E |. BA C4BB4800    MOV EDX,CPUIDLE5.0048BBC4       ; ASCII "cpuidle.ini"
0048BA83 |. E8 6890F7FF    CALL CPUIDLE5.00404AF0
0048BA88 |. A1 C0D54800    MOV EAX,DWORD PTR DS:[48D5C0]
0048BA8D |. A1 08DA4800    MOV EAX,DWORD PTR DS:[48DA08]
0048BA92 |. 8338 02        CMP DWORD PTR DS:[EAX],2
0048BA95 |. 75 2A          JNZ SHORT CPUIDLE5.0048BAC1     //判断你是不是在 WinNT 下运行该软件,如果此处不跳转则退出程序运行。
0048BA97 |. 6A 00          PUSH 0
0048BA99 |. 8D4D E4        LEA ECX,DWORD PTR SS:[EBP-1C]
0048BA9C |. BA C4130000    MOV EDX,13C4
0048BAA1 |. B8 D8BB4800    MOV EAX,CPUIDLE5.0048BBD8      ; ASCII "Sorry- This version of CpuIdle does not run on Windows NT"
0048BAA6 |. E8 C969FEFF    CALL CPUIDLE5.00472474
0048BAAB |. 8B45 E4        MOV EAX,DWORD PTR SS:[EBP-1C]  ; |
0048BAAE |. 66:8B0D 14BC48>MOV CX,WORD PTR DS:[48BC14]    ; |
0048BAB5 |. B2 01          MOV DL,1                       ; |
0048BAB7 |. E8 BCA7FAFF    CALL CPUIDLE5.00436278         ; \CPUIDLE5.00436278
0048BABC |. E9 C7000000    JMP CPUIDLE5.0048BB88
0048BAC1 |> 68 18BC4800    PUSH CPUIDLE5.0048BC18         ; /Arg3 = 0048BC18 ASCII "CpuIdle"
0048BAC6 |. 6A 00          PUSH 0                         ; |Arg2 = 00000000
0048BAC8 |. 6A 00          PUSH 0                         ; |Arg1 = 00000000
0048BACA |. E8 29B3F7FF    CALL CPUIDLE5.00406DF8         ; \CPUIDLE5.00406DF8
0048BACF |. A3 0CF04800    MOV DWORD PTR DS:[48F00C],EAX
0048BAD4 |. E8 DFB3F7FF    CALL <JMP.&KERNEL32.GetLastError> ; [GetLastError
0048BAD9 |. 3D B7000000    CMP EAX,0B7
0048BADE |. 74 09          JE SHORT CPUIDLE5.0048BAE9
0048BAE0 |. 833D 0CF04800 >CMP DWORD PTR DS:[48F00C],0
0048BAE7 |. 75 27          JNZ SHORT CPUIDLE5.0048BB10     //判断 CpuIdle 是否已经运行,如果此处不跳转则退出程序运行。
0048BAE9 |> 6A 00          PUSH 0
0048BAEB |. 8D4D E0        LEA ECX,DWORD PTR SS:[EBP-20]
0048BAEE |. BA BE130000    MOV EDX,13BE
0048BAF3 |. B8 28BC4800    MOV EAX,CPUIDLE5.0048BC28      ; ASCII "CpuIdle is already running."
0048BAF8 |. E8 7769FEFF    CALL CPUIDLE5.00472474
0048BAFD |. 8B45 E0        MOV EAX,DWORD PTR SS:[EBP-20]  ; |
0048BB00 |. 66:8B0D 14BC48>MOV CX,WORD PTR DS:[48BC14]    ; |
0048BB07 |. B2 01          MOV DL,1                       ; |
0048BB09 |. E8 6AA7FAFF    CALL CPUIDLE5.00436278         ; \CPUIDLE5.00436278
0048BB0E |. EB 78          JMP SHORT CPUIDLE5.0048BB88
0048BB10 |> A1 78D84800    MOV EAX,DWORD PTR DS:[48D878]
0048BB15 |. 8B00           MOV EAX,DWORD PTR DS:[EAX]
0048BB17 |. E8 8013FDFF    CALL CPUIDLE5.0045CE9C
0048BB1C |. A1 78D84800    MOV EAX,DWORD PTR DS:[48D878]
0048BB21 |. 8B00           MOV EAX,DWORD PTR DS:[EAX]
0048BB23 |. BA 4CBC4800    MOV EDX,CPUIDLE5.0048BC4C      ; ASCII "CpuIdle"
0048BB28 |. E8 7B0FFDFF    CALL CPUIDLE5.0045CAA8
0048BB2D |. A1 78D84800    MOV EAX,DWORD PTR DS:[48D878]
0048BB32 |. 8B00           MOV EAX,DWORD PTR DS:[EAX]
0048BB34 |. C740 74 393000>MOV DWORD PTR DS:[EAX+74],3039
0048BB3B |. E8 0462FDFF    CALL CPUIDLE5.00461D44
0048BB40 |. A1 40D64800    MOV EAX,DWORD PTR DS:[48D640]
0048BB45 |. 8B00           MOV EAX,DWORD PTR DS:[EAX]
0048BB47 |. 35 3CB7D21F    XOR EAX,1FD2B73C
0048BB4C |. 75 2F          JNZ SHORT CPUIDLE5.0048BB7D     //软件自检验的关键判断处,如果此处跳转则退出程序运行。
0048BAE9 |> 6A 00          PUSH 0
0048BB4E |. A1 78D84800    MOV EAX,DWORD PTR DS:[48D878]
0048BB53 |. 8B00           MOV EAX,DWORD PTR DS:[EAX]
0048BB55 |. C640 5B 00     MOV BYTE PTR DS:[EAX+5B],0
0048BB59 |. 8B0D FCD94800  MOV ECX,DWORD PTR DS:[48D9FC]  ; CPUIDLE5.0048F004
0048BB5F |. A1 78D84800    MOV EAX,DWORD PTR DS:[48D878]
0048BB64 |. 8B00           MOV EAX,DWORD PTR DS:[EAX]
0048BB66 |. 8B15 F0724800  MOV EDX,DWORD PTR DS:[4872F0]  ; CPUIDLE5.0048733C
0048BB6C |. E8 4313FDFF    CALL CPUIDLE5.0045CEB4
0048BB71 |. A1 78D84800    MOV EAX,DWORD PTR DS:[48D878]
0048BB76 |. 8B00           MOV EAX,DWORD PTR DS:[EAX]
0048BB78 |. E8 B713FDFF    CALL CPUIDLE5.0045CF34
0048BB7D |> A1 0CF04800    MOV EAX,DWORD PTR DS:[48F00C]
0048BB82 |. 50             PUSH EAX                          ; /hMutex => NULL
0048BB83 |. E8 50B4F7FF    CALL <JMP.&KERNEL32.ReleaseMutex> ; \ReleaseMutex
0048BB88 |> 33C0           XOR EAX,EAX
0048BB8A |. 5A             POP EDX
0048BB8B |. 59             POP ECX
0048BB8C |. 59             POP ECX
0048BB8D |. 64:8910        MOV DWORD PTR FS:[EAX],EDX
0048BB90 |. 68 AABB4800    PUSH CPUIDLE5.0048BBAA
0048BB95 |> 8D45 E0        LEA EAX,DWORD PTR SS:[EBP-20]
0048BB98 |. BA 04000000    MOV EDX,4
0048BB9D |. E8 B28CF7FF    CALL CPUIDLE5.00404854
0048BBA2 \. C3             RETN

2、自检验保护软件 MaxMem 1.01:这个软件是应一位朋友 txjgzz 的要求,进行的调试修改。这个软件的自检验保护稍弱一点,只要你修改了该软件中的任何一处,启动软件时它会提示说“ABORT: MaxMem has been corrupted, please re-install to correct the problem.. (winmain.c/564)”,这句话就是最好的解除自检验的突破口。按照上一篇操作步骤先用 OllyDbg 载入该软件,之后选择“Debug”主菜单中的“Run”项目(快捷键为F9)让软件运行,当该软件跳出错误提示对话框时,切换到 OllyDbg 中(注意:此时不要关闭出错对话框,否则下面的查找会失败)按 F12 键来到下面这里:

0040158B |. F605 7C014100 >TEST BYTE PTR DS:[41017C],10
00401592 |. 75 35          JNZ SHORT MAXMEM.004015C9
00401594 |. 6A 10          PUSH 10                                   ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00401596 |. 68 BAF34000    PUSH MAXMEM.0040F3BA                      ; |Title = "Internal error..."
0040159B |. 68 12104100    PUSH MAXMEM.00411012                      ; |Text = "ABORT: MaxMem has been corrupted, please re-install to correct the problem. (winmain.c/564)"
004015A0 |. 6A 00          PUSH 0                                    ; |hOwner = NULL
004015A2 |. 2E:FF15 E4E340>CALL DWORD PTR CS:[<&USER32.MessageBoxA>> ; \MessageBoxA
004015A9 |. EB 1E          JMP SHORT MAXMEM.004015C9

大家是不是发现,00401592 处有一个转移指令,那么是否可以把 JNZ SHORT MAXMEM.004015C9 改为 JMP SHORT MAXMEM.004015C9,经过测试发现改这里没有作用,虽然没有了提示框,但软件还是无法运行。所以,接着下面继续讲解。

选择“View”主菜单中的“Memory”项目(快捷键为Alt+M),这时会产生一个新的窗口,在这个窗口中查看标题(Owner)为 MAXMEM 的项目,共有七个地方,其中块(Section)的内容都为空(这里是个特例,一般 Section 的内容是.data、.code、.rsrc),当我们选择 Owner 为 MAXMEM 的倒数第四处地方时(因为这个 Section 中存放着出错对话框中的字符串,这里我是通过不断的测试发现的,一般这样的字符串都会存放在 Section 为.code或.data当中,但这个软件 Section 内容都为空,所以判断起来就困难一些),单击鼠标右键选择“Dump in CPU”;这里应该切换到 OllyDbg 的左下角是内存区中,单击鼠标右键选择“Search for”菜单中的“Binary string”项目,并在 ASCII 框中输入 ABORT: MaxMem,(其实也就是启动 MaxMem 时出现在错误对话框中的内容,这里我只取了前几个字符)单击“OK”按钮,没有找到。好吧,我就查找 has been corrupted,可以找到一处,再往下查找就没有了;所以,我肯定此处就是启动软件时出现的错误提示信息,找到的字符串是“%s has been corrupted, please re-install to correct the problem.”那么看来“ABORT: MaxMem”这几个字符串是在软件运行时自动填补进来的,单击鼠标右键选择“Fine references”项目又进入了一个窗口,在其中显示出了该对话框被那几地方调用过,这里只有一地方调用它,地址是 0040390F,在该处双击鼠标左键来到了 OllyDbg 左上角的汇编区中,这时的状态如下所示:

004038F1 |. E8 9DD8FFFF   CALL MAXMEM.00401193
004038F6 |. 85C0          TEST EAX,EAX
004038F8 |. 75 22         JNZ SHORT MAXMEM.0040391C
004038FA |. BA 34020000   MOV EDX,234
004038FF |. B8 F4F94000   MOV EAX,MAXMEM.0040F9F4    ; ASCII "winmain.c"
00403904 |. E8 77DDFFFF   CALL MAXMEM.00401680
00403909 |. FF35 E4014100 PUSH DWORD PTR DS:[4101E4] ; /Arg2 = 0040F894 ASCII "MaxMem"
0040390F |. 68 F3FA4000   PUSH MAXMEM.0040FAF3       ; |Arg1 = 0040FAF3 ASCII "%s has been corrupted, please re-install to correct the problem."
00403914 |. E8 6DDAFFFF   CALL MAXMEM.00401386       ; \MAXMEM.00401386

从 0040390F 向上找,可以知道只要把 004038F8 处的指令 JNZ SHORT MAXMEM.0040391C 改为 JMP SHORT MAXMEM.0040391C(注:JMP 指令是无条件转移指令;即不论条件是否匹配,它都会永远跳转到目标地址),之后就可以跳过这个出错对话框继续往下执行。具体的修改方法在上面我已介绍过了,这里不再重复讲述。

3、 自检验保护软件 RegEditor 1.2:这个软件是应论坛上一位朋友 mimizero 的要求,进行的调试修改。跟踪调试方法我就不多说了,与上面讲的基本相同,只是该软件在解除自检验后就无法再使用它所具有的任何功能了,只要使用该软件的任何一个功能就自动退出运行,这种保护方式可能以后会有很多软件开发人员使用,所以在此我也提一下。我们可以通过中断 PostQuitMessage 函数来达到调试的目的,操作步骤:在 OllyDbg 中按 Ctrl+N 键在其中选择 user32.PostQuitMessage 函数-->按 Enter 键之后选中有 Call 语句的地方,按 F2 键下断点-->之后,运行该软件中任何一个功能,立刻就会被 OllyDbg 中断,回到 OllyDbg 的主界面左上角的汇编区中向上找是否有能跳过此处的指令,比如:JNZ、JZ等,之后把找到的地方改为 JMP 就行了。对于该软件共可以找到五处地方调用了 user32.PostQuitMessage 函数,但只要修改其中的三处地方即可完全解决该软件执行功能自动退出的情况,其它两处好象都是执行软件的正常退出,决对不能改,否则软件将不能正常退出了。

上面讲到的这三种软件自检验保护方式应该是目前最常见的。当然,也不是说你学会这篇文章中的全部内容就能对付所有软件的自检验了,在我们的汉化过程中会碰到一些有很强自检验保护的软件,比如:CacheX、flax、CuteFTP Pro、HyperSnap-DX等,这些软件的自检验真可谓是最难解除的了,像 CacheX 它就的是根据自检验的结果来动态还原某些运行代码,如果你改动了软件中的任何地方,这些动态生成的代码将得不到正确的还原,一旦运行肯定就会出错。此类软件如果大家遇到就只能耐心慢慢分析调试了。

OllyDbg 的网址:http://home.t-online.de/home/Ollydbg,你可以到它的网站去下载该软件的最新版本。

飞鹰山庄汉化天地飞鹰   写于2002年4月26日

汉化新世纪 责任编辑: 乾 .:|:. 标签(Tag): 自校验

·上一篇: 修正 WinHex 汉化版中存在的ASCII字体/字号问题 ·下一篇: 汉化提高课─UPXPR 的脱壳方法

· 版权申明: 本文引自《汉化教学》,如有版权疑问请及时联系本站,以便本站处理。

· 转载申明: 本文引自《汉化教学》[ 作者: 飞鹰],如需转载请直接联系原始作者,并请注明原始出处。

相关文章                                                                                发表评论 打印此文 关闭窗口

| 设为首页 | 加入收藏 | 联系我们 | 友情链接
Creative Commons License,创作共用协议(中文版)  署名 非商业性使用 禁止演绎
本站内容,除转载或版权特别申明的内容外,皆遵守 创造共用协议中文版之“署名-非商业性使用-禁止演绎 2.5 中国大陆”条款
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 2.5 China License.
本网站内容源自汉化新世纪论坛的摘录和汉化新世纪成员的原创文章。
凡汉化新世纪论坛的文字皆默认为汉化新世纪与原作者共同拥有并授权发布。
如对本站发布文章有所异议请来信告知,我们将及时删除。
凡商业摘录本站文字请先与我们联系,本站将保留非授权商业发布的追究权利。
凡非商业摘录本站文字请明显注明出处和原作者,并不得改动,凡改动必先征求原作者同意。
苏ICP备05002283号