首页
社区
课程
招聘
[原创]金山游侠V序列号验证算法分析
发表于: 2005-3-19 09:17 13053

[原创]金山游侠V序列号验证算法分析

2005-3-19 09:17
13053

【破解作者】 隐者无疆[BCG]
【使用工具】 InstallShield Decompiler v1.00
【破解平台】 WinXP SP2
【软件名称】 金山游侠V
【软件简介】 游戏修改利器!
【加壳方式】 无壳
【破解声明】 我是一只小菜鸟,偶得一点心得,愿与大家分享:)
--------------------------------------------------------------------------------
【破解内容】

前几天在网上down了一份《金山游侠V》。以前从来没有研究过 InstallShield 编写的东东,这次就拿它来开刀吧。
1.将下载的安装文件解压,看到里面有名为“setup,inx”的文件。用InstallShield Decompiler将这个文件反编译,
保存为script.txt.
2.打开script.txt,在文件中搜索“serial”字串。
  看到有一字符串“IDS_MSG_WRONG_SERIAL_NUMBER”,推测是安装程序定义的序列号出错消息。接下来,搜索
  “IDS_MSG_WRONG_SERIAL_NUMBER”,到达下述位置:
/* 000050B1: 0021 */    function_492(s7, s6);
/* 000050BD: 0021 */    function_8(s7);
/* 000050C6: 0021 */    function_11(s7);
/* 000050CF: 0006 */    n5 = LAST_RESULT;
/* 000050D9: 0004 */    if(! n5) goto label_5;                           // normal if
/* 000050E5: 0021 */    function_9("RegisteredOwner", s4);
/* 00005100: 0021 */    function_9("RegisteredOrganization", s5);
/* 00005122: 0005 */    goto label_6;

// : Jump Referenced(1):
// :  000050D9,
label_5:
/* 0000512D: 0021 */    function_312("IDS_MSG_WRONG_SERIAL_NUMBER");
                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
可见跳转来自/* 000050D9: 0004 */处。向上找,发现/* 000050C6: 0021 */ 处对function_11(s7)的调用可疑,
分析可知,此Call即为关键Call.贴出其对应的代码如下:

function NUMBER function_11(s0)
    STRING s1;
    STRING s2;
    STRING s3;
    STRING s4[10];
    STRING s5[2];
    NUMBER n0;
    NUMBER n1;
    NUMBER n2;
    NUMBER n3;
    NUMBER n4;
    NUMBER n5;
    NUMBER n6;
begin
/* 00006CF5: 0022 */    // -- Start Function Code -- //
/* 00006CFE: 0006 */    s1 = "055900-110000-";
/* 00006D16: 0021 */    StrUpperCase(s3, s0);
/* 00006D22: 0021 */    function_8(s3);
/* 00006D2B: 0021 */    StrLen(s3);
/* 00006D34: 0006 */    n4 = LAST_RESULT;
/* 00006D3E: 0021 */    StrLen("000000-000000-000000-000000");
/* 00006D62: 0006 */    n5 = LAST_RESULT;
/* 00006D6C: 000E */    n4 = n4 != n5;                                   //序列号的长度必须为27
/* 00006D79: 0004 */    if(! n4) goto label_58;                          // normal if
/* 00006D85: 0027 */    // -- Start Return Code -- //
/* 00006D89: 0023 */    return 0;

// : Jump Referenced(1):
// :  00006D79,
label_58:
/* 00006D94: 0021 */    StrLen(s1);
/* 00006D9D: 0006 */    n4 = LAST_RESULT;
/* 00006DA7: 0029 */    StrSub(s2, s3, 0, n4);
/* 00006DB9: 000E */    n4 = s2 != s1;                          //序列号的前半部分必须为"055900-110000-"
/* 00006DC6: 0004 */    if(! n4) goto label_59;                          // normal if
/* 00006DD2: 0027 */    // -- Start Return Code -- //
/* 00006DD6: 0023 */    return 0;

// : Jump Referenced(1):
// :  00006DC6,
label_59:
/* 00006DE1: 001E */    n4 = s3[19];
/* 00006DF0: 000F */    n4 = 105 - n4;
/* 00006DFF: 001D */    s4[9] = n4;                //s4[9] = 105 - s3[19]

