【破解作者】 隐者无疆[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语言代码就可以轻松地分析出算法。
--------------------------------------------------------------------------------
【版权声明】 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法