• 标 题:Lambda Pro v2.0安装序列号破解(1) (16千字)
  • 作 者:FiNALSErAPH
  • 时 间:2001-12-8 5:05:41
  • 链 接:http://bbs.pediy.com

/////////////////////////////////////////////////////////////////////
//
//  目标软件:Lambda Pro
//
//  软件版本:v2.0-MAC-Limit-DEMO-0724
//
//  官方网站:http://www.coretek.com.cn/
//
//  软件授权:商用软件
//
//  操作系统:Win95/98/ME、WinNT/2000
//
//  软件简介:
//
//  中国拥有自己知识产权的实时操作系统 - Delta OS的IDE。因为是简体中文
//
//  软件,个人觉得很适合于初学实时操作系统(RTOS)的人们作为学习参考。
//
//  软件保护:IntsallShield v6.x序列号保护(此序列号与网卡MAC地址有关)
//
/////////////////////////////////////////////////////////////////////
//
//  使用工具:InstallShield Decompiler v1.00 beta 7
//            (用于反汇编SETUP.INX脚本文件)
//
//            Borland C++ v3.1
//            (用于编写序列号生成器)
//
//            Our Brain...:-)
//
/////////////////////////////////////////////////////////////////////
//
//  关于本文:本文主要目的在于教学,让初学者掌握InstallShoeld序列号分
//
//            析的一般方法,所以找了这个很不常见的软件...请勿将此教程
//
//            用于商业目的。
//
//                              Always Your Best Friend: FiNALSErAPH
//
//  水平有限,难免疏漏...
//
//  Any Question?
//  Mail To: FiNALSErAPH@yahoo.com.cn
//
//                                                        2001-12-04
//
/////////////////////////////////////////////////////////////////////
//
//  第一部分:脚本分析
//
/////////////////////////////////////////////////////////////////////
//
//  ISD SETUP.INX SETUP.TXT -O -E
//  (将SETUP.INX反编译并将结果输出至SETUP.TXT文件)
//
/////////////////////////////////////////////////////////////////////
function program()
begin
/* 000055A5: 0006 */    g_str27 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

/* 000055D3: 0006 */    g_str28 = "YW9KV8IU7MT6DS5NQ4AP3LJ2EH1RG0OFZCBX";

/* 00005601: 0021 */    function_22();
                        //将安装目录下的TEST_001.EXE文件拷贝到C:\并重命名
                        //为GETMAC.EXE。执行C:\GETMAC.EXE(获取网卡MAC地址)
                        //生成C:\MACINFO.TXT(里面就是网卡的物理地址)
                        //在安装正常完成后这些文件会被删除

/* 00005607: 0021 */    function_184(12);

/* 00005612: 0021 */    function_10();

/* 00005618: 0021 */    function_8();

/* 0000561E: 0021 */    function_9();

/* 00005624: 0006 */    g_number28 = 0;

/* 00005630: 0021 */    function_1();
                        //密码验证程序入口
  .
  .
  .
end;
/////////////////////////////////////////////////////////////////////
// : Call Referenced(1):
// :  00005630,
function NUMBER function_1()
    NUMBER n0;
    NUMBER n1;
begin

// : Jump Referenced(1):
// :  00005A82,
label_13:
/* 00005A4F: 0021 */    function_23();
                        //从C:\MACINFO.TXT中获取网卡信息备用

// : Jump Referenced(1):
// :  00005AB8,
label_14:
/* 00005A57: 0021 */    function_11();
                        //显示欢迎画面
/* 00005A5D: 0006 */    n0 = LAST_RESULT;
/* 00005A67: 000D */    n1 = n0 == 12;
/* 00005A76: 0004 */    if(! n1) goto label_15;
/* 00005A82: 0005 */    goto label_13;

// : Jump Referenced(2):
// :  00005A76, 00005AEE,
label_15:
/* 00005A8D: 0021 */    function_12();
                        //显示版权信息
/* 00005A93: 0006 */    n0 = LAST_RESULT;
/* 00005A9D: 000D */    n1 = n0 == 12;
/* 00005AAC: 0004 */    if(! n1) goto label_16;
/* 00005AB8: 0005 */    goto label_14;

// : Jump Referenced(3):
// :  00005AAC, 00005B3F, 00005B83,
label_16:
/* 00005AC3: 0021 */    function_13();
                        //获取用户输入的序列号(赋给g_str26)
