标题:SoftIce45_for_win9x的安装序列码获取及序列码生成机编写
作者:leafred
主页:http://leafred.126.com/
工具:isDcc v1.22,TRW2000
如有错误欢迎来信指正(leafspring@21cn.com)
以前搞破解,都用TRW2000,今天为了搞一个程序,结果TRW2000总是出错,无奈想起SoftIce,高高兴兴的下载完SoftIce,准备安装,没想到是要序列码的,谁叫咱会Crack呢,自己来动手找吧。哈哈,来破解Crack工具,有点滑稽吧。
先用isDcc来把setup.ins给反编译出来,当然了,setup.ins是在SoftIce安装时在系统临时目录下找到的了。包括后面要提到的动态库。
首先是想能直接从反编译的文件总给找到,来个“The serial number you entered is not valid for this product”搜索,铛的一声,弹出一个提示Search
string not found!,心一沉,看来要费点劲了。
慢慢看吧。
嗯,这个声明prototype UTILITY.DigitCheck(string);可疑,从字面上看数字检查,很想序列码检查哎,先看看谁调用它吧。
找到一下这段代码,发现是function143调用,再找function143谁调用,发现果真是此处进行序列码检查。
首先看看调用function143的地方:
abel187: //Ref: 00667F
006699:0152: RegDBGetKeyValueEx(lString0, "Onomatopoeia",
lNumber1, lString1, lNumber3);
====》取得序列码,先从注册表获取初始值,让我们进行修改,原来没有当然输入新值了。
。。。。。。
label188: //Ref: 0066D0
====》先进行数据初步校验
0066FF:00B4: NMINST32.ValidCookie(2, 0, lString1);
006711:0021: lNumber5 = LAST_RESULT;
006719:0128: lNumber5 = lNumber5 = 1;
00672B:0022: if (lNumber5 = 0) then
goto label190;
endif;
=====》初步校验通过,进行正式检查
006739:00B5: function143(lString3);
。。。。。。
现在再来看函数
// ------------- FUNCTION function143 --------------
function function143(pString0)
====》省略掉变量声明
。。。。。
begin
0067BE:002F: StrLength(pString0); ==》获取长度
0067C3:0021: lNumber1 = LAST_RESULT;
0067CB:0128: lNumber1 = lNumber1 != 14;
=====》长度不等于14 ?
0067DD:0022: if (lNumber1 = 0) then
=======》 No,等于14,OK下一步检查
goto label192;
endif;
====》Yes,不等于14,返回0,这里可以知道输入的字符共12位,因为还含两个“-”
0067EB:012F: return(0);
label192: //Ref: 0067DD
=====》取第一个框里的字符
0067F8:0030: StrSub(lString1, pString0, 0, 4);
=====》取第二个框里的字符
00680A:0030: StrSub(lString2, pString0, 5, 6);
=====》取第三个框里的字符
00681C:0030: StrSub(lString3, pString0, 12, 2);
00682E:0124: lString6 = lString1 + lString2;
006839:0124: lString0 = lString6 + lString3;
====》以上代码合并输入的内容,去掉“-”
006844:0031: StrFind(lString0, "-");
=====》还含有“-”吗?
00684D:0128: lNumber1 = LAST_RESULT >= 0;
00685F:0022: if (lNumber1 = 0) then
====》No,不含了,OK继续检查
goto label193;
endif;
====》还含“-”,返回0,由此看出我们输入的字符不可含有“-”
00686D:012F: return(0);
====》现在开始装载UTILITY.dll了
label193: //Ref: 00685F
00687A:0125: lString5 = SUPPORTDIR ^ "UTILITY.dll";
006890:00B2: UseDLL(lString5);
006895:0021: lNumber1 = LAST_RESULT;
00689D:0128: lNumber1 = lNumber1 = 0;
0068AF:0022: if (lNumber1 = 0) then
goto label194;
endif;
======》调用UTILITY.dll的DigitCheck来检查
0068BD:00B4: UTILITY.DigitCheck(lString0);
0068C5:0021: lNumber0 = LAST_RESULT;
0068CD:00B3: UnUseDLL(lString5);
label194: //Ref: 0068AF
0068D6:0128: lNumber1 = lNumber0 = 1;
0068E8:0022: if (lNumber1 = 0) then
goto label195;
endif;
0068F6:012F: return(1);
0068FF:002C: goto label196;
OK,至此我们已经知道它如何进行序列号检查的,首先进行ValidCookie,通过则检查长度,长度也通过进行最后的DigitCheck。
我们现在可以把上面用来检查的两个动态库搞过来反汇编,慢慢读程序,我现在就不这样做了,我直接用TRW2000了,不要installshiled防TRW2000哦。
老一套了,用hmemcpy中断,几个F12来到此处:
017F:01541C44 LEA EAX,[ESP+0C]
017F:01541C48 PUSH EAX
017F:01541C49 PUSH DWORD 01555820
017F:01541C4E CALL 0154AAA0
在这里我们来个D EAX看看,发现是第一个框里的前三位数字,其实往上看看我们就可以看到前三个数字被移到ESP+0C处的代码。它是先移到ESP+10处,然后把ESP减4,POP一个值了。不就是用ESP+0C来引用吗。
再D 01555820,发现是许多数字组合,再跟进去,发现0154AAA0是用来判断EAX的内容是不是在01555820中的某个数字组合中。
下面还有几处,只要有一处找到,就可以了。
因此可以知道前三个数字必须在这些数字组合中,具体的是:
230 400 401 410 411 420 421 430 431 480 481 510 930 931 950 951 ==》第一处
231 401 411 421 431 481 511 931 951 ===》第二处,一下还有几处全部没有,也就是说它现在只使用两处,下面的几处可能是保留给将来版本使用。
好了,现在再随便挑一个,重新输入再进入,(当然也可以直接改了)
来到此处:
017F:01541CA1 CALL 0154A5F0
关键所在,F8进入。
017F:0154A64E PUSH DWORD 01556C20
017F:0154A653 CALL `KERNEL32!LoadLibraryA`
017F:0154A659 MOV ESI,EAX
017F:0154A65B TEST ESI,ESI
017F:0154A65D JNZ 0154A693
====》装载UTILITY.dll
。。。。。
017F:0154A693 PUSH DWORD 01554588
017F:0154A698 PUSH ESI
017F:0154A699 CALL `KERNEL32!GetProcAddress`==》获取DigitCheck入口
017F:0154A69F TEST EAX,EAX
017F:0154A6A1 JZ 0154A6B1
017F:0154A6A3 LEA ECX,[ESP+0C]
017F:0154A6A7 PUSH ECX
017F:0154A6A8 CALL EAX ======》此处进入DigitCheck了!!!!!
017F:0154A6AA ADD ESP,BYTE +04
进入017F:0154A6A8 CALL EAX
。。。。。。
017F:01BC1136 CALL 01BC11D0
=====》此处功能是查表求得8个数字(包含对非数字的特殊处理)
017F:01BC113B CALL 01BC1280
=====》利用上面的8个数字,再查表得8个数字。
。。。。。。
=====》01BC91B0处存放的是上面求得的8个数字
017F:01BC114A MOV AL,[ECX+01BC91B4]===》后四位
017F:01BC1150 MOV DL,[ECX+01BC91B0]===》前四位
017F:01BC1156 XOR AL,DL ===》先XOR ECX+4与ECX处数字(ECX从0到3)
017F:01BC1158 MOV DL,[01BC91B7] ===》最后一位
017F:01BC115E OR AL,DL ====》 再OR最后一位
017F:01BC1160 OR AL,30===》再OR 0x30
017F:01BC1162 CMP AL,39 ===》判断是否为数字
017F:01BC1164 MOV [ECX+01BC91B8],AL
017F:01BC116A JNG 01BC1174
017F:01BC116C ADD AL,07 ===》 加7转为字母(A-Z)
017F:01BC116E MOV [ECX+01BC91B8],AL
017F:01BC1174 MOV AL,[ECX+01BC91B8]
017F:01BC117A MOV DL,[ECX+01BC9188]
017F:01BC1180 CMP AL,DL ====》与输入的后四位比较
017F:01BC1182 JZ 01BC118A
017F:01BC1184 OR AL,20 ===》不分大小写
017F:01BC1186 CMP AL,DL
017F:01BC1188 JNZ 01BC119C
017F:01BC118A INC ECX
017F:01BC118B CMP ECX,BYTE +04
017F:01BC118E JL 01BC114A
017F:01BC1190 MOV [01BC91AC],ECX
017F:01BC1196 MOV EAX,01
017F:01BC119B RET
至此,我们完全清楚它干什么了,我们可以在017F:01BC1180 中断。
每次修改DL让它与AL相等,并几下AL值四次AL的值就是正确的后四位。
也就是说它根据我们输入的东西,判一下前三位,然后进行计算,算出后四位,再与输入的后四位比较,正确,则通过。
因而,也就有了序列码生成机(不知可有更好的名字,因为它不能叫做注册机了)的概念。
代码如下:(仅仅要你输入前八位数值,不带“-”)
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[])
{
unsigned int tab[8][10] = {
{15,1,11,3,8,4,13,7,12,0},
{10,12,1,8,2, 0 ,9, 15, 5, 11},
{9 ,5, 12, 2, 7, 6, 15, 4 , 14, 10},
{3, 4, 12, 11,1, 0, 13 ,8, 0, 14},
{13 ,1, 6,11 ,8 ,10 ,14 ,4,3, 12},
{7,11,6,10,5,9,4,8,0,3},
{0,12,3,15,10,8,2,12,4,6},
{9, 5, 13, 1,3,11,12 ,4, 2 ,8}
} ; //索引表
char *fthree[] ={
"230" ,"231","400","401","410","411" ,"420",
"421", "430", "431",
"480", "481","510","511","930","931",
"950","951"
}; //前三个字符范围
unsigned char fthreelen = 18;
char regcode[4],getcode[80];
int i,j;
unsigned int itmp;
unsigned int code[8] ={0,0,0,0,0,0,0,0} ;
printf("SoftIce4.5 for Win9x serial number Generater\n");
printf("Written by Leafred\n");
printf("Http://leafred.126.com/\n");
printf("\nPlease Input the initial 8 letters:\n");
do {
gets(getcode);
if(strlen(getcode) != 8)
printf("Please Input the initial 8 letters:\n");
else
break;
} while(1) ;
for(i=0 ;i < fthreelen ; i++)
if(! strncmp(getcode,fthree[i],3)) break;
if(! (i < fthreelen)){
printf("\nFirst three letters must in:\n");
for(i=0;i< fthreelen;i++)
printf("%s ",fthree[i]);
printf("\n");
return 0 ;
}
strupr(getcode);
//第一个CALL
for(i=0;i<8;i++){
itmp = getcode[i] ;
if(itmp >='0' && itmp <= '9')
itmp = 132;
else if(itmp >= 'A' && itmp <=
'F')
itmp = 129;
else if(itmp >= 'G' && itmp <=
'Z')
itmp = 1;
else if(itmp >= 'a' && itmp <=
'f')
itmp = 130;
else if(itmp >= 'g' && itmp <=
'z')
itmp = 2;
else
itmp = 16;
if(!(itmp & 4))break;
code[i] = getcode[i] & 0xf;
}
//对前8各输入有字母处理
if(i < 8)
{
i--;
j = 7;
do{
if(i>=0){
code[j]=code[i];
i--;
}
else
code[j]
= 0;
j--;
if(j < 0)
break;
}while (1) ;
}
//查表取值
for(i=0;i<8;i++)
code[i] = tab[i][code[i]];
//最后一步
for(i=0;i<4;i++){
regcode[i] = code[i] ^ code[i+4];
regcode[i] |= code[7];
regcode[i] |= 0x30 ;
if(regcode[i] > 0x39)regcode[i] += 7;
}
printf("Your serial number is:\n");
printf("%c%c%c%c-%s%c%c-%c%c\n",getcode[0],getcode[1],getcode[2],getcode[3],getcode+4,regcode[0],regcode[1],regcode[2],regcode[3]);
return 0;
}
- 标 题:SoftIce45_for_win9x的安装序列码获取及序列码生成机编写(无实际意义,纯粹好玩) (9千字)
- 作 者:Leafred
- 时 间:2001-5-23 8:34:55
- 链 接:http://bbs.pediy.com