/* 00006E0E: 001E */    n4 = s3[26];
/* 00006E1D: 000F */    n4 = 105 - n4;
/* 00006E2C: 001D */    s4[8] = n4;                //s4[8] = 105 - s3[26]
/* 00006E3B: 001E */    n4 = s4[8];
/* 00006E4A: 000F */    n4 = n4 - 48;
/* 00006E59: 0010 */    n1 = 6 * n4;
/* 00006E68: 0008 */    n1 = n1 % 10;              //n1 = ( (s4[8] - 48) *6) % 10

/* 00006E77: 001E */    n4 = s3[24];
/* 00006E86: 000F */    n2 = n4 - 48;              //n2 = s3[24] - 48

/* 00006E95: 0009 */    n4 = n2 < n1;
/* 00006EA2: 0004 */    if(! n4) goto label_60;                          // normal if
/* 00006EAE: 0007 */    n2 = n2 + 10;

// : Jump Referenced(1):
// :  00006EA2,
label_60:
/* 00006EBF: 000F */    n4 = n2 - n1;
/* 00006ECC: 0007 */    n4 = 48 + n4;
/* 00006EDB: 001D */    s4[7] = n4;            //s4[7] = n2 - n1 + 48
/* 00006EEA: 001E */    n4 = s4[7];
/* 00006EF9: 000F */    n4 = n4 - 48;
/* 00006F08: 0010 */    n1 = 4 * n4;
/* 00006F17: 0008 */    n1 = n1 % 10;         //n1=( (s4[7]-48) *4) % 10

/* 00006F26: 001E */    n4 = s3[16];
/* 00006F35: 000F */    n2 = n4 - 48;         //n2 = s3[16] - 48

/* 00006F44: 0009 */    n4 = n2 < n1;
/* 00006F51: 0004 */    if(! n4) goto label_61;                          // normal if
/* 00006F5D: 0007 */    n2 = n2 + 10;

// : Jump Referenced(1):
// :  00006F51,
label_61:
/* 00006F6E: 000F */    n4 = n2 - n1;
/* 00006F7B: 0007 */    n4 = 48 + n4;
/* 00006F8A: 001D */    s4[6] = n4;           //s4[6] = n2 - n1 + 48
/* 00006F99: 001E */    n4 = s4[6];
/* 00006FA8: 000F */    n4 = n4 - 48;
/* 00006FB7: 0010 */    n1 = 7 * n4;
/* 00006FC6: 0008 */    n1 = n1 % 10;         //n1=( (s4[6]-48)* 7) % 10

/* 00006FD5: 001E */    n4 = s3[22];
/* 00006FE4: 000F */    n2 = n4 - 48;         //n2 = s3[22] - 48

/* 00006FF3: 0009 */    n4 = n2 < n1;
/* 00007000: 0004 */    if(! n4) goto label_62;                          // normal if
/* 0000700C: 0007 */    n2 = n2 + 10;

// : Jump Referenced(1):
// :  00007000,
label_62:
/* 0000701D: 000F */    n4 = n2 - n1;
/* 0000702A: 0007 */    n4 = 48 + n4;
/* 00007039: 001D */    s4[5] = n4;           //s4[5] = n2 - n1 + 48
/* 00007048: 001E */    n4 = s4[6];
/* 00007057: 000F */    n4 = n4 - 48;
/* 00007066: 0010 */    n1 = 3 * n4;
/* 00007075: 0008 */    n1 = n1 % 10;         //n1 = ( (s4[6]-48) *3) % 10

/* 00007084: 001E */    n4 = s3[25];
/* 00007093: 000F */    n2 = n4 - 48;         //n2 = s3[25] - 48

/* 000070A2: 0009 */    n4 = n2 < n1;
/* 000070AF: 0004 */    if(! n4) goto label_63;                          // normal if
/* 000070BB: 0007 */    n2 = n2 + 10;

