首页
社区
课程
招聘
[旧帖] [原创]Internet Cyclone2.1注册算法分析 0.00雪花
发表于: 2011-7-16 11:13 2693

[旧帖] [原创]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直播授课

上传的附件:
收藏
免费 7
支持
分享
最新回复 (1)
雪    币: 622
活跃值: (294)
能力值: ( LV13,RANK:410 )
在线值:
发帖
回帖
粉丝
2
CHAR un[256];
CHAR predefined_str[]="ICIDW9XXP03V187";
CHAR prefix_str[]="ICR";	//anything within 3 chars is OK
int len;
printf("your username is: ");
scanf("%s",un);
len=lstrlenA(un);
if (len>lstrlenA(predefined_str)) len=lstrlenA(predefined_str);
printf ("your sn is: %s",&prefix_str);
for (int i = 0;i<len;i++)
{
	un[i]=un[i] ^ predefined_str[i];
	printf ("%02X",un[i]);
}
printf ("\n");

理论上和逻辑上这样是对的,但是C学的不好,编译起来总是有问题。
2011-7-16 14:42
0
游客
登录 | 注册 方可回帖
返回
//