对某软件的逆向分析与注册机编写

  • 前言
  • 没有注册的情况
  • 破解过程
    • 查看软件信息
    • 反编译出源代码
    • 分析源代码
    • 编写注册机
    • 生成注册码

前言

这个软件会获取计算机的硬件信息(包括:CPU序号、MAC地址、硬盘序列号),然后根据这些硬件信息生成一个序列号。使用者把序列号发给软件提供者,然后提供者将注册码(.lic格式文件)发给使用者,使用者利用注册码即可完成注册。

本文将解决以下问题:

  1. 软件如何利用硬件信息生成序列号?(硬件信息序列号的转换关系)
  2. 软件如何根据序列号来判断注册码是否有效
  3. 如何根据序列号(或者硬件信息)得到注册码?

注意:以下内容将屏蔽敏感信息!本文仅做技术研究!

没有注册的情况

首先运行软件:

软件会直接弹出对话框。
点击“确定”后,点击上方菜单栏中的“注册”,点击“获取硬件信息”,此时会自动打开软件安装目录下的“硬件信息采集工具.exe”。


在界面中可以直接看到这个软件读取到的硬件信息:CPU序号、MAC地址、硬盘序列号。
点击“硬件序号”,就得到了序列号

正常流程下,我需要把这个序列号发给软件提供者,然后从提供者那里得到注册码,再点击图2中的“注册”。

破解过程

查看软件信息

同样地,使用ExeinfoPe查看这个软件的编写语言,查看是否加壳。

显然,这个软件使用C#语言语言编写,基于.NET框架。

C#这种把源代码编译为中间代码的语言,可以很轻松地从中间代码上反编译出原始代码!
因此,接下来就可以用C#反编译软件ILSpy为所欲为~

反编译出源代码

ILSpy打开这个软件的主exe程序

在左边视图中可以看到,这个软件有3个命名空间:Quality.Startup、Quality.Startup.Config、Quality.Startup.Properties。

根据这些命名空间下面的类名,很容易猜到注册功能是在UCRegister这个类中实现的!

接下来就是分析UCRegister类的代码。下面展示实现功能的核心代码:

    //流程第1步(笔者注释)private bool Authorize(){try{string text = uiTxtRegisterKey.Text;string text2 = "<License>";string text3 = "</License>";//流程第2步(笔者注释)if (!text.Contains(text3) || !text.Contains(text2)){new Form().ShowErrorDialog("硬件序号异常,请在生成硬件序号时拷贝所有字符信息");return false;}//流程第2步(笔者注释):首尾替换text = text.Replace(text2, "").Replace(text3, "").Trim();//流程第3步(笔者注释)text = ExtendedUtils.Decrypt(text.Substring(0, text.Count() - 4), text.Substring(text.Count() - 4));HardMessage hardMessage = JsonHepler.Json_DeserializeObject<HardMessage>(text);if (hardMessage == null){new Form().ShowErrorDialog("硬件序号异常,请在生成硬件序号时完整拷贝,且不要改动任意字符信息");return false;}EnumHelper.GetEnumDescription(hardMessage.Duration);if (hardMessage.CPUInfo != HardWareInformation.CPUInfo || hardMessage.DiskNo != HardWareInformation.DiskNo || hardMessage.MacAddress != HardWareInformation.MacAddress){new Form().ShowErrorDialog("硬件信息不匹配");return false;}ServerMessage serverMessage = new ServerMessage();serverMessage.Clients = 1;serverMessage.Code = Guid.NewGuid().ToString();serverMessage.Date1 = DateTime.Now;switch (hardMessage.Duration){case EDuration.Forever:serverMessage.Date2 = DateTime.Now.AddYears(100);break;case EDuration.OneMonth:serverMessage.Date2 = DateTime.Now.AddMonths(1);break;case EDuration.ThreeMonth:serverMessage.Date2 = DateTime.Now.AddMonths(3);break;case EDuration.SixMonth:serverMessage.Date2 = DateTime.Now.AddMonths(6);break;case EDuration.OneYear:serverMessage.Date2 = DateTime.Now.AddYears(1);break;case EDuration.TwoYear:serverMessage.Date2 = DateTime.Now.AddYears(2);break;case EDuration.FiveYear:serverMessage.Date2 = DateTime.Now.AddYears(5);break;default:serverMessage.Date2 = DateTime.Now.AddMonths(1);break;}serverMessage.HDMessage = new HardMessage{CPUInfo = HardWareInformation.CPUInfo,DiskNo = HardWareInformation.DiskNo,MacAddress = HardWareInformation.MacAddress};File.WriteAllText(Paths.AppLicfilePath, ExtendedUtils.Encrypts(JsonHepler.Json_SerializeObject(serverMessage)));if (serverMessage != null){skinLabelLastTime.Text = LimitTime(serverMessage);}UIMessageTip.ShowOk("注册完成");skinLabelLastTime.Visible = true;uiLabel.BringToFront();uiLabel.Visible = true;skinLabelLastTime.BringToFront();MainForm.Instance.Text = MainForm.RegisteredTitle;MainForm.Instance.SetStatusMsg(string.Empty);return true;}catch (Exception ex){LogHelper.Error(ex);}return false;}

