·汉化新世纪 ·汉化新世纪论坛 ·百家争鸣 ·论坛集萃 ·汉化问答 ·软件介绍
文章首页 >> 汉化教学 >> 特殊汉化 >> 基地址引深    Creative Commons License,创作共用协议(中文版)  署名 非商业性使用 禁止演绎

基地址引深

作者: 梁利峰 来源:点睛工作室 时间:2003-08-02 点击:9360


基地址引深


声明

个人可以自由转载本文,不过应保持原文的完整性,并通知我;商业转载先请和我联系。

本文没有任何明确或不明确地提示说本文完全正确,阅读和使用本文的内容是您自己的选择,本人不负任何责任。

如果您发现本文有错漏的地方,请您给我指出;如果有什么不理解的,请您给我提出。

意见、建议和提出的问题最好写在我的主页 http://llf.126.com 的留言版上。

前言

关于明白所写的增加 C 程序字符串长度的文章想必大家都看了。不过伟写信给我,说 winimp 使用明白所说的方法不行,而只能用 W32dasm ,不过我觉得,这并不是说明白所说的方法不行,其实明白说的方法和使用 W32dasm 的原理是一样的,在这里主要问题应该在于基地址的选取。

关于基地址,我已经说过就是 Image of base ,本身并没有很多可说的,所以在这里我要说的是另外的概念,为了说明方便,我又捏造了一个名词叫做“基偏移”,而“基偏移”中比较重要的是“代码基偏移”“数据基偏移”

Delphi 程序

明白的文章中说过,Delphi 程序的基地址是 400C00h ,那么事实上又如何呢?我们用 FoxMail 3.0 beta 2 中附带的 Notifier.exe 来做例子。(Foxmail.exe 太大了:)

使用 W32dasm 打开 Notifier.exe ,保存,然后打开 Notifier.alf ,开头的部分是这样的:

Disassembly of File: Notifier.exe
Code Offset = 00000400, Code Size = 0000FE00
Data Offset = 00010200, Data Size = 00000400

Number of Objects = 0008 (dec), Imagebase = 00400000h

   Object01: CODE     RVA: 00001000 Offset: 00000400 Size: 0000FE00 Flags: 60000020
   Object02: DATA     RVA: 00011000 Offset: 00010200 Size: 00000400 Flags: C0000040
   Object03: BSS      RVA: 00012000 Offset: 00010600 Size: 00000000 Flags: C0000000
   Object04: .idata   RVA: 00013000 Offset: 00010600 Size: 00001000 Flags: C0000040
   Object05: .tls     RVA: 00014000 Offset: 00011600 Size: 00000000 Flags: C0000000
   Object06: .rdata   RVA: 00015000 Offset: 00011600 Size: 00000200 Flags: 50000040
   Object07: .reloc   RVA: 00016000 Offset: 00011800 Size: 00001400 Flags: 50000040
   Object08: .rsrc    RVA: 00018000 Offset: 00012C00 Size: 00002A00 Flags: 50000040

这里,我们见到的蓝色的部分就是基地址,它的值并不是 400C00h ,而是 400000h !

现在,需要用到我所说的“代码基偏移”和“数据基偏移”了。

我们见到上面第二行是“Code Offset”,也就是代码偏移,它的值是 400h ,和它相同的段偏移是“Object01”,它们都用红色标示出来了。这说明“Object01”就是代码段。

另外我们见到上面第三行是“Data Offset”,也就是数据偏移,它的值是 10200h ,和它相同的段偏移是“Object02”,它们都用绿色标示出来了。这说明“Object02”就是数据段。

在这里的的描述中,我们需要了解的是,其中的“RVA”是虚拟地址偏移,表示此在内存中相对于基地址的偏移;而“Offset”表示的是实际偏移,表示此的起始位置在可执行文件中的偏移。

明白的文章中所说的方法就是要修改代码,而其中的偏移量指的是在内存中的偏移量,所以需要进行可执行文件中偏移量和内存中偏移量之间的换算。

首先是“代码基偏移”。代码基偏移 = 基地址 + 代码RVA - 代码Offset 。在这个例子中,是这样的,代码基偏移 = 400000h + 1000h - 400h = 400C00h 。

然后是“数据基偏移”。数据基偏移 = 基地址 + 数据RVA - 数据Offset 。在这个例子中,是这样的,数据基偏移 = 400000h + 11000h - 10200h = 400E00h 。

