首页
社区
课程
招聘
[好文转贴][原创]破解技术在汉化过程中的应用之AsfTool篇
发表于: 2004-11-8 21:06 5876

[好文转贴][原创]破解技术在汉化过程中的应用之AsfTool篇

2004-11-8 21:06
5876
转贴自 FCG论坛 http://www.fcgchina.com/ctb

作者:you_known

[原创]破解技术在汉化过程中的应用之AsfTool篇

很久没写文章了,写出来却又不知道贴到哪个区~苦恼......
===========================================

声明:
1.本文可能夹杂大量技术术语,适用于有一定Delphi编程经验、了解破解及汉化过程的用户阅读。如果您对此感到不快,请勿继续阅读。
3.本文仅仅从技术角度讨论汉化问题的一些思路,不会提供文中涉及的内容下载,请自行查找。勿将之用于侵犯版权等非法目的,或损害他人利益。如果您对此感到失望,请勿继续阅读。
4.本文系本人(you_known@163.com)原创,版权归作者所有,转载前请先征得作者同意并保持文章的完整性。

    AsfTools 3.1是一款修复、转换Asf流媒体的小工具,本身是免费软件。或许正因为是免费软件,作者不希望自己的辛苦工作被人篡改,程序中写入了自效验代码,防止程序被修改。而对于汉化来说,不得不对程序本身进行修改,所以第一步就是去除程序的自效验:
    首先,我们必须确认源程序是何种语言编写,以便利用工具针对性的分析。祭出FileInfo(PEid等也可)查看原程序,显示为UPX加壳,很容易的脱掉壳,现出原形为Delphi编写程序。双击运行脱壳后的程序,发现程序界面闪现一下就退出了,确定其含有自效验代码。
    下面再看它是如何进行自效验的。既然是Delphi程序,自然拿出Delphi的反汇编利器DeDe将脱壳后的程序反汇编,DeDe将他顺利的搞定,于是它就什么秘密都没有了~回忆一下,它是先显示About对话框,然后需要用户确认后进入主界面,在主界面闪现后退出,根据经验,自效验代码部分应写在主界面窗体中。既然主界面会显示,该代码自然不在FormCreate事件中,猜测会在FormShow事件中,找到TMainForm的FormShow代码:

代码:
004AF0B4   55                     push    ebp
004AF0B5   8BEC                   mov     ebp, esp
004AF0B7   33C9                   xor     ecx, ecx
004AF0B9   51                     push    ecx
004AF0BA   51                     push    ecx
004AF0BB   51                     push    ecx
004AF0BC   51                     push    ecx
004AF0BD   51                     push    ecx
004AF0BE   51                     push    ecx
004AF0BF   51                     push    ecx
004AF0C0   51                     push    ecx
004AF0C1   53                     push    ebx
004AF0C2   8945FC                 mov     [ebp-$04], eax
004AF0C5   33C0                   xor     eax, eax
004AF0C7   55                     push    ebp

* Possible String Reference to: '橐R?腚[?]?
|
004AF0C8   68F5F14A00             push    $004AF1F5

***** TRY
|
004AF0CD   64FF30                 push    dword ptr fs:[eax]
004AF0D0   648920                 mov     fs:[eax], esp
004AF0D3   55                     push    ebp

* Reference to: main.Proc_004AEE08
|
004AF0D4   E82FFDFFFF             call    004AEE08
004AF0D9   59                     pop     ecx
004AF0DA   8D55F8                 lea     edx, [ebp-$08]
004AF0DD   33C0                   xor     eax, eax

* Reference to: System.ParamStr(Integer):String;
|
004AF0DF   E8D839F5FF             call    00402ABC
004AF0E4   8B45F8                 mov     eax, [ebp-$08]

* Reference to: main.Proc_004ABFE0
|
004AF0E7   E8F4CEFFFF             call    004ABFE0
<!-- CETagParser ~color=red~ --><font color="red"><!-- /CETagParser -->004AF0EC   8BD8                   mov     ebx, eax
004AF0EE   B880841E00             mov     eax, $001E8480
004AF0F3   2BC3                   sub     eax, ebx
004AF0F5   3D80641900             cmp     eax, $00196480
004AF0FA   740D                   jz     004AF109

* Reference to MainForm
|
004AF0FC   8B45FC                 mov     eax, [ebp-$04]