分析源代码

经分析,读取注册码后的流程为:

  1. 用户指定注册码文件路径后,软件调用uiSymbolButton1_Click方法读取注册码文件,得到注册码text。用户点击“注册”按钮,软件调用Authorize方法(该方法就是上面展示的核心代码);
  2. 如果text中不包含字符串"<License>" 或 “</License>”,则报错。否则,把"<License>" 和 “</License>“都替换成空字符串,也就是删掉text中的”<License>” 和 “</License>”,得到text
  3. 调用ExtendedUtils.Decrypt方法对text解密。密文是text的第0位到倒数第5位(text.Substring(0, text.Count() - 4)),解密密钥是text的最后4位(text.Substring(text.Count() - 4))。解密后的明文也存在text中;
  4. 调用JsonHepler.Json_DeserializeObject方法对text反序列化,得到hardMessage;
  5. 分别提取hardMessage中的CPUInfo字段、DiskNo字段和MacAddress字段(这些字段代表了注册码中的硬件信息),与本机的实际硬件信息对比,如果全部匹配,则注册码有效!

数据的大致流程图如下(注意:hardMessage的字段除了图中的三个以外,根据反编译出来的源代码可知,还有Clients字段):

以上的流程回答了问题2


至此,再来回答问题1
既然软件验证注册码的时候用到Json_DeserializeObject方法来反序列化(字符串→硬件信息)
那么生成注册码的时候就可以用Json_SerializeObject方法来序列化(硬件信息→字符串)


最后回答问题3
对于破解者来说,需要写一个程序(或者称为注册机),输入硬件信息(CPU序号、MAC地址、硬盘序列号),输出注册码
参考上面的流程图,很容易想到,只要把这个流程反过来就行。
既然软件判断注册码是否有效的流程是:
(注册码)去掉两个字符串→解密(得到序列号)→反序列化→对比硬件信息

那么破解者的程序流程就应该是:
输入硬件信息→序列化(得到序列号)→加密→加上两个字符串(得到注册码)!!

参考源代码:
软件使用ExtendedUtils.Decrypt方法解密
那么注册机就可以用ExtendedUtils.Encrypt方法加密

软件使用JsonHepler.Json_DeserializeObject方法反序列化
那么注册机就可以用JsonHepler.Json_SerializeObject方法序列化


其中要注意的一个小细节是:根据源代码可知,解密用的密文在前,4位长度的解密密钥紧跟着密文后面,密文和解密密钥是不重叠的!密文在前解密密钥在后组成字符串。因此,解密用到的密钥不是固定的,完全就是字符串的最后四位

而且在ILSpy中继续查看ExtendedUtils.Decrypt方法的实现方法(如下图),发现是使用DES算法加密,这是一种对称加密算法,加密密钥和解密密钥相等,因此加密密钥是可以任意指定4位字符串的!

编写注册机

接下来就可以编写一个注册机了,这也是最激动人心的时候!

与软件相同,注册机也用C#语言写,使用Winform做一个小窗体界面。
输入:硬件信息(包括CPU序号、MAC地址、硬盘序列号)。
输出:注册码文件。

注意:以下只展示核心代码


首先需要定义一个HardMessage类,作为序列化的依据。

class HardMessage
{public string CPUInfo { get; set; }public string DiskNo { get; set; }public string MacAddress { get; set; }public int Clients { get; set; }
}

然后就到了注册机的核心部分:

//构造硬件信息变量hardmessage,对hardmessage序列化为SerializeMessage
HardMessage hardmessage = new HardMessage { CPUInfo = MyCPUInfo, DiskNo = MyDiskNo, MacAddress = MyMacAddress, Clients = 1 };
string SerializeMessage = JsonHepler.Json_SerializeObject(hardmessage);//加密。明文为SerializeMessage,加密密钥为"abcd"(密钥可任意指定一个长度为4的字符串)
//加密后的密文为EncryptMessage
string EncryptMessage = ExtendedUtils.Encrypt(SerializeMessage, "abcd");//在密文EncryptMessage前加"<License>",后加"</License>"
string License = "<License>" + EncryptMessage + "</License>";//生成注册码文件
StreamWriter sw = new StreamWriter("注册码.lic");
sw.Write(License);
sw.Dispose();

生成注册码

代码写全后,编译运行。


把硬件信息输入后,在注册机所在目录下就生成了“注册码.lic”的文件。
最后,在图2中的界面点击“浏览”,选择这个“注册码.lic”文件,点击注册。。。。。。