// : Jump Referenced(1):
// :  000070AF,
label_63:
/* 000070CC: 000F */    n4 = n2 - n1;
/* 000070D9: 0007 */    n4 = 48 + n4;
/* 000070E8: 001D */    s4[4] = n4;            //s4[4] = n2 - n1 + 48
/* 000070F7: 001E */    n4 = s3[14];
/* 00007106: 000F */    n4 = n4 - 48;          //n4 = s3[14] - 48

/* 00007115: 001E */    n5 = s4[9];
/* 00007124: 000F */    n5 = n5 - 48;
/* 00007133: 0007 */    n1 = n4 + n5;
/* 00007140: 0008 */    n4 = n1 % 10;
/* 0000714F: 0007 */    n4 = 48 + n4;
/* 0000715E: 001D */    s4[3] = n4;           //s4[3]= ( s4[9]-48+n4 ) % 10 + 48

/* 0000716D: 001E */    n4 = s4[9];
/* 0000717C: 000F */    n4 = n4 - 48;
/* 0000718B: 0010 */    n1 = 2 * n4;
/* 0000719A: 0008 */    n1 = n1 % 10;         //n1 = ( (s4[9]-48) *2) % 10

/* 000071A9: 001E */    n4 = s3[18];
/* 000071B8: 000F */    n2 = n4 - 48;         //n2 = s3[18] - 48

/* 000071C7: 0009 */    n4 = n2 < n1;
/* 000071D4: 0004 */    if(! n4) goto label_64;                          // normal if
/* 000071E0: 0007 */    n2 = n2 + 10;

// : Jump Referenced(1):
// :  000071D4,
label_64:
/* 000071F1: 000F */    n4 = n2 - n1;
/* 000071FE: 0007 */    n4 = 48 + n4;
/* 0000720D: 001D */    s4[2] = n4;             //s4[2] = n2 - n1 + 48

/* 0000721C: 001E */    n4 = s4[9];
/* 0000722B: 000F */    n4 = n4 - 48;
/* 0000723A: 0010 */    n1 = 7 * n4;
/* 00007249: 0008 */    n1 = n1 % 10;           //n1 = ( (s4[9]-48) *7) % 10

/* 00007258: 001E */    n4 = s3[15];
/* 00007267: 000F */    n2 = n4 - 48;           //n2 = n4 - 48

/* 00007276: 0009 */    n4 = n2 < n1;
/* 00007283: 0004 */    if(! n4) goto label_65;                          // normal if
/* 0000728F: 0007 */    n2 = n2 + 10;

// : Jump Referenced(1):
// :  00007283,
label_65:
/* 000072A0: 000F */    n4 = n2 - n1;
/* 000072AD: 0007 */    n4 = 48 + n4;
/* 000072BC: 001D */    s4[1] = n4;             //s4[1] = n2 - n1 + 48

/* 000072CB: 001E */    n4 = s4[9];
/* 000072DA: 000F */    n4 = n4 - 48;
/* 000072E9: 0010 */    n1 = 3 * n4;
/* 000072F8: 0008 */    n1 = n1 % 10;           //n1=( (s4[9]-48) *3) % 10

/* 00007307: 001E */    n4 = s3[21];
/* 00007316: 000F */    n2 = n4 - 48;           //n2 = s3[21] - 48

/* 00007325: 0009 */    n4 = n2 < n1;
/* 00007332: 0004 */    if(! n4) goto label_66;                          // normal if
/* 0000733E: 0007 */    n2 = n2 + 10;

// : Jump Referenced(1):
// :  00007332,
label_66:
/* 0000734F: 000F */    n4 = n2 - n1;
/* 0000735C: 0007 */    n4 = 48 + n4;
/* 0000736B: 001D */    s4[0] = n4;              //s4[0] = n2 - n1 + 48

/* 0000737A: 0006 */    n3 = 0;                  //存储加和
/* 00007386: 0006 */    n0 = 0;                  //s4[] 的下标
// : Jump Referenced(1):
// :  000073E7,
label_67:
/* 00007394: 000B */    n4 = n0 <= 9;
/* 000073A3: 0004 */    if(! n4) goto label_68;                          // normal if
/* 000073AF: 001E */    n4 = s4[n0];
/* 000073BC: 000F */    n4 = n4 - 48;
/* 000073CB: 0007 */    n3 = n3 + n4;              //n3 = n3 + ( s4[n0]-48 )
/* 000073D8: 0007 */    n0 = n0 + 1;               //n0++
/* 000073E7: 0005 */    goto label_67;

