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;
}
=======================全文完=======================
XoftSpy 4.13的注册算法分析的更多相关文章
- 1-3 Postman 注册账号与登录
1.为什么要注册postman账号 注册postman账号是免费的.当注册并登陆一个postman账号后,用户可以获得如下权限. (1)同步和备份历史,集合,环境,和预置头. (2)可以轻松的处理来自 ...
- C# 系统应用之通过注册表获取USB使用记录(一)
该文章是“个人电脑历史记录清除软件”项目的系统应用系列文章.前面已经讲述了如何清除IE浏览器的历史记录.获取Windows最近访问文件记录.清除回收站等功能.现在我需要完成的是删除USB设备上的U盘. ...
- 【转】IAR for STM8介绍、下载、安装与注册
Ⅰ.写在前面 本文讲述的内容是IAR for STM8(EWSTM8)的介绍.下载.安装与注册,其安装.注册过程和IAR for ARM类似,如果需要了解IAR for ARM相关的文章,可以到我博客 ...
- IAR for STM8介绍、下载、安装与注册--转
Ⅰ.写在前面 本文讲述的内容是IAR for STM8的介绍.下载.安装与注册,其安装.注册过程和IAR for ARM类似,如果需要了解IAR for ARM相关的文章,可以到我博客,或微信公众号查 ...
- 3DMax下载与安装(注册机为网上收集,仅供学习与研究,支持正版)
3DS Max 全称3D Studio Max,是Autodesk公司开发的三维动画制作和渲染软件(Autodesk AutoCAD 2012也是Autodesk公司的软件产品) 3DS Max广泛应 ...
- SpringCloud 源码系列(1)—— 注册中心 Eureka(上)
Eureka 是 Netflix 公司开源的一个服务注册与发现的组件,和其他 Netflix 公司的服务组件(例如负载均衡.熔断器.网关等)一起,被 Spring Cloud 整合为 Spring C ...
- 测试脚本配置、ORM必知必会13条、双下划线查询、一对多外键关系、多对多外键关系、多表查询
测试脚本配置 ''' 当你只是想测试django中的某一个文件内容 那么你可以不用书写前后端交互的形式而是直接写一个测试脚本即可 脚本代码无论是写在应用下的test.py还是单独开设py文件都可以 ' ...
- ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式
由于ASP.NET Core应用是一个同时处理多个请求的服务器应用,所以在处理某个请求过程中抛出的异常并不会导致整个应用的终止.出于安全方面的考量,为了避免敏感信息的外泄,客户端在默认的情况下并不会得 ...
- 十三. JEB破解三
一.启动环境 JEB 2.0Demo版本启动后出现这样一个界面 当前环境算出的许可证数据 48000000BDEAE192E4CEFC82B34C2AC67F3A85DF5C0E262E421772C ...
随机推荐
- unity3d遍历出Cube里面所有子对象
cube目录下有n个cube,可不可以一下子遍历出所有的对象,而不用一个一个的find?find(“Cube1”) 1.foreach(Transform ts in cube) 2.cub ...
- php5.4window下连接mssql
第一步 下载 http://www.microsoft.com/en-us/download/details.aspx?id=20098 [PHP_PDO_SQLSRV] extension=php_ ...
- 在Ubuntu下配置Apache多域名服务器
1. 目标: 在本机 实现访问不同域名 可以访问不同的目录. 即:访问a.com 进入 /var/www/a 目录下的程序,访问b.com 进入/var/www/b目录下的程序. 2.遇到的问题: / ...
- Win7中修改Chrome浏览器缓存文件目录
方法有两种: 第一种: 在Windows 7下可以用mklink命令把Chrome浏览器的缓存位置设置为自己需要的文件夹路径. Chrome浏览器默认的缓存文件位于: CC:\Users\登录用户名\ ...
- [Guava学习笔记]Basic Utilities: Null, 前置条件, Object方法, 排序, 异常
我的技术博客经常被流氓网站恶意爬取转载.请移步原文:http://www.cnblogs.com/hamhog/p/3842433.html,享受整齐的排版.有效的链接.正确的代码缩进.更好的阅读体验 ...
- JetBRAINS 系列注册机
转载说明 本篇文章可能已经更新,最新文章请转:http://www.sollyu.com/1118/ 说明 这个是一国外的大牛写的一个 JetBRAINS 系列注册机,他里面包含了很多,我就不打字了. ...
- 2014-10 u-boot make xxx_defconfig 过程分析
/** ****************************************************************************** * @author Maox ...
- 从一个乘法来分析C语言
昨天碰到一个很奇怪的问题,首先来看这段代码: #include<stdio.h> int main(int argc,char *argv[]) { ; ; long long res1 ...
- HACMP 学习笔记--转载自wangjialiang-csdn博客
An41 教程: Ha: 初始阶段的规划最重要 第一部分:概念和模型 Ha 目标:掩盖和消除计划和非计划的宕机 Eliminate SPOF :消除单节点故障, single point of fai ...
- 锋利的qjuey-ajax
jquery 中的ajax load方法主要获取web服务器上静态数据 1 load方法载入HTML文档 load(url [,data] [,callback]) $(function(){ $ ...