Bingo!!

【我爱破解】对某软件的逆向分析与注册机编写相关推荐

  1. 代码保护软件VMP逆向分析虚拟机指令:VMP代码的提取

    VMProtect是一种很可靠的工具,可以保护应用程序代码免受分析和破解,但只有在应用程序内保护机制正确构建且没有可能破坏整个保护的严重错误的情况下,才能实现最好的效果. VMProtect通过在具有 ...

  2. 代码保护软件VMP逆向分析虚拟机指令

    VMProtect是一种很可靠的工具,可以保护应用程序代码免受分析和破解,但只有在应用程序内保护机制正确构建且没有可能破坏整个保护的严重错误的情况下,才能实现最好的效果. VMProtect通过在具有 ...

  3. TraceMe.exe注册码破解及注册机编写

    一.追注册码步骤解析 打开OllyDbg反汇编软件,对实验程序TraceMe.exe进行反汇编. 点击View-Executable modules查看可执行模块,在新窗口中右击,选择Show nam ...

  4. 黑马python2019吾爱破解_2019KCTF 南充茶坊(python逆向)

    1.前言 本文讲的是一道python逆向题,逆向分析python打包程序,首先对它进行解压缩,使用python逆向工具提取出关键py文件,分析py文件中的算法,然后写出求解flag的代码. 2.工具 ...

  5. Dubbo Spring Cloud 逆向分析服务注册事件变化的处理过程

    这篇介绍了如何从接收事件的方法逆向推出完整的事件处理过程,这个方法适合在解决具体问题或学习源码时,倒着把处理过程理顺. 起因 原来用的 Spring Boot + Dubbo 开发架构,在架构中有一个 ...

  6. 实战操作——一次简单的逆向分析破解锁机软件

    事情的起因是这样的,群里有位小朋友的手机被锁了,问及原因,原来是下载了一个名叫"cf外挂助手激活版"的这么一个软件,我收到了这份软件之后看到他是这样的... emmm....才二百 ...

  7. 8.继续分析一破解加密码获取-最最最简单的注册机

    先看程序: 大体上是输入密码吧. 先第一个思路,直接破解密码校验的地方.直接改汇编代码. 跟踪字符串快速缩小范围:Password Is Wrong 找到了,然后直接改: OK破解成功: 现在换个思路 ...

  8. 010Edit分析 爆破 + 算法逆向 + 注册机编写

    爆破 假码 pName = xuanci pKey = 00112233445566778899 登录出错 复制错误信息 --------------------------- 010 Editor ...

  9. 庖丁解牛破解与注册机编写

    注册原理: 1. 机器码生成原理: 根据函数得到dwSerial,然后与一个常数0x51627384异或,结果的十六进制表示就是机器码. LPTSTR pVolumeNameBuffer = new ...

  10. 逆向分析CrackMe系列——CrackMe004之注册码算法分析

    逆向分析CrackMe系列--CrackMe004注册码算法分析 本文内容承接前面的工作,记录了自己每一步的分析过程和思路,由于内容较长,故单独写一篇. (本系列的CrackMe资源均来自我爱破解网) ...

最新文章

  1. Apache启用mod_expires模块
  2. 【深度学习】基于Torch的Python开源机器学习库PyTorch卷积神经网络
  3. vim C plugins
  4. boost::process::throw_on_error相关的测试程序
  5. PHP 错误与异常 笔记与总结(12 )异常
  6. MySQL 面试,必须掌握的 8 大核心点
  7. cdr放大后内容消失了_今日推荐:AI智能图片清晰放大神器强势来袭,简直无敌了...
  8. kb931125—rootsupd_kb931125-rootsupd补丁下载
  9. Postman下载与安装操作步骤(只有两步骤下载)
  10. 二维数组与数组指针详解
  11. apache设置开机启动启动
  12. 个人网站建设基本步骤解析
  13. Redis入门总结(二):主从复制,事务和发布订阅
  14. 潭州学院html学习(day03)
  15. 检测号码是否开通微信如何做?
  16. 独立开发变现周刊(第41期):一个开源项目一个人每月收入8万美金
  17. Maven使用与学习
  18. Python爬取淘宝图片
  19. Spring框架之AOP详解(带实战详细步骤)
  20. 【云计算小知识】什么是云计算?云计算特点是什么?

热门文章

  1. 用友U8修改货位现存量
  2. 数据智能、孪生城市——展望未来智慧城市产业发展
  3. win10 动态磁盘 linux,教你如何将win10系统动态磁盘改成基本磁盘?
  4. java接口的实现原理_Java接口和抽象类原理详解
  5. 收文和发文管理流程分析
  6. IDEA2017破解办法
  7. cpp的vector初始化方法
  8. 中国地图流动图(一)
  9. 汽车级485通信电路
  10. java英语美式读音