设为首页收藏本站官方微博

汉化教程 【转】基于OPENGL引擎3D游戏逆向分析及汉化修改实例(下)

[复制链接]
查看: 2084|回复: 0
打印 上一主题 下一主题

[汉化教程] 【转】基于OPENGL引擎3D游戏逆向分析及汉化修改实例(下)

跳转到指定楼层
楼主
发表于 2011-1-30 14:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

【转】基于OPENGL引擎3D游戏逆向分析及汉化修改实例(下)

本帖最后由 shane007 于 2011-1-30 14:08 编辑
6 \+ U+ r8 [, h0 @
1 R6 V7 Q0 }  x5 r在上文中,我们已经成功的使游戏创建了我们需要的汉字纹理,不过仅仅有这1024个汉字纹理是不行的,还得想办法让它显示出来。前面说过,游戏会调用glCallLists显示显示列表,glCallLists原型如下:1 l5 {* Y% m) r! E* F( m

" t, C9 J6 F0 l5 C# w代码:
: T( Y2 U: S' h9 G& ]0 j1 ^void WINAPI glCallLists() `+ t/ ^% B& |6 J: K$ w
    GLsizei n,7 r' Q/ W6 R. o3 G7 k6 H2 M- u7 D
    GLenum type,8 `: o4 b! ^0 u3 s- V0 p
    const GLvoid *lists
4 [3 G7 T5 l7 D. v);
8 }# ?: c( j2 A* M+ @' I( z  其中n为字符串长度,type为字符串类型,*lists为字符串指针,glCallLists函数下断调试发现,游戏在调用glCallLists时第二个参数使用了0x1400,即GL_BYTE,表示单字节:
2 e' l- H$ f4 _7 h1 w
7 M: Q! e. v' o$ J: u代码:9 g6 n. A  p- @6 g* g
00439D3D  |.  BB 00140000   mov     ebx, 1400                        ;  第二个参数,GL_BYTE
  u( m* @- K5 Q! d7 x8 l00439D42  |.  890424        mov     dword ptr [esp], eax
6 W& L% s5 P: B5 C. k  Z  N( a9 a6 d7 C00439D45  |.  E8 464B0500   call    <jmp.&OPENGL32.glListBase>. W. ^7 f) e4 }
00439D4A  |.  83EC 04       sub     esp, 48 g) _  f3 J7 t  ]4 K$ o, E2 a
00439D4D  |.  893424        mov     dword ptr [esp], esi             ; |& i( {! O: ]2 |9 U  p0 K
00439D50  |.  E8 136D0800   call    <jmp.&msvcrt.strlen>             ; \strlen2 ~, \% o4 c; u, V$ B6 k' _
00439D55  |.  890424        mov     dword ptr [esp], eax             ; 将strlen结果作为第一个参数
  U9 g# Z& t9 w00439D58  |.  897424 08     mov     dword ptr [esp+8], esi
6 Z1 @, V/ S7 |+ I" G+ X! [00439D5C  |.  895C24 04     mov     dword ptr [esp+4], ebx
( X7 i$ b( L# [/ K) B7 N5 ^00439D60  |.  E8 234B0500   call    <jmp.&OPENGL32.glCallLists>: y9 Q' _$ w6 n4 k5 t; k
  因为游戏原有256个显示列表,字符串为单字节字符串,而现在我们要使用1024个显示列表,相应的字符串必须使用双字节编码,这里第二个参数必须修改,截取gl.h部分如下:* P1 M( _% `, y6 p( O

3 d; u# [- X/ `0 t# S1 m代码:
7 z# b' y- @7 p! b#define GL_BYTE                           0x1400
5 n# q) P0 o. c& N" ]) q4 m#define GL_UNSIGNED_BYTE                  0x1401
! {( F5 I  t; g#define GL_SHORT                          0x1402& l# [# j( C6 q& B$ U& i2 Y$ _
#define GL_UNSIGNED_SHORT                 0x1403! g+ a2 T& g1 J& Y$ `" C" o
#define GL_INT                            0x14047 t5 n% `$ Q- R: L. O! ?: y9 ]
#define GL_UNSIGNED_INT                   0x1405
' Q1 ?" K$ z, s4 p$ C+ O( S7 x4 J& B#define GL_FLOAT                          0x1406
3 c0 O( ~7 v; w5 s! U#define GL_2_BYTES                        0x1407
2 ?; B3 O. F6 C. g- Q#define GL_3_BYTES                        0x1408: ^: q2 d) n* l. |& ]
#define GL_4_BYTES                        0x1409! g* ?6 l$ u0 J* Y" v2 A0 b- }
#define GL_DOUBLE                         0x140A
1 J- J3 Q9 w$ K7 o* T/ }' y) z% H; U( w! J  无符号双字节为GL_UNSIGNED_SHORT,所以应将0x00439D3D处指令改为mov     ebx, 1403。接下来修改第一个参数,第一个参数改起来比较麻烦。原游戏使用ascii码所以可以调用strlen,而我们使用双字节字符串,那么必须使用wcslen来求字符串长度,而导入表里没有wcslen,这时候我们必须自己加入一个导入函数。这里为了省事我使用了pe工具stud_pe,wcslen位于动态链接库msvcvrt.dll中,增添该函数后如图:
  ]# ~$ S) x# y( R1 l$ @+ C# L* P- T4 J! h! W, M- z
  图中可以看出,导入函数wcslen的RVA为0xB05214B,理论上只要我将call <jmp.&msvcrt.strlen>改为call [0xB05214B],便可以达到目的。但是事情总是比之前想象的复杂一点。这里如果直接改为call dword ptr [0xB05214B],目的地址与指令地址偏移量大,call为远call,指令长度为6字节,而原来的call是近call,指令长度为5字节,这将覆盖掉下面的mov dword ptr [esp], eax指令。后果将是glCallLists永远得不到正确的字符串长度。
& H1 Q+ J9 }0 E* l. D  不过这很容易解决,我们只需要在代码的缝隙中找到一块6字节的空白区,然后加入指令jmp [0xB05214B],再call到这条新加入的指令,就可以顺利解决了。我将这条指令放在了0x439c36,然后修改0x439d50处的指令为call 0x439c36,问题解决。如图:, T7 M/ B+ ?3 ^1 R& j5 E% h0 o

4 z1 i* T2 ?1 H+ l  p  至此,对游戏引擎的修改已经结束。& G  @* o9 ~5 Z
  剩下的工作比较简单了,将游戏的英文文本找出并逐一翻译。统计翻译后的中文文本,也就是统计使用了那些汉字。然后制作一张32格*32格的字库,其中前128个位置放置游戏原有字符并与游戏原来字符顺序保持一致,以便能够正常显示一些特殊字符,后896个位置依次放入统计出的汉字。按照字符在字库上的位置制作一张码表,然后按照码表将翻译后的文本进行编码转换,再将转换后的结果导入游戏。9 p4 ?, g- b; i( P7 P# W
  事实上,我有意无意地淡化了在分析调试过程中遇到的种种麻烦,因为事后想想也不过如此。逆向是非常痛苦的,因为下一步总是不可预料的。任何一个小小的麻烦都有可能导致前功尽弃。然而逆向的魅力也正在于此,当咬牙踏出那一步之后,回头看看自己的脚印,我想这都是值得的。
8 K" [4 w) U; M  最后附上一张中文版截图:
0 o5 E" y) b* @0 ~( r: P3 K

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

冒险解谜游戏中文网 ChinaAVG

官方微博官方微信号小黑屋 微信玩家群  

(C) ChinaAVG 2004 - 2019 All Right Reserved. Powered by Discuz! X3.2
辽ICP备11008827号 | 桂公网安备 45010702000051号

冒险,与你同在。 冒险解谜游戏中文网ChinaAVG诞生于2004年9月9日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

快速回复 返回顶部 返回列表