1996年的上古老作……有点麻烦

脚本garbro能解包,但是加密,进行了简单尝试,猜不出密钥。于是大概dbg逆向碰碰运气。

搜内存,在内存中找到了解密后的脚本。提取出来,与密文进行异或,发现整整齐齐……得到了15位的密钥,采用异或加密。

但是……尝试用密钥解密其他文件时,发现不行。观察发现,之前得到的密钥其实是文件的第4-19位;脚本中的0-4位为一个int,代表文件头中的偏移列表的长度i。前20 + 4 * i位为文件头,不加密;后面用文件的第4-19位异或即可得到解密后的脚本。

文件的第4-20位意义不明,怀疑是文件的签名,修改文件后很可能没法识别;加上我懒得仔细解析脚本了,于是我决定是用hook的方法动态替换文本。在之前找到的脚本中文本的位置下硬件断点,找到了读取脚本文本的地方。测试发现,更改指向文本的指针,即可更改显示的文本。

然而……这样有问题。文本后面还有一些控制代码,控制消除文本等操作,如果不恢复这些代码,输出的文本会全部叠在一起。暂时不知道怎么解决,于是继续分析脚本。

分析得到脚本中文本命令的结构:[\x01-\x02][\x00-\xff][\x00-\x01][\x04\x05\x0d][\x00-\x07]\xff,后面跟着文本。其中2-3位为命令的长度l,从第三位开始,往后面读取l位,即可得到文本。发现,这里面除了文本,文本后面还有一些二进制代码,如:文本文本\x00\x02\x03\x00。这正好与前面的控制代码相对应。经过测试,更改文本指针后在文本后面恢复这些内容,文本显示就正常了。

翻译后,导出一个trans.dat文件,其中每一行都是原文=译文(怎么处理sjis不支持的汉字参见前面几篇文章)。其中,译文后面还跟着前面所说的控制代码。游戏运行时,读取这个文件,生成一个map;再读取文本的位置,根据原本的文本在map中进行匹配,然后修改指针,指向map所对应的文本(后面跟着控制代码),这样就做到了文本的正常显示。