吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3370|回复: 11
收起左侧

[.NET逆向] SDF Viewer KEY算法分析1

[复制链接]
gksj 发表于 2022-3-22 04:02
本帖最后由 涛之雨 于 2022-3-22 08:23 编辑

这是我在52pojie发的第一篇内容,因为我昨天才注册
最近在分析某工业机器人仿真软件插件的时候发现关键数据都是用SDF数据库保存的,网上搜了一下SDF Viewer适合干这个活,所以就下载了一个,用了几天提示剩余天数,想想顺便研究一下算法吧,于是,就开始了~

使用工具:

1.Detect It Easy(查壳工具)
2.dnspy(反编译工具)
3.De4Dot ToolKit V 2.0(脱壳工具)
4.C#代码在线执行网站(加密解密代码执行 KeyGen)

分析过程

首先我们先用查壳工具看一下
QQ截图20220322032730.png
显示VB.NET,嗯有的搞
dnspy载入看一下
QQ截图20220322033148.png
这明显就是加了壳的

试着用De4Dot脱一下
QQ截图20220322032831.png
QQ截图20220322032925.png
代码基本上算是能看了
QQ截图20220322033240.png
打开软件的注册,试着随便输入注册,看提示信息
QQ截图20220322034330.png QQ截图20220322034341.png
Name or Key error
记住这个消息,然后用dnspy打开脱壳后的程序.
CTRL+F打开查找信息框输入这个错误信息
漫长的查找时间...
QQ截图20220322034554.png
最后在资源文件的SDFviewer.SDF.resources找到了这个字符串
记住前面这个str120,这个是程序里引用的资源名
顺便记录一下其他的关键信息

// str116‎ = "Licence has been Withdrawn."//注册码被撤销
// str117‎ = "Please contact sales@flyhoward.com for further details."
// str118‎ = "Licence Error"
// str119‎ = "Registered to "//注册到    这里很关键,提示注册成功了
// str12‎ = "Enter Password for: "
// str120‎ = "Name or Key error"  //注册码错误信息

然后我们在所有代码数据里面查找str120和str119
又是漫长的查找过程...
QQ截图20220322034634.png

if (Operators.CompareString(Class1.smethod_3(Class1.string_17), Class1.string_16, false) == 0)
{
        Class1.string_11 = Class1.resourceManager_0.GetString("str119") + Class1.string_16;//Registered to  
        Class1.int_0 = 2;
}
else
{
        Class7.smethod_0().Name = string.Empty;
        Class7.smethod_0().KeyString = string.Empty;//Name or Key error
        Interaction.MsgBox(Class1.resourceManager_0.GetString("str120"), MsgBoxStyle.OkOnly, Class1.resourceManager_0.GetString("str121"));
        Class1.smethod_2();
}

仔细看代码if (Operators.CompareString(Class1.smethod_3(Class1.string_17), Class1.string_16, false) == 0)
其中调用了Class1.smethod_3,我们找一下这个方法的作用

private static string smethod_3(string string_29)
{
        byte[] rgbKey = new byte[0];
        byte[] rgbIV = new byte[] { 18, 52, 86, 115, 144, 171, 205, 239 };
        byte[] array = new byte[checked(string_29.Length + 1)];
        string result;
        try
        {
                rgbKey = Encoding.UTF8.GetBytes("f1owChk1");
                DESCryptoServiceProvider descryptoServiceProvider = new DESCryptoServiceProvider();
                array = Convert.FromBase64String(string_29);//1.Key先从BASE64转换成二进制
                MemoryStream memoryStream = new MemoryStream();
                CryptoStream cryptoStream = new CryptoStream(memoryStream, descryptoServiceProvider.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);//2.然后执行Decryptor解密方法
                cryptoStream.Write(array, 0, array.Length);//3.然后把二进制Key写进解密方法
                cryptoStream.FlushFinalBlock();
                result = Encoding.UTF8.GetString(memoryStream.ToArray());//4.最后ToArry的数据转换成字符串
        }
        catch (Exception ex)
        {
                result = string.Empty;
        }
        return result;

解密算法就摆在眼前
仔细看这行代码array = Convert.FromBase64String(string_29);
还有CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write)

梳理一下这个算法

1.Key先从BASE64转换成二进制
2.然后执行Decryptor解密方法
3.然后把二进制Key写进解密方法
4.最后ToArry的数据转换成字符串

5.把结果返回到上一个方法进行比较

加密算法就是反过来
1.把Name(字符串)转换成二进制
2.然后执行Encryptor加密方法
3.然后把二进制Name写进加密算法
4.最后ToArry的数据转换成BASE64字符串

5.最后BASE64字符串就是Key

