-
-
[旧帖] [原创]Internet Cyclone2.1注册算法分析 0.00雪花
-
发表于: 2011-7-16 11:13 2693
-
从http://www.newhua.com/soft/18462.htm下载的Internet Cyclone2.1。纯练手用的。
软件是delphi写的,没有保护措施。查找字符串可以找到thank you for registering internet cyclone.因此可以直接定位到注册码验证的位置
004B9581 |. 33C0 xor eax, eax
004B9583 |. 55 push ebp
004B9584 |. 68 50974B00 push 004B9750
004B9589 |. 64:FF30 push dword ptr fs:[eax]
004B958C |. 64:8920 mov dword ptr fs:[eax], esp
004B958F |. 8D55 F8 lea edx, [local.2]
004B9592 |. 8B83 00030000 mov eax, dword ptr [ebx+300]
004B9598 |. E8 57D4F8FF call 004469F4 ; * Reference to: Controls.TControl.GetText(TControl):TCaption;
004B959D |. 8D55 FC lea edx, [local.1]
004B95A0 |. 8B83 10030000 mov eax, dword ptr [ebx+310]
004B95A6 |. E8 49D4F8FF call 004469F4 ; * Reference to: Controls.TControl.GetText(TControl):TCaption;
004B95AB |. 8B4D FC mov ecx, [local.1]
004B95AE |. 8B55 F8 mov edx, [local.2]
004B95B1 |. 8BC3 mov eax, ebx
004B95B3 |. E8 90030000 call 004B9948 ; 注册码验证函数
004B95B8 |. 85C0 test eax, eax
004B95BA 0F85 60010000 jnz 004B9720 ;这一行改为nop就爆破了
004B95C0 |. 6A 00 push 0
004B95C2 |. 66:8B0D 60974>mov cx, word ptr [4B9760]
004B95C9 |. B2 02 mov dl, 2
004B95CB |. B8 6C974B00 mov eax, 004B976C ; thank you for registering internet cyclone.
004B95D0 |. E8 1B65F8FF call 0043FAF0 ;成功,messsagebox
004B95D5 |. B2 01 mov dl, 1
004B95D7 |. A1 98DC4600 mov eax, dword ptr [46DC98] ;下面的代码是把用户名和注册码写入到注册表中,每次启动时都会验证
004B95DC |. E8 BB47FBFF call 0046DD9C
004B95E1 |. 8BD8 mov ebx, eax
004B95E3 |. 8B06 mov eax, dword ptr [esi]
004B95E5 |. 8998 88040000 mov dword ptr [eax+488], ebx
004B95EB |. 8BC3 mov eax, ebx
004B95ED |. BA 01000080 mov edx, 80000001
004B95F2 |. E8 8148FBFF call 0046DE78
004B95F7 |. 8B06 mov eax, dword ptr [esi]
004B95F9 |. 8B80 88040000 mov eax, dword ptr [eax+488]
004B95FF |. B9 A0974B00 mov ecx, 004B97A0 ; software\internet cyclone ;注册表项
004B9604 |. 83CA FF or edx, FFFFFFFF
004B9607 |. E8 2C50FBFF call 0046E638
004B960C |. 8B45 F8 mov eax, [local.2]
004B960F |. 50 push eax
004B9610 |. 8B06 mov eax, dword ptr [esi]
004B9612 |. 8B80 88040000 mov eax, dword ptr [eax+488]
004B9618 |. B9 C4974B00 mov ecx, 004B97C4 ; name
004B961D |. BA D4974B00 mov edx, 004B97D4 ; registration
004B9622 |. E8 7151FBFF call 0046E798
004B9627 |. 8B45 FC mov eax, [local.1]
004B962A |. 50 push eax
004B962B |. 8B06 mov eax, dword ptr [esi]
004B962D |. 8B80 88040000 mov eax, dword ptr [eax+488]
004B9633 |. B9 EC974B00 mov ecx, 004B97EC ; serialnumber
004B9638 |. BA D4974B00 mov edx, 004B97D4 ; registration
下面看看注册码验证函数
004B9948 /$ 55 push ebp
004B9949 |. 8BEC mov ebp, esp
004B994B |. 83C4 D4 add esp, -2C
004B994E |. 53 push ebx
004B994F |. 56 push esi
004B9950 |. 57 push edi
004B9951 |. 33DB xor ebx, ebx
004B9953 |. 895D D4 mov [local.11], ebx
004B9956 |. 895D D8 mov [local.10], ebx
004B9959 |. 895D E4 mov [local.7], ebx
004B995C |. 895D E0 mov [local.8], ebx
004B995F |. 895D DC mov [local.9], ebx
004B9962 |. 894D F8 mov [local.2], ecx
004B9965 |. 8955 FC mov [local.1], edx
004B9968 |. 8B45 FC mov eax, [local.1]
004B996B |. E8 CCAFF4FF call 0040493C ; * Reference to: System.@LStrAddRef(void;void):Pointer;
004B9970 |. 8B45 F8 mov eax, [local.2]
004B9973 |. E8 C4AFF4FF call 0040493C ; * Reference to: System.@LStrAddRef(void;void):Pointer;
004B9978 |. 33C0 xor eax, eax
004B997A |. 55 push ebp
004B997B |. 68 FD9A4B00 push 004B9AFD
004B9980 |. 64:FF30 push dword ptr fs:[eax]
004B9983 |. 64:8920 mov dword ptr fs:[eax], esp
004B9986 |. 83CB FF or ebx, FFFFFFFF
004B9989 |. 8D45 F8 lea eax, [local.2]
004B998C |. 50 push eax
004B998D |. 8B45 F8 mov eax, [local.2]
004B9990 |. E8 BFADF4FF call 00404754 ; * Reference to: System.@LStrLen(String):Integer;//注册码长度
004B9995 |. 8BC8 mov ecx, eax
004B9997 |. BA 04000000 mov edx, 4
004B999C |. 8B45 F8 mov eax, [local.2] ; local2:伪码,psw
004B999F |. E8 08B0F4FF call 004049AC ; * Reference to: System.@LStrCopy;
004B99A4 |. 8D45 E4 lea eax, [local.7] ; local7:伪码.substring(从4开始),psw_1。从后面看注册码的前3位没有用,可以为任意值
004B99A7 |. BA 189B4B00 mov edx, 004B9B18 ; ICIDW9XXP03V187。固定的参考字符串,用于生成注册码constr
004B99AC |. E8 83ABF4FF call 00404534 ; * Reference to: System.@LStrLAsg(void;void;void;void);
004B99B1 |. C745 EC 01000>mov [local.5], 1
004B99B8 |. BF 01000000 mov edi, 1
004B99BD |. 8B45 F8 mov eax, [local.2]
004B99C0 |. E8 87AFF4FF call 0040494C ; * Reference to: System.@LStrToPChar(String):PAnsiChar;//类型转换
004B99C5 |. 8BF0 mov esi, eax
004B99C7 |. 8B45 F8 mov eax, [local.2]
004B99CA |. E8 85ADF4FF call 00404754 ; * Reference to: System.@LStrLen(String):Integer;//注册码截取前4位后剩余的长度
004B99CF |. 8945 F4 mov [local.3], eax ; local3:psw_1的长度,用于控制循环,每次-2,对应004B9A94
004B99D2 |. 8B45 E4 mov eax, [local.7] ; local7:固定字符串。constr
004B99D5 |. E8 7AADF4FF call 00404754 ; * Reference to: System.@LStrLen(String):Integer;//内部字符串的长度15
004B99DA |. 8945 E8 mov [local.6], eax ; local6:constr_lenth,固定字符串的长度
004B99DD |. 8B45 E8 mov eax, [local.6]
004B99E0 |. 3B45 F4 cmp eax, [local.3] ; 内部字符串constr长度与截取后的长度比较,取小的值,存在local3中
004B99E3 |. 7E 06 jle short 004B99EB
004B99E5 |. 8B45 F4 mov eax, [local.3]
004B99E8 |. 8945 E8 mov [local.6], eax
004B99EB |> 837D F4 00 cmp [local.3], 0 ; 长度<0;退出了
004B99EF |. 0F8E C7000000 jle 004B9ABC
004B99F5 |> 8A06 /mov al, byte ptr [esi] ; psw_1的指针,从psw_1中取一个字符,命名为a
004B99F7 |. 8BD0 |mov edx, eax
004B99F9 |. 80EA 0A |sub dl, 0A ; 如果每个字符-a==0,处理下一个字符
004B99FC |. 74 0A |je short 004B9A08
004B99FE |. 80EA 03 |sub dl, 3 在-3==0,处理下一个字符
004B9A01 |. 74 05 |je short 004B9A08
004B9A03 |. 80EA 13 |sub dl, 13
004B9A06 |. 75 06 |jnz short 004B9A0E ; 再-13 ==0,处理下一个字符,以上去除了控制字符,即保证注册码中的字符都大于‘0’
004B9A08 |> 46 |inc esi
004B9A09 |. E9 86000000 |jmp 004B9A94
004B9A0E |> E8 61FEFFFF |call 004B9874 ; 查表函数,放到后面看。a=fun()
004B9A13 |. 8945 F0 |mov [local.4], eax
004B9A16 |. 46 |inc esi
004B9A17 |. 8A06 |mov al, byte ptr [esi] ;从psw_1中再取下一个字符,命名为b
004B9A19 |. E8 56FEFFFF |call 004B9874 ; b=fun()
004B9A1E |. 8BD8 |mov ebx, eax
004B9A20 |. 46 |inc esi
004B9A21 |. 8B45 F0 |mov eax, [local.4]
004B9A24 |. C1E0 04 |shl eax, 4 ;a=a<<4
004B9A27 |. 03D8 |add ebx, eax ;b=b+a;
004B9A29 |. 8B45 E4 |mov eax, [local.7]
004B9A2C |. 8B55 EC |mov edx, [local.5] ; local5:局部变量。int值,用于从字符串constr中取字符
004B9A2F |. 0FB64410 FF |movzx eax, byte ptr [eax+edx-1] a= constr[local.5]
004B9A34 |. 33D8 |xor ebx, eax ;b=b^a;
004B9A36 |. FF45 EC |inc [local.5]
004B9A39 |. 8B45 EC |mov eax, [local.5]
004B9A3C |. 3B45 E8 |cmp eax, [local.6]
004B9A3F |. 7E 07 |jle short 004B9A48
004B9A41 |. C745 EC 01000>|mov [local.5], 1
004B9A48 |> 8D45 D8 |lea eax, [local.10]
004B9A4B |. 8BD3 |mov edx, ebx
004B9A4D |. E8 2AACF4FF |call 0040467C ; strFormChar(string,char)
004B9A52 |. 8B55 D8 |mov edx, [local.10]
004B9A55 |. 8D45 E0 |lea eax, [local.8]
004B9A58 |. E8 FFACF4FF |call 0040475C ; StrCat
004B9A5D |. BB 64000000 |mov ebx, 64 ; (initial cpu selection) 从该行到 004B9A92不知道有什么用
004B9A62 |> 8D45 DC |/lea eax, [local.9]
004B9A65 |. 8B55 E0 ||mov edx, [local.8]
004B9A68 |. E8 C7AAF4FF ||call 00404534 ; * Reference to: System.@LStrLAsg(void;void;void;void);
004B9A6D |. B8 0A000000 ||mov eax, 0A
004B9A72 |. E8 5995F4FF ||call 00402FD0 ; 生成一个随机数,0-10?
004B9A77 |. 8B55 FC ||mov edx, [local.1]
004B9A7A |. 8A5402 FF ||mov dl, byte ptr [edx+eax-1] ; 用户名[k-1]
004B9A7E |. 8D45 D4 ||lea eax, [local.11]
004B9A81 |. E8 F6ABF4FF ||call 0040467C ; strFormChar(string,char)
004B9A86 |. 8B55 D4 ||mov edx, [local.11]
004B9A89 |. 8B45 DC ||mov eax, [local.9]
004B9A8C |. E8 07AEF4FF ||call 00404898 ; * Reference to: System.@LStrCmp;
004B9A91 |. 4B ||dec ebx
004B9A92 |.^ 75 CE |\jnz short 004B9A62
004B9A94 |> 836D F4 02 |sub [local.3], 2 ;
004B9A98 |. 8B45 E0 |mov eax, [local.8]
004B9A9B |. 8A4438 FF |mov al, byte ptr [eax+edi-1]
004B9A9F |. 8B55 FC |mov edx, [local.1]
004B9AA2 |. 3A443A FF |cmp al, byte ptr [edx+edi-1] ; 依次比较上面生成的b与用户名中对应位置的字符。
004B9AA6 /75 04 jnz short 004B9AAC
004B9AA8 |. |33DB |xor ebx, ebx
004B9AAA |. |EB 05 |jmp short 004B9AB1
004B9AAC |> \83CB FF |or ebx, FFFFFFFF
004B9AAF |. EB 24 |jmp short 004B9AD5
004B9AB1 |> 47 |inc edi
004B9AB2 |. 837D F4 00 |cmp [local.3], 0
004B9AB6 |.^ 0F8F 39FFFFFF \jg 004B99F5 ;没有处理完注册码,循环
再看看fun()
004B9874 /$ 55 push ebp
004B9875 |. 8BEC mov ebp, esp
004B9877 |. 6A 00 push 0
004B9879 |. 53 push ebx
004B987A |. 8BD8 mov ebx, eax
004B987C |. 33C0 xor eax, eax
004B987E |. 55 push ebp
004B987F |. 68 39994B00 push 004B9939
004B9884 |. 64:FF30 push dword ptr fs:[eax]
004B9887 |. 64:8920 mov dword ptr fs:[eax], esp
004B988A |. 33C0 xor eax, eax
004B988C |. 8AC3 mov al, bl
004B988E |. 83C0 D0 add eax, -30 ; Switch (cases 30..46)
004B9891 |. 83F8 16 cmp eax, 16
004B9894 |. 0F87 84000000 ja 004B991E
004B989A |. 8A80 A7984B00 mov al, byte ptr [eax+4B98A7]
004B98A0 |. FF2485 BE984B>jmp dword ptr [eax*4+4B98BE]
004B98A7 |. 01 db 01 ; 分支 004B98BE 索引表
004B98A8 |. 01 db 01
004B98A9 |. 01 db 01
004B98AA |. 01 db 01
004B98AB |. 01 db 01
004B98AC |. 01 db 01
004B98AD |. 01 db 01
004B98AE |. 01 db 01
004B98AF |. 01 db 01
004B98B0 |. 01 db 01
004B98B1 |. 00 db 00
004B98B2 |. 00 db 00
004B98B3 |. 00 db 00
004B98B4 |. 00 db 00
004B98B5 |. 00 db 00
004B98B6 |. 00 db 00
004B98B7 |. 00 db 00
004B98B8 |. 02 db 02
004B98B9 |. 03 db 03
004B98BA |. 04 db 04
004B98BB |. 05 db 05
004B98BC |. 06 db 06
004B98BD |. 07 db 07
004B98BE |. 1E994B00 dd Internet.004B991E ; 分支表 被用于 004B98A0
004B98C2 |. DE984B00 dd Internet.004B98DE
004B98C6 |. F4984B00 dd Internet.004B98F4
004B98CA |. FB984B00 dd Internet.004B98FB
004B98CE |. 02994B00 dd Internet.004B9902
004B98D2 |. 09994B00 dd Internet.004B9909
004B98D6 |. 10994B00 dd Internet.004B9910
004B98DA |. 17994B00 dd Internet.004B9917
004B98DE |> 8D45 FC lea eax, [local.1] ; Cases 30 ('0'),31 ('1'),32 ('2'),33 ('3'),34 ('4'),35 ('5'),36 ('6'),37 ('7'),38 ('8'),39 ('9') of switch 004B988E
004B98E1 |. 8BD3 mov edx, ebx
004B98E3 |. E8 94ADF4FF call 0040467C ; System.@LStrFromChar(String;String;Char);
004B98E8 |. 8B45 FC mov eax, [local.1]
004B98EB |. E8 C0F3F4FF call 00408CB0 ; SysUtils.StrToInt(AnsiString):Integer;
004B98F0 |. 8BD8 mov ebx, eax
004B98F2 |. EB 2F jmp short 004B9923
004B98F4 |> BB 0A000000 mov ebx, 0A ; Case 41 ('A') of switch 004B988E
004B98F9 |. EB 28 jmp short 004B9923
004B98FB |> BB 0B000000 mov ebx, 0B ; Case 42 ('B') of switch 004B988E
004B9900 |. EB 21 jmp short 004B9923
004B9902 |> BB 0C000000 mov ebx, 0C ; Case 43 ('C') of switch 004B988E
004B9907 |. EB 1A jmp short 004B9923
004B9909 |> BB 0D000000 mov ebx, 0D ; Case 44 ('D') of switch 004B988E
004B990E |. EB 13 jmp short 004B9923
004B9910 |> BB 0E000000 mov ebx, 0E ; Case 45 ('E') of switch 004B988E
004B9915 |. EB 0C jmp short 004B9923
004B9917 |> BB 0F000000 mov ebx, 0F ; Case 46 ('F') of switch 004B988E
004B991C |. EB 05 jmp short 004B9923
004B991E |> BB 07000000 mov ebx, 7 ; Default case of switch 004B988E
004B9923 |> 33C0 xor eax, eax
004B9925 |. 5A pop edx
004B9926 |. 59 pop ecx
004B9927 |. 59 pop ecx
004B9928 |. 64:8910 mov dword ptr fs:[eax], edx
004B992B |. 68 40994B00 push 004B9940
004B9930 |> 8D45 FC lea eax, [local.1]
004B9933 |. E8 64ABF4FF call 0040449C ; * Reference to: System.@LStrClr(void;void);
004B9938 \. C3 retn
根据传入的字符,返回一个字符。具体就是把字符0~f,返回他们的16进制的int值。其它字符,返回数字7
写成代码
int[] num = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf };
int dealNum ( char ch )
{
int tmp = ch - '0';
if (tmp >= 0 && tmp < 16)
return num[tmp];
else
return 7;
}
注册码验证算法 f(注册码)=用户名,这里的比较是逐个字符的比较。具体过程
1、去掉注册码的前三位,得到新的注册码psw_1
2、取psw_1的长度和内部使用的字符串constr="ICIDW9XXP03V187"的长度中的小值,做为循环条件maxlen。也就是说注册码长度最大18位就可以了,超过18位也只处理前18位
////////////开始循环处理。i=0;i<maxlen;i++
3、从注册码中取前2个字符,分别为a,b; 这里会对a进行处理,要求a>='0'。如果不满足去掉psw_1的前1位,到步骤3
4、用函数dealNum处理a,b得到int值
5、a = a << 4;
b += a;
a = constr[count1]; 其中count1从0开始,每次加1。当count1>constr长度时,令count1=1;重新开始计数
count1++;
b = b ^ a;
6、判断(char)b ?= 用户名[i] 。相等,执行步骤7继续处理下一个,不等注册失败程序退出。
7、再去掉psw_1的前2位,到步骤3
//////////////循环结束
根据注册码生成用户名的代码(C#)
const string constr="ICIDW9XXP03V187";
static int[] num = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf };
static int dealNum ( char ch )
{
int tmp = ch - '0';
if (tmp >= 0 && tmp < 16)
return num[tmp];
else
return 7;
}
private static void GetName ()
{
string strpsw = "0123456";// 注册码
string name = "";
string strpsw_1 = strpsw.Substring ( 3 );
int circle = strpsw_1.Length > constr.Length ? constr.Length : strpsw_1.Length;
int count = 0;
int count1 = 0;
while (circle > 0)
{
if (count > circle)
count = 1;
if (strpsw_1[count] - '0' < 0)
{
circle--;
continue;
}
int a = dealNum ( strpsw_1[count] );
count++;
int b = dealNum ( strpsw_1[count] );
count++;
a = a << 4;
b += a;
a = constr[count1];
count1++;
b = b ^ a;
name += ( (char)b ).ToString ();
circle--;
}
}
根据用户名生成注册码的方法
int pswlen = 0;
int count_constr = 0;
string psw = "012";
while ((pswlen++)<name.Length)
{
if (count_constr >= 15)
count_constr = 1;
int a = constr[count_constr];
int c = name[pswlen];
c = c ^ a;
int b = c % 16;
a = c / 16;
psw += reDealNum ( a );
psw += reDealNum ( b );
count_constr++;
}
这种方法会生成很多控制字符,在注册码框里无法输入,不知道该怎么解决。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
- [求助]系统时间相关的断点 2125
- 如何分析文件的结构,文件内容没有加密 2093
- [原创]mp4格式转换器注册算法分析,顺便请教个问题 2819
- [原创]Internet Cyclone2.1注册算法分析 2694
- [求助]用来练手的软件都是怎么找到的? 1283