发新话题
打印

《幻想水浒传12宫》破解纪实

本主题由 demon19870115 于 2009-2-9 18:08 提升

《幻想水浒传12宫》破解纪实

《幻想水浒传12宫》破解纪实



前言

  从2007年9月入组到2009年初,有一年多的时间了。
  我经历了从使用现成的汉化工具到自己写工具;从纯粹的在hex编辑器观察数据破解到现在的NDS ASM这么一段历程。也算是“资深破解”啦 =^_^=
  非常感谢一位好友,flyeyes。是他让我对汉化有了深入的了解,也使我的技术有了质的飞跃,使我能够亲手汉化我喜欢的游戏(名师出高徒嘛,呵呵)。同时也感谢everyphoto 帮我修改帖子^^
  我从前辈那汲取了不少“营养”,也该给后辈们留下些“财富”。春节放假比较空闲,就写了《幻想水浒传12宫》破解纪实。(由于文本量很大,ACG没有做的打算。)
  文章将分字库查找篇文本查找篇文本解密篇(ASM篇)三个方面来详细解说该游戏的破解过程。
  我写的比较详细(可能会有些罗嗦——),就算是初次接触汉化的朋友,慢慢看也应该能懂。当然C or C++的一些基础知识,以及ARM指令还是得掌握的。不然看到后面,就和看天书一样啦。
---------------------------------------------------------------------分割线----------------------------------------------------------------------
字库查找篇
  用NDSTOOL拆ROM后,打开在data目录(data目录是放游戏资源文件的地方,要汉化的文件绝大部分都在这里),真不错,直接就看见了font文件夹


  (对于一般游戏,可在data目录下搜索 “*font*”,“*.NFTR”,“*fnt*”,“*LD*”,“*kan*”等关键字)
    进到font目录,看见两个字库


  (NFTR是Nintendo Font Resource的缩写。一种Nintendo制定的字库文件,格式已被完全破解。)
    根据经验大的那个应该就是剧情字库。具体验证过程很简单,只要把字库里面的假名擦掉,再打包回游戏运行,看看游戏对话里还能不能显示假名即可。若不能,则说明找对字库了。经验证,的确是剧情字库。
    我们用CT2的NFTR编辑器查看下gd_sysfont_jp.nftr的参数


  10×9 单色1BPP。不过汉字对10×10以下的字支持不太好,最好做个10×10的。


  我们再看到字库的0x1F处,在下图中用红框围住的地方,


  那里是00,表示文本为UTF-8编码(0x00,UTF-8;0x01,Unicode;0x02,Shift-JIS)。
  到现在,字库算是研究清楚啦(另外一个字库gd_debugfont_jp.nftr从名字来看,是开发游戏时调试用的,我们无需理会),下面该研究文本了。

---------------------------------------------------------------------分割线----------------------------------------------------------------------
文本查找篇

  很显然,文本文件应该在 rom目录里面。进到rom目录下,

  看见一个叫text的目录,很有文本的“嫌疑”,进去看看再说。(对于文本文件,一般可在data目录里面搜索“*mes*”,“*scr*”,“*tex*”,“*txt*”,“*script*”等关键字查找,而系统文本如:道具、魔法、武器、人名等若不在data目录,则很有可能在ARM9.bin和overlay里面)

  text目录下有4个文件

  我们用CT2随便打开一个文件,编码选择UTF-8。
  晕……全是乱码,一点文本的影子都没有……

  选择Unicode编码,也是乱码……再看看其它的*.txrc文件也都是乱码。麻烦了……看txrc的文件头不像是压缩文件,因为没看见哪里记录解压大小,估计是文本被加密了;当然也有可能txrc文件根本就不是文本。总之,我们要另辟蹊径寻找文本了。

  用模拟器打开游戏(我用的是NO$GBA,模拟效果不错)运行到开始出现文本的地方(就是能看见那些10×9的字的地方)

  随便挑一段连续的日文(在此之前,我已经确认这是文本。因为把字库擦掉之后,字就显示不出来了),我选“文字”两个汉字,因为我不会打假名——|||。新建一个txt文件,再里面输入“文件”两个字,再将txt另存为UTF-8格式。用CT2打开该txt文件,编码选择UTF-8,可以看见,“文字”的编码为E69687E5AD97(txt文件的开头3字节EFBBBF不用管,那个是UTF-8文本的文件头)。

  我们在ROM里面搜索E69687E5AD97,结果无匹配数据……
  再次晕……再搜索“文字”的Unicode编码,也没有……再再次晕……
  也许文本在ARM9和overlay然后它们正好压缩了……?用CT2查看NDS文件信息



  但都没压缩。没辙了,游戏里面的文本是被动了手脚,只好老老实实跟踪吧T__T

