satan53x / SExtractor

从GalGame脚本提取和导入文本
GNU General Public License v3.0
225 stars 15 forks source link

Reallive引擎 #1

Closed yqw1231 closed 1 year ago

yqw1231 commented 1 year ago

QK6E Y9F%Z5%WU2$2VWAMAW 您好,我打算使用您的工具提取Reallive引擎的文本(Seen.txt),工作目录底下就一个txt文件,选项如图所示,但是生成的文件夹是空文件夹,可以请您指导一下吗?

satan53x commented 1 year ago

Seen.txt并不是脚本而是包,你还先需要解包,解包之后会有很多子txt。我是用arc_conv进行的解包和封包。 解包出来的txt在编辑器比如010Editor中能看到shift-jis编码的明文。 但如果看到开头有一部分乱码,说明还需要进行二次解密。 已经把二次解密的脚本seen_fix.py上传到Tools目录了。目录下也有调用arc_conv的bat,需要修改为你自己的路径。 但最大的问题是二次解密的码表并不是固定的,每个游戏不同,暂未找到生成代码,需要人工制作码表,原理如下: 1 子txt头部的20h处读取四个字节为小端整数,加上100h就是二次加密的起始地址(如图地址为27Eh+100h=37Eh),加密段长度为101h。 2 可以看到正常的文本显示不全,有截断,那么我们就可以从截断处反推码表。 找一个有文本被截断的txt,在游戏中找到对应的句子,把游戏里截断前边的明文按shift-jis编码,和txt中的密文进行异或,就能得到码表。 因为码表是16字节循环使用的,所以最好是找一个被截断超过8个日文字符的句子,使用其txt密文进行异或。 码表可以填入py脚本使用,注意因为加密段长度是101h,多一个字节,如果是从后往前获取的码表需要循环右移一字节。 同一个游戏码表相同。

yqw1231 commented 1 year ago

非常感谢,也就是说,现在没法做出Reallive引擎的通用提取文本的工具是吗?我目前想提取的是裸足少女的作品《プリンセスハートリンク~剣姫たちの艶舞~》的文本

satan53x commented 1 year ago

是的,每个游戏码表是不一样的,你可以通过以上原理自己制作码表。 不过你说的这个游戏已经有人找我做过码表了,在seen_fix.py脚本的头部可以选择对应预设。

yqw1231 commented 1 year ago

非常感谢,刚刚看到tools里新增Reallive文件夹

yqw1231 commented 1 year ago

您好,刚刚发现bat里需要arc_conv.exe,请问是没有上传吗,还是说在其他文件夹里有

satan53x commented 1 year ago

是通用解封包工具,需要自行下载,搜索引擎搜arc_conv很多地方都能下载exe。 也可以下载源码运行bat编译https://github.com/amayra/arc_conv

yqw1231 commented 1 year ago

好的,十分感谢

yqw1231 commented 1 year ago

尝试了一下将new文件夹作为工作目录,还是生成空文件夹,所以是需要自己写工具提取吗?

satan53x commented 1 year ago

你用arc_conv解包出来会有很多小txt,比如Seen1010.txt,把那个作为工作目录就行。引擎要选BIN。

yqw1231 commented 1 year ago

我目前是将所有的txt所在的new文件夹作为工作目录,如下图所示: L%T( H_DYCIKS $ZSFGB@HW Q_7VMJI8J_EIUD J`CFWN4N

但是生成的orig文件夹只有部分文件 TSZL5OY}@0JM7`NAXIX}_0X

而且有些文件的开头会出现乱码 DRG1PW82XOJ 6HBM VOSA$U

请问是什么原因呢?还是说需要一个工作目录只能放置一个txt吗?

satan53x commented 1 year ago

可以看打印,有些不生成json可能是txt本来就不包含文本。 开头乱码是不是你seen_fix.py预设类型没选对?

yqw1231 commented 1 year ago

不是,是后面很多文件直接停止了,那些文件我单独拿到一个文件夹,发现是可以生成的,类型应该是选对的,我选的是2

yqw1231 commented 1 year ago