/* 00005AC9: 0006 */    n0 = LAST_RESULT;
/* 00005AD3: 000D */    n1 = n0 == 12;
/* 00005AE2: 0004 */    if(! n1) goto label_17;
/* 00005AEE: 0005 */    goto label_15;

// : Jump Referenced(1):
// :  00005AE2,
label_17:
/* 00005AF9: 000D */    n1 = n0 == 1;
/* 00005B08: 0004 */    if(! n1) goto label_18;
/* 00005B14: 0021 */    function_24();
                        //序列号验证程序的核心部分(即算法验证部分)
/* 00005B1A: 0006 */    n1 = LAST_RESULT;
/* 00005B24: 000D */    n1 = n1 == 1;
/* 00005B33: 0004 */    if(! n1) goto label_18;
/* 00005B3F: 0005 */    goto label_16;
                        //输入序列号错误则陷入循环
  .
  .
  .
end;
/////////////////////////////////////////////////////////////////////
// : Call Referenced(1):
// :  00005B14,
function NUMBER function_24()
    STRING s0;
    STRING s1[13];
    STRING s2;
    NUMBER n0;
    NUMBER n1;
    NUMBER n2;
    NUMBER n3;
    NUMBER n4;
    NUMBER n5;
    NUMBER n6;
    NUMBER n7;
    NUMBER n8;
begin
/* 00007036: 0006 */    s2 = g_str26;
/* 00007040: 0021 */    function_455(s2);
/* 00007049: 0006 */    n7 = LAST_RESULT;
/* 00007053: 000E */    n7 = n7 != 52;
/* 00007062: 0004 */    if(! n7) goto label_82;
/* 0000706E: 0021 */    function_304("Invalid serial number!", -65535);
/* 00007092: 0027 */    // -- Start Return Code -- //
/* 00007096: 0023 */    return 1;
//判断输入的序列号是否为52位

// : Jump Referenced(1):
// :  00007062,
label_82:
/* 000070A1: 0006 */    n0 = 0;

// : Jump Referenced(1):
// :  00007106,
label_83:
/* 000070AF: 000B */    n7 = n0 <= 51;
/* 000070BE: 0004 */    if(! n7) goto label_84;
/* 000070CA: 001E */    n7 = s2[n0];
/* 000070D7: 0021 */    function_18(n7);
/* 000070E0: 0006 */    n7 = LAST_RESULT;
/* 000070EA: 001D */    s2[n0] = n7;
/* 000070F7: 0007 */    n0 = n0 + 1;
/* 00007106: 0005 */    goto label_83;
//将输入序列号中的小写字母全部换成大写字母

// : Jump Referenced(1):
// :  000070BE,
label_84:
/* 00007111: 001E */    n7 = s2[0];
/* 00007120: 000C */    n7 = n7 >= 48;
/* 0000712F: 001E */    n8 = s2[0];
/* 0000713E: 000B */    n8 = n8 <= 52;
/* 0000714D: 0019 */    n7 = n7 && n8;
/* 0000715A: 0004 */    if(! n7) goto label_85;
/* 00007166: 0006 */    g_str28 = "YW9KV8IU7MT6DS5NQ4AP3LJ2EH1RG0OFZCBX";
/* 00007194: 0005 */    goto label_86;

// : Jump Referenced(1):
// :  0000715A,
label_85:
/* 0000719F: 0006 */    g_str28 = "IR6UQ5GP4MO3YN2SK1AJ0THZLFX9ECW8DBV7";

// : Jump Referenced(1):
// :  00007194,
label_86:
/* 000071CF: 0006 */    n0 = 1;
//根据输入的第一个字符选择“字符替换表”

// : Jump Referenced(1):
// :  00007244,
label_87:
/* 000071DD: 000B */    n7 = n0 <= 51;
/* 000071EC: 0004 */    if(! n7) goto label_88;
/* 000071F8: 001E */    n7 = s2[n0];
/* 00007205: 0021 */    function_19(g_str28, n7);
/* 00007211: 0006 */    n1 = LAST_RESULT;
/* 0000721B: 001E */    n7 = g_str27[n1];
/* 00007228: 001D */    s2[n0] = n7;
/* 00007235: 0007 */    n0 = n0 + 1;
/* 00007244: 0005 */    goto label_87;
//根据上面选择的“字符替换表”对输入字符串进行变换(注意:[00]不变,只变换[01] - [51])
//由g_str28确定位置 - >对应于g_str27的字符

