[C#] [安全] [加密解密] 逆向某GIS软件验证函数后生成的加密解密算法

目录

1.Intro

2.Details

3.Theory

4.Environment 

5.Source

注册机概览:

注册码生成(加密模块):

注册码验证(解密模块):

许可调用的功能模块:

6.Conclusion


1.Intro

爬虫在耳边萦绕,倾听着浏览器的呢喃,从urllib2到selenium,飞向scrapy,直至穿越服务器的心间,一切都只不过是Mongo下的微粒... 正当做着白日梦的时候,一声听起来无力又有点肾虚的呼唤搅屎了我的诗作:“猿儿!你快过来下!”

他撅起屁股,哦不,是张开嘴,我就知道绝逼没有比如请我吃饭的好事:“ ***那个软件太贵了!买不起啊兄弟!我看你一表人才,给破解下呗~”

一表人才还行,但我是一个罕见的十分正直的人:“淦!我们搞GIS的,又不是黑帽,不要再蹦逼了,整不来整不来”

X:“那个新来女同事的微信...”

我:“你我都是兄弟,凡事好商量”

就这样,继做爬虫之后,又从一个搞地信开发的变成了搞破解的,天天不务正业说的就是本猿。


2.Details

说起来这个软件,在GIS业内倒也不是很出名,只是有很多满足一些国土和地理信息生产业务的功能,而且做的也比较成熟,所以说不得不用,但是授权方式是每人一套,一套的价格大概是1w+,本着能用破解版就绝壁不买的原则(深受ArcGIS的影响,一套正版的高级版ArcGIS桌面产品大概是149000.....),就反编译了一下解密模块,值得庆幸的是这个软件厂商并没有加壳和进行源代码混淆,所以基本上所有的解密模块代码就都搞出来了....如果问为什么不直接Copy他的核心功能函数,因为功能比较多,类库依赖关系和动态链接库配置比较复杂,而且我又懒(主要原因),所以还不如逆向一下解密模块算求了。

逆向了一下这个软件的解密过程,大概就用到两种加密算法,Base64和RSA(比较鸡贼,居然用RSA)。

加密信息是获取CPU序列号、主板序列号、硬盘序列号转成大写后用字符 “_” 连接(就是一般的获取硬件序列号方法)。

加密方法是将加密信息先通过RSA不对称加密,再通过Base64对称加密,然后将许可时间写入到注册表,在把许可时间组合通过Base64加密,最后生成两行许可信息(具体内容在代码注释中可以找到)。

由于对方使用了RSA,所以没办法生成注册机,原因为RSA是对信息进行私(公)钥加密,然后用公(私)钥去验证,私钥只被加密方持有,我这只持有公钥,所以只能挥泪咒骂,这下好了,美女同事的微信也没了。但是这个加密解密的方法还是值得学习的,整理下,自己生成一个RSA密钥对,可以用在以后软件的加密模块上,倒也算一个收获。


3.Theory

网上找了几张图,图解一下两种加密方式的原理,具体的算法原理可以上别处找去,啧。

对称加密(Base64):具体来说,就是密钥是同一把,可以加密可以解密。

不对称加密(RSA):两把不同的密钥,一把加密,一把解密。


4.Environment 

Environment:Windows All

Language:C#

IDE:Visual Studio 2012


5.Source

注册机概览:

注册码生成(加密模块):

using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms;

namespace KeyGen
{
    public class LicGenerate
    {
        private string _sysinfo = "";

        public LicGenerate(string sysInfo)
        {
            this._sysinfo = sysInfo;
        }

        #region 许可参数
        //许可时间信息
        private string _fromDateTime = "";
        private string _toDateTime = "";

        //机器序列号
        private static string _systemInfo = string.Empty;

        //许可文件内容
        private string keyLicenseCode = "";
        private string timeLicenseCode = "";

        /// <summary>
        /// 许可开始时间
        /// </summary>
        public string fromDateTime
        {
            set { _fromDateTime = value; }
            get { return _fromDateTime; }
        }

        /// <summary>
        /// 许可结束时间
        /// </summary>
        public string toDateTime
        {
            set { _toDateTime = value; }
            get { return _toDateTime; }
        }

        /// <summary>
        /// 私钥
        /// </summary>
        private const string privateKey = "<RSAKeyValue><Modulus>r+Fknz/UEsPyB+rOJpRt6BLPUnPvYFEAuXFtL6x23NI7LrUf+Xvcfo1iPMMJruOdNPs+wYNpxNy1166n5mRuSLn7EPbt1aumfCmtgq150NDWWdmx1y5rHNGFu9sUSUm+EgNEgVNbrjTTq8ru7ZJU2X5CLuLMYevuXwBaLZoS8kk=</Modulus><Exponent>AQAB</Exponent><P>6UVOdO86q+jMO8pdQGivk1EW2AnO3LRzkULvKcsXhqXXlQAjDhjPEF192osfmmnLXiqMkYd9DxcVb9oa5sLxXw==</P><Q>wQSLzXpqLsdb2lExGRx2iNEGZvxgjQxIkgb21DLrzgKSu6dTUzhxnZ2Iag4XcB5AWedseqRVvcGEkPmchQ31Vw==</Q><DP>kS/X0yQKqnCsnRIo1CvUC6bOxwvjuq59t42neaW0MNQLx+tb5iw+xHrMGDe7JcpvD18AOpvPlJLTftiLIdF3lQ==</DP><DQ>C5YYRkdY5GH3M424IsfAncneVoRDz3OzT4C3hFliKkWhRT5wFAjJWSrBq4wZABPwzPTFYD9JHlDlgkZZjOsflQ==</DQ><InverseQ>hnXlKRysPRroqHNd8SlzAcEPnWpgExIxLU2McE6slDO0DrABEyb/LHG6BTc8eBvzO6G+JiaKddTVKhHCLVU/rA==</InverseQ><D>Vo6JU6o494dBTM4s6GWx9T2UlJKD4xXaUmlU/9pToPdBswnmk4R2jj2MdDTURiK0kod3agr/eafZQi0takBQ2V4Kq86JI/Ei2VvMP781sPE/pnfENMufwfbdcbHdrU4heyd3DBT0NtTfOA71jeAlVbvMrCJVYDo/H3VVukGntUU=</D></RSAKeyValue>";

        /// <summary>
        /// 第一行的许可信息
        /// </summary>
        public string KeyLicenseCode
        {
            set{ keyLicenseCode = value; }
            get{ return keyLicenseCode; }
        }

        /// <summary>
        /// 第二行的许可信息
        /// </summary>
        public string TimeLicenseCode
        {
            set{ timeLicenseCode = value; }
            get{ return timeLicenseCode; }
        }

        /// <summary>
        /// SHA1(Secure Hash Algorithm)安全哈希算法的哈希值,主要用于数字签名验证
        /// </summary>
        private static HashAlgorithm DefaultHashAlgorithm
        {
            get
            {
                return (HashAlgorithm)new SHA1CryptoServiceProvider();
            }
        }

        /// <summary>
        /// 默认字节顺序编码为UTF-16编码
        /// </summary>
        private static Encoding ByteConvertor
        {
            get
            {
                return Encoding.Unicode;
            }
        }
        #endregion

        #region 逆向许可方法
        #region 生成许可文件
        /// <summary>
        /// 许可文件保存
        /// </summary>
        /// <returns>返回许可文件路径</returns>
        private string licenseFileSave()
        {
            try
            {
                string licenseFilePath;
                SaveFileDialog saveFileDialog = new SaveFileDialog();
                saveFileDialog.InitialDirectory = "D:\\";
                saveFileDialog.Filter = "许可文件(*.lic)|*.lic";
                saveFileDialog.RestoreDirectory = true;
                DialogResult dr = saveFileDialog.ShowDialog();
                if (dr == DialogResult.OK && saveFileDialog.FileName.Length > 0)
                {
                    licenseFilePath = saveFileDialog.FileName;
                }
                else
                {
                    return null;
                }
                return licenseFilePath;
            }
            catch
            {
                MessageBox.Show("许可文件存储失败!");
                return null;
            }        
        }
        #endregion

        #region 注册码生成
        /// <summary>
        /// 时间许可
        /// </summary>
        /// <returns>返回加密的时间许可代码</returns>
        private string timeLicense()
        {
            try
            {
                DateTime fromDate;
                DateTime toDate;

                fromDate = DateTime.Parse(fromDateTime);
                toDate = DateTime.Parse(toDateTime);

                DateTime nowDate = DateTime.Now;

                string str = Convert.ToBase64String(Encoding.Default.GetBytes(fromDate.ToString() + (object)"$" + toDate.ToShortDateString() + "$" + (object)nowDate.ToString()));
                return str;
            }
            catch
            {
                MessageBox.Show("时间许可生成失败!");
                return null;
            }
            
        }

        /// <summary>
        /// 私钥签名
        /// </summary>
        /// <param name="licenseFilePath">许可路径</param>
        /// <param name="signatureData">需要签名的数据(机器码)</param>
        /// <param name="privateKey">私钥</param>
        /// <returns></returns>
        private string privateKeySignature(byte[] signatureData, string privateKey)
        {
            try 
            {
                //私钥签名
                RSACryptoServiceProvider cryptoServiceProvider = new RSACryptoServiceProvider();
                cryptoServiceProvider.FromXmlString(privateKey);

                //用SHA1的哈希算法指定字节数组的哈希值,并对计算所得的哈希值进行签名,得到加密后的字节数组
                byte[] signature = cryptoServiceProvider.SignData(signatureData, (object)DefaultHashAlgorithm);

                //签名数据用Base64算法进行加密
                string keyCode = Convert.ToBase64String(signature);
                return keyCode;
            }        
            catch
            {
                MessageBox.Show("许可签名失败!");
                return null;
            }
        }
        #endregion

        //#region 系统信息
        ///// <summary>
        ///// 获得机器码信息
        ///// </summary>
        //private static string SystemInfo
        //{
        //    get
        //    {
        //        try
        //        {
        //            //如果字符串系统信息为空值
        //            if (string.IsNullOrEmpty(_systemInfo))
        //            {
        //                /*
        //                 * 1.GetCpuId().ToUpper():获取CPU的ID信息(序列号),并转成大写
        //                 * 2.GetMotherBoardId().ToUpper():获取主板的ID信息(序列号),并转成大写
        //                 * 3.GetHarDiskId().ToUpper():获取硬盘的ID信息(序列号),并转成大写
        //                 * 两个信息用"_"相连接,返回系统信息字符串。
        //                 */
        //                _systemInfo = GetCpuId().ToUpper() + "_" + GetMotherBoardId().ToUpper() + "_" + GetHardDiskId().ToUpper();
        //            }
        //            return _systemInfo;
        //        }
        //        catch
        //        {
        //            MessageBox.Show("机器码序列号获取失败!");
        //            return null;
        //        }
                
        //    }
        //}

        ///// <summary>
        ///// 获取CPU ID信息
        ///// </summary>
        ///// <returns>返回获取CPU ID</returns>
        //private static string GetCpuId()
        //{
        //    //传入"Win32_Processor"可获得CPU处理器信息
        //    ManagementObjectCollection instances = new ManagementClass("Win32_Processor").GetInstances();

        //    string str = (string)null;

        //    //
        //    using (ManagementObjectCollection.ManagementObjectEnumerator enumerator = instances.GetEnumerator())
        //    {
        //        if (enumerator.MoveNext())
        //            str = enumerator.Current.Properties["ProcessorId"].Value.ToString();
        //    }
        //    return str;
        //}

        ///// <summary>
        ///// 获取硬盘ID信息
        ///// </summary>
        ///// <returns>返回硬盘ID信息</returns>
        //private static string GetHardDiskId()
        //{
        //    ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");
        //    string str = (string)null;
        //    foreach (ManagementBaseObject managementBaseObject in managementObjectSearcher.Get())
        //        str = managementBaseObject["SerialNumber"].ToString().Trim();
        //    return str;
        //}

        ///// <summary>
        ///// 获取主板信息
        ///// </summary>
        ///// <returns>返回主板信息</returns>
        //private static string GetMotherBoardId()
        //{
        //    //
        //    ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BaseBoard");
        //    string str = string.Empty;
        //    using (ManagementObjectCollection.ManagementObjectEnumerator enumerator = managementObjectSearcher.Get().GetEnumerator())
        //    {
        //        if (enumerator.MoveNext())
        //        {
        //            object obj = enumerator.Current["SerialNumber"];
        //            if (obj != null)
        //                str = obj.ToString();
        //        }
        //    }
        //    return str;
        //}
        //#endregion

        #region 注册表清理
        /// <summary>
        /// 注册表清理
        /// </summary>
        /// <returns>返回注册表清理结果</returns>
        private bool regeditWrite()
        {
            DateTime fromDate;
            DateTime toDate;

            fromDate = DateTime.Parse(fromDateTime);
            toDate = DateTime.Parse(toDateTime);

            try
            {
                using (RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\PrivateCMW\\TimeLimitKey", true))
                {
                    //如果注册表存在,就删除注册表
                    if (registryKey != null)
                    {
                        //using (RegistryKey registryCreate = Registry.CurrentUser.CreateSubKey("SOFTWARE\\PrivateCMW\\TimeLimitKey"))
                        //{
                        //    //写入许可开始时间
                        //    registryCreate.SetValue("Start", (object)fromDate.ToString());
                        //    //写入许可结束时间
                        //    registryCreate.SetValue("End", (object)toDate.ToShortDateString());
                        //}
                        //return true;
                        try
                        {
                            RegistryKey registryDelete = Registry.CurrentUser;
                            registryDelete.DeleteSubKey("SOFTWARE\\PrivateCMW\\TimeLimitKey", true);
                            registryDelete.Close();
                        }
                        catch
                        {
                            MessageBox.Show("注册表清理失败!");
                            return false;
                        }
                        //using (RegistryKey registryCreate = Registry.CurrentUser.CreateSubKey("SOFTWARE\\PrivateCMW\\TimeLimitKey"))
                        //{
                        //    //写入许可开始时间
                        //    registryCreate.SetValue("Start", (object)fromDate.ToString());
                        //    //写入许可结束时间
                        //    registryCreate.SetValue("End", (object)toDate.ToShortDateString());
                        //}
                    }

                    ////如果存在就清理并创建新的注册表
                    //else
                    //{
                        
                    //}
                }
                return true;
            }
            catch
            {
                MessageBox.Show("注册表清理失败!");
                return false;
            }
        }
        #endregion

        #region 许可文件写入
        /// <summary>
        /// 许可文件写入
        /// </summary>
        /// <param name="licenseFilePath">许可文件路径</param>
        /// <param name="keyCode">密钥许可</param>
        /// <param name="timeCode">时间许可</param>
        /// <returns>返回许可文件写入结果</returns>
        private bool licenseWrite(string licenseFilePath, string keyCode, string timeCode)
        {
            try
            {
                if (!File.Exists(licenseFilePath))
                {
                    using (FileStream fileStream = new FileStream(licenseFilePath, FileMode.Create, FileAccess.Write))
                    {
                        using (StreamWriter streamWriter = new StreamWriter((Stream)fileStream, Encoding.Default))
                        {
                            streamWriter.WriteLine(keyCode);
                            streamWriter.WriteLine(timeCode);
                        }
                    }
                    return true;
                }
                else
                {
                    using (FileStream fileStream = new FileStream(licenseFilePath, FileMode.Open, FileAccess.Write))
                    {
                        using (StreamWriter streamWriter = new StreamWriter((Stream)fileStream, Encoding.Default))
                        {
                            streamWriter.WriteLine(keyCode);
                            streamWriter.WriteLine(timeCode);
                        }
                    }
                    return true;
                }
            }
            catch
            {
                MessageBox.Show("许可文件写入失败!");
                return false;
            }
        }
        #endregion
        #endregion

        #region 执行生成许可文件
        /// <summary>
        /// 生成注册码
        /// </summary>
        public void hackExcute()
        {
            /* 许可验证步骤:
             *  1.许可文件过滤
             *  2.许可文件读取
             *  3.注册表验证(许可时间)
             *  4.加密算法验证许可文件
             */

            //反向生成注册码
            // 1.许可过滤(存在、合法[.lic结尾]、不为空[文本内容])
            if (fromDateTime == "" || toDateTime == "" || (fromDateTime == "" && toDateTime == ""))
            {
                MessageBox.Show("时间许可不能为空!");
                return;
            }
            // 2.许可写入
            //需要进行私钥签名的机器序列号数据
            //byte[] signature = ByteConvertor.GetBytes(SystemInfo);

            byte[] sys = Convert.FromBase64String(_sysinfo);

            //获得第一行的许可注册码(经过RSA不对称算法私钥签名和Base64加密的机器码信息)
            keyLicenseCode = privateKeySignature(sys, privateKey);
            //获得第二行的许可注册吗(经过Base64加密的时间组合信息)
            timeLicenseCode = timeLicense();

            // 3.注册许可
            //对注册表进行清理,并注册新的许可
            bool regeditControllder = regeditWrite();

            //返回结果
            //if (regeditControllder)
            //    MessageBox.Show("注册表清理成功!");
        }

        /// <summary>
        /// 生成许可文件
        /// </summary>
        /// <returns>返回生成结果</returns>
        public bool licenseFileGenerate()
        {
            try 
            {
                string licenseFilePath = licenseFileSave();
                //写入许可文件,返回结果
                bool licenseController = licenseWrite(licenseFilePath, keyLicenseCode, timeLicenseCode);
                return licenseController;
            }
            catch 
            {
                MessageBox.Show("写入文件失败!");
                return false;
            }    
        }
        #endregion
    }
}

注册码验证(解密模块):

using LicenseCommonUtil;
using Microsoft.Win32;
using System;
using System.IO;
using System.Security.Cryptography;

namespace LicenseClient
{
  public sealed class LicenseClient
  {
    public static bool CheckLicense(string licenseFilePath, out string message)
    {
        const string PublicKey = "<RSAKeyValue><Modulus>r+Fknz/UEsPyB+rOJpRt6BLPUnPvYFEAuXFtL6x23NI7LrUf+Xvcfo1iPMMJruOdNPs+wYNpxNy1166n5mRuSLn7EPbt1aumfCmtgq150NDWWdmx1y5rHNGFu9sUSUm+EgNEgVNbrjTTq8ru7ZJU2X5CLuLMYevuXwBaLZoS8kk=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

        try
        {
            message = "";

            #region 许可过滤(不存在、不合法、空)
            if (!File.Exists(licenseFilePath))
            {
            message = "许可文件不存在!";
            return false;
            }

            //.lic结尾的文件
            Path.GetExtension(licenseFilePath).Trim().ToUpper();
            if (!Path.GetExtension(licenseFilePath).Trim().ToUpper().Equals(LicenseUtil.DefaultLicenseFileExtension.ToUpper()))
            {
                message = "指定的许可文件不合法!";
                return false;
            }

            string s = LicenseUtil.ReadContentFromFile2(licenseFilePath);

            if (string.IsNullOrEmpty(s))
            {
                message = "许可内容为空!";
                return false;
            }
            #endregion

            #region 对许可解密获取时间信息(fromDate,toDate,lastDate)
            DateTime fromDate;
            DateTime toDate;
            DateTime lastDate;
            LicenseUtil.ReadDateTiFromFile(licenseFilePath, out fromDate, out toDate, out lastDate);
            #endregion

            #region 许可使用的注册表判断
            bool flag1 = false; //注册表信息控制器
            string str1 = "";
            string str2 = "";
            if (lastDate == fromDate) //如果起始时间等于最后时间
            {
                try
                {
                    //检索 SOFTWARE\\PrivateCMW\\TimeLimitKey,是否在当前用户的注册表中,不将写访问权限应用于该项。
                    using (RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\PrivateCMW\\TimeLimitKey", false))
                    {
                        //如果是空的话,注册表信息控制值为true
                        if (registryKey == null)
                        {
                            flag1 = true;
                        }
                        else
                        {
                            //如果不为空,则检索注册表中与指定名称关联的值
                            str1 = registryKey.GetValue("Start").ToString();
                            str2 = registryKey.GetValue("End").ToString();

                            //判断两个值中是否包含 fromDate 和 toDate 两个值
                            //如果包含了这两个值,则判断许可已经使用
                            if (str1.Contains(fromDate.ToString()) && str2.Contains(toDate.ToShortDateString()))
                            {
                                message = "许可已使用!";
                                return false;
                            }
                            //如果不包含 fromDate 和 toDate ,则返回true
                            flag1 = true;
                        }
                    }
                }
                catch (Exception)
                {
                    message = "验证注册表失败";
                }
            }
            #endregion

            #region 许可使用的时间期限判断
            /*
            * fromDate(授权许可开始的时间)
            * toDate(授权许可结束的时间)
            * lastDate(授权许可最后一次生效的时间)
            * 
            * DataTime.Now < lastData(现在的时间 小于 授权许可最后一次生效的时间)
            * lastDate < fromDate(授权许可最后一次生效的时间 小于 授权许可开始的时间)
            * lastDate > toDate(授权许可最后一次生效的时间 大于 授权许可结束的时间)
            * DateTime.Now < fromDate(现在的时间 小于 授权许可开始的时间)
            * DateTime.Now > toDate(现在的时间 大于 授权许可结束的时间)
            * 
            */
            if (DateTime.Now < lastDate || lastDate < fromDate || (lastDate > toDate || DateTime.Now < fromDate) || DateTime.Now > toDate)
            {
                message = "许可已经过期!";
                return false;
            }
            #endregion

            #region 加密算法验证许可文件
            //创建一个 RSA不对称加密解密算法 对象
            RSACryptoServiceProvider cryptoServiceProvider = new RSACryptoServiceProvider();

            //XML字符串中的密钥信息(包含公钥或者包含公钥和私钥):
            //<RSAKeyValue><Modulus>uqYMs9AxuAfGsbVvo+ah8Z7c91qbYJ8ARbX/7585ZVH1Jl9V5ebnjUEv+cuMjDEYzMCbJujoKZbqSRD5X5f9I2b9lNhRBhvBNBJj6ntzYKYp7HxYGTOr5NQ+eqNUejPhv9+fGedNa1oe/KyyfvE//NshoUN/oxVvCMlBIgHS98s=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>

            /* PEM格式公钥
                            -----BEGIN PUBLIC KEY-----
            MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6pgyz0DG4B8axtW+j5qHxntz3
            WptgnwBFtf/vnzllUfUmX1Xl5ueNQS/5y4yMMRjMwJsm6OgplupJEPlfl/0jZv2U
            2FEGG8E0EmPqe3NgpinsfFgZM6vk1D56o1R6M+G/358Z501rWh78rLJ+8T/82yGh
            Q3+jFW8IyUEiAdL3ywIDAQAB
                            -----END PUBLIC KEY-----
            */
            //初始化 RSA不对称加密解密算法
            cryptoServiceProvider.FromXmlString(PublicKey);
        
            bool flag2;

            try
            {
                //将字符编码转为一个UTF-16格式的字节序列
                byte[] bytes = LicenseUtil.ByteConvertor.GetBytes(LicenseUtil.SystemInfo);

                //打开许可文件,读取第一行的秘钥信息(s),通过Base64算法解密
                byte[] signature = Convert.FromBase64String(s);

                //传入字符序列,SHA1加密算法的哈希值,Base64的解密信息进行验证
               /*
                * VerifyData(buffer, halg, signature)
                * 通过使用提供的公钥计算签名中的哈希值,然后将其与提供的数据的哈希值进行比较,从而验证数字签名是否有效。
                * 
                * 返回值:
                * 如果签名有效,则为 true;否则为 false。
                * 
                * 参数:
                * buffer
                *    Type: Byte[]
                *     已签名的数据。
                * 
                * halg
                *    Type: Object
                *    用于创建数据哈希值的哈希算法的名称。
                * 
                * signature
                *    Type: System.Byte[]
                *    要验证的签名数据。
                * 
                */
                flag2 = cryptoServiceProvider.VerifyData(bytes, (object)LicenseUtil.DefaultHashAlgorithm, signature);
            }
            catch
            {
                message = "许可文件验证错误!";
                return false;
            }
            #endregion

            #region 注册表和许可文件更新
            //加密解密算法验证通过
            if (flag2)
            {
                //注册表验证通过
                if (flag1)
                {
                    //检索注册表 SOFTWARE\\PrivateCMW\\TimeLimitKey,并支持写入操作
                    using (RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\PrivateCMW\\TimeLimitKey", true))
                    {
                        //如果注册表为空
                        if (registryKey == null)
                        {
                            //创建注册表信息
                            using (RegistryKey subKey = Registry.CurrentUser.CreateSubKey("SOFTWARE\\PrivateCMW\\TimeLimitKey"))
                            {
                                //写入许可开始时间
                                subKey.SetValue("Start", (object)fromDate.ToString());
                                //写入许可结束时间
                                subKey.SetValue("End", (object)toDate.ToShortDateString());
                            }
                        }

                        else
                        {
                            //如果不为空
                            //追加新的许可开始时间和结束时间
                            registryKey.SetValue("Start", (object)(str1 + ";" + fromDate.ToString()));
                            registryKey.SetValue("End", (object)(str2 + ";" + toDate.ToShortDateString()));
                        }
                    }
                }
                //
                LicenseUtil.UpdateDateToFile(licenseFilePath, DateTime.Now);
            }
            else
            {
                message = "许可文件验证不通过!";
            }
            return flag2;
            #endregion
        }  
        catch
        {
            message = "许可文件可能被篡改!";
            return false;
        }
        
    }
  }
}

许可调用的功能模块:

using System;
using System.Collections.Generic;
using System.IO;
using System.Management;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms;

namespace LicenseCommonUtil
{
  public static class LicenseUtil
  {
    private static string _systemInfo = string.Empty;

    public static Encoding ByteConvertor
    {
      get
      {
        return Encoding.Unicode;
      }
    }

    public static HashAlgorithm DefaultHashAlgorithm
    {
      get
      {
        return (HashAlgorithm) new SHA1CryptoServiceProvider();
      }
    }

    public static string DefaultLicenseFileExtension
    {
      get
      {
        return ".lic";
      }
    }

    public static string SystemInfo
    {
      get
      {
          //如果字符串系统信息为空值
          if (string.IsNullOrEmpty(LicenseUtil._systemInfo))
          {
              /*
               * 1.GetCpuId().ToUpper():获取CPU的ID信息(序列号),并转成大写
               * 2.GetMotherBoardId().ToUpper():
               * 
               * 
               */

              LicenseUtil._systemInfo = LicenseUtil.GetCpuId().ToUpper() + "_" + LicenseUtil.GetMotherBoardId().ToUpper() + "_" + LicenseUtil.GetHardDiskId().ToUpper();
          }
          return LicenseUtil._systemInfo;
      }
    }

    private static string GetCpuId()
    {
        //传入"Win32_Processor"可获得CPU处理器信息
        ManagementObjectCollection instances = new ManagementClass("Win32_Processor").GetInstances();
        
        string str = (string) null;

        //
        using (ManagementObjectCollection.ManagementObjectEnumerator enumerator = instances.GetEnumerator())
        {
            if (enumerator.MoveNext())
                str = enumerator.Current.Properties["ProcessorId"].Value.ToString();
        }
        return str;
    }

    private static string GetHardDiskId()
    {
      ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");
      string str = (string) null;
      foreach (ManagementBaseObject managementBaseObject in managementObjectSearcher.Get())
        str = managementBaseObject["SerialNumber"].ToString().Trim();
      return str;
    }

    private static string GetMotherBoardId()
    {
      //
      ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BaseBoard");
      string str = string.Empty;
      using (ManagementObjectCollection.ManagementObjectEnumerator enumerator = managementObjectSearcher.Get().GetEnumerator())
      {
        if (enumerator.MoveNext())
        {
          object obj = enumerator.Current["SerialNumber"];
          if (obj != null)
            str = obj.ToString();
        }
      }
      return str;
    }

    public static void SaveFile(string fileContent, string defaultExtension, string filter)
    {
      SaveFileDialog saveFileDialog = new SaveFileDialog();
      saveFileDialog.AddExtension = true;
      saveFileDialog.DefaultExt = defaultExtension;
      saveFileDialog.Filter = filter;
      saveFileDialog.FileName = "licenseInfo";
      if (saveFileDialog.ShowDialog() != DialogResult.OK)
        return;
      using (FileStream fileStream = new FileStream(saveFileDialog.FileName, FileMode.Create, FileAccess.Write))
      {
        using (StreamWriter streamWriter = new StreamWriter((Stream) fileStream, Encoding.Default))
        {
          streamWriter.Write(fileContent);
          int num = (int) MessageBox.Show("文件保存成功!", "提示");
        }
      }
    }

    public static void SaveFile(string fileContent, string nyr, string defaultExtension, string filter)
    {
      SaveFileDialog saveFileDialog = new SaveFileDialog();
      saveFileDialog.AddExtension = true;
      saveFileDialog.DefaultExt = defaultExtension;
      saveFileDialog.Filter = filter;
      saveFileDialog.FileName = "license.lic";
      if (saveFileDialog.ShowDialog() != DialogResult.OK)
        return;
      using (FileStream fileStream = new FileStream(saveFileDialog.FileName, FileMode.Create, FileAccess.Write))
      {
        using (StreamWriter streamWriter = new StreamWriter((Stream) fileStream, Encoding.Default))
        {
          streamWriter.WriteLine(fileContent);
          streamWriter.WriteLine(nyr);
          int num = (int) MessageBox.Show("文件保存成功!", "提示");
        }
      }
    }

    public static void SaveFile(string fileContent, string nyr, string todate, string defaultExtension, string filter)
    {
      SaveFileDialog saveFileDialog = new SaveFileDialog();
      saveFileDialog.AddExtension = true;
      saveFileDialog.DefaultExt = defaultExtension;
      saveFileDialog.Filter = filter;
      saveFileDialog.FileName = "license.lic";
      if (saveFileDialog.ShowDialog() != DialogResult.OK)
        return;
      using (FileStream fileStream = new FileStream(saveFileDialog.FileName, FileMode.Create, FileAccess.Write))
      {
        using (StreamWriter streamWriter = new StreamWriter((Stream) fileStream, Encoding.Default))
        {
          streamWriter.WriteLine(fileContent);
          string str = Convert.ToBase64String(Encoding.Default.GetBytes(nyr + "$" + todate));
          streamWriter.WriteLine(str);
          int num = (int) MessageBox.Show("文件保存成功!", "提示");
        }
      }
    }

    public static string ReadContentFromFile(string filePath)
    {
      using (FileStream fileStream = new FileStream(filePath, FileMode.Open))
      {
        using (StreamReader streamReader = new StreamReader((Stream) fileStream, Encoding.Default))
          return streamReader.ReadToEnd();
      }
    }

    public static string ReadContentFromFile2(string filePath)
    {
      using (FileStream fileStream = new FileStream(filePath, FileMode.Open))
      {
        using (StreamReader streamReader = new StreamReader((Stream) fileStream, Encoding.Default))
          //返回第一行的许可信息
          return streamReader.ReadLine();
      }
    }

    public static DateTime ReadDateTiFromFile(string filePath)
    {
      string s = string.Empty;
      string str1 = string.Empty;
      
      using (FileStream fileStream = new FileStream(filePath, FileMode.Open))
      {
        using (StreamReader streamReader = new StreamReader((Stream) fileStream, Encoding.Default))
        {
          string str2;
          do
          {
            str2 = streamReader.ReadLine();
            s = str2 ?? s;
          }
          while (str2 != null);
        }
      }
      return DateTime.Parse(s);
    }

    /// <summary>
    /// 从许可中读取时间信息
    /// </summary>
    /// <param name="filePath"></param>
    /// <param name="fromDate"></param>
    /// <param name="toDate"></param>
    /// <param name="lastDate"></param>
    public static void ReadDateTiFromFile(string filePath, out DateTime fromDate, out DateTime toDate, out DateTime lastDate)
    {
      List<string> list = new List<string>();
      using (FileStream fileStream = new FileStream(filePath, FileMode.Open)) //打开文件流
      {
         using (StreamReader streamReader = new StreamReader((Stream) fileStream, Encoding.Default)) //打开文件流读取内容
         {
            //逐行遍历文件
            //如果行字符串不为空,则继续遍历
            //每次读取新的一行
            for (string str = streamReader.ReadLine(); !string.IsNullOrEmpty(str); str = streamReader.ReadLine())
            {
                //将每行的字符串信息添加到列表中存储
                list.Add(str);
            }
         }
      }
      
      //将当前计算机的本地时间赋值给三个变量
      fromDate = toDate = lastDate = DateTime.Now;

      //获取到列表的第二个索引对应的值
      string s = list[1];

      //如果第二个索引对应的值为空,则返回空值
      if (string.IsNullOrEmpty(s))
        return;
      
      //创建字符串数组
      /* 传入第二行的值
       * 从Base64加密算法解密再转换成字符串
       * 通过'$'符号对字符串进行分割,得到字符串数组,并且返回值不包含空字符串
       * 得到的三个值分别为 fromDate、toDate、lastDate(如果字符串数组的长度大于2)
       * 通过out参数传出
       */
      string[] strArray = Encoding.Default.GetString(Convert.FromBase64String(s)).Split(new char[1]{'$'}, StringSplitOptions.RemoveEmptyEntries);

      //分别对应索引值进行赋值
      fromDate = DateTime.Parse(strArray[0]);
      toDate = DateTime.Parse(strArray[1]);
      if (strArray.Length > 2)
        lastDate = DateTime.Parse(strArray[2]);
      else
        lastDate = fromDate;
    }

    public static void UpdateDateToFile(string filePath, DateTime nowDate)
    {
      List<string> list = new List<string>();
      //只读
      using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
      {
        using (StreamReader streamReader = new StreamReader((Stream) fileStream, Encoding.Default))
        {
            //如果文件行不为空,逐行遍历,并添加到列表中
            for (string str = streamReader.ReadLine(); !string.IsNullOrEmpty(str); str = streamReader.ReadLine())
            {
                list.Add(str);
            }
        }
      }

      
      DateTime dateTime1;
      DateTime dateTime2 = dateTime1 = DateTime.Now;
      
      //许可第二行的内容
      string s = list[1];

      //如果许可第二行不为空
      if (!string.IsNullOrEmpty(s))
      {
        //创建字符串数组
          /* 传入第二行的值
           * 从Base64加密算法解密再转换成字符串
           * 通过'$'符号对字符串进行分割,得到字符串数组,并且返回值不包含空字符串
           */
          string[] strArray = Encoding.Default.GetString(Convert.FromBase64String(s)).Split(new char[1]
        {
          '$'
        }, StringSplitOptions.RemoveEmptyEntries);
          
        //dataTime2是通过Base64解密的通过'$'进行分割得到的第一行时间数据
        dateTime2 = DateTime.Parse(strArray[0]);

        //dataTime1
        dateTime1 = DateTime.Parse(strArray[1]);
      }
    
      //支持写入
      using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Write))
      {
        using (StreamWriter streamWriter = new StreamWriter((Stream) fileStream, Encoding.Default))
        {
          //写入许可文件的第一行内容
          streamWriter.WriteLine(list[0]);

          /* 通过Base64加密算法进行加密
           * 传入参数类型:字节序列
           * 参数:
           *    1.fromDate
           *    2.toDate
           *    3.lastDate
           * 
           */
          string str = Convert.ToBase64String(Encoding.Default.GetBytes(dateTime2.ToString() + (object)"$" + dateTime1.ToShortDateString() + (object)"$" + (object)nowDate.ToString()));
          streamWriter.WriteLine(str);
        }
      }
    }

    public static string GetStringFromByte(byte[] datas)
    {
      if (datas == null)
        return string.Empty;
      string str = string.Empty;
      foreach (byte num in datas)
        str = str + (object) num + "_";
      return str;
    }
  }
}

6.Conclusion

作为一个GIS开发者,我其实想当个房东,每个月开着玛莎拉蒂去收收租多好,想着想着,X突然闪现到我身后的绝对领域,准备gank我,然而我根本是毫无破绽,虽然眼神迷离但是手一刻也没有停歇的敲击着黑轴机械,大眼珠子已经贴在了屏幕上,随着指尖的高潮,这个项目破解算是告一段落了,美女新同事的微信也吹了。

GitHub地址:https://github.com/Asada2142/.Net_EncryptionAnddecryption

猜你喜欢

转载自blog.csdn.net/weixin_42015762/article/details/84134377
今日推荐