现在让我们看一些此文件中的代码:

* Possible StringData Ref from Code Obj ->"SOFTWARE\Borland\Delphi\RTL"
                                  |
:004028B4 6834294000              push 00402934

在这里,我用红色标出的是 W32dasm 提示我们说,这个字符串在代码段里。所以我们用代码基偏移计算一下,402934h - 400C00h = 1D34h ,用 UEdit 打开 Notifier.exe ,跳到 1D34h 处,可以看到,就是字符串“SOFTWARE\Borland\Delphi\RTL”的开始位置。

再看另一段代码:

* Possible StringData Ref from Data Obj ->"Runtime error     at 00000000"
                                  |
:004030F2 BA1C104100              mov edx, 0041101C

红色部分标出,这个字符串在数据段中,所以我们用数据基偏移计算一下,0041101Ch - 400E00h = 1021Ch ,跳到 1021Ch 处,发现此处正是字符串“Runtime error at 00000000”的开始位置。

我们也可以反过来计算,从数据在可执行文件中的位置得知它在代码中应该是什么样子,明白的“代码转换器”就是完成这个功能的,它所欠缺的是对于段的分析,不过因为有自定义功能,我们是可以自行添入“代码基偏移”“数据基偏移”进行分析的。

段的分析

如果字符串只在代码段和数据段里好像还好,最多进行两次运算就可以得到我们所需的地址,但是并不是所有的字符串都在代码段或数据段里的,也可能在一些非常奇怪的段内,何况,两次运算也同样太多了!

我们还以 Notifier.exe 为例,还是那一段 W32dasm 的开头:

Disassembly of File: Notifier.exe
Code Offset = 00000400, Code Size = 0000FE00
Data Offset = 00010200, Data Size = 00000400

Number of Objects = 0008 (dec), Imagebase = 00400000h

   Object01: CODE     RVA: 00001000 Offset: 00000400 Size: 0000FE00 Flags: 60000020
   Object02: DATA     RVA: 00011000 Offset: 00010200 Size: 00000400 Flags: C0000040
   Object03: BSS      RVA: 00012000 Offset: 00010600 Size: 00000000 Flags: C0000000
   Object04: .idata   RVA: 00013000 Offset: 00010600 Size: 00001000 Flags: C0000040
   Object05: .tls     RVA: 00014000 Offset: 00011600 Size: 00000000 Flags: C0000000
   Object06: .rdata   RVA: 00015000 Offset: 00011600 Size: 00000200 Flags: 50000040
   Object07: .reloc   RVA: 00016000 Offset: 00011800 Size: 00001400 Flags: 50000040
   Object08: .rsrc    RVA: 00018000 Offset: 00012C00 Size: 00002A00 Flags: 50000040

上面用蓝色标示出来的是每个段在可执行文件中的偏移,所以我们其实可以通过这些数值来确定究竟字符串处于那个段中。

比如有一个字符串“Error resolving remote host”在可执行文件的 ACCCh 处,这个值处于 400h 和 10200h 之间,所以属于“Object01”的代码段,所以计算方式如下:ACCCh + 400000h + 1000h - 400h = 40B8CCh ,反过来是“CC B8 40 00”,在此文件中查找“CC B8 40 00”,找到一个,修改这个地方就可以改变字符串的起始位置,当然,这个字符串是随便找的,我不知道它会在什么地方出现,不能演示,不过我们可以看一看 W32dasm 中关于这个字符串的部分,查找表明,此字符串只出现了这一次:

* Possible StringData Ref from Code Obj ->"Error resolving remote host"
                                  |
:0040B7D3 B9CCB84000              mov ecx, 0040B8CC

其中我用绿色标示出了这一偏移量的字节代码,和我们在可执行文件中找到的一样。

当然,如果你是在 Notifier.alf 中找到的这个代码,也同样可以在可执行文件中查找“CC B8 40 00”以便找到它的字节代码所在的位置,但是也可以计算得到,上面蓝色的部分是此字节代码的虚拟偏移量,用它减去代码基偏移就是在可执行文件中的偏移了:40B7D3h - 400C00 = ABD3h ,跳到 ABD3h 处,可以看到,就是字节代码“B9 CC B8 40 00”所在的位置,使用这种方法,可以一次完成准确的定位,不过需要计算,稍微麻烦一点。