// : Jump Referenced(1):
// :  000071EC,
label_88:
/* 0000724F: 0006 */    n2 = 1;
/* 0000725B: 0006 */    n1 = 49;

// : Jump Referenced(1):
// :  000073AE,
label_89:
/* 00007269: 000B */    n7 = n1 <= 51;
/* 00007278: 0004 */    if(! n7) goto label_93;
/* 00007284: 001E */    n7 = s2[n2];
/* 00007291: 0021 */    function_20(n7);
/* 0000729A: 0006 */    n3 = LAST_RESULT;
/* 000072A4: 0007 */    n0 = n2 + 1;
/* 000072B3: 0007 */    n7 = n2 + 15;

// : Jump Referenced(1):
// :  00007319,
label_90:
/* 000072C4: 000B */    n8 = n0 <= n7;
/* 000072D1: 0004 */    if(! n8) goto label_91;
/* 000072DD: 001E */    n8 = s2[n0];
/* 000072EA: 0021 */    function_20(n8);
/* 000072F3: 0006 */    n8 = LAST_RESULT;
/* 000072FD: 0014 */    n3 = n3 ^ n8;
/* 0000730A: 0007 */    n0 = n0 + 1;
/* 00007319: 0005 */    goto label_90;

// : Jump Referenced(1):
// :  000072D1,
label_91:
/* 00007324: 0021 */    function_21(n3);
/* 0000732D: 0006 */    n3 = LAST_RESULT;
/* 00007337: 001E */    n7 = s2[n1];
/* 00007344: 000E */    n7 = n3 != n7;
/* 00007351: 0004 */    if(! n7) goto label_92;
/* 0000735D: 0021 */    function_304("Invalid Serial Number!", -65535);
/* 00007381: 0027 */    // -- Start Return Code -- //
/* 00007385: 0023 */    return 1;

// : Jump Referenced(1):
// :  00007351,
label_92:
/* 00007390: 0007 */    n2 = n2 + 16;
/* 0000739F: 0007 */    n1 = n1 + 1;
/* 000073AE: 0005 */    goto label_89;
//对新生成的字符串进行初步校验
//[00]
//[01] [02] [03] [04] [05] [06] [07] [08] [09] [10] [11] [12] [13] [14] [15] [16]  -  [49]
//[17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30] [31] [32]  -  [50]
//[33] [34] [35] [36] [37] [38] [39] [40] [41] [42] [43] [44] [45] [46] [47] [48]  -  [51]
//将[01] - [48]的字符分成3组:[01] - [16],[17] - [32],[33] - [48]
//分别作以下运算:
//将每一个字符进行变换(字符0 - 9 -> 数字0 - 9,字符A - F -> 数字10 - 15,字符G - Z ->其ASCII值)
//进行XOR -> 校验数 -> 字符
//校验数变换为字符规则(数字0 - 9 -> 字符0 - 9,数字10 - 15 -> 字符A - F,其他原样返回)
//然后与校验位比较,看是否相同。若相同则继续

// : Jump Referenced(1):
// :  00007278,
label_93:
/* 000073B9: 0006 */    n1 = 1;
/* 000073C5: 0006 */    n0 = 40;

// : Jump Referenced(1):
// :  00007426,
label_94:
/* 000073D3: 000B */    n7 = n0 <= 48;
/* 000073E2: 0004 */    if(! n7) goto label_95;
/* 000073EE: 001E */    n7 = s2[n0];
/* 000073FB: 001D */    s0[n1] = n7;
/* 00007408: 0007 */    n1 = n1 + 1;
/* 00007417: 0007 */    n0 = n0 + 1;
/* 00007426: 0005 */    goto label_94;

// : Jump Referenced(1):
// :  000073E2,
label_95:
/* 00007431: 0006 */    n0 = 1;

// : Jump Referenced(1):
// :  00007492,
label_96:
/* 0000743F: 000B */    n7 = n0 <= 39;
/* 0000744E: 0004 */    if(! n7) goto label_97;
/* 0000745A: 001E */    n7 = s2[n0];
/* 00007467: 001D */    s0[n1] = n7;
/* 00007474: 0007 */    n1 = n1 + 1;
/* 00007483: 0007 */    n0 = n0 + 1;
/* 00007492: 0005 */    goto label_96;