B(A9DR(0JM~QU8R95}X`_61 这个是console的输出。

satan53x commented 1 year ago

那就奇怪了,这游戏之前别人也是这样提取的,没有问题啊。

yqw1231 commented 1 year ago

Seen.txt~.zip 这是我要提取的文件,如果可以的话,希望您能在我这上面测试一下。

satan53x commented 1 year ago

错误的原因好像是码表不正确,难道是因为之前那个是DL版,你这是安装版吗?

yqw1231 commented 1 year ago

噢,对的,主要是因为有个append disk不适用于DL版,所以用的安装版的。

satan53x commented 1 year ago

不过因为文本都是一样的,很方便的就找到了码表,你可以更新下seen_fix.py试试。

yqw1231 commented 1 year ago

好的,非常感谢您这样的热心肠,已经提取出全部文本了,最后有几个问题,一是我的配置问题,请问最合理的配置是这样子的吗? HB{J3EGYO7_I} }O841H2WO

二是我如果要打包的话,是先将翻译文本所在的目录作为工作目录,然后以一模一样的配置,点击提取/写入,然后将生成的txt文件使用封包工具封包,最后将游戏的Seen.txt替换,这样子的流程吗?

satan53x commented 1 year ago

一,最好打开截断字典新增复制。方便在导入时生成的cutoff.json中人工修正截断。 二,导入方式看工具内说明。 导入时工作目录不变,还是以日文txt为目录,译文json根据你单文档导出或多文档导出进行放置。 导入完成后需要对其进行加密再封包,同样使用seen_fix.py,因为异或运算的加解密函数是一样的。

yqw1231 commented 1 year ago

非常感谢,我已经明白您的意思了,最后辛苦您为我解答了这么多的问题。

yqw1231 commented 1 year ago

您好,又要麻烦您了。我现在为了作测试,将前十个seen.txt.json文件进行了翻译,并将翻译好的这十个文件放入trans中,然后按照相同的config,点击提取/写入按钮,发现在new文件夹中生成了十个txt文件。然后我将这十个txt文件,用seen_fix.py进行二次加密,然后覆盖解包出来的源文件。最后使用工具封包,得到新的Seen.txt。替换原有的Seen.txt后,打开游戏发现已经翻译的句子变成了乱码。请问我是有什么操作做错了吗?

satan53x commented 1 year ago

exe的字符集和编码范围判断全部修改完了吗?

yqw1231 commented 1 year ago

这个没有修改过。。。

satan53x commented 1 year ago

可按通用教程修改。 这个引擎编码范围判断比较多,可以观察字节流的规律进行批量替换。 我没修改过你这个游戏,我修改的同社其他游戏,可以用编辑器比如010Editor把A0 72全部替换为FE 72,其中只有一个不是编码范围,还原一下就行。 具体哪一个不是可以由ida反编译判断。没有尝试过不还原能否运行,也可以试试不还原。

yqw1231 commented 1 year ago

好的,我会尝试一下的,感谢

Cosetto commented 1 year ago

Actually, text_conv from arc_conv can deal with the script extracted: Dump command: text_conv.exe rlseen seen1001.txt > seen1001.out.txt Insert command: text_conv.exe rlseen seen1001.txt seen1001_new.txt < seen1001.out.txt Though there are still some missing texts. I don't why. Vntextpatch also support RealLive, but it doesn't work on newer games of Hadashi Shoujo.

satan53x commented 1 year ago

Though there are still some missing texts. I don't why.

2 Perhaps because some games by Hadashi Shoujo have secondary encryption at the beginning of each TXT file. This script is used for secondary decryption: seen_fix.py However, the XOR cipher key for each game is different, and the generation method has not yet been discovered. Therefore, manual creation of the cipher key is necessary for each game.

Cosetto commented 1 year ago

So, I only need to use seen_fix.py to fix the text right? What about test_xor.py?

satan53x commented 1 year ago

Just use seen_fix.py and select the folder where SeenXXXX.txt is located. ( You need to change the "GameType" in the script header to the corresponding game in "XorTable") test_xor.py is a testing script used for manually creating the cipher key. If you already have the cipher key for your game, there's no need to use it.

Cosetto commented 1 year ago

Thanks

Cosetto commented 1 year ago

@satan53x Btw, can you explain the method to find the secondary xor key?

satan53x commented 1 year ago

@Cosetto Here, you can translate this comment. https://github.com/satan53x/SExtractor/issues/1#issuecomment-1688678377

Cosetto commented 1 year ago

image Sorry, but I'm still confused. Like do I take the Japanese line which is still gibberish and encode it with shift-jis?

satan53x commented 1 year ago

@Cosetto 4 First, locate the normal text following the encrypted segment. There should be a truncated text preceding it. As shown in the figure, "「皿洗い、ぼくがしておくよ。葉桜もカバンを持っておいでよ」" is the plaintext, and "間だ。#" is the truncated text with encrypted ciphertext preceding it.

5 Next, run the Japanese game and find the plaintext of the truncated dialogue in the game: "ぼくたちも登校の時間だ。"

6 Encode this plaintext, then perform an XOR operation with the ciphertext. The result will be the encoding table. Since the length of the encrypted segment is 101h, while the cipher key's length is 10h, the last encrypted byte '1D' is not utilized for the XOR operation. ('1D' is clearly not within the range of the Shift-JIS encoding, so it's encrypted.)

As for choosing which txt to use as a breakthrough point, it's sufficient to find a truncated encrypted dialogue that's not less than 16 bytes in length. This is because the cipher key is used in a 16-byte cycle.

Cosetto commented 1 year ago

When you say, "perform an XOR operation with the ciphertext", does it mean I need to xor the "ぼくたちも登校の時間だ。" with "59 89 62 D3 3A 91... 57 09" with Binary Xor of 010editor?

satan53x commented 1 year ago

6

Yes, "59 89 62 D3 3A 91... 57 09" Xor with this. Many tools can do this, you can choose the one you prefer. Even my script: text_xor.py.

Cosetto commented 1 year ago

It works! Also is it possible to add force line breaker to your tool like this and this. You know, English text needs word-wrapping.

satan53x commented 1 year ago

Sorry, I don't quite understand this line break. It seems that there's no "\r\n" in Japanese text. Are you referring to handling the presence of "\r\n" in the translated text? After looking into VNT, it appears to be replaced with a sequence of bytes. Could you directly replace "\r\n" with the corresponding byte sequence "#\0\x03\xC9\0\0" in the translated text using a text editor? (Is it something like this?) Furthermore, my tool already handles "\r\n" specially, so if line breaks are needed, it's better to use only "\n". If there's a need, perhaps you can use only "seen_fix.py" and use another tool for extraction.

satan53x commented 1 year ago

@Cosetto In fact, this engine in my tool is a simple brute-force scan extraction using regular expressions without modifying function indices, and the text length requirement must not be increased. So, if you have additional requirements, it's still advisable to use other tools for extraction.

Cosetto commented 1 year ago

Alright, thanks anyway. Normally, other engines should use "\n" for line breaker, but Reallive seems using "#\0\x03\xC9\0\0" in this case.

Cosetto commented 1 year ago

@satan53x The rest of Hadashi xortable:

    # 3Ping Lovers! ☆ Ippu Nisai no Sekai e Youkoso♪
    4: bytearray.fromhex('66 8A 20 D4 6E C3 B4 B8 4B F8 38 93 AC AC 70 0A'),

    # Niizuma Shino
    5: bytearray.fromhex('8C 03 CC 55 9F 1D 41 38 A1 60 D4 12 5D 2D 85 D4'),

    # Niizuma Koyomi
    6: bytearray.fromhex('80 05 D7 40 89 15 5D 3C A7 62 D3 17 41 39 86 D0'),

    # Lovedori Halation
    7: bytearray.fromhex('74 3C 2F FC 6E CD B4 BF 4B D4 2A 25 A3 84 70 04'),

    # Mizugi Shoujo to Biyaku Ice ~Zannen na Kanojo no Shitsukekata, Oshiemasu~
    8: bytearray.fromhex('93 02 CB 40 89 23 52 38 B0 7E D2 1A 5A 29 AD D1')

But there's something wrong with Niizuma Koyomi's Seen7100.txt, the above of it seems fine, but the rest is truncated. image seen.bak.txt

satan53x commented 1 year ago

@Cosetto thx for ur xortable first. I checked the Seen7100.txt, and the text in the latter half of it appears to be for control purposes, perhaps for settings or something similar, and may not need to be extracted. In summary, the fix is correct, and the text is indeed in plaintext.

yqw1231 commented 10 months ago

可按通用教程修改。 这个引擎编码范围判断比较多,可以观察字节流的规律进行批量替换。 我没修改过你这个游戏,我修改的同社其他游戏,可以用编辑器比如010Editor把A0 72全部替换为FE 72,其中只有一个不是编码范围,还原一下就行。 具体哪一个不是可以由ida反编译判断。没有尝试过不还原能否运行,也可以试试不还原。

你好,时隔几个月我又来问问题了,还是关于之前的这个问题。我已经按照你说的修改了编码范围,没有修改exe字符集,发现文本还是会出现乱码,然后我看了一下别人的教程视频,发现是通过修改CreateFontA函数的入参charset来解决的,但是我尝试了一下发现不行,麻烦能指点一二吗

satan53x commented 10 months ago

你好,时隔几个月我又来问问题了,还是关于之前的这个问题。我已经按照你说的修改了编码范围,没有修改exe字符集,发现文本还是会出现乱码,然后我看了一下别人的教程视频,发现是通过修改CreateFontA函数的入参charset来解决的,但是我尝试了一下发现不行,麻烦能指点一二吗

两个都要改啊,charset字符集是让你显示中文,编码范围是让你扩大编码的范围,因为GBK比shift-jis范围大。 修改charset编码和编码范围一般不都是一个教程嘛。 比如:https://www.bilibili.com/read/cv12543346 不过它是用的dbg,用ida一样的原理。

CreateFont系的都有可能,CreateFontA/W或者CreateFontIndirectA/W。 Indirect顾名思义是间接调用,它charset一般不是push 80h,有些需要往上边找找mov ..., 80h。

yqw1231 commented 10 months ago

你好,时隔几个月我又来问问题了,还是关于之前的这个问题。我已经按照你说的修改了编码范围,没有修改exe字符集,发现文本还是会出现乱码,然后我看了一下别人的教程视频,发现是通过修改CreateFontA函数的入参charset来解决的,但是我尝试了一下发现不行,麻烦能指点一二吗

两个都要改啊,charset字符集是让你显示中文,编码范围是让你扩大编码的范围,因为GBK比shift-jis范围大。 修改charset编码和编码范围一般不都是一个教程嘛。 比如:https://www.bilibili.com/read/cv12543346。 不过它是用的dbg,用ida一样的原理。

CreateFont系的都有可能,CreateFontA/W或者CreateFontIndirectA/W。 Indirect顾名思义是间接调用,它charset一般不是push 80h,有些需要往上边找找mov ..., 80h。

可能是我表达的不够清楚,我明白要改两个地方,后面那个我用你教我的方法已经改好了,我的意思是在改前面那个的时候发现了问题。谢谢你的回复,我去研究一下。

yqw1231 commented 10 months ago

你好,时隔几个月我又来问问题了,还是关于之前的这个问题。我已经按照你说的修改了编码范围,没有修改exe字符集,发现文本还是会出现乱码,然后我看了一下别人的教程视频,发现是通过修改CreateFontA函数的入参charset来解决的,但是我尝试了一下发现不行,麻烦能指点一二吗

两个都要改啊,charset字符集是让你显示中文,编码范围是让你扩大编码的范围,因为GBK比shift-jis范围大。 修改charset编码和编码范围一般不都是一个教程嘛。 比如:https://www.bilibili.com/read/cv12543346。 不过它是用的dbg,用ida一样的原理。

CreateFont系的都有可能,CreateFontA/W或者CreateFontIndirectA/W。 Indirect顾名思义是间接调用,它charset一般不是push 80h,有些需要往上边找找mov ..., 80h。

我其实就是看的这个作者的视频改的,我看他改的charset。。。

satan53x commented 10 months ago

我其实就是看的这个作者的视频改的,我看他改的charset。。。

是改charset啊,你是没找到charset还是? 不过不是所有游戏都一定是80,有些是1或者0,具体是以参数顺序为准。 函数参数列表参考微软官网: https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createfonta

yqw1231 commented 10 months ago

我其实就是看的这个作者的视频改的,我看他改的charset。。。

是改charset啊,你是没找到charset还是? 不过不是所有游戏都一定是80,有些是1或者0,具体是以参数顺序为准。 函数参数列表参考微软官网: https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createfonta

是的,我看他这个charset是1,所以我把上面的push 0x01改成了push 0x86

satan53x commented 10 months ago

是的,我看他这个charset是1,所以我把上面的push 0x01改成了push 0x86

恩,有些游戏可能有多个createFont,有些并不是对话的文本用的,搜下是不是还有CreateFontIndirect? 还有就是有些游戏是不能转区或者是只能转区运行的,不然文字会有问题,都试试。