原帖我在BATHOME发的,感觉微不足道,为了凑个积分在这边发一次。
去年就开始拆了,发现译文信息里一部分翻译是明文,一部分又是给出了另一个字典的索引
要自己挖,还分层的挖,烦了就停了。今年想起来又接着搞,挖成明文后对数据格式化,改
成Perl的hash/array复合结构。分成了五六个脚本吧,拆解部分不一一张贴,主要说方法。
准备
●
安装 有道字典增强版 (下载的V6.2),安装目录下会有 localdicts 文件夹,包含字典文
件以及索引文件。
C:\USERS\%USERNAME%\APPDATA\LOCAL\YOUDAO\DICT\APPLICATION\LOCALDICTS
2016/06/06 09:20 <DIR> ..
2016/06/06 09:20 28,460,334 21EC.ydic
2016/06/06 09:20 8,094,269 basicCE.ydic
2016/06/06 09:20 16,692,913 basicEC.ydic
2016/06/06 09:20 3,737,882 CE.idx
2016/06/06 09:20 250 CE.ifo
2016/06/06 09:20 7,991,892 EC.idx
2016/06/06 09:20 334 EC.ifo
2016/06/06 09:20 9,900,103 newCE.ydic
2016/06/06 09:20 5,475,078 phrase.ydic
2016/06/06 09:20 42,980,352 sentenceDict.sql
.ifo 文件是摘要信息(比如某个字典有多少单词量)
.idx 文件分两部分,第一部分是索引数据,第二部分是单词内容
.ydic 文件是翻译信息
分析
● 先针对英汉字典(EC.idx basicCE.ydic)
比较业余,用了几种方法,就.idx文件来说,已经知道是索引,将其转成16进制按N组一行的方式
排列(用的Perl提取划分,虽然我知道有些工具更好用),发现其中的规律是,每12个字节为一组
数据,在一组里面,每4个字节合为一个数值(低位在前,这是后来发现的)。以及按4列16进制值显示后
发现到了某个位置规律就不一样了。
1057288 16 6a 39 00
1057289 83 b6 fe 00
1057290 17 00 00 00
1057291 1b 6a 39 00
1057292 9a b6 fe 00
1057293 17 00 00 00 //以下为第二部分,没有明显规律
1057294 37 73 71 65
1057295 63 75 37 73
1057296 75 60 64 37
1057297 74 7f 72 75
1057298 37 74 62 79
然后对ydic分析字节频率,以下是频率较高的字节,左边是出现的次数
00337934 ac 00352074 6d00352432 6b 00378084 22 00477148 f5 00563980 2a 00567693 75 00692001 21 00997268 33 02211802 32
然而并没有什么卵用,6d 和 6b 33 和 32 是什么? m k 3 2 ?写了一个脚本: 输入16进制值,试转UTF、GBK
input:6d 6b 33 32
mk32 gbk 109
mk32 big5 109
mk32 utf8 109
歭社 utf16-le 27501
not utf16-be 但是好在想起了单词数量,在ifo文件:WordCount:352431
6b 和 6d的出现次数和这个非常接近,可能作为分隔符。
解码:
●
随便指定一个单词,比如 area,用类似二分法的方式,断开网络,对ydic翻译文件对半裁剪。
用有道词典查询该单词,不能查到就提取另一半/继续对半裁剪,最后定位数据:
6b 32 60 32 2a 32 37 de a5 d9 89 62 79 d9 89 32 3c 32 75 32 2a 4b 32 7e 3e 33 33 30 f5 9c aa f5 8f 8f ff ac 9c f5 8c a0 f5 9c aa ff ac 8b f9 8d b2 f7 b7 bf ff ac 8b f8 9c 93 f5 8b a4 32 4d 3c 32 75 68 32 2a 32 21 33 22 26 22 29 27 29 23 26 33 26 20 20 32 3c 32 75 68 32 2a 32 22 33 23 26 23 26 23 29 23 33 23 21 27 23 32 6d
offset: 0d6130
length: 0x6c
将翻译内容:“n. 区域,地区;面积;范围”, 试转为不同编码
gbk: 6e 2e 20 c7 f8 d3 f2 a3 ac b5 d8 c7 f8 a3 bb c3 e6 bb fd a3 bb b7 b6 ce a7 big5: 6e 2e 20 3f b0 ec a1 41 a6 61 3f a1 46 ad b1 3f a1 46 ad 53 3f utf8: 6e 2e 20 e5 8c ba e5 9f 9f ef bc 8c e5 9c b0 e5 8c ba ef bc 9b e9 9d a2 e7 a7 af ef bc 9b e8 8c 83 e5 9b b4 utf16-le: 6e 0 2e 0 20 0 3a 53 df 57 c ff 30 57 3a 53 1b ff 62 97 ef 79 1b ff 3 83 f4 56
总结出编码以及加密方式:翻译内容为UTF8编码,做了简单的处理,hex的高位如果是奇数,高位-1,否则高位+1 , 还原数据:
{"p":"'εəriə","e":["n.## 区域,地区;面积;范围"],"ex":"1#26297936#600","ex":"2#3636393#3173"}
"ex":"1#26297936#600" 表示引用字典 21EC.ydic 的数据,offset 为 26297936,600是数据长度
"ex":"2#3636393#3173" 表示引用字典 phrase.ydic的数据,offset 为 3636393,3173是数据长度
用二分法锁定字节区域是碰了运气,因为有很多数据都是引用另一个字典,再绕一点都会烦得不行。
现在回去看idx文件:
好像也是通过对半截取的方式,找到了对应的单词,因为,如果单词或者索引删掉了,会导致搜不到。
(去年探索的,具体忘了。。。)加密方式和译文的一样。
总结:
idx文件,第一部分为索引,索引数据长度 = 352431(单词量) * 12(数据段) = 4229172
4个字节为一个值,低位在前。后面部分为单词,单词部分没有划分符,根据索引进行提取划分,
单词部分采用非常简单的加密:高位奇数时-1,偶数时+1
00 00 00 00 第一单词起点
00 00 00 00 译文起点
16 00 00 00 译文长度
06 00 00 00 第二单词起点
16 00 00 00 译文起点
16 00 00 00 译文长度
0b 00 00 00 。。。
2c 00 00 00
16 00 00 00
拆解
此处略过,因为是不同时间去折腾的,分了多个脚本和步骤,再整理一遍真是烦
转为明文后的字典下载地址 :
http://523066680.ys168.com/ [临时]文件夹
Youdao_En_Cn_PerlStruct 202016-06.7z
Youdao EN2CN OneFile 2016-06.7z
字典搜索示例 use Encode;
use YAML 'Dump';
my $PATH = "D:\\Local\\Dict\\Youdao\\Analyse_EC";
open READ,"<:raw", "$PATH\\EN2CN.txt";
my $s;
our $data;
while ($s = <READ>)
{
if ($s=~/^words :/i)
{
$s=~/^(.+) \: (.*)\r?\n/i;
eval "\$data = $2";
delete $data->{'pr'}; #不显示“相关词组”信息
print utf8_to_gbk( Dump($data) );
}
}
close READ;
sub utf8_to_gbk
{
return encode('gbk', decode('utf8', $_[0]));
}
显示结果
--- e: - n. 字(word的复数);话语;言语 - v. 用言语表达(word的三单形式) p: w?:dz
音标包含一些gbk以外的符号,在终端显示不全
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)