* Reference to: Forms.TCustomForm.Close(TCustomForm);
|
<!-- CETagParser ~color=red~ --><font color="red"><!-- /CETagParser -->004AF0FF   E8C4E8FAFF             call    0045D9C8
004AF104   E9D1000000             jmp     004AF1DA

    看这里的004AF0FF   E8C4E8FAFF call    0045D9C8;Forms.TCustomForm.Close(TCustomForm),这个是Delphi关闭窗体的函数,刚刚才Show出来怎么就Close掉,有问题,往上看到有一个减法运算,比较某个数字与$001E8480的差是否等于$00196480,若相等则跳走,否则关闭窗体。先将$001E8480-$00196480得到$52000转为十进制335872,这个数很眼熟啊,点原程序的属性一看,哇勒~就是原始文件的大小嘛,嘿嘿,这个就是效验程序是否被脱壳了,要是脱了自然大小就不一样了。改掉它不管什么大小都继续:

代码:
004AF0FA   EB0D                   jmp     004AF109

    好高兴得运行一下,奇怪了,半天没动静,只听到硬盘哗啦啦的转,MD,还有暗桩~再来继续往下看:

代码:
004AF109   8D55EC                 lea     edx, [ebp-$14]

* Possible String Reference to: '路径'
|
004AF10C   B80CF24A00             mov     eax, $004AF20C

* Reference to: Unit_00408010.Proc_0040DC78
|
004AF111   E862EBF5FF             call    0040DC78
004AF116   FF75EC                 push    dword ptr [ebp-$14]
004AF119   681CF24A00             push    $004AF21C
004AF11E   8D55E8                 lea     edx, [ebp-$18]

* Possible String Reference to: 'windir'
|
004AF121   B828F24A00             mov     eax, $004AF228

* Reference to: Unit_00408010.Proc_0040DC78
|
004AF126   E84DEBF5FF             call    0040DC78
004AF12B   FF75E8                 push    dword ptr [ebp-$18]
004AF12E   681CF24A00             push    $004AF21C
004AF133   8D55E4                 lea     edx, [ebp-$1C]

* Possible String Reference to: 'windir'
|
004AF136   B828F24A00             mov     eax, $004AF228

* Reference to: Unit_00408010.Proc_0040DC78
|
004AF13B   E838EBF5FF             call    0040DC78
004AF140   FF75E4                 push    dword ptr [ebp-$1C]

* Possible String Reference to: 'system'
|
004AF143   6838F24A00             push    $004AF238
004AF148   681CF24A00             push    $004AF21C
004AF14D   8D55E0                 lea     edx, [ebp-$20]

* Possible String Reference to: 'windir'
|
004AF150   B828F24A00             mov     eax, $004AF228

* Reference to: Unit_00408010.Proc_0040DC78
|
004AF155   E81EEBF5FF             call    0040DC78
004AF15A   FF75E0                 push    dword ptr [ebp-$20]

* Possible String Reference to: 'system32'
|
004AF15D   6848F24A00             push    $004AF248
004AF162   8D45F0                 lea     eax, [ebp-$10]
004AF165   BA09000000             mov     edx, $00000009

* Reference to: System.Proc_00404E20
|
004AF16A   E8B15CF5FF             call    00404E20
004AF16F   8B55F0                 mov     edx, [ebp-$10]
004AF172   8D4DF4                 lea     ecx, [ebp-$0C]

* Possible String Reference to: 'wmvcore.dll'
|
004AF175   B85CF24A00             mov     eax, $004AF25C

* Reference to: Unit_00408010.Proc_00409708
|
004AF17A   E889A5F5FF             call    00409708
004AF17F   837DF400               cmp     dword ptr [ebp-$0C], +$00
004AF183   753A                   jnz     004AF1BF

* Possible String Reference to: '警告:在您的系统中发现有视频组件丢失
|                                !请安装"Microsoft Media Encoder 7.1
|                                ".它可以免费从www.microsoft.com获得
|                                .您可以继续使用但某些功能会被禁用.'
|
004AF185   B870F24A00             mov     eax, $004AF270

* Reference to: Dialogs.ShowMessage(AnsiString);
|
004AF18A   E8CDA4F8FF             call    0043965C

* Reference to MainForm
|
004AF18F   8B45FC                 mov     eax, [ebp-$04]