// : Jump Referenced(1):
// :  0000744E,
label_97:
/* 0000749D: 0006 */    n0 = 1;

// : Jump Referenced(1):
// :  000074EF,
label_98:
/* 000074AB: 000B */    n7 = n0 <= 48;
/* 000074BA: 0004 */    if(! n7) goto label_99;
/* 000074C6: 001E */    n7 = s0[n0];
/* 000074D3: 001D */    s2[n0] = n7;
/* 000074E0: 0007 */    n0 = n0 + 1;
/* 000074EF: 0005 */    goto label_98;
//对字符串进行“换位”,规则如下:
//[00]
//[01] [02] [03] [04] [05] [06] [07] [08] [09] [10] [11] [12] [13] [14] [15] [16]
//[17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30] [31] [32]
//[33] [34] [35] [36] [37] [38] [39] [40] [41] [42] [43] [44] [45] [46] [47] [48]
//[49] [50] [51]
//
//变为
//
//[00]
//[40] [41] [42] [43] [44] [45] [46] [47] [48] [01] [02] [03] [04] [05] [06] [07]
//[08] [09] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23]
//[24] [25] [26] [27] [28] [29] [30] [31] [32] [33] [34] [35] [36] [37] [38] [39]
//[49] [50] [51]

// : Jump Referenced(1):
// :  000074BA,
label_99:
/* 000074FA: 001E */    n7 = s2[1];
/* 00007509: 001D */    g_str24[0] = n7;
/* 00007518: 0006 */    n0 = 14;

// : Jump Referenced(1):
// :  00007579,
label_100:
/* 00007526: 000B */    n7 = n0 <= 32;
/* 00007535: 0004 */    if(! n7) goto label_101;
/* 00007541: 000F */    n7 = n0 - 13;
/* 00007550: 001E */    n8 = s2[n0];
/* 0000755D: 001D */    g_str24[n7] = n8;
/* 0000756A: 0007 */    n0 = n0 + 1;
/* 00007579: 0005 */    goto label_100;
//生成字符串g_str24,规则如下:
//[00]
//[01] [02] [03] [04] [05] [06] [07] [08] [09] [10] [11] [12] [13] [14] [15] [16]
//[17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30] [31] [32]
//[33] [34] [35] [36] [37] [38] [39] [40] [41] [42] [43] [44] [45] [46] [47] [48]
//[49] [50] [51]
//
//[01] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28]
//[29] [30] [31] [32]

// : Jump Referenced(1):
// :  00007535,
label_101:
/* 00007584: 0006 */    n0 = 0;

// : Jump Referenced(1):
// :  000075E5,
label_102:
/* 00007592: 000B */    n7 = n0 <= 14;
/* 000075A1: 0004 */    if(! n7) goto label_103;
/* 000075AD: 0007 */    n7 = n0 + 14;
/* 000075BC: 001E */    n7 = s2[n7];
/* 000075C9: 001D */    g_str25[n0] = n7;
/* 000075D6: 0007 */    n0 = n0 + 1;
/* 000075E5: 0005 */    goto label_102;
//生成字符串g_str25,规则如下:
//[00]
//[01] [02] [03] [04] [05] [06] [07] [08] [09] [10] [11] [12] [13] [14] [15] [16]
//[17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30] [31] [32]
//[33] [34] [35] [36] [37] [38] [39] [40] [41] [42] [43] [44] [45] [46] [47] [48]
//[49] [50] [51]
//
//[14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28]

// : Jump Referenced(1):
// :  000075A1,
label_103:
/* 000075F0: 001E */    n7 = s2[29];
/* 000075FF: 0009 */    n7 = n7 < 50;
/* 0000760E: 001E */    n8 = s2[29];
/* 0000761D: 000A */    n8 = n8 > 57;
/* 0000762C: 0018 */    n7 = n7 || n8;
/* 00007639: 0004 */    if(! n7) goto label_104;
/* 00007645: 0021 */    function_304("Invalid serial number!", -65535);
/* 00007669: 0027 */    // -- Start Return Code -- //
/* 0000766D: 0023 */    return 1;
//继续校验:
//[00]
//[01] [02] [03] [04] [05] [06] [07] [08] [09] [10] [11] [12] [13] [14] [15] [16]
//[17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30] [31] [32]
//[33] [34] [35] [36] [37] [38] [39] [40] [41] [42] [43] [44] [45] [46] [47] [48]
//[49] [50] [51]
//
//[29]必须为字符2 - 9

