锦州市广厦电脑维修|上门维修电脑|上门做系统|0416-3905144热诚服务,锦州广厦维修电脑,公司IT外包服务
topFlag1 设为首页
topFlag3 收藏本站
 
maojin003 首 页 公司介绍 服务项目 服务报价 维修流程 IT外包服务 服务器维护 技术文章 常见故障
锦州市广厦电脑维修|上门维修电脑|上门做系统|0416-3905144热诚服务技术文章
[原创] 一款串口调试助手的序列号计算算法分析

作者: 佚名  日期:2018-05-17 06:55:12   来源: 本站整理

本次我花费了大约两个半小时破解了一款名为“Serial Port Utility”的软件(又名友善串口调试助手),该软件的串口调试功能比较强大,今天试着分析了一下其序列号算法,这也是我第一次做序列号分析。 注册成功截图如下:  
    
我们首先使用PEID对程序查壳,结果如下:
 
发现是一个叫做“yoda's Protector v1.02 (.dll,.ocx)-> Ashkbiz Danehkar (h) *”的壳,在网上查询后得知,这个结果有可能是错误的。 于是我们更换了另一个工具“ExeinfoPE”,结果如下:
 
这个软件的结果显示,这个程序没有壳。

我们从软件目录下看到了大量Qt5开头的动态链接库,证明其软件是用Qt5编写的。
    
现在用OD加载程序,观察ASCII字符串,我们会注意到这样一个字符串: 
 
双击定位:
 
其中,经过分析可以得知,eax保存的是Qt独有格式的字符串(输入的序列号字符串),并且偏移地址0x04处是字符串长度,0x0C处是前导说明信息块的字节数,或者说是字符串信息的偏移地址。这一段代码说明,若序列号长度不为0x1D(即29个字符),就会报错。那么我们任意输入一个29字符的字符串,出现以下提示:
 
然后我们定位到具体字符串,结果如下:
 
双击定位到代码:
 
这个代码显然是通过别的地方的代码通过跳转指令跳转过来的(因为上方有一个jmp,顺序执行的流程直接被阻断),我们发现跳转来自004150C0:
 
je成立的条件是,al=0,而在test al,al上方是一条call语句,我们知道函数的返回值通常通过eax寄存器返回,因此可以推得,al来自于函数00439F30的返回值,我们跟进去:
 
发现一条call指令,我们跟进去:
 
可见该函数首先判断长度是否为0x1D(地址0x4399F5处),上方Qt5Core._ZN7QString14trimmed_helperERKS_从名字上就可看出是用于去除字符串两端空白字符的。如果长度不为0x1D,直接返回0(因为004399F3处有一句xor eax,eax等价于mov eax,0)。我们跟着004399F8处的je来到下面:
刚开始的代码都是一些和Qt5内核有关的代码,直接无视,看到下面关键代码:
 
我们注意到这个循环,我发现Qt的程序有一个风格,就是函数传值的时候,不使用push指令,而是直接通过mov去写堆栈。
这段汇编代码等价于下面的代码:
[C++] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
*edi = 0B217808;//Qt字符串对象地址
eax = *edi;
ebx = 0;
esi = 0;
 
do
{
    edx = eax + ebx * 2;//字符串当前字符位置地址计算
    edx += *(eax + 0xC);//加上字符串信息起始偏移地址
    ecx = 0;
    edx = (unsigned short)*edx;
    eax = (short)dl;
 
    if(dx > 0xFF)
    {
        eax = ecx;
    }
 
    ecx = *(ebp - 0x5C);
    sub_00438680(eax);
    esi += eax;//校验和计算
    eax = *edi;
    ebx++;
    ecx = *(eax + 4);
    edx = ecx - 2;
}while(edx > ebx)

我们看一下00438680函数:
 
其中有一个jmp.&libstdc++-6._ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE4findEcj引起了我们的注意,从名称上我猜测是char_trait的find函数,经过百度查询如下:
 
详见:https://msdn.microsoft.com/zh-cn/library/y33bd1yh.aspx
可见,这是一个字符串定位函数,这个call的作用是将在一个字符串中查找某一个字符并返回该字符的索引。
那个字符串经过研究测试是“0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ”。
该函数的作用:如果输入的字符是”-”,那么直接返回0,否则返回索引。
我们回到之前调用该函数的代码,可以发现计算的校验和就是序列号前27个字符对应字符串中的索引之和,除了”-”符号。 我们继续往下看:
 
作者没有删除代码中的调试信息,里面提供了很多信息,这里提醒我们刚才计算的是校验和,我们将字符串最后两个字符按照上面校验和的算法计算,发现这个数值和刚才的校验和正好相等,说明字符串最后两个字符就是用于校验的。
我们往下可以看到大量的信息,这里只挑选一个字段说明:
 
其中,00439F95处的eax是字符串内容开始偏移0x0C处(由00439F78处得到的)的文本(注意该字符串是wchar_t*类型),调用了一个函数,地址位于004386B0,我们跟进去看到如下代码:
    
