【标题】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;
}

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

XoftSpy 4.13的注册算法分析的更多相关文章

  1. 1-3 Postman 注册账号与登录

    1.为什么要注册postman账号 注册postman账号是免费的.当注册并登陆一个postman账号后,用户可以获得如下权限. (1)同步和备份历史,集合,环境,和预置头. (2)可以轻松的处理来自 ...

  2. C# 系统应用之通过注册表获取USB使用记录(一)

    该文章是“个人电脑历史记录清除软件”项目的系统应用系列文章.前面已经讲述了如何清除IE浏览器的历史记录.获取Windows最近访问文件记录.清除回收站等功能.现在我需要完成的是删除USB设备上的U盘. ...

  3. 【转】IAR for STM8介绍、下载、安装与注册

    Ⅰ.写在前面 本文讲述的内容是IAR for STM8(EWSTM8)的介绍.下载.安装与注册,其安装.注册过程和IAR for ARM类似,如果需要了解IAR for ARM相关的文章,可以到我博客 ...

  4. IAR for STM8介绍、下载、安装与注册--转

    Ⅰ.写在前面 本文讲述的内容是IAR for STM8的介绍.下载.安装与注册,其安装.注册过程和IAR for ARM类似,如果需要了解IAR for ARM相关的文章,可以到我博客,或微信公众号查 ...

  5. 3DMax下载与安装(注册机为网上收集,仅供学习与研究,支持正版)

    3DS Max 全称3D Studio Max,是Autodesk公司开发的三维动画制作和渲染软件(Autodesk AutoCAD 2012也是Autodesk公司的软件产品) 3DS Max广泛应 ...

  6. SpringCloud 源码系列(1)—— 注册中心 Eureka(上)

    Eureka 是 Netflix 公司开源的一个服务注册与发现的组件,和其他 Netflix 公司的服务组件(例如负载均衡.熔断器.网关等)一起,被 Spring Cloud 整合为 Spring C ...

  7. 测试脚本配置、ORM必知必会13条、双下划线查询、一对多外键关系、多对多外键关系、多表查询

    测试脚本配置 ''' 当你只是想测试django中的某一个文件内容 那么你可以不用书写前后端交互的形式而是直接写一个测试脚本即可 脚本代码无论是写在应用下的test.py还是单独开设py文件都可以 ' ...

  8. ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式

    由于ASP.NET Core应用是一个同时处理多个请求的服务器应用,所以在处理某个请求过程中抛出的异常并不会导致整个应用的终止.出于安全方面的考量,为了避免敏感信息的外泄,客户端在默认的情况下并不会得 ...

  9. 十三. JEB破解三

    一.启动环境 JEB 2.0Demo版本启动后出现这样一个界面 当前环境算出的许可证数据 48000000BDEAE192E4CEFC82B34C2AC67F3A85DF5C0E262E421772C ...

随机推荐

  1. unity3d遍历出Cube里面所有子对象

     cube目录下有n个cube,可不可以一下子遍历出所有的对象,而不用一个一个的find?find(“Cube1”)   1.foreach(Transform ts in cube)   2.cub ...

  2. php5.4window下连接mssql

    第一步 下载 http://www.microsoft.com/en-us/download/details.aspx?id=20098 [PHP_PDO_SQLSRV] extension=php_ ...

  3. 在Ubuntu下配置Apache多域名服务器

    1. 目标: 在本机 实现访问不同域名 可以访问不同的目录. 即:访问a.com 进入 /var/www/a 目录下的程序,访问b.com 进入/var/www/b目录下的程序. 2.遇到的问题: / ...

  4. Win7中修改Chrome浏览器缓存文件目录

    方法有两种: 第一种: 在Windows 7下可以用mklink命令把Chrome浏览器的缓存位置设置为自己需要的文件夹路径. Chrome浏览器默认的缓存文件位于: CC:\Users\登录用户名\ ...

  5. [Guava学习笔记]Basic Utilities: Null, 前置条件, Object方法, 排序, 异常

    我的技术博客经常被流氓网站恶意爬取转载.请移步原文:http://www.cnblogs.com/hamhog/p/3842433.html,享受整齐的排版.有效的链接.正确的代码缩进.更好的阅读体验 ...

  6. JetBRAINS 系列注册机

    转载说明 本篇文章可能已经更新,最新文章请转:http://www.sollyu.com/1118/ 说明 这个是一国外的大牛写的一个 JetBRAINS 系列注册机,他里面包含了很多,我就不打字了. ...

  7. 2014-10 u-boot make xxx_defconfig 过程分析

    /** ****************************************************************************** * @author    Maox ...

  8. 从一个乘法来分析C语言

    昨天碰到一个很奇怪的问题,首先来看这段代码: #include<stdio.h> int main(int argc,char *argv[]) { ; ; long long res1 ...

  9. HACMP 学习笔记--转载自wangjialiang-csdn博客

    An41 教程: Ha: 初始阶段的规划最重要 第一部分:概念和模型 Ha 目标:掩盖和消除计划和非计划的宕机 Eliminate SPOF :消除单节点故障, single point of fai ...

  10. 锋利的qjuey-ajax

    jquery 中的ajax   load方法主要获取web服务器上静态数据 1 load方法载入HTML文档 load(url [,data] [,callback]) $(function(){ $ ...