【详细过程】:ComExplorer的注册算法分析
【文章作者】: chimney
【软件名称】: ComExplorer
【保护方式】: 密码
【使用工具】: OD
【操作平台】: winxp
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
     最近整理硬盘的时候找到了这个两年前写的笔记,于是整理了下。算法很简单给新手看看。大侠飘过!
   
【详细过程】
  bpx GetWindowTextA 断下N次后注册界面出现。输入假的注册名和注册码后F9.断在

代码:
  
  004328B4  |.  FF7424 08     PUSH DWORD PTR SS:[ESP+8]                ; |Buffer
  004328B8  |.  FF71 1C       PUSH DWORD PTR DS:[ECX+1C]               ; |hWnd
  004328BB  |.  FF15 D4044500 CALL DWORD PTR DS:[<&USER32.GetWindowTex>; \GetWindowTextA   ; 断在这
  004328C1  |.  EB 12         JMP SHORT comexp.004328D5
  004328C3  |>  FF7424 08     PUSH DWORD PTR SS:[ESP+8]
  004328C7  |.  8B10          MOV EDX,DWORD PTR DS:[EAX]
  004328C9  |.  8BC8          MOV ECX,EAX
  004328CB  |.  FF7424 08     PUSH DWORD PTR SS:[ESP+8]
  004328CF  |.  FF92 84000000 CALL DWORD PTR DS:[EDX+84]
  004328D5  \>  C2 0800       RETN 8
  
  F8往下走RETN 后来到
  
  00408F07   .  68 FF000000   PUSH 0FF
  00408F0C   .  68 68994600   PUSH comexp.00469968                     ;  ASCII "xmbreeze"
  00408F11   .  8D8E A8040000 LEA ECX,DWORD PTR DS:[ESI+4A8]
  00408F17   .  E8 8D990200   CALL comexp.004328A9                     ;  取得输入用户名,放入ESI+4A8,EAX为用户名位数
  00408F1C   .  68 FF000000   PUSH 0FF
  00408F21   .  68 689A4600   PUSH comexp.00469A68                     ;  ASCII "5211314567"
  00408F26   .  8D8E 6C040000 LEA ECX,DWORD PTR DS:[ESI+46C]
  00408F2C   .  E8 78990200   CALL comexp.004328A9                     ;  取得输入注册码,放入ESI+46C,EAX为注册码位数
  00408F31   .  68 68994600   PUSH comexp.00469968                     ;  ASCII "xmbreeze"
  00408F36   .  8D4C24 0C     LEA ECX,DWORD PTR SS:[ESP+C]
  00408F3A   .  E8 02600200   CALL comexp.0042EF41
  00408F3F   .  8B00          MOV EAX,DWORD PTR DS:[EAX]
  00408F41   .  68 98414600   PUSH comexp.00464198                     ; /Arg2 = 00464198 ASCII "UNREGISTERED USER"
  00408F46   .  50            PUSH EAX                                 ; |Arg1
  00408F47   .  E8 33330100   CALL comexp.0041C27F                     ; \comexp.0041C27F
  00408F4C   .  83C4 08       ADD ESP,8
  00408F4F   .  8D4C24 08     LEA ECX,DWORD PTR SS:[ESP+8]
  00408F53   .  85C0          TEST EAX,EAX
  00408F55   .  0F94C3        SETE BL
  00408F58   .  E8 765F0200   CALL comexp.0042EED3
  00408F5D   .  84DB          TEST BL,BL
  00408F5F   .  74 0F         JE SHORT comexp.00408F70
  00408F61   .  6A 01         PUSH 1
  00408F63   .  8BCE          MOV ECX,ESI
  00408F65   .  E8 83A70200   CALL comexp.004336ED
  00408F6A   .  5E            POP ESI
  00408F6B   .  5B            POP EBX
  00408F6C   .  83C4 08       ADD ESP,8
  00408F6F   .  C3            RETN
  00408F70   >  E8 1BFCFFFF   CALL comexp.00408B90                     ;  算法Call跟进
  00408F75   .  85C0          TEST EAX,EAX
  00408F77   .  0F84 AB000000 JE comexp.00409028
  
  跟进后来到:
  
  00408B90  /$  6A FF         PUSH -1
  00408B92  |.  68 88B64400   PUSH comexp.0044B688                     ;  SEH 处理程序安装
  00408B97  |.  64:A1 0000000>MOV EAX,DWORD PTR FS:[0]
  00408B9D  |.  50            PUSH EAX
  00408B9E  |.  64:8925 00000>MOV DWORD PTR FS:[0],ESP
  00408BA5  |.  83EC 08       SUB ESP,8
  00408BA8  |.  57            PUSH EDI
  00408BA9  |.  BF 68994600   MOV EDI,comexp.00469968                  ;  ASCII "xmbreeze"
  00408BAE  |.  83C9 FF       OR ECX,FFFFFFFF
  00408BB1  |.  33C0          XOR EAX,EAX
  00408BB3  |.  F2:AE         REPNE SCAS BYTE PTR ES:[EDI]
  00408BB5  |.  F7D1          NOT ECX
  00408BB7  |.  49            DEC ECX
  00408BB8  |.  83F9 08       CMP ECX,8                               
  00408BBB  |.  894C24 08     MOV DWORD PTR SS:[ESP+8],ECX
  00408BBF  |.  7D 10         JGE SHORT comexp.00408BD1                 ;用户名长度和8比较小于8则结束
  00408BC1  |.  5F            POP EDI
  00408BC2  |.  8B4C24 08     MOV ECX,DWORD PTR SS:[ESP+8]
  00408BC6  |.  64:890D 00000>MOV DWORD PTR FS:[0],ECX
  00408BCD  |.  83C4 14       ADD ESP,14
  00408BD0  |.  C3            RETN

  00408BD1  |>  53            PUSH EBX
  00408BD2  |.  55            PUSH EBP
  00408BD3  |.  56            PUSH ESI
  00408BD4  |.  68 68994600   PUSH comexp.00469968             ;  ASCII "xmbreeze"
  00408BD9  |.  E8 24300200   CALL comexp.0042BC02               ;  将用户名转化为小写
  00408BDE  |.  83C4 04       ADD ESP,4
  00408BE1  |.  8D4C24 10     LEA ECX,DWORD PTR SS:[ESP+10]
  00408BE5  |.  68 FC404600   PUSH comexp.004640FC                     ;  ASCII "6769-" 注册码前5位固定
  00408BEA  |.  E8 52630200   CALL comexp.0042EF41
  00408BEF  |.  33F6          XOR ESI,ESI
  00408BF1  |.  897424 20     MOV DWORD PTR SS:[ESP+20],ESI
  00408BF5  |>  8B2D 483E4600 /MOV EBP,DWORD PTR DS:[463E48]           ;  0123456789    注册算法要查这张表
  00408BFB  |.  83C9 FF       |OR ECX,FFFFFFFF                         ;  /*
  00408BFE  |.  8BFD          |MOV EDI,EBP                             ;      表长度
  00408C00  |.  33C0          |XOR EAX,EAX
  00408C02  |.  F2:AE         |REPNE SCAS BYTE PTR ES:[EDI]
  00408C04  |.  F7D1          |NOT ECX
  00408C06  |.  49            |DEC ECX                                 ;                 */
  00408C07  |.  8BC6          |MOV EAX,ESI
  00408C09  |.  33D2          |XOR EDX,EDX
  00408C0B  |.  8BFD          |MOV EDI,EBP
  00408C0D  |.  F7F1          |DIV ECX
  00408C0F  |.  8B4C24 14     |MOV ECX,DWORD PTR SS:[ESP+14]
  00408C13  |.  8BC6          |MOV EAX,ESI
  00408C15  |.  0FBE1C2A      |MOVSX EBX,BYTE PTR DS:[EDX+EBP]
  00408C19  |.  33D2          |XOR EDX,EDX
  00408C1B  |.  F7F1          |DIV ECX                                 ;  N除以用户名长度,取余,取用户名的第余数位进行计算
  00408C1D  |.  0FBE82 689946>|MOVSX EAX,BYTE PTR DS:[EDX+469968]      ;  /*
  00408C24  |.  8D1440        |LEA EDX,DWORD PTR DS:[EAX+EAX*2]        ;  X=D*ASII(N)  8<=N<=40  ASII(N)//用户名的ASII码
  00408C27  |.  8D0490        |LEA EAX,DWORD PTR DS:[EAX+EDX*4]        ;  */
  00408C2A  |.  8BD6          |MOV EDX,ESI                             ;  /*
  00408C2C  |.  0FAFD6        |IMUL EDX,ESI
  00408C2F  |.  0FAFD6        |IMUL EDX,ESI                            ;  Y=N*N*N*用户名位数
  00408C32  |.  0FAFD1        |IMUL EDX,ECX                            ;  */
  00408C35  |.  03D8          |ADD EBX,EAX                             ;  H=X+ASII(N)
  00408C37  |.  83C9 FF       |OR ECX,FFFFFFFF
  00408C3A  |.  33C0          |XOR EAX,EAX
  00408C3C  |.  03DA          |ADD EBX,EDX                             ;  Z=Y+H
  00408C3E  |.  F2:AE         |REPNE SCAS BYTE PTR ES:[EDI]
  00408C40  |.  F7D1          |NOT ECX
  00408C42  |.  49            |DEC ECX
  00408C43  |.  8BC3          |MOV EAX,EBX
  00408C45  |.  33D2          |XOR EDX,EDX
  00408C47  |.  F7F1          |DIV ECX                              ;  Z/10余数就位第N位的注册码值
  00408C49  |.  8D4C24 10     |LEA ECX,DWORD PTR SS:[ESP+10]
  00408C4D  |.  8A042A        |MOV AL,BYTE PTR DS:[EDX+EBP]
  00408C50  |.  50            |PUSH EAX
  00408C51  |.  E8 34660200   |CALL comexp.0042F28A                    ;  合并注册码
  00408C56  |.  85F6          |TEST ESI,ESI
  00408C58  |.  74 1D         |JE SHORT comexp.00408C77
  00408C5A  |.  8BC6          |MOV EAX,ESI
  00408C5C  |.  33D2          |XOR EDX,EDX
  00408C5E  |.  B9 03000000   |MOV ECX,3
  00408C63  |.  F7F1          |DIV ECX
  00408C65  |.  85D2          |TEST EDX,EDX       ;  若N位3的倍数,则在注册码后面补“-”
  00408C67  |.  75 0E         |JNZ SHORT comexp.00408C77
  00408C69  |.  68 F8404600   |PUSH comexp.004640F8
  00408C6E  |.  8D4C24 14     |LEA ECX,DWORD PTR SS:[ESP+14]
  00408C72  |.  E8 EC650200   |CALL comexp.0042F263              ;  加上个"-"
  00408C77  |>  46            |INC ESI                                 ;  计算下一位
  00408C78  |.  83FE 09       |CMP ESI,9                          ;  N和9比较小于9则计算下一位
  00408C7B  |.^ 0F82 74FFFFFF \JB comexp.00408BF5
  
  00408C81  |.  8B5424 10     MOV EDX,DWORD PTR SS:[ESP+10]
  00408C85  |.  68 689A4600   PUSH comexp.00469A68            ; /假注册码入栈
  00408C8A  |.  52            PUSH EDX                                          ; |真注册码入栈
  00408C8B  |.  E8 EF350100   CALL comexp.0041C27F            ; \真假判断
  
  注册算法:
  码表为:0123456789
  注册名有k位(8<=k<=64)
  计算第N位注册码:假设第N位用户名位的ASII为X(n),第n位码表的ASII位Y(n)
  
  (X(N%k)*D+Y(N%A)+N*N*N*k)/A余数在查码表,结果即为第N位真的注册码
  "6769-"+所有位注册码即为即为最终注册码
  
  
  说的有点模糊,还是看注册算法描述吧:
  
代码:
  
  void CComExplorerDlg::OnOk1() 
  {
    // TODO: Add your control notification handler code here
    char table[10]={'0','1','2','3','4','5','6','7','8','9'};   //码表
    char *first="6769-";                    //注册码的头4位,为固定值
    char name[64];
    char num[64]={0};
    char temp[64]={0};
    GetDlgItemText(IDC_EDIT1,name,64);
    int  iSizeName=strlen(name);
    if(iSizeName!=0)
    {
      for(int i=0;i<iSizeName;i++)
      {
        if(name[i]>='A'&&name[i]<='Z')
          name[i]=name[i]+32;
        
      }
      int j=0;
  
      if(iSizeName<8||iSizeName>64)
        AfxMessageBox("用户名必须大于7位");  
      else{
      for(int i=0;i<=8;i++,j++)
      {
        int itemp=0;
        itemp=name[i%iSizeName]*13+table[i%10]+i*i*i*iSizeName;
        num[i]=table[itemp%10];
        temp[j]=num[i];
        if((i!=0)&&(i%3==0))
        {
          j++;
          temp[j]='-';
  
        }
      }
      strcpy(num,first);
      strcat(num,temp);
      SetDlgItemText(IDC_EDIT2,num);
    
      }
    }
    else
      AfxMessageBox("请输入用户名!用户名必须大于7位。");
  }
 
上传的附件 附件.rar