zoukankan      html  css  js  c++  java
  • XoftSpy 4.13的注册算法分析

    【标题】XoftSpy 4.13的注册算法分析
    【作者】forever[RCT]
    【语言】VC
    【工具】ida4.6,ollydbg1.1
    【正文】
          这个软件的算法很简单,正好拿来做逆向分析。我就会捏软柿子。呵呵。
          因为这个软件注册失败会弹出一个对话框来提示您,所以在ollydbg中在函数MessageBox上下断点很容易就找到软件的关键算法处。这个软件装载时间很长,所以如果您也要分析它,建议用ollydbg来attach一下。我就是这么的。:)
          其他的都省略了。这里只分析一下关键的算法部分:
          
          
    .text:00417690 sub_417690      proc near 
    .text:00417690                                
    .text:00417690
    .text:00417690 var_28          = dword ptr -28h
    .text:00417690 var_24          = dword ptr -24h
    .text:00417690 var_20          = dword ptr -20h
    .text:00417690 var_1C          = dword ptr -1Ch
    .text:00417690 var_18          = dword ptr -18h
    .text:00417690 var_14          = dword ptr -14h
    .text:00417690 var_10          = dword ptr -10h
    .text:00417690 var_C           = dword ptr -0Ch
    .text:00417690 var_4           = dword ptr -4
    .text:00417690 arg_myName      = dword ptr  4
    .text:00417690 arg_myCode      = dword ptr  8
    .text:00417690
    .text:00417690                 push    0FFFFFFFFh
    .text:00417692                 push    offset unknown_libname_428
    .text:00417697                 mov     eax, large fs:0
    .text:0041769D                 push    eax
    .text:0041769E                 mov     large fs:0, esp
    .text:004176A5                 sub     esp, 1Ch
    .text:004176A8                 push    ebx
    .text:004176A9                 push    esi
    .text:004176AA                 push    edi
    .text:004176AB                 mov     eax, [esp+34h+arg_myName]
    .text:004176AF                 push    offset byte_48FA48  //这里是0
    .text:004176B4                 push    eax
    .text:004176B5                 mov     [esp+3Ch+var_4], 1
    .text:004176BD                 call    __mbscmp
    .text:004176C2                 add     esp, 8
    .text:004176C5                 test    eax, eax
    .text:004176C7                 jz      loc_4178F5   
                   //注册名为空则退出
    .text:004176CD                 mov     ecx, [esp+34h+arg_myCode]
    .text:004176D1                 push    offset byte_48FA48
    .text:004176D6                 push    ecx
    .text:004176D7                 call    __mbscmp
    .text:004176DC                 add     esp, 8
    .text:004176DF                 test    eax, eax
    .text:004176E1                 jz      loc_4178F5   
                   //注册码为空则退出
    .text:004176E7                 mov     edx, [esp+34h+arg_myCode]
    .text:004176EB                 cmp     dword ptr [edx-8], 21
    .text:004176EF                 jl      loc_4178F5   
                   //注册码长度小于21位则退出
    .text:004176F5                 lea     eax, [esp+34h+var_18]
    .text:004176F9                 push    11
    .text:004176FB                 push    eax
    .text:004176FC                 lea     ecx, [esp+3Ch+arg_myCode]
    .text:00417700                 call    ?Left@CString@@QBE?AV1@H@Z ; CString::Left(int)
    .text:00417705                 mov     ecx, [esp+34h+var_18]  
                   //取注册码左边11个字符
    .text:00417709                 xor     esi, esi              
                   //mov指令执行后ecx是字符串的地址
    .text:0041770B                 xor     edx, edx               
                   //这是指针和变量的区别,变量一般用lea
    .text:0041770D                 mov     byte ptr [esp+34h+var_4], 2
    .text:00417712                 mov     [esp+34h+var_14], esi
    .text:00417716                 xor     eax, eax
    .text:00417718
    .text:00417718 loc_417718:                             
    .text:00417718                 movsx   edi, byte ptr [eax+ecx] 
                   //取一个字符(符号扩展的,所以edi是整型数)
    .text:0041771C                 add     edx, edi                
                   //累加到edx
    .text:0041771E                 inc     eax                     
                   //索引加1
    .text:0041771F                 cmp     eax, 0Ah                
    .text:00417722                 jle     short loc_417718        
                   //这里用的jle,所以累加11个字节
    .text:00417724                 mov     [esp+34h+var_10], edx   
                   //保存累加和
    .text:00417728                 mov     edx, [esp+34h+arg_myName]
    .text:0041772C                 xor     eax, eax
    .text:0041772E                 mov     ecx, [edx-8]             
                   //这个位置是CString类型的变量的长度
    .text:00417731                 test    ecx, ecx
    .text:00417733                 jle     short loc_417744        
                   //用户名长度小于等于0则跳
    .text:00417735
    .text:00417735 loc_417735:                             
    .text:00417735                 movsx   edi, byte ptr [eax+edx] 
                   //取用户名一个字符
    .text:00417739                 add     esi, edi                
                   //累加到esi
    .text:0041773B                 inc     eax
    .text:0041773C                 cmp     eax, ecx
    .text:0041773E                 jl      short loc_417735        
                   //(注意这里用的jl)
    .text:00417740                 mov     [esp+34h+var_14], esi   
                   //保存用户名累加和
    .text:00417744
    .text:00417744 loc_417744:                            
    .text:00417744                 mov     ecx, [esp+34h+arg_myCode]
    .text:00417748                 push    ebp
    .text:00417749                 lea     edx, [esp+38h+var_28]
    .text:0041774D                 mov     eax, [ecx-8]
    .text:00417750                 lea     ecx, [esp+38h+arg_myCode]
    .text:00417754                 add     eax, -12                 
                   //注册码长度减去12
    .text:00417757                 push    eax
    .text:00417758                 push    edx
    .text:00417759                 call    ?Right@CString@@QBE?AV1@H@Z ; CString::Right(int)
    .text:0041775E                 lea     eax, [esp+38h+var_1C]      
                   //上面是取右半部分,不要左边的12个字符
    .text:00417762                 push    3
    .text:00417764                 push    eax
    .text:00417765                 lea     ecx, [esp+40h+var_28]
    .text:00417769                 mov     byte ptr [esp+40h+var_4], 3
    .text:0041776E                 call    ?Left@CString@@QBE?AV1@H@Z ; CString::Left(int)
    .text:00417773                 mov     ecx, [esp+38h+var_1C]    
                   //取右半部分的左边3个字符
    .text:00417777                 mov     byte ptr [esp+38h+var_4], 4
    .text:0041777C                 push    ecx             ; char *
    .text:0041777D                 call    _atoi                    
                   //转换成整数
    .text:00417782                 cdq
    .text:00417783                 add     esp, 4
    .text:00417786                 sub     eax, edx
    .text:00417788                 lea     edx, [esp+38h+var_20]
    .text:0041778C                 mov     esi, eax                
                   //结果放在这里
    .text:0041778E                 push    3
    .text:00417790                 push    3
    .text:00417792                 push    edx
    .text:00417793                 lea     ecx, [esp+44h+var_28]
    .text:00417797                 sar     esi, 1                  
                   //除以2(符号右移1位)
    .text:00417799                 call    ?Mid@CString@@QBE?AV1@HH@Z ; CString::Mid(int,int)
    .text:0041779E                 mov     eax, [esp+38h+var_20]   
                   //依次再取3个字符
    .text:004177A2                 mov     byte ptr [esp+38h+var_4], 5
    .text:004177A7                 push    eax             ; char *
    .text:004177A8                 call    _atoi                   
                   //转换成整数
    .text:004177AD                 cdq
    .text:004177AE                 add     esp, 4
    .text:004177B1                 and     edx, 3
    .text:004177B4                 add     eax, edx
    .text:004177B6                 lea     ecx, [esp+38h+var_24]
    .text:004177BA                 push    3
    .text:004177BC                 mov     edi, eax               
                   //结果放在这里
    .text:004177BE                 push    ecx
    .text:004177BF                 lea     ecx, [esp+40h+var_28]
    .text:004177C3                 sar     edi, 2                  
                   //除以4(符号右移2位)
    .text:004177C6                 call    ?Right@CString@@QBE?AV1@H@Z ; CString::Right(int)
    .text:004177CB                 mov     edx, [esp+38h+var_24]   
                   //取右半部分最右边3位
    .text:004177CF                 push    edx             ; char *
    .text:004177D0                 call    _atoi                   
                   //转换成整数
    .text:004177D5                 mov     ecx, eax
    .text:004177D7                 mov     eax, 55555556h          
                   //乘以55555556h
    .text:004177DC                 imul    ecx
    .text:004177DE                 mov     eax, edx                
                   //模 2的32次方
    .text:004177E0                 add     esp, 4
    .text:004177E3                 shr     eax, 1Fh               
                   //处理符号位
    .text:004177E6                 add     edx, eax
                                                            
                   //上面实际上是除以3,我们看看怎么计算的:
                   // ecx * 55555556h / 2^32 
                   //= ecx * 1431655766 / 4294967296
                   //= ecx / 2.9999999986030161387273035297509 
                   //= ecx / 3
                                                            
    .text:004177E8                 mov     eax, [esp+38h+arg_myName] 
    .text:004177EC                 mov     ebx, edx                 
                   //结果放在这里
    .text:004177EE                 movsx   ecx, byte ptr [eax]      
                   //取用户名一个字节到ecx
    .text:004177F1                 mov     ebp, [eax-8]             
    .text:004177F4                 cmp     esi, ecx                 
                   //和第一个整数比较
    .text:004177F6                 movsx   edx, byte ptr [eax+1]    
                   //取用户名第2个字符到edx
    .text:004177FA                 movsx   eax, byte ptr [eax+ebp-1]
                   //取用户名最后一个字节到eax
    .text:004177FF                 pop     ebp
    .text:00417800                 jnz     loc_4178AF
    .text:00417806                 cmp     edi, edx             
                   //第2个字符和第2个整数比较
    .text:00417808                 jnz     loc_4178AF
    .text:0041780E                 cmp     ebx, eax             
                   //最后一个字符和第3个整数比较
    .text:00417810                 jnz     loc_4178AF
    .text:00417816                 mov     eax, [esp+34h+var_14]    
                   //用户名累加和
    .text:0041781A                 mov     ecx, 0Ah
    .text:0041781F                 cdq
    .text:00417820                 idiv    ecx
    .text:00417822                 mov     eax, [esp+34h+var_10]    
                   //注册码左半部分累加和
    .text:00417826                 mov     esi, 0Ah
    .text:0041782B                 mov     ecx, edx    
                   //这个是用户名累加和模10的结果
    .text:0041782D                 cdq
    .text:0041782E                 idiv    esi         
                   //注册码左半部分累加和模10的结果在edx
    .text:00417830                 cmp     edx, ecx    //比较
    .text:00417832                 jnz     short loc_4178AF  
    .text:00417834                 lea     ecx, [esp+34h+var_24]
    .text:00417838                 mov     byte ptr [esp+34h+var_4], 5
    .text:0041783D                 call    ??1CString@@QAE@XZ ; CString::~CString(void)
    .text:00417842                 lea     ecx, [esp+34h+var_20]
    .text:00417846                 mov     byte ptr [esp+34h+var_4], 4
    .text:0041784B                 call    ??1CString@@QAE@XZ ; CString::~CString(void)
    .text:00417850                 lea     ecx, [esp+34h+var_1C]
    .text:00417854                 mov     byte ptr [esp+34h+var_4], 3
    .text:00417859                 call    ??1CString@@QAE@XZ ; CString::~CString(void)
    .text:0041785E                 lea     ecx, [esp+34h+var_28]
    .text:00417862                 mov     byte ptr [esp+34h+var_4], 2
    .text:00417867                 call    ??1CString@@QAE@XZ ; CString::~CString(void)
    .text:0041786C                 lea     ecx, [esp+34h+var_18]
    .text:00417870                 mov     byte ptr [esp+34h+var_4], 1
    .text:00417875                 call    ??1CString@@QAE@XZ ; CString::~CString(void)
    .text:0041787A                 lea     ecx, [esp+34h+arg_myName]
    .text:0041787E                 mov     byte ptr [esp+34h+var_4], 0
    .text:00417883                 call    ??1CString@@QAE@XZ ; CString::~CString(void)
    .text:00417888                 lea     ecx, [esp+34h+arg_myCode]
    .text:0041788C                 mov     [esp+34h+var_4], 0FFFFFFFFh
    .text:00417894                 call    ??1CString@@QAE@XZ ; CString::~CString(void)
    .text:00417899                 pop     edi
    .text:0041789A                 pop     esi
    .text:0041789B                 mov     al, 1
    .text:0041789D                 pop     ebx
    .text:0041789E                 mov     ecx, [esp+28h+var_C]
    .text:004178A2                 mov     large fs:0, ecx
    .text:004178A9                 add     esp, 28h
    .text:004178AC                 retn    8
    .text:004178AF ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪
    .text:004178AF
    .text:004178AF loc_4178AF:                             
    .text:004178AF                 lea     ecx, [esp+34h+var_24]
    .text:004178B3                 mov     byte ptr [esp+34h+var_4], 5
    .text:004178B8                 call    ??1CString@@QAE@XZ ; CString::~CString(void)
    .text:004178BD                 lea     ecx, [esp+34h+var_20]
    .text:004178C1                 mov     byte ptr [esp+34h+var_4], 4
    .text:004178C6                 call    ??1CString@@QAE@XZ ; CString::~CString(void)
    .text:004178CB                 lea     ecx, [esp+34h+var_1C]
    .text:004178CF                 mov     byte ptr [esp+34h+var_4], 3
    .text:004178D4                 call    ??1CString@@QAE@XZ ; CString::~CString(void)
    .text:004178D9                 lea     ecx, [esp+34h+var_28]
    .text:004178DD                 mov     byte ptr [esp+34h+var_4], 2
    .text:004178E2                 call    ??1CString@@QAE@XZ ; CString::~CString(void)
    .text:004178E7                 lea     ecx, [esp+34h+var_18]
    .text:004178EB                 mov     byte ptr [esp+34h+var_4], 1
    .text:004178F0                 call    ??1CString@@QAE@XZ ; CString::~CString(void)
    .text:004178F5
    .text:004178F5 loc_4178F5:                             
    .text:004178F5                 lea     ecx, [esp+34h+arg_myName]
    .text:004178F9                 mov     byte ptr [esp+34h+var_4], 0
    .text:004178FE                 call    ??1CString@@QAE@XZ ; CString::~CString(void)
    .text:00417903                 lea     ecx, [esp+34h+arg_myCode]
    .text:00417907                 mov     [esp+34h+var_4], 0FFFFFFFFh
    .text:0041790F                 call    ??1CString@@QAE@XZ ; CString::~CString(void)
    .text:00417914                 mov     ecx, [esp+34h+var_C]
    .text:00417918                 pop     edi
    .text:00417919                 pop     esi
    .text:0041791A                 xor     al, al
    .text:0041791C                 pop     ebx
    .text:0041791D                 mov     large fs:0, ecx
    .text:00417924                 add     esp, 28h
    .text:00417927                 retn    8
    .text:00417927 sub_417690      endp

    算法总结:

    1.注册码长度大于等于21个字符; 
    2.注册码分左右两部分处理,左边取11个字符,右边取除左边12个字符的所有字符;
    2.用户名累加和模10 和 注册码左边11个字节累加和模10 相等;
    3.注册码右半部分的前3个字符转换成整数和用户名第一个字符比较;
    4.注册码右半部分的接着3个字符转换成整数和用户名第二个字符比较;
    5.注册码右半部分最后3个字符转换成整数和用户名最后一个字符比较;

    /////////////////////////////////////////////////////////////
    //逆向如下://///////////////////////////////////////////////
    /////////////////////////////////////////////////////////////
    BOOL fun1(CString myName,CString myCode)
    {
        CString tmp1,tmp2;
        int iLeftSum,iNameSum;
        int x,y,z;
        int i;
        int iLen;
        
        if(myName.IsEmpty())return FALSE;
        if(myCode.IsEmpty())return FALSE;
        if(myCode.GetLength() < 21)return FALSE;
        
        tmp1 = myCode.Left(11);
        iLen = tmp1.GetLength();
        iLeftSum = 0;
        for(i = 0;i < iLen;i ++)
        {
            iLeftSum += tmp1.GetAt(i);
        }
        
        iLen = myName.GetLength();
        iNameSum = 0;
        for(i = 0;i < iLen;i ++)
        {
            iNameSum += myName.GetAt(i);
        }
        
        tmp1 = myCode.Right(myCode.GetLength() - 12);
        tmp2 = tmp1.Left(3);
        x    = atoi(tmp2);
        x    = x / 2;
        
        tmp2 = tmp1.Mid(3,3);
        y    = atoi(tmp2);
        y    = y / 4;
        
        tmp2 = tmp1.Right(3);
        z    = atoi(tmp2);
        z    = z / 3;
        
        if(x != myName.GetAt(0))return FALSE;
        if(y != myName.GetAt(1))return FALSE;
        if(z != myName.GetAt(myName.GetLength() - 1))return FALSE;
        if(iLeftSum != iNameSum)return FALSE;
        
        return TRUE;
    }

    /////////////////////////////////////////////////////////////
    //注册机算法如下:////////////////////////////////////////////
    /////////////////////////////////////////////////////////////
    CString fun1(const CString myName)
    {
        int i,iLen;
        int iNameSum;
        int iLeftSum;
        char tmp[4];
        char tmp1[12];
        CString myCode;
        
        iNameSum = 0;
        iLen = myName.GetLength();
        for(i = 0;i < iLen;i ++)
        {
            iNameSum += myName.GetAt(i);
        }
        
        memset(tmp1,0,12);
        srand( (unsigned)time( NULL ) );
        for(i = 0;i < 10;i ++)
        {
            tmp1[i] = rand() % 10 + 0x30;
        }
        iLeftSum = 0;
        for(i = 0;i < 10;i ++)
        {
            iLeftSum += tmp1[i];
        }
        
        iLeftSum %= 10;
        iNameSum %= 10; 
           
        tmp1[10] = (iLeftSum >= iNameSum? iLeftSum - iNameSum:iNameSum - iLeftSum);
      if(tmp1[10] <= 7)tmp1[10] += 50;  //保证注册码都是数字
      else tmp1[10] += 40;    

        myCode += tmp1;
      myCode += "-";
        
        memset(tmp,0,4);
        sprintf(tmp,"%03d",myName.GetAt(0)*2);
        myCode += tmp;
        
        memset(tmp,0,4);
        sprintf(tmp,"%03d",myName.GetAt(1)*4);
        myCode += tmp;
        
        memset(tmp,0,4);
        sprintf(tmp,"%03d",myName.GetAt(myName.GetLength() - 1)*3);
        myCode += tmp;
        
        return myCode;
    }

    =======================全文完=======================

  • 相关阅读:
    VUE入门
    搭建内网穿透服务
    nacos集群配置安装
    jenkins入门
    Linux系统管理与自动化运维
    SVN
    JAR包启动
    服务器rm -rf 恢复案例 好文章
    docker入门到放弃
    CentOS7安装图形界面及报错处理
  • 原文地址:https://www.cnblogs.com/milantgh/p/3871508.html
Copyright © 2011-2022 走看看