// : Jump Referenced(1):
// :  000073A3,
label_68:
/* 000073F2: 0008 */    n3 = n3 % 100;             //n3=n3%100

/* 00007401: 0011 */    n4 = n3 / 10;
/* 00007410: 0007 */    n4 = n4 + 48;
/* 0000741F: 001D */    s5[0] = n4;                //s5[0]= n3/10 + 48

/* 0000742E: 0008 */    n4 = n3 % 10;
/* 0000743D: 0007 */    n4 = n4 + 48;
/* 0000744C: 001D */    s5[1] = n4;                //s5[1]= n3%10 + 48

/* 0000745B: 001E */    n4 = s5[0];
/* 0000746A: 001E */    n5 = s3[17];     
/* 00007479: 000E */    n4 = n4 != n5;             //s5[0]==s3[17]

/* 00007486: 001E */    n5 = s5[1];
/* 00007495: 001E */    n6 = s3[23];
/* 000074A4: 000E */    n5 = n5 != n6;             //s5[1]==s3[23]
/* 000074B1: 0018 */    n4 = n4 || n5;                                               
/* 000074BE: 0004 */    if(! n4) goto label_69;                          // normal if
/* 000074CA: 0027 */    // -- Start Return Code -- //
/* 000074CE: 0023 */    return 0;

// : Jump Referenced(1):
// :  000074BE,
label_69:
/* 000074D9: 0027 */    // -- Start Return Code -- //
/* 000074DD: 0023 */    return 1;
/* 000074E6: 0026 */    // -- Create Local Variables -- //
end;

3.注册算法简析:
代码分析如上所述。
总结如下:
   可用的序列号满足如下条件:
   <1>.序列号长度必须为27位。
   <2>.序列号的前半部分为"055900-110000-"
   <3>.序列号的第17位和第23位由序列号后半部分的其它各位的通过一系列的运算得出。
4.注册机思路:
  InstallShield脚本语言为C语言风格,因此在此例中,注册机的核心代码可以直接引用反汇编出来的脚本代码。
只要稍作修改即可。
  出于大家可以理解的原因,这里就不公开注册机的源代码了。

致谢:在分析本软件的过程中,参考了FiNALSErAPH[OCG]对“金山毒霸2002”的分析,再次表示感谢。
  
--------------------------------------------------------------------------------
【破解总结】

尽管本软件在验证序列号合法性的过程中,没有出现明码比较;但是也差不多了。从反编译出的类C语言代码就可以轻松地分析出算法。
--------------------------------------------------------------------------------
【版权声明】 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (6)
雪    币: 6051
活跃值: (1441)
能力值: ( LV15,RANK:1473 )
在线值:
发帖
回帖
粉丝
2
金山系列V和2003系列的都是这种算法的,如果手头没有现成的序列号,介绍一个最简单的方法:
把Setup.inx用记事本打开,查找一下形如******-******-字符串的,应该在000000-000000-000000-000000字符串附近的,这就是序列号的前二节了,然后再补上后二节000009-000009,即******-******-000009-000009,屡试不爽!!

另:算法很简单,完全可以写一个金山系列的通用注册机的,我就有一个,不过只是自己用,不违法吧?呵呵
2005-3-19 12:17
0
雪    币: 162
活跃值: (63)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
2005-3-19 12:48
0
雪    币: 61
活跃值: (160)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
4
2005-3-19 14:26
0
雪    币: 214
活跃值: (100)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
2005-3-19 18:31
0
雪    币: 214
活跃值: (86)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
6
谢谢,呵呵

我也研究过金山的木马专杀软件序列号,其实也差不多的~~~~
2005-3-20 15:12
0
雪    币: 107
活跃值: (54)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
upup
2005-3-20 15:56
0
游客
登录 | 注册 方可回帖
返回
//