另外,我们见到,1023Ch 处的字符串是“Error”,此偏移量位于 10200h 和 10600h 之间,所以处于“Object02”的数据段,计算如下:1023Ch + 400000h + 11000h - 10200h = 41103Ch ,反过来是“3C 10 41 00”,查找“3C 10 41 00”,也只找到一个,修改这里就可以修改此字符串的偏移地址了,其中 W32dasm 中关于此字符串的反汇编代码也只有一句:

* Possible StringData Ref from Data Obj ->"Error"
                                  |
:0040310A 683C104100              push 0041103C

当然也不是必须使用 W32dasm ,关于基地址和段偏移还有段虚偏移也同样可以使用诸如 eXeScope 或 ProcDump 之类的工具得到,而且这种方法显然也并不只限于 Delphi 程序,一般来说,所有的程序都可以使用这种方法修改,不过类似 VB 之类的程序可能并不以字符串起始作为字符串偏移,而有可能把地址计算为从其前面的字符串大小计数器开始,因为我并没有试过,所以仍然是值得一试的。

WinImp 1.11

WinImp 1.11 中的问题是工具栏的文字说明,以第二个工具按钮 Open 为例,这个 Open 在可执行文件中的偏移为 49EB0h 。让我们看一下 W32dasm 产生文件的开头吧:

Disassembly of File: winimp32.exe
Code Offset = 00000400, Code Size = 0003BE00
Data Offset = 0003DE00, Data Size = 00012000

Number of Objects = 0006 (dec), Imagebase = 00400000h

   Object01: AUTO     RVA: 00001000 Offset: 00000400 Size: 0003BE00 Flags: 60000020
   Object02: .idata   RVA: 0003D000 Offset: 0003C200 Size: 00001C00 Flags: C0000040
   Object03: DGROUP   RVA: 0003F000 Offset: 0003DE00 Size: 00012000 Flags: C0000040
   Object04: .bss     RVA: 00051000 Offset: 00000000 Size: 00005E00 Flags: C0000080
   Object05: .reloc   RVA: 00057000 Offset: 0004FE00 Size: 00004000 Flags: 42000040
   Object06: .rsrc    RVA: 0005B000 Offset: 00053E00 Size: 0001D600 Flags: 40000040

这个文件比较奇怪,“Object04”的“.bss”段的 Offset 是 00000000h ,不过计算表明,“Object03”的“DGROUP”的开始位置为 3DE00h ,而结束位置是 Offset + Size = 3DE00h + 12000h = 4FE00h ,所以我们知道,“Object03”应该和“Object05”是相连的。

(其实在这里 AUTO 段就是代码段,而 DGROUP 段就是数据段。这不是 VC 的程序,用 FileInfo 2.3 可以知道是用“Watcom32 C/C++”编写的。)

好的,这表明此字符串在 DGROUP 段内,计算如下:49EB0h + 400000h + 3F000h - 3DE00h = 44B0B0h ,反过来就是“B0 B0 44 00”,所以查找“B0 B0 44 00”,找到两个,修改第二个就可以了。那么第一个是什么呢?

* Possible StringData Ref from Data Obj ->"Open"
                                  |
:00413B9B 68B0B04400              push 0044B0B0
:00413BA0 68C0000000              push 000000C0
:00413BA5 6A00                    push 00000000
:00413BA7 56                      push esi

* Reference To: USER32.AppendMenuA, Ord:0001h
                                  |
:00413BA8 2EFF15F0D64300          Call dword ptr cs:[0043D6F0]

我们见到的蓝色部分是第一个找到的“B0 B0 44 00”,红色的部分说明这是一个添加菜单的函数,那么找到的第一个“B0 B0 44 00”也应该修改了,这个菜单在哪里呢? —— 在 WinImp 的主界面上点鼠标右键看看。 :)

点睛工作室·梁利锋 结稿于 2000.7.24

汉化新世纪 责任编辑: 乾 .:|:. 标签(Tag): 基地址 Delphi

·上一篇: 汉化中的几个问题 ·下一篇: Delphi 字体修改一例

· 版权申明: 本文引自《点睛工作室》,如有版权疑问请及时联系本站,以便本站处理。

· 转载申明: 本文引自《点睛工作室》[ 作者: 梁利峰],如需转载请直接联系原始作者,并请注明原始出处。

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

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