// : Jump Referenced(1):
// :  00007639,
label_104:
/* 00007678: 001E */    n7 = s2[31];
/* 00007687: 0021 */    function_20(n7);
/* 00007690: 0006 */    n3 = LAST_RESULT;
/* 0000769A: 0016 */    n3 = n3 << 4;
/* 000076A9: 001E */    n7 = s2[32];
/* 000076B8: 0021 */    function_20(n7);
/* 000076C1: 0006 */    n7 = LAST_RESULT;
/* 000076CB: 0013 */    n3 = n3 | n7;
/* 000076D8: 0012 */    n4 = n3 & 1;
/* 000076E7: 000D */    n7 = n4 == 0;
/* 000076F6: 0004 */    if(! n7) goto label_105;
/* 00007702: 0021 */    function_304("Invalid serial number!", -65535);
/* 00007726: 0027 */    // -- Start Return Code -- //
/* 0000772A: 0023 */    return 1;
//继续校验:
//[00]
//[01] [02] [03] [04] [05] [06] [07] [08] [09] [10] [11] [12] [13] [14] [15] [16]
//[17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30] [31] [32]
//[33] [34] [35] [36] [37] [38] [39] [40] [41] [42] [43] [44] [45] [46] [47] [48]
//[49] [50] [51]
//
//[31]进行变换(字符0 - 9 -> 数字0 - 9,字符A - F -> 数字10 - 15,字符G - Z ->其ASCII值)
//结果 *16
//与
//[32]进行变换(字符0 - 9 -> 数字0 - 9,字符A - F -> 数字10 - 15,字符G - Z ->其ASCII值)
//结果 按位或
//最低位必须为1
//
//下面的校验已转为明文,即MAC字符串为最后生成的52位字符串的前12位,详见注册机程序

// : Jump Referenced(1):
// :  000076F6,
label_105:
/* 00007735: 0021 */    function_347(g_number33, s1);
/* 00007741: 0006 */    n6 = LAST_RESULT;

// : Jump Referenced(1):
// :  0000786B,
label_106:
/* 0000774D: 0001 */    // -- While -- //
/* 00007751: 000D */    n7 = n6 == 0;
/* 00007760: 0004 */    if(! n7) goto label_111;
/* 0000776C: 0006 */    n0 = 0;
/* 00007778: 0006 */    n5 = 1;

// : Jump Referenced(1):
// :  00007820,
label_107:
/* 00007786: 0001 */    // -- While -- //
/* 0000778A: 000D */    n7 = n5 == 1;
/* 00007799: 0009 */    n8 = n0 < 12;
/* 000077A8: 0019 */    n7 = n7 && n8;
/* 000077B5: 0004 */    if(! n7) goto label_109;
/* 000077C1: 0007 */    n7 = n0 + 2;
/* 000077D0: 001E */    n7 = s2[n7];
/* 000077DD: 001E */    n8 = s1[n0];
/* 000077EA: 000E */    n7 = n7 != n8;
/* 000077F7: 0004 */    if(! n7) goto label_108;
/* 00007803: 0006 */    n5 = 0;

// : Jump Referenced(1):
// :  000077F7,
label_108:
/* 00007811: 0007 */    n0 = n0 + 1;
/* 00007820: 0005 */    goto label_107;

// : Jump Referenced(1):
// :  000077B5,
label_109:
/* 0000782B: 000D */    n7 = n5 == 1;
/* 0000783A: 0004 */    if(! n7) goto label_110;
/* 00007846: 0027 */    // -- Start Return Code -- //
/* 0000784A: 0023 */    return 0;

// : Jump Referenced(1):
// :  0000783A,
label_110:
/* 00007855: 0021 */    function_349(g_number33, s1);
/* 00007861: 0006 */    n6 = LAST_RESULT;
/* 0000786B: 0005 */    goto label_106;

// : Jump Referenced(1):
// :  00007760,
label_111:
/* 00007876: 000D */    n7 = n5 == 0;
/* 00007885: 0004 */    if(! n7) goto label_112;
/* 00007891: 0021 */    function_304("Invalid Serial Number!", -65535);
/* 000078B5: 0027 */    // -- Start Return Code -- //
/* 000078B9: 0023 */    return 1;