---------------------------------------------------------------------分割线----------------------------------------------------------------------
文本解密篇(ASM篇)

  说到ASM,很多朋友肯定都会觉得很神秘,其实就跟调试C++程序差不多,别被吓到了,呵呵。
  我用的是NO$GBA 2.6A共享版,就是大家常说的NO$GBA debug版,


  估计很多朋友都没有,不过没关系用ideas也是一样的。诚然NO$GBA比起ideas来是强大很多,但是过分强调工具的好坏是不明智的。就像写C++程序,最重要的不是编译器的好坏,而是程序员的素质^^( ideas的debug可以参见 http://www.ndsbbs.com/read.php?tid=180038&keyword= )
  运行到上述的“文字”画面,将内存dump出来(注意NDS的内存是从0x2000000开始的。另外建议不要只dump 4M,因为当你看见画面时,数据可能已经不在内存了)。
  在dump出的内存中搜索E69687E5AD97,哦耶^^ 找到了


  地址为0x10E6D5换算成内存地址为0x210E6D5(加0x2000000,再次强调:NDS的内存从0x2000000开始)。
  在0x210E6D5处设置写入断点[0x210E6D5]! 重新运行游戏。
  在这里中断

  即向r14指向的内存写入数据之后中断。用F7单步走一圈,发现是在一个循环里面,游戏用r3在[r1]处读取数据,然后写入到[r14]。去[r1]处看看

  原来文本在这里就已经解密了。改设断点[211509C]!,追踪解压文本的来源。这次中断在这

  看来是r0的写入导致的,那么现在的目标就是追踪这个r0的来源。
  继续F7,晕……有好多的代码……只好先F8(Run to Sub-return 运行到子函数返回处)了……
  再几次F8之后,一段代码闪现在眼前……

  啊!看见eor(就是C&C++中的异或)了!!!一般解密代码里都会有eor的影子,看来狐狸终于露出尾巴啦,哇咔咔!
  好,开始F7……啊哈,和我想得一样,在几次F7之后就又看见了strb r0,[r9,r8],看来异或得到的r0就是解密后的文本数据。那么现在的目标还是追踪这个r0的来源。
  注意到在eor之前,有几个ldrb指令ldrb r2,[r1,4h]等,那就去看看[r1]处是啥。

  哦……原来是已经解密过的数据。注意前8个字节5458524381B4C77F不就是文件gd_textres_jpn.txrc的文件头么

  看来这里就是在对它解密。OK,文本已找到,差得就是具体的解密算法。

实际上现在已经可以锁定解密的过程就是
0205157C E5D13004 ldrb    r3,[r1,4h]
02051580 E5D62007 ldrb    r2,[r6,7h]
02051584 E7D61005 ldrb    r1,[r6,r5]
02051588 E0203092 mla     r0,r2,r0,r3
0205158C E20000FF and     r0,r0,0FFh
02051590 E0200001 eor     r0,r0,r1
02051594 E20000FF and     r0,r0,0FFh

  这几句,现在的任务就是弄明白各个寄存器中数据的来源。其实在前面不用F8,而是跟进子函数,就能弄明白各个寄存器中数据的来源,但读一大堆代码比较烦人,所以我采取另外的办法。
  改设断点[234CC08]!(因为前8字节是文件头,并未加密,我们关心的是8字节之后的加密数据)。中断在

  这里实际上是在搬运缓冲区的数据到[r5],可以理解为载入文件到[r5]的过程。按下F9(继续运行)。中断在

  在这里可以看出,r1是文本首地址指针,r5是当前解密数据的相对偏移。

  再利用F8运行到eor处,

  显然,r3中存放的就是文件7h处的字节,r1存放待解密字节。又搞清楚了2个寄存器^^
  那么就还差r0,r4两个了。再再利用F8运行到eor处


    大家发现啥了么?呵呵,条件有点少,估计很难有突破性的发现。那我们再多看几个。大家注意r0,r4的变化,以及它们与r5之间的关系。

r5=0xB  r0=0x3  r4=0x2

r5=0xC  r0=0x4  r4=0x0

r5=0xD  r0=0x4  r4=0x1

r5=0xE  r0=0x4  r4=0x2

r5=0xF  r0=0x5  r4=0x0

  大家看出点啥名堂了么?r5每次都+1;而r0则是r5每+3之后才+1;r4则是在0~2之间取值。还没想到啥么?那我也没辙了……公布答案吧
  r0 = r5/3;    //r0是r5除以3的商
  r4 = r5%3;  //r4是r5除以3的余数
  那几个被跳过的子函数就是用来得到r0和r4的,有兴趣的朋友可以去看看。
  好了,到现在我们已经把解密算法也搞定啦。

   估计大家可能有点晕,看到这里可以先停住,理顺下思路。

  这里给出一个C的代码,将ARM指令“直译”成C语言。因为是“直译”,所以有些多余的代码。(随手写的,表见笑。在VS2008下编译通过)。
复制内容到剪贴板
代码:

/*
TXRC解密程序
      Joyce
  2009.1.24
*/
#include<stdio.h>
//使用命令行程序是为了方便批处理调用
int main(int argc,char *argv[1])
{
      if(argc != 3)
      {
            printf("参数个数错误。");

            return -1;
      }

      FILE *ifp = fopen(argv[1],"rb"),//待解密文件
           *ofp = fopen(argv[2],"wb");//解密后的文件

      unsigned int r0 = 0,//key
                   r1 = 0,//密文
                   r2 = 0,//seed1
                   r3 = 0,//seed2
                   r4 = 0,
                   r5 = 0;//待解密字节的偏移

      for(r4 = 0;r4 < 8;r4++)
            putc(getc(ifp),ofp);//向解密后的文件写入文件头

      fseek(ifp,7,0);
      r2 = getc(ifp);//r2的值就是文件的第八个字节,在解密过程中它恒定不变

      for(r5 = 8; ;r5++)
      {
//--------------产生用于解密的key----------------------            
            r0 = r5/3;
            r4 = r5%3;

            fseek(ifp,r4+4,0);//从这里可以看出,文件的h-7h这四字节实际上是用来解密的
            r3 = getc(ifp);

            fseek(ifp,r5,0);
            if((r1=getc(ifp)) == EOF) //unsigned int 用EOF居然也没问题?!
                  break;

            r0 = r2*r0 + r3;
            r0 &= 0xFF;

//-------------用密文与key异或解密---------------------
            r0 ^= r1;
            r0 &= 0xFF;

            putc(r0,ofp);

      }

      _fcloseall();

      return 0;
}
用编译好的exe解密,唔,看见文本咯。说明我们之前的猜想是正确的^^
       不过想要做这个游戏还是有些难度的……因为文本格式比较特别,文本是连在一起的,想要导出必须要弄明白指针表以及游戏读取它的方式。
  因为组里不开坑,这个问题我不打算深入了,有兴趣做这个游戏的朋友可以深入研究。


  写到这里,本教程就结束了。初次写教程没啥经验,要是哪里我没说明白,可以在下面跟贴提问。

---------------------------------------------------------------------分割线----------------------------------------------------------------------
后记

  写教程好辛苦啊!我自己破解这个游戏就不到1小时,写这个教程居然用了5个多小时……

  前面已经说了一些关于字库和文本查找方面的个人经验,最后再谈谈ASM方面的吧。不过我也是ASM初学者,说的不好的地方还请大家指正。

1.把握整体,以函数为单位思考

  上百条的指令和一个个的子函数跟进会让你看的心力交瘁——。第一次跟踪可以采取运行到子函数返回处,大致分析下函数的作用,再有针对性的跟进某个函数做仔细的分析。还有一些常见的固有模块也要掌握,比如CpuFastSet,DMA等。特别是DMA3,太常见了,要是不了解的话在跟踪时遇到了会相当费解的。这些都可以在GBATEK上查到。GBATEK应该是目前最权威的非官方GBA&NDS参考资料啦。在本帖的附件中有下载,有txt版本,也有我转好的pdf。
  这是官网 http://nocash.emubase.de/gbatek.htm

2.与抓关键指令

  例如对于解密,eor就是关键指令,因为eor是解密过程,当看见eor之后,我就可以追溯key的来源,从而破解解密算法。
  ldr str也很重要。不论是解压还是解密,都有读写数据的过程吧,那么我们可以通过追溯ldr(读取待解密/解压数据)之后的过程,或者str之前的一些指令(写入解密/写入解压后的数据)来捕获解密/解压算法。
  当然前提是要对NDS的解密/解压基本算法有所了解,不然你跟踪到了那个过程也未必能知道它的作用。NDS游戏加密我见过4个,《放学后少年》、《口袋妖怪白金》、《幻想水浒传12宫》、《梦幻之星0》,它们无一例外的都使用了对称异或加密算法。说白了就是 密文^key=明文。当然这个产生key的算法是多种多样的。
  压缩的倒是见过很多,这里举几个非老任标准LZ压缩(即BIOS 11h函数无法解压的)的游戏: 《灵光守护者》、《弧光之源2》、《心灵传说》、《卡片英雄》、《FFCC EOT》、《梦幻之星0》等,当然还有很多PSP的,就不列举了。除了0x24,0x28开头的任氏Huffman和0x30开头的任氏RLE压缩之外(都出现在《卡片英雄》),其余都是基于LZSS算法。可以这么说:理解了LZSS算法,再加上一些跟踪技术,那就能搞定绝大部分NDS游戏的压缩文件了。

3.善于分析和思考

  跟踪时,不要一味想着把每条指令都弄懂,当然都明白是最好不过的,但那样也费时费力。很多时候,我们没必要去深究细节,完全可以通过分析已知信息,大胆假设,就像《幻想水浒传12宫》的文本解密破解那样。当然,假设完了别忘记小心求证。
  要说的就这么多啦,希望本文对大家的汉化之旅能有所帮助=^_^=
                                                                                                                                                                      2009.2.8

GBATEK version 2.5-PDF.zip (530.04 KB)
GBATEK version 2.5-txt.zip (266.88 KB)

[ 本帖最后由 joyce_jq 于 2009-2-9 17:31 编辑 ]
本帖最近评分记录

TOP

感谢分享

[ 本帖最后由 everyphoto 于 2009-2-8 23:36 编辑 ]
本帖最近评分记录
  • joyce_jq 浮云 +1 送云 2009-2-9 18:13
测~测~测~测成大头鬼

TOP

淫公提升
本帖最近评分记录
  • joyce_jq 浮云 +1 生日快乐~~ 2009-2-9 18:13
喜欢海贼王的人都是好人~~

TOP

感谢LS二位

TOP

催汉化自重哦~~~
测~测~测~测成大头鬼

TOP

好强大啊!你们真厉害!
为什么你会来这里,为什么你会在这里,你现在自己去寻找答案。当你了解一切之后,我会回来。

TOP

第一页留个名好了...

TOP

LS还不换签名啊…………

TOP

懒得换,反正也不差...话说你现在天天泡论坛啊...

TOP

还版聊灭了你们
喜欢海贼王的人都是好人~~

TOP

由于文本量很大,ACG没有做的打算
这个春节最悲剧的消息,本来还指望等坑填完的ACG会做的
哎。。。对着攻略玩日版去了

TOP

引用:
原帖由 sAviOr1986 于 2009-2-9 19:05 发表
由于文本量很大,ACG没有做的打算
这个春节最悲剧的消息,本来还指望等坑填完的ACG会做的
哎。。。对着攻略玩日版去了
没办法。。。。某人坑太多了
测~测~测~测成大头鬼

TOP

前排留名
匣浅难羁宝剑锋 玉藏石中也玲珑 初试清啼长天破 云光凝碧远岚平

TOP

引用:
原帖由 sAviOr1986 于 2009-2-9 19:05 发表
由于文本量很大,ACG没有做的打算
这个春节最悲剧的消息,本来还指望等坑填完的ACG会做的
哎。。。对着攻略玩日版去了
唉……
就知道玩游戏,我看着真是伤心啊……
本帖最近评分记录
  • zy8784 浮云 +1 能不能把破解的文本发出来 网络汉化吧 2009-2-10 02:10

TOP

前来支持美女

TOP

发新话题
最近访问的版块