风河的产品,一般都需要一个序列号来进行安装.比如:x#yyo-YVXT#-nozVy-wwoyx-VXy#o-UbFBF是Tornado2.2 for arm的cd1的安装序列号.这一串字符代表什么意思呢?让我们来一步一步追踪.
以下的分析使用Tornado2.2 for arm的安装文件.
一:
随便把序列号改一个字符,立刻弹出一个对话框:"The installation key you entered is invalid ......". 我们在安装目录下搜索这一句话,定位到一个文件:
RESOURCE/TCL/REGISTER.TCL
这句信息的定义:
set strTable(REGISTRATION_WARN_6) \
"The installation key you entered is invalid - please re-check it.\
Note that the key must be entered exactly as shown, including\
capitalization and dashes."
继续在文件里面搜索"REGISTRATION_WARN_6":
if {![catch {setupKeyValidate [instKeyGet]} error]} {
......
} else {
if { [isGUImode] } {
if { $ctrlVals(useInputScript) } {
......
} else {
messageBox [strTableGet REGISTRATION_WARN_6]
return 0
}
} else { # TEXT MODE
......
}
}
应该就是这里弹出的对话框,是根据setupKeyValidate [instKeyGet]的返回值判断的.
继续在安装目录搜索setupKeyValidate:
X86\WIN32\SETUPTCL.DLL
看来这个函数就在这个DLL里面.接下来就分析这个文件.
二:
首先用IDA打开这个文件,找到setupKeyValidate对应的地方:
.data:10023BD0 dd offset aSetupkeyvalida ; "setupKeyValidate"
.data:10023BD4 dd offset sub_1000B600
应该是TCL脚本传递需要调用的函数的名字,然后再查找对应的函数地址,再进行调用.那么"setupKeyValidate"对应的函数就是sub_1000B600了.
利用IDA的调用关系分析功能,可以看到这个函数大致的调用关系.一共十几个函数,很容易就能分析完毕.分析过程就不写了.
三:
首先,对序列号进行预处理,去掉中间的分隔符'-':
x#yyoYVXT#nozVywwoyxVXy#oUbFBF
然后,把符号转换成数字.这里有一个转换表:
table[64] = "F9CgKpUzb8DhM@qVBEeiN$rWd6ajP%sX75GkQ&tYf4HmR*uZA3InS+vxc2JoT#wy";
序列号中的每一个字符在转换表中的位置,就是这个字符对应的数值.序列号转换后的结果:
37 3d 3f 3f 3b 27 0f 1f 3c 3d 33 3b 07 0f 3f 3e 3e 3b 3f 37 0f 1f 3f 3d 3b 06 08 00 10 00
每个数值包含6bit的信息.
转换后的序列号,长度30个字节.每个字节包含6位,一共是180位.并不是所有的位都用来保存信息,所以有一个函数根据字节长度返回有效位长度:
sub_1600: 根据序列号长度转换位长度:
25 -> 95
30 -> 125
35 -> 155
40 -> 185
45 -> 215
序列号中包含了若干数据,每个数据的位顺序都是打乱了的,通过一个位置表来组合.目前发现有8个表:
int bp_1F404[215];// component list
int bp_1F760[11]; // checksum
int bp_1F78C[20]; // license number
int bp_1F7DC[ 9]; // 似乎固定为511
int bp_1F800[17]; // CD_VENDOR_ID
int bp_1F844[26];
int bp_1F8AC[26];
int bp_1F914[26];
bp_1F760描述校验和.
计算校验和时,首先把校验和所在位清0,然后把转换后的序列号每一个字节处理后异或累加,得到的就是校验和.
bp_1F78C描述license number.
风河的每一个产品都有一个编号,就是这个license number.
bp_1F7DC描述固定值511.
bp_1F800描述CD_VENDOR_ID.
每个ISO都有一个类似这样的名字:"CDR-R118794.1-1".去掉前面的"CDR-R1", 接下来的数字18794就是CD_VENDOR_ID.
但是对于这种名字:"TDK-14624-ZC-00",尚不知道数字编号与CD_VENDOR_ID的对应关系.
三个26位长度的数据,其实是bp_1F7DC和bp_1F800混合后,打乱顺序组成的数据.三个数据被转换成一个十进制字符串.是用来解密的(dec_key).
bp_1F404描述剩余的位.每一个位表示一个组件是否允许安装.
四:
风河的早期产品,安装数据包都放在WIND目录下,以WIND.xxx命名.打开这些文件,可以看到"PK"标志,说明这些都是ZIP格式.把扩展名改为.zip就可以解开.但解开后的数据都是加密的.
在IDA中搜索"WIND.000",可以定位到setupInit函数.对其分析发现,安装程序先解开WIND.000中的PARTS.TDB文件,然后用序列号中的dec_key对其内容进行解密.
解密函数定位在sub_100017E0(0, file, dec_key).分析这个函数就可以发现具体的解密算法:
先读取文件最后20个字节: 5个大端dword
0: 0x01311964 固定值
1: 0x50AD8A94 校验和
2: 0x12151992 固定值
3: 0x00003B1B 文件长度
4: 0x10021996 固定值
int dec_key_len = strlen(dec_key);
int check_sum = 0;
for(i=0; i<file_len; i++){
ch = src[i];
key = dec_key[i%dec_key_len];
ch = (ch+key+0x62)&0xff;
src[i] = ch;
check_sum = check_sum+ch^check_sum;
}
解密后的PARTS.TDB的第一行:
721 TDK-14624-ZC-00 58 511
可以发现,721对应bp_1F800, 511对应bp_1F7DC.
58是WIND目录下zip包的个数,从WIND.001开始,到WIND.058结束
721和511都要和序列号中的值比较.
PARTS.TDB的其他行:
"23 100-23273-30 tornado-comp-gnu Compiler - GNU: x86-win32 x arm tornado-comp-gnu Compiler - GNU: x86-win32 x arm 1 490 none 0 non-core 43560962"
每一个这样的行描述一个组件.
23: 对应bp_1F404中的一位
100-23273-30 和 tornado-comp-gnu : 组合成100-23273-30_tornado-comp-gnu.db. 这个db文件应该是描述这个组件的文件信息.
五:
从前面的分析可以看到,密钥其实就是CD_VENDOR_ID,只有17位数据.
对于"CDR-R118794.1-1"这类ISO,可以直接取得CD_VENDOR_ID.
对于"TDK-14624-ZC-00"这类ISO,我们可以写一个程序穷举所有可能的值,对PARTS.TDB的前面几个字节进行解密.一旦发现解密出来的数据就是当前用的ID,解密就完成了.
有了CD_VENDOR_ID,我们就可以根据各种信息重建序列号了.这些有待写程序验证.