// : Jump Referenced(1):
// :  00007885,
label_112:
/* 000078C4: 0027 */    // -- Start Return Code -- //
/* 000078C8: 0023 */    return 0;
end;
/////////////////////////////////////////////////////////////////////
//
//  第二部分:序列号生成器
//
//  为了便于初学者学习,全部使用数组,只需有一点C的基础...:-)
//
//  另:MACINFO.TXT可执行TEST_001.EXE获得
//
/////////////////////////////////////////////////////////////////////
/*-------------------------------------------------------------*/
/*                        某某研究所                          */
/*                                                            */
/*                  版权所有(C) 19xx - 2001                    */
/*-------------------------------------------------------------*/
/*                  实时操作系统 - 辅助程序                    */
/*                                                            */
/*              REAL TIME OPERATING SYSTEM (RTOS)              */
/*-------------------------------------------------------------*/
/*                                                            */
/*-------------------------------------------------------------*/
/*              文件名    :    KeyGen.C                    */
/*                描述    :    Lambda Pro v2.0安装序列号    */
/*                                生成器。                    */
/*            创建日期    :    2001-08-13                  */
/*        最后修改日期    :    2001-08-13                  */
/*              编制人    :    FiNALSErAPH                  */
/*-------------------------------------------------------------*/
/*                                                            */
/*-------------------------------------------------------------*/
/*  修改号  日期        修改人    修改描述                  */
/*-------------------------------------------------------------*/
/*  初始版本 2001-08-13    HZH      这是整理后的改写版添加    */
/*                                  了注释,比较易懂          */
/*-------------------------------------------------------------*/
/*  头文件段                                                  */
/*-------------------------------------------------------------*/
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <process.h>
#include <dos.h>
#include <time.h>
/*-------------------------------------------------------------*/
/*  数据定义段                                                */
/*-------------------------------------------------------------*/
FILE *InMacInfo;
FILE *OutSerial;

int iCount = 0;
int iTemp = 0;

char cTable0[36] = {'A','B','C','D','E','F','G','H','I','J','K','L',
            'M','N','O','P','Q','R','S','T','U','V','W','X',
            'Y','Z','0','1','2','3','4','5','6','7','8','9'};
char cTable1[36] = {'Y','W','9','K','V','8','I','U','7','M','T','6',
            'D','S','5','N','Q','4','A','P','3','L','J','2',
            'E','H','1','R','G','0','O','F','Z','C','B','X'};
char cTable2[36] = {'I','R','6','U','Q','5','G','P','4','M','O','3',
            'Y','N','2','S','K','1','A','J','0','T','H','Z',
            'L','F','X','9','E','C','W','8','D','B','V','7'};
char cTarget[36];
/*-------------------------------------------------------------*/
/*  内部函数调用声明段                                        */
/*-------------------------------------------------------------*/
void vCopyRightMsg(void);
void vKeyGenerate(void);
void vWaitFor(void);
char cCharToNum(char cInput);
char cNumToChar(char cInput);
int iCheckLocation(char cInput);
/*-------------------------------------------------------------*/
/*  代码段                                                    */
/*-------------------------------------------------------------*/
void main(void)
{
  vCopyRightMsg();
  vWaitFor();
  vKeyGenerate();
}

void vCopyRightMsg(void)
{
  printf("+----------------------------------------+\n");
  printf("|  LambdaPro v2.0-MAC-Limit-DEMO-0724  |\n");
  printf("|      Install Key Generator v1.0.1      |\n");
  printf("|        =- Proudly  Present -=        |\n");
  printf("|              2001-08-14              |\n");
  printf("|              FiNAL SErAPH              |\n");
  printf("+----------------------------------------+\n");
  printf("\n");
}