我们发现该函数和00438680处的函数类似,除了下面多了一条div指令以外,经过分析可以得到,其将会将find函数的返回值对一个参数中指定的值取余数。
我们由00439F7D处的代码,可以看到那个值是9。00439FA0处,把转换后的值保存到了[ebp-0xB0]的位置。
右边的说明提醒我们这个字段是”License Version”,类似的还有”Product Name”,”Product Version”,”Active Mode”,”Language”,”SoftwareType”,”Valid Period”,其中前两个参数的转换后的值分别保存到了[ebp-0xB4]和[ebp-0xB8]处,其它参数的值转换完仅供调试信息输出用。
 
我们继续跟踪到这里,在0043A8A8行附近,可以在右边寄存器窗口eax处看到输出的调试信息(作者居然忘了删除掉调试信息输出代码,看的一清二楚)。
由0043A8CA到0043A8F2的代码我们可知,只有当”License Version”等于3,”Product Name”等于1并且”ProductVersion”不等于2,函数才会返回1表示成功。
我们去网上搜索了一个序列号:
SA56W-UR34V-7KY76-XB31F-HZPAU 
有效期:1年 
可以看到序列号的格式类似于这样,并且我们知道以下信息:
Calculate Sum:390
License Version:3
Product Name:1
Product Version:3
Active Mode:1
Language:1
Software Type:2
Valid Period:2
我们开始尝试修改Software Type的值,发现其值等于2时表示个人版,为3时表示专业版。
然后我们尝试修改Valid Period的值,发现其值等于1时表示一个月,2表示一年,3表示3年,4表示5年,5表示终生。
所以最终序列号是这样的:11111-UR311-85111-11111-1112J
其中“UR311”以及”85”必须固定,其它的随便写,校验码算对,这样出来的序列号一定是专业版终生。
软件下载链接:
链接:https://pan.baidu.com/s/1T_zvD2aUjn-xJrL5CNATVA 密码:zyv9 
另附分析程序:
[C++] 纯文本查看 复制代码
01
56
57
58
59
60
// Serial Port Utility破解.cpp: 定义控制台应用程序的入口点。
//
 
#include "stdafx.h"
 
char *ss = (char *)"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char sn[29];
 
int GetSSN(char ch)
{
char p[2];
p[1] = 0;
p[0] = ch;
return strstr(ss,p) - ss;
}
 
int sndiv(int x,int p)
{
return x % p;
}
 
 
int main()
{
char *str = (char *)"SA56W-UR34V-7KY76-XB31F-HZPAU";
 
//06 - License Version [ebp - 0xB0] = 3 /9
//07 - Product Name [ebp - 0xB4] = 1 /2
//08 - Product Version [ebp - 0xB8] != 2 /5
//09 - Active Mode /3
//0A - Language /5
//0C - Software Type /5
//0D - Valid Period /6
//char *str = (char *)"11111-UR311-81111-11111-1112F";
 
 
int i;
int sum = 0;
 
for(i = 0;i < 29;i++)
{
if(str[i] != '-')
{
sn[i] = GetSSN(str[i]);
}
else
{
sn[i] = 0;
}
}
 
for(i = 0;i < 27;i++)
{
sum += sn[i];
}
 
printf("Calculate Sum:%d\n",sum);
printf("License Version:%d\nProduct Name:%d\nProduct Version:%d\nActive Mode:%d\nLanguage:%d\nSoftware Type:%d\nValid Period:%d\n",sndiv(sn[0x06],9),sndiv(sn[0x07],2),sndiv(sn[0x08],5),sndiv(sn[0x09],3),sndiv(sn[0x0A],5),sndiv(sn[0x0C],5),sndiv(sn[0x0D],6));
return 0;
}


热门文章
  • 机械革命S1 PRO-02 开机不显示 黑...
  • 联想ThinkPad NM-C641上电掉电点不...
  • 三星一体激光打印机SCX-4521F维修...
  • 通过串口命令查看EMMC擦写次数和判...
  • IIS 8 开启 GZIP压缩来减少网络请求...
  • 索尼kd-49x7500e背光一半暗且闪烁 ...
  • 楼宇对讲门禁读卡异常维修,读卡芯...
  • 新款海信电视机始终停留在开机界面...
  • 常见打印机清零步骤
  • 安装驱动时提示不包含数字签名的解...
  • 共享打印机需要密码的解决方法
  • 图解Windows 7系统快速共享打印机的...
  • 锦州广厦电脑上门维修

    报修电话:13840665804  QQ:174984393 (联系人:毛先生)   
    E-Mail:174984393@qq.com
    维修中心地址:锦州广厦电脑城
    ICP备案/许可证号:辽ICP备2023002984号-1
    上门服务区域: 辽宁锦州市区
    主要业务: 修电脑,电脑修理,电脑维护,上门维修电脑,黑屏蓝屏死机故障排除,无线上网设置,IT服务外包,局域网组建,ADSL共享上网,路由器设置,数据恢复,密码破解,光盘刻录制作等服务

    技术支持:微软等