private static string smethod_3(string Nametext)
{
        byte[] rgbKey = new byte[0];
        byte[] rgbIV = new byte[] { 18, 52, 86, 115, 144, 171, 205, 239 };
        byte[] array = new byte[checked(Nametext.Length)];
        string result;
        try
        {
                rgbKey = Encoding.UTF8.GetBytes("f1owChk1");
                DESCryptoServiceProvider descryptoServiceProvider = new DESCryptoServiceProvider();
                array = new ASCIIEncoding().GetBytes(NameText);//1.把Name(字符串)转换成二进制
                MemoryStream memoryStream = new MemoryStream();
                CryptoStream cryptoStream = new CryptoStream(memoryStream, descryptoServiceProvider.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);//2.然后执行Encryptor加密方法
                cryptoStream.Write(array, 0, array.Length);//3.然后把二进制Name写进加密算法
                cryptoStream.FlushFinalBlock();
                result = Convert.ToBase64String(memoryStream.ToArray());//4.最后ToArry的数据转换成BASE64字符串
        }
        catch (Exception ex)
        {
                result = string.Empty;
        }
        return result;

把这些代码转化一下,找个在线C#代码执行网站试一下看看能不能算出来注册码

完整代码如下:

using System;
using System.Text;//文本处理命名空间
using System.IO;//MemoryStream读写数据流用的命名空间
using System.Security.Cryptography;//加密解密用的命名空间

namespace KeyGen
{
    class Program
    {
        static void Main(string[] args)
        {
            string Name = "52pojie";//双引号内是Name内容,不支持特殊符号和中文
            //
            byte[] rgbKey = Encoding.UTF8.GetBytes("f1owChk1");
            byte[] rgbIV = new byte[] { 18, 52, 86, 115, 144, 171, 205, 239 };
            byte[] array = new ASCIIEncoding().GetBytes(Name);
            DESCryptoServiceProvider descryptoServiceProvider = new DESCryptoServiceProvider();;
            MemoryStream memoryStream = new MemoryStream();
            CryptoStream cryptoStream = new CryptoStream(memoryStream, descryptoServiceProvider.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
            cryptoStream.Write(array, 0, array.Length);
            cryptoStream.FlushFinalBlock();
            string result = Convert.ToBase64String(memoryStream.ToArray());
            Console.WriteLine(result);

        }
    }
}


把执行的代码结果在软件内进行注册,完美!


插曲
其实分析期间在解密的代码那里我是下过断点调试过的,因为不确定是不是解密的Key秘钥.
在对比秘钥之前的代码里有一段代码非常有意思

if (Operators.CompareString(Class1.string_17, "SIWphRddOncC+9dfqM39Cw==", false) == 0 || Operators.CompareString(Class1.string_17, "yoU2LTox9ji1ME2xsQ21UA==", false) == 0 || Operators.CompareString(Class1.string_17, "9hzsfFcMHlaq7e9ItbsEHsutKigmkZgM", false) == 0 || Operators.CompareString(Class1.string_17, "5Prfc4iGPGwH3w84uOx84w==", false) == 0 || Operators.CompareString(Class1.string_17, "oIGoCNG9iBn0GaHaD1KuAA==", false) == 0 || Operators.CompareString(Class1.string_17, "bi1F2hrFoxWbDy9/9XW38A==", false) == 0 || Operators.CompareString(Class1.string_17, "o4rHyS9417d+TiSf6vpCxA==", false) == 0 || Operators.CompareString(Class1.string_17, "8vUnN+97Lmo=", false) == 0)
                {
                        Class7.smethod_0().Name = string.Empty;
                        Class7.smethod_0().KeyString = string.Empty;
                        Class7.smethod_0().Save();
                        Interaction.MsgBox(Class1.resourceManager_0.GetString("str116") + "\r\n" + Class1.resourceManager_0.GetString("str117"), MsgBoxStyle.OkOnly, Class1.resourceManager_0.GetString("str118"));
                        Class1.int_0 = 0;
                        Class3.smethod_3().method_28().Close();
                        ProjectData.EndApp();
                }

仔细看代码里有GetString("str116")
前面有提到:

// str116‎ = "Licence has been Withdrawn."//注册码被撤销

软件开发者比较狠,因为不知道是注册码泄露还是其他人破解的秘钥,作者发现了直接把这些秘钥列到黑名单里面啦,哈哈哈~
不过因为上面判断代码里面Class1.string_17的判断字符串都是BASE64编码,所以我很确定解密算法里面肯定是解密的Key,而且是BASE64编码
通过我用C#做的界面程序进行解密,把这些黑名单的用户名发一下:

Key Name
SIWphRddOncC+9dfqM39Cw== dan quinn
yoU2LTox9ji1ME2xsQ21UA== Carlos Cardona
9hzsfFcMHlaq7e9ItbsEHsutKigmkZgM Gail Fitzmaurice
5Prfc4iGPGwH3w84uOx84w= Ng Choon Bok
oIGoCNG9iBn0GaHaD1KuAA== Yam Poudel
bi1F2hrFoxWbDy9/9XW38A== Cameron Kelly
o4rHyS9417d+TiSf6vpCxA== omegaredgroup
8vUnN+97Lmo= Kyu Kim

以上黑名单人员看用户名就没有中国的,看来作者是没到国内的网站搜索过啊,呵呵呵~

免费评分

参与人数 5威望 +1 吾爱币 +24 热心值 +4 收起 理由
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
笙若 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
狄人3 + 1 + 1 用心讨论,共获提升!
NittleNineANN + 1 我很赞同!
侃遍天下无二人 + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

涛之雨 发表于 2022-3-22 08:25
帮你重新编辑了一下,以后如果修改补充的话请直接点帖子左下角的”编辑“按钮进行编辑

emmm

图片的话我没有原图,请楼主自行上传一下,
 楼主| gksj 发表于 2022-3-22 04:13
if (Operators.CompareString(Class1.smethod_3(Class1.string_17), Class1.string_16, false) == 0)
{
        Class1.string_11 = Class1.resourceManager_0.GetString("str119") + Class1.string_16;//Registered to  
        Class1.int_0 = 2;
}
else
{
        Class7.smethod_0().Name = string.Empty;
        Class7.smethod_0().KeyString = string.Empty;//Name or Key error
        Interaction.MsgBox(Class1.resourceManager_0.GetString("str120"), MsgBoxStyle.OkOnly, Class1.resourceManager_0.GetString("str121"));
        Class1.smethod_2();
}

仔细看代码if (Operators.CompareString(Class1.smethod_3(Class1.string_17), Class1.string_16, false) == 0)
其中调用了Class1.smethod_3,我们找一下这个方法的作用
QQ截图20220322034804.png

private static string smethod_3(string string_29)
{
        byte[] rgbKey = new byte[0];
        byte[] rgbIV = new byte[] { 18, 52, 86, 115, 144, 171, 205, 239 };
        byte[] array = new byte[checked(string_29.Length + 1)];
        string result;
        try
        {
                rgbKey = Encoding.UTF8.GetBytes("f1owChk1");
                DESCryptoServiceProvider descryptoServiceProvider = new DESCryptoServiceProvider();
                array = Convert.FromBase64String(string_29);//1.Key先从BASE64转换成二进制
                MemoryStream memoryStream = new MemoryStream();
                CryptoStream cryptoStream = new CryptoStream(memoryStream, descryptoServiceProvider.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);//2.然后执行Decryptor解密方法
                cryptoStream.Write(array, 0, array.Length);//3.然后把二进制Key写进解密方法
                cryptoStream.FlushFinalBlock();
                result = Encoding.UTF8.GetString(memoryStream.ToArray());//4.最后ToArry的数据转换成字符串
        }
        catch (Exception ex)
        {
                result = string.Empty;
        }
        return result;

解密算法就摆在眼前
仔细看这行代码array = Convert.FromBase64String(string_29);
还有CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write)

梳理一下这个算法

1.Key先从BASE64转换成二进制
2.然后执行Decryptor解密方法
3.然后把二进制Key写进解密方法
4.最后ToArry的数据转换成字符串

5.把结果返回到上一个方法进行比较

加密算法就是反过来
1.把Name(字符串)转换成二进制
2.然后执行Encryptor加密方法
3.然后把二进制Name写进加密算法
4.最后ToArry的数据转换成BASE64字符串

5.最后BASE64字符串就是Key

private static string smethod_3(string Nametext)
{
        byte[] rgbKey = new byte[0];
        byte[] rgbIV = new byte[] { 18, 52, 86, 115, 144, 171, 205, 239 };
        byte[] array = new byte[checked(Nametext.Length)];
        string result;
        try
        {
                rgbKey = Encoding.UTF8.GetBytes("f1owChk1");
                DESCryptoServiceProvider descryptoServiceProvider = new DESCryptoServiceProvider();
                array = new ASCIIEncoding().GetBytes(NameText);//1.把Name(字符串)转换成二进制
                MemoryStream memoryStream = new MemoryStream();
                CryptoStream cryptoStream = new CryptoStream(memoryStream, descryptoServiceProvider.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);//2.然后执行Encryptor加密方法
                cryptoStream.Write(array, 0, array.Length);//3.然后把二进制Name写进加密算法
                cryptoStream.FlushFinalBlock();
                result = Convert.ToBase64String(memoryStream.ToArray());//4.最后ToArry的数据转换成BASE64字符串
        }
        catch (Exception ex)
        {
                result = string.Empty;
        }
        return result;

把这些代码转化一下,找个在线C#代码执行网站试一下看看能不能算出来注册码

完整代码如下:

using System;
using System.Text;//文本处理命名空间
using System.IO;//MemoryStream读写数据流用的命名空间
using System.Security.Cryptography;//加密解密用的命名空间

namespace KeyGen
{
    class Program
    {
        static void Main(string[] args)
        {
            string Name = "52pojie";//双引号内是Name内容,不支持特殊符号和中文
            //
            byte[] rgbKey = Encoding.UTF8.GetBytes("f1owChk1");
            byte[] rgbIV = new byte[] { 18, 52, 86, 115, 144, 171, 205, 239 };
            byte[] array = new ASCIIEncoding().GetBytes(Name);
            DESCryptoServiceProvider descryptoServiceProvider = new DESCryptoServiceProvider();;
            MemoryStream memoryStream = new MemoryStream();
            CryptoStream cryptoStream = new CryptoStream(memoryStream, descryptoServiceProvider.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
            cryptoStream.Write(array, 0, array.Length);
            cryptoStream.FlushFinalBlock();
            string result = Convert.ToBase64String(memoryStream.ToArray());
            Console.WriteLine(result);

        }
    }
}

QQ截图20220322035056.png
把执行的代码结果在软件内进行注册,完美!
QQ截图20220322035158.png QQ截图20220322035238.png
插曲
其实分析期间在解密的代码那里我是下过断点调试过的,因为不确定是不是解密的Key秘钥.
在对比秘钥之前的代码里有一段代码非常有意思
QQ截图20220322035335.png

if (Operators.CompareString(Class1.string_17, "SIWphRddOncC+9dfqM39Cw==", false) == 0 || Operators.CompareString(Class1.string_17, "yoU2LTox9ji1ME2xsQ21UA==", false) == 0 || Operators.CompareString(Class1.string_17, "9hzsfFcMHlaq7e9ItbsEHsutKigmkZgM", false) == 0 || Operators.CompareString(Class1.string_17, "5Prfc4iGPGwH3w84uOx84w==", false) == 0 || Operators.CompareString(Class1.string_17, "oIGoCNG9iBn0GaHaD1KuAA==", false) == 0 || Operators.CompareString(Class1.string_17, "bi1F2hrFoxWbDy9/9XW38A==", false) == 0 || Operators.CompareString(Class1.string_17, "o4rHyS9417d+TiSf6vpCxA==", false) == 0 || Operators.CompareString(Class1.string_17, "8vUnN+97Lmo=", false) == 0)
                {
                        Class7.smethod_0().Name = string.Empty;
                        Class7.smethod_0().KeyString = string.Empty;
                        Class7.smethod_0().Save();
                        Interaction.MsgBox(Class1.resourceManager_0.GetString("str116") + "\r\n" + Class1.resourceManager_0.GetString("str117"), MsgBoxStyle.OkOnly, Class1.resourceManager_0.GetString("str118"));
                        Class1.int_0 = 0;
                        Class3.smethod_3().method_28().Close();
                        ProjectData.EndApp();
                }

仔细看代码里有GetString("str116")
前面有提到:
// str116‎ = "Licence has been Withdrawn."//注册码被撤销

软件开发者比较狠,因为不知道是注册码泄露还是其他人破解的秘钥,作者发现了直接把这些秘钥列到黑名单里面啦,哈哈哈~
不过因为上面判断代码里面Class1.string_17的判断字符串都是BASE64编码,所以我很确定解密算法里面肯定是解密的Key,而且是BASE64编码
通过我用C#做的界面程序进行解密,把这些黑名单的用户名发一下:

Key Name
SIWphRddOncC+9dfqM39Cw== dan quinn
yoU2LTox9ji1ME2xsQ21UA== Carlos Cardona
9hzsfFcMHlaq7e9ItbsEHsutKigmkZgM Gail Fitzmaurice
5Prfc4iGPGwH3w84uOx84w= Ng Choon Bok
oIGoCNG9iBn0GaHaD1KuAA== Yam Poudel
bi1F2hrFoxWbDy9/9XW38A== Cameron Kelly
o4rHyS9417d+TiSf6vpCxA== omegaredgroup
8vUnN+97Lmo= Kyu Kim

以上黑名单人员看用户名就没有中国的,看来作者是没到国内的网站搜索过啊,呵呵呵~

mikepj 发表于 2022-3-22 09:50
windflower57521 发表于 2022-3-22 10:50
尽管没有完全明白,但是学到了很多
dunniu 发表于 2022-3-22 11:49
这个就比较牛了!
tukuai88ya 发表于 2022-3-22 12:09
感谢分享,学到了
NittleNineANN 发表于 2022-3-22 13:16
学到了很多
shenshouaowu 发表于 2022-3-23 11:33
学到了很多,感谢楼主的分享
glorymusic 发表于 2022-4-1 21:37
虽然现在看起来有点吃力,还是感谢楼主的分享!!!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 12:37

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表