基于windows平台的游戏汉化,软件汉化已经比较成熟,网上的教程攻略,帖子也非常多。但是基于iOS平台的软件汉化网上却鲜有资源。我这里想说的是两个比较另类的软件汉化方法。由于项目有些久远,记忆有些偏差,可能有部分内容记录的会有问题。
多数跨平台的游戏,可执行文件资源可能都是基于同一套代码编译。那么对于跨平台游戏的汉化可以采用借尸还魂的方法。当然该方法可能并不通用,智能能够借尸还魂还要看具体的游戏。例如恶霸鲁尼,这款游戏其实是跨平台的游戏,在我要汉化这款游戏的时候Windows平台的游戏已经有3dm的汉化版本。为了提高汉化速度和减少工作量,就可以采用使用3dm已经汉化的资源替换iOS版本的资源的方式进行汉化。
汉化后效果(iPad截图):
由于当时的记录记得比较简略, 只有如下几行,如果想要分析具体的改动内容可以下载汉化版ipa(链接: https://pan.baidu.com/s/142dUnjCkL-OV4POi1-9FxQ 密码: dk59)参考目录下的压缩文件进行对比:
不管是游戏汉化还是游戏破解,汉化后的资源都比较难以进行保护。如果要进行相关的资源保护,不让劳动成果被轻易的窃取,那么可以通过注入dylib动态解密资源信息。例如两年前比较流行的旅行青蛙,还有个姊妹产品叫做猫咪后院。这个游戏如果要汉化可以采用和旅行青蛙一样的方式,直接修改资源。
那么除了直接修改资源文件,那么有没有更简单的方法完成汉化呢?通过分析游戏的渲染可以发现,最终游戏的问题都是通过HpLib_Graphics makeTextImage:]函数来实现的贴图。那么,如果直接hook该函数,将要渲染的文本做成一个字典进行动态匹配,那么也就解决了汉化的问题。并且同时可以保证自己的dylib在被别人去除掉之后游戏的汉化将会失效。从某种程度上也就保证了自己的dylib的存活概率,当然这个不能保证dylib一定会被存活,如果分析了dylib的具体原理,那么完全可以自己写一个dylib替换现有的dylib。那么就需要进行进一步的保护,对翻译的字典文件进行加密,进一步提高被替换的成本。
渲染函数的原型如下:
Hook代码:
下一步就是加密翻译文本字典,通过BABYStringEncoding来实现,这个库是Google的一份开源代码,代码修改了类名和方法名。
解密通过如下代码实现:
除了上面的渲染函数,另外可能还有其他的需要处理的方法,并不是所有的文本都是通过这个渲染函数来实现的,还有一部分是通过其他的方法实现的。具体可以参考项目里面的代码。
汉化效果:
字典文件加密解密方法:
加密key aCDEfGHijKlMnopQRsUvWXz012345689
加密:
GTM_Encoder -encodeFile 加密key 要加密的输入文件 输出加密文件
GTM_Encoder -encodeFile aCDEfGHijKlMnopQRsUvWXz012345689 /Users/obaby/Desktop/小项目/汉化保护/cn_strings_jp.plist /Users/obaby/Desktop/小项目/汉化保护/cn_strings_jp.enc
揭秘:
GTM_Encoder -decodeFile 加密key 要解密的输入文件 输出解密文件
GTM_Encoder -decodeFile aCDEfGHijKlMnopQRsUvWXz012345689 /Users/obaby/Desktop/小项目/汉化保护/cn_strings_jp.enc /Users/obaby/Desktop/小项目/汉化保护/cn_strings_jp.plist.dec
github:https://github.com/obaby/ipa_chinesizing_via_hook
id
__cdecl
-
[HpLib_Graphics makeTextImage:](HpLib_Graphics
*
self
, SEL a2,
id
a3)
id
__cdecl
-
[HpLib_Graphics makeTextImage:](HpLib_Graphics
*
self
, SEL a2,
id
a3)
@class
HpLib_Graphics;
CHDeclareClass(HpLib_Graphics);
CHOptimizedMethod(
1
,
self
,
id
, HpLib_Graphics, makeTextImage,NSString
*
, arg1)
{
NSLog(@
"BABY_HOOK: makeTextImage original:%@"
,arg1);
NSString
*
ch_string
=
@
"喵喵喵"
;
if
([ch_dic objectForKey:arg1]) {
ch_string
=
[ch_dic objectForKey:arg1];
if
([ch_string length]
=
=
0
) {
ch_string
=
@
"喵喵喵"
;
}
NSLog(@
"BABY_HOOK: makeTextImage chinese:%@"
,ch_strin
return
CHSuper(
1
, HpLib_Graphics,makeTextImage, ch_string);
}
else
{
return
CHSuper(
1
, HpLib_Graphics,makeTextImage, arg1);
}
}
/
/
猫咪后院
CHLoadLateClass(HpLib_GSystem);
CHHook(
1
, HpLib_GSystem, strNSString);
CHLoadLateClass(NSPlaceholderString);
CHHook(
3
, NSPlaceholderString ,initWithBytes,length,encoding);
CHHook(
2
, NSPlaceholderString ,initWithCString,encoding);
CHHook(
1
, NSPlaceholderString ,initWithUTF8String);
CHLoadLateClass(HpLib_Graphics);
CHHook(
1
, HpLib_Graphics, makeTextImage);
@class
HpLib_Graphics;
CHDeclareClass(HpLib_Graphics);
CHOptimizedMethod(
1
,
self
,
id
, HpLib_Graphics, makeTextImage,NSString
*
, arg1)
{
NSLog(@
"BABY_HOOK: makeTextImage original:%@"
,arg1);
NSString
*
ch_string
=
@
"喵喵喵"
;
if
([ch_dic objectForKey:arg1]) {
ch_string
=
[ch_dic objectForKey:arg1];
if
([ch_string length]
=
=
0
) {
ch_string
=
@
"喵喵喵"
;
}
NSLog(@
"BABY_HOOK: makeTextImage chinese:%@"
,ch_strin
return
CHSuper(
1
, HpLib_Graphics,makeTextImage, ch_string);
}
else
{
return
CHSuper(
1
, HpLib_Graphics,makeTextImage, arg1);
}
}
/
/
猫咪后院
CHLoadLateClass(HpLib_GSystem);
CHHook(
1
, HpLib_GSystem, strNSString);
CHLoadLateClass(NSPlaceholderString);
CHHook(
3
, NSPlaceholderString ,initWithBytes,length,encoding);
CHHook(
2
, NSPlaceholderString ,initWithCString,encoding);
CHHook(
1
, NSPlaceholderString ,initWithUTF8String);
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2020-9-17 17:21
被obaby编辑
,原因: 修复图片