* Reference to control TMainForm.SpeedButton10 : TSpeedButton
|
004AF192   8B80B8030000           mov     eax, [eax+$03B8]
004AF198   33D2                   xor     edx, edx
004AF19A   8B08                   mov     ecx, [eax]

* Reference to method TSpeedButton.SetEnabled(Boolean)
|
004AF19C   FF5164                 call    dword ptr [ecx+$64]

* Reference to MainForm
|
004AF19F   8B45FC                 mov     eax, [ebp-$04]

* Reference to control TMainForm.SpeedButton11 : TSpeedButton
|
004AF1A2   8B80BC030000           mov     eax, [eax+$03BC]
004AF1A8   33D2                   xor     edx, edx
004AF1AA   8B08                   mov     ecx, [eax]

* Reference to method TSpeedButton.SetEnabled(Boolean)
|
004AF1AC   FF5164                 call    dword ptr [ecx+$64]

* Reference to MainForm
|
004AF1AF   8B45FC                 mov     eax, [ebp-$04]

* Reference to control TMainForm.SpeedButton13 : TSpeedButton
|
004AF1B2   8B80C4030000           mov     eax, [eax+$03C4]
004AF1B8   33D2                   xor     edx, edx
004AF1BA   8B08                   mov     ecx, [eax]

* Reference to method TSpeedButton.SetEnabled(Boolean)
|
004AF1BC   FF5164                 call    dword ptr [ecx+$64]
<!-- CETagParser ~color=red~ --><font color="red"><!-- /CETagParser -->004AF1BF   B887D61200             mov     eax, $0012D687
004AF1C4   2BC3                   sub     eax, ebx
004AF1C6   3D87B60D00             cmp     eax, $000DB687
004AF1CB   740D                   jz     004AF1DA

* Reference to: Unit_00488EF4.Proc_00489408
|
004AF1CD   E836A2FDFF             call    00489408

* Reference to MainForm
|
004AF1D2   8B45FC                 mov     eax, [ebp-$04]

* Reference to: Forms.TCustomForm.Close(TCustomForm);
|
<!-- CETagParser ~color=red~ --><font color="red"><!-- /CETagParser -->004AF1D5   E8EEE7FAFF             call    0045D9C8

    原来这里004AF1D5   E8EEE7FAFF call    0045D9C8还有一处效验,和上面的一样嘛,就是两个常数变了$0012D687-$000DB687还是等于$52000,还是看文件大小,照样改掉:

代码:
004AF1CB   EB0D                   jmp     004AF1DA

    再来运行,这回没问题了……

代码:
004AF1DA   33C0                   xor     eax, eax
004AF1DC   5A                     pop     edx
004AF1DD   59                     pop     ecx
004AF1DE   59                     pop     ecx
004AF1DF   648910                 mov     fs:[eax], edx

****** FINALLY
|

* Possible String Reference to: '[?]?
|
004AF1E2   68FCF14A00             push    $004AF1FC
004AF1E7   8D45E0                 lea     eax, [ebp-$20]
004AF1EA   BA07000000             mov     edx, $00000007

* Reference to: System.@LStrArrayClr(void;void;Integer);
|
004AF1EF   E8D858F5FF             call    00404ACC
004AF1F4   C3                     ret

* Reference to: System.@HandleFinally;
|
004AF1F5   E95252F5FF             jmp     0040444C
004AF1FA   EBEB                   jmp     004AF1E7

****** END
|
004AF1FC   5B                     pop     ebx
004AF1FD   8BE5                   mov     esp, ebp
004AF1FF   5D                     pop     ebp
004AF200   C3                     ret

    再来看看如何将加密的字符串汉化过来。经过初步汉化,程序界面的大部分内容都已经是中文显示,但是关于对话框仍旧是英文界面,先从这里下手,控件的字符串都是在其显示之前被赋予的,可能会放在FormCreate、FormShow、FormActivate等事件代码中,通常来讲会是FormCreate,这个是该窗体所有代码中最先被执行的,查找TAboutForm的FormCreate汇编代码:

引用:
procedure TAboutForm.FormCreate(Sender : TObject);
begin
(*
00489A0C   55                     push    ebp
00489A0D   8BEC                   mov     ebp, esp
00489A0F   B904000000             mov     ecx, $00000004
00489A14   6A00                   push    $00
00489A16   6A00                   push    $00
00489A18   49                     dec     ecx
00489A19   75F9                   jnz     00489A14
00489A1B   51                     push    ecx
00489A1C   53                     push    ebx
00489A1D   8BD8                   mov     ebx, eax
00489A1F   33C0                   xor     eax, eax
00489A21   55                     push    ebp

* Possible String Reference to: '橹??脎?]?
|
00489A22   68F19A4800             push    $00489AF1

***** TRY
|
00489A27   64FF30                 push    dword ptr fs:[eax]
00489A2A   648920                 mov     fs:[eax], esp
00489A2D   8D55F4                 lea     edx, [ebp-$0C]

* Possible String Reference to: 'pluvL}rK"gn~rI'
|
00489A30   B8089B4800             mov     eax, $00489B08

* Reference to: Unit_00488EF4.Proc_004890F4
|
00489A35   E8BAF6FFFF             call    004890F4
00489A3A   8B45F4                 mov     eax, [ebp-$0C]
00489A3D   8D55F8                 lea     edx, [ebp-$08]

* Reference to: Unit_00488EF4.Proc_004890F4
|
00489A40   E8AFF6FFFF             call    004890F4
00489A45   8B45F8                 mov     eax, [ebp-$08]
00489A48   8D55FC                 lea     edx, [ebp-$04]

* Reference to: Unit_00488EF4.Proc_004890F4
|
00489A4B   E8A4F6FFFF             call    004890F4
00489A50   8B55FC                 mov     edx, [ebp-$04]
00489A53   8BC3                   mov     eax, ebx

* Reference to: Controls.TControl.SetText(TControl;TCaption);
|
00489A55   E8166AFBFF             call    00440470
00489A5A   8D55EC                 lea     edx, [ebp-$14]

* Possible String Reference to: 'Ez'
|
00489A5D   B8209B4800             mov     eax, $00489B20

* Reference to: Unit_00488EF4.Proc_004890F4
|
00489A62   E88DF6FFFF             call    004890F4
00489A67   8B45EC                 mov     eax, [ebp-$14]
00489A6A   8D55F0                 lea     edx, [ebp-$10]

* Reference to: Unit_00488EF4.Proc_004890F4
|
00489A6D   E882F6FFFF             call    004890F4
00489A72   8B55F0                 mov     edx, [ebp-$10]

* Reference to control TAboutForm.Button1 : TButton
|
00489A75   8B8310030000           mov     eax, [ebx+$0310]

* Reference to: Controls.TControl.SetText(TControl;TCaption);
|
00489A7B   E8F069FBFF             call    00440470
....
...以下代码与前述类似,从略。

    注意看00489A55   E8166AFBFF call    00440470 ;Controls.TControl.SetText(TControl;TCaption)这行,这个call是Delphi的标准函数调用,功能是设置控件显示的文字,按照Delphi的传值方式,EAX用于存放控件句柄,EDX用于存放赋值的字符串。用OllyDgb单步跟到00489A50   8B55FC mov     edx, [ebp-$04]这行,发现寄存器EDX的值为"About AsfTools",很明显这里就是给标题设置显示内容的地方。我们往上看00489A30   B8089B4800 mov     eax, $00489B08这行引用字符串pluvL}rK"gn~rI,然后经过3个相同call    004890F4得到明文串About AsfTools,跟入该call发现都是对字符串的一系列运算(因为我们不是破解,这里不祥述其内容了),由此可以断定call 004890F4即对密文解密的过程。现在有两种方法可以汉化该内容,一种是容易直接想到的,即分析解密算法找出它可逆的加密算法,然后编写一个加密字符串的程序,将汉化的字符串,如"关于 AsfTools"加密成密文并写回原程序;由于我们仅仅是为了汉化它,让他显示中文内容,我们可以用第二种方法,即修改程序代码,把不相干的解密部分全部Nop掉,令这里调用SetText之前的EDX为汉化字符串,强行让它显示我们需要的内容,当然这种方法对程序改动较大,比较暴力~

    这里提供一种修改方案,利用OllyDbg或UltraEdit修改代码,将$00489B08处的密文替换为汉化后的字符串“关于 AsfTools”,改代码为mov edx,$00489B08将所有解密的代码nop掉,直接调用SetText,后面依次类推。这里有一点要注意的是“确定”按钮的文字长度超过了原来的“OK”长度,需要重新找个地址存放,我这里用了中间的一段空白地址$00489A42,你也可以使用其他地址或其他修改方法。修改后的代码如下:

引用:
00489A0C   55                     push    ebp
00489A0D   8BEC                   mov     ebp, esp
00489A0F   B904000000             mov     ecx, $00000004
00489A14   6A00                   push    $00
00489A16   6A00                   push    $00
00489A18   49                     dec     ecx
00489A19   75F9                   jnz     00489A14
00489A1B   51                     push    ecx
00489A1C   53                     push    ebx
00489A1D   8BD8                   mov     ebx, eax
00489A1F   33C0                   xor     eax, eax
00489A21   55                     push    ebp

* Possible String Reference to: '橹??脎?]?
|
00489A22   68F19A4800             push    $00489AF1

***** TRY
|
00489A27   64FF30                 push    dword ptr fs:[eax]
00489A2A   648920                 mov     fs:[eax], esp

* Possible String Reference to: '关于 AsfTools '
|
00489A2D   BA089B4800             mov     edx, $00489B08
00489A32   EB1F                   jmp     00489A53
00489A34   90                     nop
00489A35   90                     nop
00489A36   90                     nop
00489A37   90                     nop
00489A38   0000                   add     [eax], al
00489A3A   FFFF                   DB  $FF, $FF  //      
00489A3C   FFFF                   DB  $FF, $FF  //      
00489A3E   05000000C8             add     eax, -$38000000
00489A43   B7B6                   mov     bh, $B6
00489A45   A800                   test    al, $00
00489A47   0000                   add     [eax], al
00489A49   00FF                   add     bh, bh
00489A4B   FFFF                   DB  $FF, $FF  //      
00489A4D   FF00                   inc     dword ptr [eax]
00489A4F   0000                   add     [eax], al
00489A51   90                     nop
00489A52   90                     nop
00489A53   8BC3                   mov     eax, ebx

* Reference to: Controls.TControl.SetText(TControl;TCaption);
|
00489A55   E8166AFBFF             call    00440470

* Possible String Reference to: '确定'
|
00489A5A   BA429A4800             mov     edx, $00489A42
00489A5F   90                     nop
00489A60   90                     nop
00489A61   90                     nop
00489A62   90                     nop
00489A63   90                     nop
00489A64   90                     nop
00489A65   90                     nop
00489A66   90                     nop
00489A67   90                     nop
00489A68   90                     nop
00489A69   90                     nop
00489A6A   90                     nop
00489A6B   90                     nop
00489A6C   90                     nop
00489A6D   90                     nop
00489A6E   90                     nop
00489A6F   90                     nop
00489A70   90                     nop
00489A71   90                     nop
00489A72   90                     nop
00489A73   90                     nop
00489A74   90                     nop

* Reference to control Button1 : TButton
|
00489A75   8B8310030000           mov     eax, [ebx+$0310]

* Reference to: Controls.TControl.SetText(TControl;TCaption);
|
00489A7B   E8F069FBFF             call    00440470
....
...以下代码与前述类似,从略。

    程序中还有几处类似的地方无法正常汉化,需要修改加密字符串,如SampleFrame中的内容,但是这部分内容与前面又有所不同,我们可以在资源中直接找到并汉化,只是运行时被重新SetText了而不能被显示,我们可以残忍的将这部分SetText代码统统Nop掉,该死的英文就不再显示了。注意一点,这边有个CheckBox的文本是动态显示的,不要把这个也Nop了,这个例外需要像上面About中的内容一样修改。
    加密字符串搞定之后,发现还有未汉化的地方,查看资源Form发现剩下的都是以图片形式保存的,OK,将这些图片提取出来用任意图片编辑工具修改(我用Windows自带的画笔)成中文,然后将图片导回资源,运行一下,全部都变成熟悉可爱的中文了。搞定收工~!

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 1
支持
分享
最新回复 (2)
雪    币: 97697
活跃值: (200834)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
2
支持!!!
2004-11-8 22:58
0
雪    币: 16
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
3
其实阿,有时候汉化跟破解没有分别~~~~
2004-11-9 15:00
0
游客
登录 | 注册 方可回帖
返回
//