整理电脑硬盘,发现躺在某个角落里的汉籍全文检索系统,打开看了两眼,忽然想到,如今有了AI,能否借助于它来分析一下这个软件是怎么运行的。几年前下载到这个软件时,便想着能不能把里面的书籍都导出来。当时研究了一番,发现一种方式可以实现,就是使用其打印成pdf的功能,先导出为pdf再转为html格式。不过就是需要一篇篇去导,即使使用按键精灵,也是比较麻烦,况且导出转为html后,又有烦人的断行问题,只得做罢。而如今AI强大,加上自己稍懂些程序语言,或许能从软件的二进制上分析出所以然来。虽然从现在来看,里面大部分书籍都有了比较好的版本,不过如果能导出来,也算是增加了个离线资料库,说不定什么时候用到呢。
首先打开简体检索版软件运行,在任务管理器中下看到软件名为“ftrRead MFC Application(32位)”,这个软件八成应该是用C++写的MFC桌面程序了。查其LIB目录,找文件夹下容量大的文件,看其有.AMG和.FTR两种,使用二进制查看器打开,.ftr文件字节首是“TIR_IDX”,应该是是索引文件,暂时不管。
打开第一个.amg文件,文件编码选定gb,嘿,开头可以看到几个汉字明文!看情况,就是书籍的章节名称、路径和书名。之后就是乱码,可能是章节内容?往下拉,发现不断重复着章节名称、路径和书名。而在第三个章节名称下,竟然显示着明文字符串,没有夹杂一个乱码。看格式,像是rtf之类的东西,复制前面一小段问AI,确认就是rtf格式的字符串。把这段字符串完整地复制出来,粘贴到纯文本里,保存为.rtf格式,使用word顺利打开!然后想到,这个软件名“ftr”就是rtf倒过来念的。

继续浏览amg文件,发现有些是rtf格式的字符串,有些是乱码,尤其是在内容很长的时候,而每段乱码都跟在txt字符后面,都以“=”开头,头几个字节也都相同,可能就是标准的rtf字符串用什么方法转码了。

继续分析下去没有结果,转去查看主目录下的文件,有个Ftrquery.dll,从名字看,既然是查询rtf用的,那想必解析那乱码的东西就在里面。使用ida工具打开,ida我也是第一次用,摸索着在Export窗口看到导出的函数列表,找最可疑的几个:FTR_Parser…,一个个打断点,然后在主程序中打开书籍浏览,断点竟然都不触发!因为这几个函数实现太过迷惑,在我折腾了几天后才想到,难道解析的函数不在这个dll里?那就直接调试Guji2_2TMP.exe试试吧。
使用ida打开主程序,导出为汇编文本文件,直接扔给Grok让其分析,可惜文件太大了,Grok只能阅读前面一些内容,无法整体解读。关于汇编,我是一点儿都不懂,我只是从入口开始,不断地在可疑的片断处打断点调试,一旦触发,就把这个汇编片断复制下来让Grok解读。经过持续、反复地折腾,最终找到了乱码解码的几个核心函数。让Grok重点分析这几个函数,最终确认了本软件对于文本的处理是采用了LZW算法(https://zh.wikipedia.org/wiki/LZW), 根据Grok的回答,处理流程大致如下:
1. 读取变长码:从输入字节流中按当前码长(code length)读取 LZW 码,通常通过位操作实现。
2. 字典管理:维护一个动态字典(通常是数组或表),存储前缀码和字符的映射。汇编中通常使用固定大小的表(如你的 table_18h 和 table_1Ch)。
3. 码处理:如果码小于当前字典大小(next_code),从字典中提取对应的字节序列。
如果码等于 next_code(KwKwK 情况),构造新序列(前一个条目 + 其首字符)。
如果码大于 next_code,说明码无效,解码失败。
4. 特殊码处理:Clear Code(通常为 0x100)重置字典和码长。
End of Information (EOI, 通常为 0x101)表示数据结束。
5. 码长调整:当字典接近满时,增加码长以支持更多码值。
根据这些逻辑,让Grok写了python来实现对文本的解码算法。加上文件的存取过程,经过无数次debug,这个python代码在处理章节字数较少时能正常解码,可一旦章节数据过多,就会出现LZW码过大而解码失败的bug。问了Grok、Gemini和Cloud Sonet,都给不出一个完全的解决办法。问题可能出在码长更新或字典重置上,但是我对LZW算法理解不透,所以也不知怎么解决。目前在代码中,我把字典表容量设大值、最奇怪的是修改了一处码长增加的逻辑后,解码失败的几率大为降低,可以正常解码绝大部分文件了。


解码后的文件,可以直接用word打开浏览,如果有后续,可以考虑转成html格式:

不过,对于章节内容太多而无法解码的,有个办法可以手动复制,因为我在ida中找到了处理解码后的数据的汇编,只要在此处打断点,程序停下后,就可以跳转到解码后的字符串地方,把这个长字符串选中并保存后就是解码后的一个完整的rtf文件了!
更新:还好,最终只有12个文件无法解码成功,2个是因为文本太多,其他是遇到无效码。这几个手动查询后直接在复制后即可使用。目前所有文本都提取完毕并转为了html格式。代码的bug也没必要改了。