void vKeyGenerate()
{
//安装序列号生成算法 - 开始

  //从MACINFO.TXT中提取信息
  if((InMacInfo = fopen("MACINFO.TXT","r")) == NULL)
  {
      printf("Can't Open \"MACINFO.TXT\"!\n");
      exit(0);
  }

  char cMacInfo[12];
  fgets(cMacInfo,13,InMacInfo);
  fclose(InMacInfo);

  //字符转为数字
  for(iCount = 0;iCount < 12;iCount++)
  {
      cMacInfo[iCount] = cCharToNum(cMacInfo[iCount]);
  }

  //随机生成长度为52的数字串
  char cOutSerial[52];
  srand(time(NULL));
  iCount = 0;
  while(iCount < 52)
  {
      cOutSerial[iCount] = rand()%16;
      iCount++;
  }

  //将网卡MAC地址插入长度为52的数字串中
  for(iCount = 0;iCount < 12;iCount++)
  {
      cOutSerial[iCount + 2] = cMacInfo[iCount];
  }

  //使长度为52的数字串满足两种校验条件
  //1 - 控制[29]在 2 - 9之间
  iTemp = rand()%10;
  if(iTemp < 2)
  {
      iTemp = 9 - iTemp;
  }
  cOutSerial[29] = iTemp;
  //2
  cOutSerial[31] = 0;
  cOutSerial[32] = 1;

  //调整长度为52的数字串中48位的顺序
  char cTemp[9];
  for(iCount = 0;iCount < 9;iCount++)
  {
      cTemp[iCount]= cOutSerial[iCount+1];
  }
  for(iCount = 1;iCount < 40;iCount++)
  {
      cOutSerial[iCount] = cOutSerial[iCount+9];
  }
  for(iCount = 0;iCount < 9;iCount++)
  {
      cOutSerial[iCount+40] = cTemp[iCount];
  }

  //调整3个校验位
  //1
  iTemp = cOutSerial[1];
  for(iCount = 2;iCount < 17;iCount++)
  {
      iTemp = iTemp ^ cOutSerial[iCount];
  }
  cOutSerial[49] = iTemp;
  //2
  iTemp = cOutSerial[17];
  for(iCount = 18;iCount < 33;iCount++)
  {
      iTemp = iTemp ^ cOutSerial[iCount];
  }
  cOutSerial[50] = iTemp;
  //3
  iTemp = cOutSerial[33];
  for(iCount = 34;iCount < 49;iCount++)
  {
      iTemp = iTemp ^ cOutSerial[iCount];
  }
  cOutSerial[51] = iTemp;

  //将长度为52的数字串转为字符串
  for(iCount = 0;iCount < 52;iCount++)
  {
      cOutSerial[iCount] = cNumToChar(cOutSerial[iCount]);
  }

  //根据字符替换表生成最终序列号,输出结果到屏幕
  if((cOutSerial[0] >= '0') && (cOutSerial[0] <= '4'))
  {
      for(iCount = 0;iCount < 36;iCount++)
      {
        cTarget[iCount] = cTable1[iCount];
      }
  }
  else
  {
      for(iCount = 0;iCount < 36;iCount++)
      {
        cTarget[iCount] = cTable2[iCount];
      }
  }

  printf("Your Install Key:\n\n");
  printf("%c",cOutSerial[0]);
  for(iCount = 1;iCount < 52;iCount++)
  {
      cOutSerial[iCount] = cTarget[iCheckLocation(cOutSerial[iCount])];
      printf("%c",cOutSerial[iCount]);
  }

  //输出结果到文件
  if((OutSerial = fopen("SERIAL.TXT","w+")) == NULL)
  {
      printf("I Can't Create File \"SERIAL.TXT\" !!!\n");
      exit(0);
  }
  for(iCount = 0;iCount < 52;iCount++)
  {
      fputc(cOutSerial[iCount],OutSerial);
  }
  fclose(OutSerial);
//安装序列号生成算法 - 结束

}

void vWaitFor(void)
{
  delay(300);
  printf("Please wait");
  for(int i = 0;i < 6;i++)
  {
      printf(".");
      delay(400);
  }
  printf("\n\n");
}

char cCharToNum(char cInput)
{
  char cOutput;
  if((cInput >= '0') && (cInput <= '9'))
  {
      cOutput = cInput - 48;
  }
  if((cInput >= 'A') && (cInput <= 'F'))
  {
      cOutput = cInput - 55;
  }
  if((cInput >= 'a') && (cInput <= 'f'))
  {
      cOutput = cInput - 87;
  }
  return(cOutput);
}

char cNumToChar(char cInput)
{
  char cOutput;
  if((cInput >= 0) && (cInput <= 9))
  {
      cOutput = cInput + 48;
  }
  if((cInput >= 10) && (cInput <= 15))
  {
      cOutput = cInput + 55;
  }
  return(cOutput);
}

int iCheckLocation(char cInput)
{
  for(int i = 0;i < 36;i++)
  {
      if(cInput == cTable0[i])
      {
        return(i);
      }
  }
  return(-1);
}