吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 9245|回复: 201
上一主题 下一主题
收起左侧

[.NET逆向] [.NET]某 尖顶.办公 系列组件 许可证分析

    [复制链接]
跳转到指定楼层
楼主
pjy612 发表于 2023-5-18 15:01 回帖奖励
本帖最后由 pjy612 于 2023-5-18 15:14 编辑

[.NET]某 尖顶.办公 系列组件 许可证分析

前情提要

看了下论坛,虽然有几篇和这个组件相关的帖子,但似乎没有看到完整的许可分析贴,
所以就弄一个吧,不知道这个层次够不够。

嘉宾介绍

官网地址:aHR0cHM6Ly93d3cuZS1pY2VibHVlLmNvbS9JbnRyb2R1Y2Uvc3BpcmUtb2ZmaWNlLWZvci1uZXQuaHRtbA==
许可证文档:aHR0cHM6Ly93d3cuZS1pY2VibHVlLmNvbS9UdXRvcmlhbHMvTGljZW5zaW5nL0xpY2Vuc2luZy5odG1s

准备工作

包括之前的帖子 首先就是 Nuget 导包,这个真没啥好说的...
然后 弄个控制台程序
然后 Main 里面贴代码  

private static void SpireOfficeTest()
{
    //Spire.License.LicenseProvider.SetLicenseKey("");
    var document = new Spire.Doc.Document();
    var section = document.AddSection();
    var paragraph = section.AddParagraph();
    paragraph.AppendText("Hello World");
    document.SaveToFile("Hello Wrold.doc", Spire.Doc.FileFormat.Doc);
    Console.WriteLine("Word文档创建成功!");

    //Create a new workbook
    var workbook = new Spire.Xls.Workbook();
    //Initialize worksheet        
    var sheet = workbook.Worksheets[0];
    //Append text
    sheet.Range["A1"].Text = "Demo: Save Excel in .NET";
    //Save it as Excel file
    workbook.SaveToFile("Sample.xls", ExcelVersion.Version97to2003);
    Console.WriteLine("Excel 创建成功!");

    BarcodeSettings bs = new BarcodeSettings();
    bs.Type = BarCodeType.Code39;
    bs.Data = "*ABC 12345* ";
    BarCodeGenerator bg = new BarCodeGenerator(bs);
    bg.GenerateImage().Save("Code39Code.png");

    Console.WriteLine("BarCode 创建成功!");

    PdfDocument pdf = new Spire.Pdf.PdfDocument();
    PdfPageBase page = pdf.Pages.Add();
    PdfTrueTypeFont font = new PdfTrueTypeFont(@"C:\WINDOWS\Fonts\CONSOLA.TTF", 20f, PdfFontStyle.Underline);
    PdfSolidBrush brush = new PdfSolidBrush(new PdfRGBColor(System.Drawing.Color.Blue));
    page.Canvas.DrawString("Hello E-iceblue Support Team", font, brush, new PointF(10, 20));
    pdf.SaveToFile("Result.pdf", Spire.Pdf.FileFormat.PDF);
    Console.WriteLine("PDF 创建成功!");

    //create PPT document
    Presentation presentation = new Spire.Presentation.Presentation();
    //add new shape to PPT document           
    IAutoShape shape = presentation.Slides[0]
        .Shapes.AppendShape(Spire.Presentation.ShapeType.Rectangle,
            new RectangleF(0, 50, 200, 50));
    shape.ShapeStyle.LineColor.Color = Color.White;
    shape.Fill.FillType = Spire.Presentation.Drawing.FillFormatType.None;
    //add text to shape
    shape.AppendTextFrame("Hello World!");
    //set the Font fill style of text  
    var textRange = shape.TextFrame.TextRange;
    textRange.Fill.FillType = Spire.Presentation.Drawing.FillFormatType.Solid;
    textRange.Fill.SolidColor.Color = Color.Black;
    textRange.LatinFont = new TextFont("Arial Black");
    //save the document
    presentation.SaveToFile("hello.pptx", Spire.Presentation.FileFormat.Pptx2010);
    Console.WriteLine("PPT 创建成功!");

    var addressFrom = new Spire.Email.MailAddress("daisy.zhang@e-iceblue.com", "Daisy Zhang");
    var addressTo = new Spire.Email.MailAddress("susanwong32@outlook.com");
    var mail = new Spire.Email.MailMessage(addressFrom, addressTo);
    mail.Subject = "This is a test message";
    string htmlString = @"
        <p>Dear Ms. Susan,</p>
        <p>This is an example of creating an <b>outlook message</b> <u>(msg)</u>.</p>
        <ul>
        <li> Create a message with RTF file </li>
        <li> Create a message with attachment</li>
        </ul>
        <p style='color:red'>This text is in red </p>
        <p>Best regards, </p>
        <p>Daisy </p>";
    mail.BodyHtml = htmlString;
    mail.Attachments.Add(new Spire.Email.Attachment("Code39Code.png"));
    mail.Save("Sample.msg", Spire.Email.MailMessageFormat.Msg);
    Console.WriteLine("Mail 创建成功!");
}

开工

我们直接从Demo中查一下 Spire.License.LicenseProvider.SetLicenseKey 这玩意的所属。

发现 所属于 Spire.Pdf.dll
后面专门分析它就行了。
简单看一眼 有字符串混淆  

为了方便 分析和理解,老样子 de4dot 处理下先。  

由于该库用了类似韩文混淆,后续为了方便解说,我会使用 dnspy 适当修改一些字段或函数名便于理解  

自然是 先分析 SetLicenseKey 这个函数了,并分析调用。  

// Spire.License.LicenseProvider
// Token: 0x06011D49 RID: 73033
private static spr癝_LicenseInfo 권_LoadLicenseByLicenseKey(string A_0)
{
        return spr禛.께_LoadLicenseByLicenseKey(A_0);
}

继续追  

然后看 DecodeAndCheckKey

// spr禛
// Token: 0x06010117 RID: 65815
private static byte[] 권_DecodeAndCheck(string A_0_licenseKey, bool A_1_hashBytes)
{
    byte[] array = Convert.FromBase64String(A_0_licenseKey); //licenseKey 是 base64编码的
    byte[] array2 = new byte[15];
    //复制前15个字节
    Array.Copy(array, array2, array2.Length); 
    //取第一个字节的值,然后对13取余
    int num = (int)(array2[0] % 13); 
    //取第num+1个字节的值,然后与255取与,再左移8位,然后与第num+2个字节的值与255取与,最后取或
    //也就是取第num+1个字节和第num+2个字节的值,然后组成一个short类型的值
    byte[] array3 = new byte[((int)(array2[num + 1] & byte.MaxValue) << 8) | (int)(array2[num + 2] & byte.MaxValue)]; 
    //然后将 15 之后 到 array3 长度的字节 复制到 array3
    //所以 ((int)(array2[num + 1] & byte.MaxValue) << 8) | (int)(array2[num + 2] & byte.MaxValue) 为 array 的长度 
    //然后 结合下文 可以知道 array3 是 sign,array4 是 验签data
    Array.Copy(array, 15, array3, 0, array3.Length);
    num = array2.Length + array3.Length;
    byte[] array4 = new byte[array.Length - num]; // head[15] + sign 之后的数据 全取出来 为 data
    Array.Copy(array, num, array4, 0, array4.Length);
    using (RSACryptoServiceProvider rsacryptoServiceProvider = new RSACryptoServiceProvider())
    {
            rsacryptoServiceProvider.ImportParameters(new RSAParameters
            {
                    Modulus = spr瑫.권_RSA_Modulus,
                    Exponent = spr瑫.귟_RSA_Exponent
            });
            if (!rsacryptoServiceProvider.VerifyData(array4, new SHA1CryptoServiceProvider(), array3)) //验证签名
            {
                    return null;
            }
    }

    byte[] array5 = new byte[(int)array4[0]];
    Array.Copy(array4, 1, array5, 0, array5.Length);
    byte[] array6 = new byte[array4.Length - 1 - array5.Length];
    Array.Copy(array4, 1 + array5.Length, array6, 0, array6.Length);
    byte[] array7 = null;

    //根据 array4 首位来截取 DES 的 IV
    //然后 将 之后的数据 进行解密
    using (DESCryptoServiceProvider descryptoServiceProvider = new DESCryptoServiceProvider())
    {
            descryptoServiceProvider.Key = spr瑫.긲_DES_Key;
            descryptoServiceProvider.IV = array5;
            using (MemoryStream memoryStream = new MemoryStream(array6))
            {
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, descryptoServiceProvider.CreateDecryptor(), CryptoStreamMode.Read))
                    {
                            using (MemoryStream memoryStream2 = new MemoryStream())
                            {
                                    byte[] array8 = new byte[1024];
                                    int num2;
                                    while ((num2 = cryptoStream.Read(array8, 0, array8.Length)) > 0)
                                    {
                                            memoryStream2.Write(array8, 0, num2);
                                    }
                                    array7 = memoryStream2.ToArray();
                            }
                    }
            }
    }
    //DES 解密后的数据 用一个自定义算法计算一下 hash
    if (A_1_hashBytes)
    {
            spr禛.긲_LicenseBytesHash = spr禛.권_HashBytes(array7);
    }
    return array7;
}

由上述解码函数可以得知

//LicenseKey 由 15字节的head + sign + data 后 base64 组成  
//data 由 DESIV.Len + DESIV + DES(LicenseBytes) 组成
//其中 heade 只有 根据首位 计算的下标 +1 和 +2 的值有用 对应实现运算后 要等与 sing 的长度
//伪代码

data = DESIV.Len + DESIV + DES(LicenseBytes)
sign = RSASign(data)
head = 随机生成15字节()
int num = head[0] % 13
calcSignLen(sign.Len,out int n1,out int n2);
head[num+1] = n1;
head[num+2] = n2;
LicenseKey = base64(head + sign + data)

接着 继续看 LicenseBytes 是怎么解析的  

// spr禛
// Token: 0x0601010D RID: 65805
private static spr矼_LicenseInfo 귟_ParseLicenseStream(Stream A_0)
{
        if (A_0 == null)
        {
                return null;
        }
        spr矼_LicenseInfo spr矼_LicenseInfo = null;
        A_0.Position = 0L;
        using (XmlReader xmlReader = XmlReader.Create(A_0))
        {
                bool flag = false;
                bool flag2 = false;
                while (!xmlReader.EOF)
                {
            //License 节点
                        if (xmlReader.LocalName == "License") 
                        {
                                if (!xmlReader.IsEmptyElement && xmlReader.NodeType == XmlNodeType.Element)
                                {
                                        if (spr矼_LicenseInfo == null)
                                        {
                                                spr矼_LicenseInfo = new spr矼_LicenseInfo();
                                        }
                                        string attribute = xmlReader.GetAttribute("Key"); //License Key 子节点
                                        string attribute2 = xmlReader.GetAttribute("Version");//License Version 子节点
                                        spr矼_LicenseInfo.꼫_SetKey(attribute);
                                        spr矼_LicenseInfo.嘬_SetVersion(attribute2);
                                        flag = true;
                                }
                        }
            //ServerInfo 节点
                        else if (xmlReader.LocalName == "ServerInfo" && !xmlReader.IsEmptyElement && xmlReader.NodeType == XmlNodeType.Element)
                        {
                                if (spr矼_LicenseInfo == null)
                                {
                                        spr矼_LicenseInfo = new spr矼_LicenseInfo();
                                }
                                spr矼_LicenseInfo.꽾_SetServerInfoString(xmlReader.ReadInnerXml());
                                flag2 = true;
                        }
                        if (flag && flag2)
                        {
                                break;
                        }
                        xmlReader.Read();
                        spr禛.권_XmlReaderNext(xmlReader);
                }
        }
        return spr矼_LicenseInfo; 
}

比较直观和简洁 LicenseBytes 是个 XML 里面 有 License 和 ServerInfo 两个节点。

// spr禛_LicenseManager
// Token: 0x0601010E RID: 65806
private static spr癝_LicenseInfo 권_ParseLicenseStream2(Stream A_0)
{
        if (A_0 == null)
        {
                return null;
        }
        spr癝_LicenseInfo spr癝_LicenseInfo = new spr癝_LicenseInfo();
        A_0.Position = 0L;
        using (XmlReader xmlReader = XmlReader.Create(A_0))
        {
                while (!xmlReader.EOF)
                {
                        string localName = xmlReader.LocalName;
                        uint num = spr縥.권(localName); //这个不用管 类似控制流 混淆 决定下一步判断走哪儿 不影响分析
                        if (num <= 1127555431U)
                        {
                                if (num <= 470340825U)
                                {
                                        if (num != 426894090U)
                                        {
                                                if (num == 470340825U)
                                                {
                                                        if (localName == "Username" && !xmlReader.IsEmptyElement && xmlReader.NodeType == XmlNodeType.Element)
                                                        {
                                                                if (string.IsNullOrEmpty(xmlReader.Value))
                                                                {
                                                                        xmlReader.Read();
                                                                        spr禛_LicenseManager.권_XmlReaderNext(xmlReader);
                                                                }
                                                                if (xmlReader.NodeType == XmlNodeType.Text)
                                                                {
                                                                        spr癝_LicenseInfo.귟_SetUsername(xmlReader.Value);
                                                                }
                                                        }
                                                }
                                        }
                                        else if (localName == "Organization" && !xmlReader.IsEmptyElement && xmlReader.NodeType == XmlNodeType.Element)
                                        {
                                                if (string.IsNullOrEmpty(xmlReader.Value))
                                                {
                                                        xmlReader.Read();
                                                        spr禛_LicenseManager.권_XmlReaderNext(xmlReader);
                                                }
                                                if (xmlReader.NodeType == XmlNodeType.Text)
                                                {
                                                        spr癝_LicenseInfo.꺅_SetOrganization(xmlReader.Value);
                                                }
                                        }
                                }
                                else if (num != 795632884U)
                                {
                                        if (num != 954666724U)
                                        {
                                                if (num == 1127555431U)
                                                {
                                                        if (localName == "Email" && !xmlReader.IsEmptyElement && xmlReader.NodeType == XmlNodeType.Element)
                                                        {
                                                                if (string.IsNullOrEmpty(xmlReader.Value))
                                                                {
                                                                        xmlReader.Read();
                                                                        spr禛_LicenseManager.권_XmlReaderNext(xmlReader);
                                                                }
                                                                if (xmlReader.NodeType == XmlNodeType.Text)
                                                                {
                                                                        spr癝_LicenseInfo.긲_SetEmail(xmlReader.Value);
                                                                }
                                                        }
                                                }
                                        }
                                        else if (localName == "License" && !xmlReader.IsEmptyElement && xmlReader.NodeType == XmlNodeType.Element)
                                        {
                                                string attribute = xmlReader.GetAttribute("Key");
                                                string attribute2 = xmlReader.GetAttribute("Version");
                                                spr癝_LicenseInfo.꼫_SetKey(attribute);
                                                spr癝_LicenseInfo.嘬_SetVersion(attribute2);
                                        }
                                }
                                else if (localName == "LicensedDate" && !xmlReader.IsEmptyElement && xmlReader.NodeType == XmlNodeType.Element)
                                {
                                        if (string.IsNullOrEmpty(xmlReader.Value))
                                        {
                                                xmlReader.Read();
                                                spr禛_LicenseManager.권_XmlReaderNext(xmlReader);
                                        }
                                        DateTime dateTime;
                                        if (xmlReader.NodeType == XmlNodeType.Text && DateTime.TryParse(xmlReader.Value, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out dateTime))
                                        {
                                                spr癝_LicenseInfo.권_SetLicensedDate(dateTime);
                                        }
                                }
                        }
                        else if (num <= 3213063382U)
                        {
                                if (num != 2565758308U)
                                {
                                        if (num == 3213063382U)
                                        {
                                                if (localName == "Issuer" && !xmlReader.IsEmptyElement && xmlReader.NodeType == XmlNodeType.Element)
                                                {
                                                        spr禛_LicenseManager.귟_SetIssuer(xmlReader, spr癝_LicenseInfo);
                                                }
                                        }
                                }
                                else if (localName == "SerialNumber" && !xmlReader.IsEmptyElement && xmlReader.NodeType == XmlNodeType.Element)
                                {
                                        if (string.IsNullOrEmpty(xmlReader.Value))
                                        {
                                                xmlReader.Read();
                                                spr禛_LicenseManager.권_XmlReaderNext(xmlReader);
                                        }
                                        if (xmlReader.NodeType == XmlNodeType.Text)
                                        {
                                                spr癝_LicenseInfo.권_SerialNumber(xmlReader.Value);
                                        }
                                }
                        }
                        else if (num != 3316904022U)
                        {
                                if (num != 3408678061U)
                                {
                                        if (num == 3512062061U)
                                        {
                                                if (localName == "Type" && !xmlReader.IsEmptyElement && xmlReader.NodeType == XmlNodeType.Element)
                                                {
                                                        if (string.IsNullOrEmpty(xmlReader.Value))
                                                        {
                                                                xmlReader.Read();
                                                                spr禛_LicenseManager.권_XmlReaderNext(xmlReader);
                                                        }
                                                        if (xmlReader.NodeType == XmlNodeType.Text)
                                                        {
                                                                spr癝_LicenseInfo.권_LicenseType(spr禛_LicenseManager.꺅_ParseLicenseType(xmlReader.Value));
                                                        }
                                                }
                                        }
                                }
                                else if (localName == "Products" && !xmlReader.IsEmptyElement && xmlReader.NodeType == XmlNodeType.Element)
                                {
                                        spr禛_LicenseManager.권_SetProducts(xmlReader, spr癝_LicenseInfo);
                                }
                        }
                        else if (localName == "ExpiredDate" && !xmlReader.IsEmptyElement && xmlReader.NodeType == XmlNodeType.Element)
                        {
                                if (string.IsNullOrEmpty(xmlReader.Value))
                                {
                                        xmlReader.Read();
                                        spr禛_LicenseManager.권_XmlReaderNext(xmlReader);
                                }
                                DateTime dateTime2;
                                if (xmlReader.NodeType == XmlNodeType.Text && DateTime.TryParse(xmlReader.Value, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out dateTime2))
                                {
                                        spr癝_LicenseInfo.귟_ExpiredDate(dateTime2);
                                }
                        }
                        xmlReader.Read();
                        spr禛_LicenseManager.권_XmlReaderNext(xmlReader);
                }
        }
        return spr癝_LicenseInfo;
}
// spr禛_LicenseManager
// Token: 0x0601010F RID: 65807
private static void 귟_SetIssuer(XmlReader A_0, spr癝_LicenseInfo A_1)
{
        if (A_0 != null && A_1 != null)
        {
                if (A_0.LocalName == "Issuer")
                {
                        if (!A_0.IsEmptyElement)
                        {
                                A_1.권_SetIssuerInfo(new spr皰_IssuerInfo());
                        }
                        A_0.Read();
                        spr禛_LicenseManager.권_XmlReaderNext(A_0);
                        while (A_0.LocalName != "Issuer")
                        {
                                string localName = A_0.LocalName;
                                if (!(localName == "Name"))
                                {
                                        if (!(localName == "Email"))
                                        {
                                                if (localName == "Url" && !A_0.IsEmptyElement && A_0.NodeType == XmlNodeType.Element)
                                                {
                                                        if (string.IsNullOrEmpty(A_0.Value))
                                                        {
                                                                A_0.Read();
                                                                spr禛_LicenseManager.권_XmlReaderNext(A_0);
                                                        }
                                                        if (A_0.NodeType == XmlNodeType.Text)
                                                        {
                                                                A_1.뀤_GetIssuerInfo().긲_SetUrl(A_0.Value);
                                                        }
                                                }
                                        }
                                        else if (!A_0.IsEmptyElement && A_0.NodeType == XmlNodeType.Element)
                                        {
                                                if (string.IsNullOrEmpty(A_0.Value))
                                                {
                                                        A_0.Read();
                                                        spr禛_LicenseManager.권_XmlReaderNext(A_0);
                                                }
                                                if (A_0.NodeType == XmlNodeType.Text)
                                                {
                                                        A_1.뀤_GetIssuerInfo().귟_SetEmail(A_0.Value);
                                                }
                                        }
                                }
                                else if (!A_0.IsEmptyElement && A_0.NodeType == XmlNodeType.Element)
                                {
                                        if (string.IsNullOrEmpty(A_0.Value))
                                        {
                                                A_0.Read();
                                                spr禛_LicenseManager.권_XmlReaderNext(A_0);
                                        }
                                        if (A_0.NodeType == XmlNodeType.Text)
                                        {
                                                A_1.뀤_GetIssuerInfo().권_SetName(A_0.Value);
                                        }
                                }
                                A_0.Read();
                                spr禛_LicenseManager.권_XmlReaderNext(A_0);
                        }
                }
                return;
        }
}

// spr禛_LicenseManager
// Token: 0x06010110 RID: 65808
private static void 권_SetProducts(XmlReader A_0, spr癝_LicenseInfo A_1)
{
        if (A_0 != null && A_1 != null)
        {
                if (A_0.LocalName == "Products")
                {
                        A_0.Read();
                        spr禛_LicenseManager.권_XmlReaderNext(A_0);
                        List<spr眃_ProductInfo> list = new List<spr眃_ProductInfo>();
                        spr眃_ProductInfo spr眃_ProductInfo = new spr眃_ProductInfo();
                        while (A_0.LocalName != "Products")
                        {
                                string localName = A_0.LocalName;
                                if (!(localName == "Product"))
                                {
                                        if (!(localName == "Name"))
                                        {
                                                if (!(localName == "Version"))
                                                {
                                                        if (localName == "Subscription" && !A_0.IsEmptyElement && A_0.NodeType == XmlNodeType.Element)
                                                        {
                                                                spr禛_LicenseManager.권_SetSubscription(A_0, spr眃_ProductInfo);
                                                        }
                                                }
                                                else if (!A_0.IsEmptyElement && A_0.NodeType == XmlNodeType.Element)
                                                {
                                                        if (string.IsNullOrEmpty(A_0.Value))
                                                        {
                                                                A_0.Read();
                                                                spr禛_LicenseManager.권_XmlReaderNext(A_0);
                                                        }
                                                        if (A_0.NodeType == XmlNodeType.Text)
                                                        {
                                                                spr眃_ProductInfo.귟_SetVersion(A_0.Value);
                                                        }
                                                }
                                        }
                                        else if (!A_0.IsEmptyElement && A_0.NodeType == XmlNodeType.Element)
                                        {
                                                if (string.IsNullOrEmpty(A_0.Value))
                                                {
                                                        A_0.Read();
                                                        spr禛_LicenseManager.권_XmlReaderNext(A_0);
                                                }
                                                if (A_0.NodeType == XmlNodeType.Text)
                                                {
                                                        spr眃_ProductInfo.권_Name(A_0.Value);
                                                }
                                        }
                                }
                                else if (!A_0.IsEmptyElement && A_0.NodeType == XmlNodeType.Element)
                                {
                                        spr眃_ProductInfo = new spr眃_ProductInfo();
                                        list.Add(spr眃_ProductInfo);
                                }
                                A_0.Read();
                                spr禛_LicenseManager.권_XmlReaderNext(A_0);
                        }
                        if (list.Count > 0)
                        {
                                A_1.권_SetProductInfos(list.ToArray());
                        }
                }
                return;
        }
}

// spr禛_LicenseManager
// Token: 0x06010111 RID: 65809
private static void 권_SetSubscription(XmlReader A_0, spr眃_ProductInfo A_1)
{
        if (A_0 != null && A_1 != null)
        {
                if (A_0.LocalName == "Subscription")
                {
                        A_0.Read();
                        spr禛_LicenseManager.권_XmlReaderNext(A_0);
                        A_1.권_SubscriptionInfo(new spr睖_SubscriptionInfo());
                        while (A_0.LocalName != "Subscription")
                        {
                                string localName = A_0.LocalName;
                                if (!(localName == "NumberOfPermittedDeveloper"))
                                {
                                        if (!(localName == "NumberOfPermittedSite"))
                                        {
                                                if (localName == "NumberOfServerLicenses" && !A_0.IsEmptyElement && A_0.NodeType == XmlNodeType.Element)
                                                {
                                                        if (string.IsNullOrEmpty(A_0.Value))
                                                        {
                                                                A_0.Read();
                                                                spr禛_LicenseManager.권_XmlReaderNext(A_0);
                                                        }
                                                        if (A_0.NodeType == XmlNodeType.Text)
                                                        {
                                                                string value = A_0.Value;
                                                                int num;
                                                                if (!string.IsNullOrEmpty(value) && int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out num))
                                                                {
                                                                        A_1.긲_SubscriptionInfo().긲_NumberOfServerLicenses(num);
                                                                }
                                                        }
                                                }
                                        }
                                        else if (!A_0.IsEmptyElement && A_0.NodeType == XmlNodeType.Element)
                                        {
                                                if (string.IsNullOrEmpty(A_0.Value))
                                                {
                                                        A_0.Read();
                                                        spr禛_LicenseManager.권_XmlReaderNext(A_0);
                                                }
                                                if (A_0.NodeType == XmlNodeType.Text)
                                                {
                                                        string value2 = A_0.Value;
                                                        int num2;
                                                        if (!string.IsNullOrEmpty(value2) && int.TryParse(value2, NumberStyles.Integer, CultureInfo.InvariantCulture, out num2))
                                                        {
                                                                A_1.긲_SubscriptionInfo().귟_NumberOfPermittedSite(num2);
                                                        }
                                                }
                                        }
                                }
                                else if (!A_0.IsEmptyElement && A_0.NodeType == XmlNodeType.Element)
                                {
                                        if (string.IsNullOrEmpty(A_0.Value))
                                        {
                                                A_0.Read();
                                                spr禛_LicenseManager.권_XmlReaderNext(A_0);
                                        }
                                        if (A_0.NodeType == XmlNodeType.Text)
                                        {
                                                string value3 = A_0.Value;
                                                int num3;
                                                if (!string.IsNullOrEmpty(value3) && int.TryParse(value3, NumberStyles.Integer, CultureInfo.InvariantCulture, out num3))
                                                {
                                                        A_1.긲_SubscriptionInfo().권_NumberOfPermittedDeveloper(num3);
                                                }
                                        }
                                }
                                A_0.Read();
                                spr禛_LicenseManager.권_XmlReaderNext(A_0);
                        }
                }
                return;
        }
}

上面的也没啥好说的 就是 单纯的 解析 XML 根据上面的 代码 可以得到 许可证的 XML 模板

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<License Key="" Version="">
    <Type></Type>
    <Username></Username>
    <Email></Email>
    <Organization></Organization>
    <LicensedDate></LicensedDate>
    <ExpiredDate></ExpiredDate>
    <Products>
        <Product>
            <Name></Name>
            <Version></Version>
            <Subscription>
                <NumberOfServerLicenses></NumberOfServerLicenses>
                <NumberOfPermittedDeveloper></NumberOfPermittedDeveloper>
                <NumberOfPermittedSite></NumberOfPermittedSite>
            </Subscription>
        </Product>
    </Products>
    <Issuer>
        <Name></Name>
        <Email></Email>
        <Url></Url>
    </Issuer>
</License>
<ServerInfo>
</ServerInfo>

但是 我们好像还没碰到这些值具体都有什么用。
那就 接着往上层回溯

发现 红框中的 赋值 好像并没有 在之前的解析中 涉及到,咱们查一下 谁改动和读取了这里。  

// spr璾
// Token: 0x0601007F RID: 65663
internal static spr癝_LicenseInfo 권_VerifyLicense(spr癝_LicenseInfo A_0, Type A_1, object A_2)
{
        if (A_0 == null)
        {
                return null;
        }
        Assembly assembly = Assembly.GetAssembly(A_1);
        AssemblyName name = assembly.GetName();
        string text = spr璾.권(assembly);
        text = text.Replace(".Office.", ".");

        PackageAttribute[] array = PackageAttribute.GetPackage(assembly); // 取程序集上的 Package 特性
        PackageAttribute packageAttribute = null;
        DateTime? dateTime;

        PackageAttribute[] array2 = spr璾.권(assembly, array, out dateTime);  
        // 这里又过了一次 特性校验 有兴趣可以自己深入
        // dateTime 默认是 程序集特性 [assembly: ReleaseDate("2023-04-27")] 但是 会过一次解码验证 可能被重新赋值。
        // 由于我们对这些不做改动 所以略过
        if (array2 != null)
        {
                array = array2;
        }
        spr眃_ProductInfo spr眃_ProductInfo = null;
        spr眃_ProductInfo[] array3 = A_0.꿑_GetProductInfos();
        int i = 0;
        while (i < array3.Length)
        {
                spr眃_ProductInfo spr眃_ProductInfo2 = array3[i];
                string text2 = spr眃_ProductInfo2.권_Name().Replace(".Office.", ".");
                //版本号得有效 至少大于 1.3
                if (((A_0.녰_GetMergedLicenseVersionInfo() != null && A_0.녰_GetMergedLicenseVersionInfo().권_DiffVersion(1, 3) >= 0) || (A_0.녰_GetMergedLicenseVersionInfo() == null && A_0.뉩_GetLicenseVersionInfo().권_DiffVersion(1, 3) >= 0)) && array != null && array.Length != 0)
                {
                        PackageAttribute[] array4 = array;
                        int j = 0;
                        while (j < array4.Length)
                        {
                                PackageAttribute packageAttribute2 = array4[j];
                                if (!packageAttribute2.Name.Equals(text2))
                                {
                                        j++;
                                }
                                else
                                {
                                        packageAttribute = packageAttribute2;
                                        spr眃_ProductInfo = spr眃_ProductInfo2;
                                        IL_EC:
                                        if (spr眃_ProductInfo == null)
                                        {
                                                goto IL_F0;
                                        }
                                        goto IL_111; // license 中的 Product 的 Name 至少要和 Package 中的 一个一致。
                                }
                        }
                        goto IL_EC;
                }
                IL_F0:
                if (!text.Equals(text2))
                {
                        i++;
                        continue;
                }
                spr眃_ProductInfo = spr眃_ProductInfo2;
                IL_111:
                if (spr眃_ProductInfo == null)
                {
                        return null;
                }
                if (spr璾.권_CheckBlackList(A_0)) //判断 黑名单,自己构建的许可证可以无视这个
                {
                        A_0.긲_InValid(true); //在就知道 之前没涉及到 字段 true 的情况为失效
                        A_0.께_ErrorMsg("Your license has been blacklisted, please contact E-ICEBLUE sales to obtain a new license.");
                        return A_0;
                }
                spr瞩_SubscriptionType spr瞩_SubscriptionType = spr眃_ProductInfo.긲_SubscriptionInfo().께_SubscriptionType();
                if (spr瞩_SubscriptionType == spr瞩_SubscriptionType.꼫_CloudServer) //云
                {
                        // CloudServer 的订阅模式需要额外解析 ServerInfo 我们不需要 可以略过
                        if (string.IsNullOrEmpty(A_0.늼_GetServerInfoString())) 
                        {
                                return null;
                        }
                        List<spr畤> list = spr甑.꺅();
                        if (list == null && list.Count <= 0)
                        {
                                return null;
                        }
                        string text3 = spr甑.권(A_0.늼_GetServerInfoString());
                        spr疷 spr疷 = new spr疷(text3);
                        if (string.IsNullOrEmpty(spr疷.권()) || string.IsNullOrEmpty(spr疷.귟()))
                        {
                                return null;
                        }
                        bool flag = false;
                        foreach (spr畤 spr畤 in list)
                        {
                                if (!flag && spr疷.귟().Contains(spr畤.귟()) && spr疷.권().Contains(spr畤.긲()))
                                {
                                        flag = true;
                                        break;
                                }
                        }
                        if (!flag)
                        {
                                return null;
                        }
                }
                //LicenseType 为 demo 或 unknow 需要 验证 过期时间是否小于当前时间
                if (A_0.귟_LicenseType() == spr碢_LicenseType.귟_demo || A_0.귟_LicenseType() == spr碢_LicenseType.꺅_unknow)
                {
                        DateTime dateTime2 = DateTime.Now.ToUniversalTime();
                        A_0.긲_InValid(A_0.꽾_ExpiredDate() < dateTime2);
                }
                if (A_0.덢_InValid()) //失效就直接返回
                {
                        return A_0;
                }
                if (dateTime != null) //如果程序集有发布时间 则 ExpiredDate 需要 大于 发布时间,ExpiredDate 看来是必填
                {
                        A_0.긲_InValid(A_0.꽾_ExpiredDate() < dateTime);
                }
                if (A_0.덢_InValid()) //失效就直接返回
                {
                        return A_0;
                }

                // LicensedDate 和 ExpiredDate 再和 ProductVersion 做了一层比较,不重要 大就完事了!
                int num = spr璾.권(A_0.꼫_GetLicensedDate(), A_0.꽾_ExpiredDate());                 
                if (spr璾.권(spr璾.권(spr眃_ProductInfo.귟_GetVersion(), A_0.꼫_GetLicensedDate()), (packageAttribute != null) ? packageAttribute.Version : string.Format("{0}.{1}", name.Version.Major, name.Version.Minor)) > num)
                {
                        A_0.긲_InValid(true);
                }
                if (A_0.덢_InValid())
                {
                        return A_0;
                }

                //如果之前没判定为失效的话 
                //如果订阅类型为 Developer 或 SiteEnterprise 且 ExpiredDate 大于当前时间
                //会将 License 上报到 服务器???
                if (!A_0.덢_InValid() && (spr瞩_SubscriptionType == spr瞩_SubscriptionType.귟_Developer || spr瞩_SubscriptionType == spr瞩_SubscriptionType.꺅_SiteEnterprise) && A_0.꽾_ExpiredDate() >= DateTime.Now)
                {
                        try
                        {
                                if (!spr笺.꺅_IsInServerBlackList()) //如果服务器返回 1 或者 别的 就会标记为 true。 然后 再走就默认失效了。
                                {

                                        spr笺.긲_ReportLicenseToServer(A_0.넝_GetSerialNumberOrMD5LicenseKey(), A_0.긲_GetUsername(), (int)spr瞩_SubscriptionType, spr竧.권_DateFormate(A_0.꽾_ExpiredDate()));
                                        goto IL_36A;
                                }
                                A_0.긲_InValid(true);
                        }
                        catch (Exception ex)
                        {
                                spr竧.권("LicenseUtilities_Validate", ex);
                                goto IL_36A;
                        }
                        return A_0;
                }
                IL_36A:
                if (A_0.귟_LicenseType() == spr碢_LicenseType.꺅_unknow)
                {
                        A_0.권_LicenseType(spr碢_LicenseType.긲_runtime);
                }
                return A_0;
        }
        goto IL_111;
}

所以 我们 不能 配置为 Developer 或 SiteEnterprise 的订阅。

internal spr瞩_SubscriptionType 께_SubscriptionType()
{
        if (this.긲_NumberOfServerLicenses() > 0)
        {
                return spr瞩_SubscriptionType.꼫_CloudServer;
        }
        if (this.권_NumberOfPermittedDeveloper() == 1 && this.귟_NumberOfPermittedSite() == 1)
        {
                return spr瞩_SubscriptionType.귟_Developer;
        }
        if (this.권_NumberOfPermittedDeveloper() == 1 && this.귟_NumberOfPermittedSite() == 2147483647)
        {
                return spr瞩_SubscriptionType.긲_DeveloperOEM;
        }
        if (this.권_NumberOfPermittedDeveloper() == 10 && this.귟_NumberOfPermittedSite() == 10)
        {
                return spr瞩_SubscriptionType.꺅_SiteEnterprise;
        }
        if (this.권_NumberOfPermittedDeveloper() == 50 && this.귟_NumberOfPermittedSite() == 2147483647)
        {
                return spr瞩_SubscriptionType.께_SiteOEM;
        }
        return spr瞩_SubscriptionType.귟_Developer;
}

可选的就是 DeveloperOEM 或 SiteOEM。

我们再来看 最后一个函数

那么 License 完整答案就有了!其他没什么用的 拿掉拿掉~

const string licTemplate = @"<?xml version=""1.0"" encoding=""utf-8"" standalone=""yes""?>
<License Key=""52Pojie"" Version=""999.999"">
    <Type>Runtime</Type>
    <Username>52Pojie</Username>
    <LicensedDate>2099-01-01T12:00:00Z</LicensedDate>
    <ExpiredDate>2099-12-31T12:00:00Z</ExpiredDate>
    <Products>
        <Product>
            <Name>Spire.Office Platinum</Name>
            <Version>999.999</Version>
            <Subscription>
                <NumberOfPermittedDeveloper>50</NumberOfPermittedDeveloper>
                <NumberOfPermittedSite>2147483647</NumberOfPermittedSite>
            </Subscription>
        </Product>
    </Products>
</License>";

生成许可证


string GetLicense()
{
        //根据字节长度 计算一下 head 需要设置的 n1 和 n2
        bool genHeader(int signLen, out byte b1, out byte b2)
        {
                for (int i = 0; i <= byte.MaxValue; i++)
                {
                        for (int j = 0; j <= byte.MaxValue; j++)
                        {
                                int value = ((int)(i & byte.MaxValue) << 8) | (int)(j & byte.MaxValue);
                                if (value == signLen)
                                {
                                        b1 = (byte)i;
                                        b2 = (byte)j;
                                        return true;
                                }
                        }
                }
                b1 = b2 = 0;
                return false;
        }
        //SpireOffice DES 的 Key 从程序集提取  
        byte[] DES_KEY = { 172, 252, 51, 200, 6, 139, 36, 230 };
        byte[] sign = new byte[256]; //Sign长度默认 256,懒得生成 直接写个死的
        //DES加密 IV 生成后 抛出
        byte[] DES(string x, out byte[] iv)
        {
                using (var descryptoServiceProvider = new DESCryptoServiceProvider())
                {
                        descryptoServiceProvider.Key = DES_KEY;
                        iv = descryptoServiceProvider.IV;
                        using (var memoryStream = new MemoryStream())
                        {
                                using (var cryptoStream = new CryptoStream(memoryStream, descryptoServiceProvider.CreateEncryptor(), CryptoStreamMode.Write))
                                {
                                        byte[] buffer = Encoding.UTF8.GetBytes(x);
                                        cryptoStream.Write(buffer, 0, buffer.Length);
                                }

                                return memoryStream.ToArray();
                        }
                }
        }
        //给对license 进行 DES 得到 IV
        byte[] licDesData = DES(licTemplate, out byte[] IV);
        using var ms = new MemoryStream();
        using var bw = new BinaryWriter(ms);
        bw.Write((byte)IV.Length); //写IV长度
        bw.Write(IV); //写IV
        bw.Write(licDesData); //写DES后的许可证
        byte[] data = ms.ToArray(); //提取字节数组

        //重置 MemoryStream
        ms.Seek(0, SeekOrigin.Begin);
        ms.SetLength(0);

        //Generator Random Header
        var head = new byte[15]; 
        //随机生成 15 个字节
        RandomNumberGenerator.Create().GetBytes(head);

        var num = head[0] % 13; //进行运算
        //计算 n1 n2
        if (genHeader(sign.Length, out var num1, out var num2))
        {
                head[num + 1] = num1;
                head[num + 2] = num2;
                bw.Write(head);//写head
                bw.Write(sign);//写sign
                bw.Write(data);//写body
                bw.Flush();
                return Convert.ToBase64String(ms.ToArray());//返回结果
        }
        return "";
}

验证

生成一个 License

PF82R8LWxV8dAQC8/toZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjGAKOCYiGhh9jGrfm3vT/Y1fcdDhaAmvgYw1ppUKudl811mv5I6IccnGjD4b42bNZo6/RaMd4Z4V7VzsvoSUUr8em6t8puATVS+oNPiUGSYROTLBvE/rE4WKodXu83ZhUDLyh3CSeV8735GOdxAbB23bilhiaUEwieHNKDepjMX28ENvPweqq55XP1l9bKVsUGbiIXWEttYfQKTt14DLpRZTMQiq1lXqKeOXOTbti3ZC3Vqcepqc+0ujiiFAwHNfrtfD8UllEJZ+jDUt0iqUxRicdDCZ/ZXpaFcZ5NlG8jVmCzA1oOvp1SespdPhkB1JopFD18nVI0UIZCAzwnF5evdUZ8GjNBgM00nxQ71WrueYt9lNKMbfjK1fyAVtF9xr+2kfC7OtpzG23NHiW0LESQdwoiQkJGgp/hmNVACnA7ToUdG9zMWCwMKwpslLBmacduTyC+AAU1mEZ83XSdej9yRoai85dB8OMGB0Rd0/TxWLvn4KLrZvhAEWNs8haevICuelazDfIX2pBGlLi25w0528CaQYKAVR9JPTV7+ES1QMzfzF5CpQgl6t/X0QnHc8NC8/tXRmONE4BN/TkkpAV4wWwtFTyxImrSljHffUXvxQSviqw2tiFjU3x8UHJSkMR4cKjgFqIs5SJxUzNdUDIDtzTYqzlczre7S9KaQO//59byEngoMqfE2QY1Nogu0Jq2PWDUnbel2Z41RAdpymNn8Dr36wb7/WuX8OazwwgrmqZDmggb9NHsZKW4H8PIteVFMM0x2iVKJyu/our5ExJjOZXFTfm9UHcU48wuAPSrgAEJZxf9b7j7zEHw+Zm+n3fC0KNIbO2rm8SND7Q1JxfmeLxRULcZGuOr9WxKYKCNUg==

配合 Hook RSA VerifyData ,这次就不贴图了,可以参考其他帖子  

自己动手尝试记忆更深

完美~  水印空空~  

声明

仅限学习交流,请勿用于商业或非法用途  

免费评分

参与人数 29吾爱币 +35 热心值 +28 收起 理由
b12312312 + 1 + 1 热心回复!
tb612443 + 1 + 1 热心回复!
Zz4794zZ + 1 + 1 谢谢@Thanks!
笙若 + 1 + 1 谢谢@Thanks!
luodf + 1 + 1 谢谢@Thanks!
抱歉、 + 1 我很赞同!
xzqsr + 1 + 1 谢谢@Thanks!
chb378 + 1 + 1 我很赞同!
tocabd + 1 + 1 谢谢@Thanks!
zhangbaida + 3 + 1 我很赞同!
ag129 + 1 + 1 谢谢@Thanks!
mhaitao + 1 + 1 我很赞同!
iNIC + 1 + 1 谢谢@Thanks!
DaiTian + 1 + 1 谢谢 @Thanks!
feichen0921 + 1 + 1 谢谢@Thanks!
夜泉 + 1 + 1 用心讨论,共获提升!
gqdsc + 1 + 1 非常感谢大神分享
zzti + 1 + 1 我很赞同!
yp17792351859 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
jgs + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
LuckyClover + 1 + 1 谢谢@Thanks!
jinqiaoa1a + 1 + 1 谢谢@Thanks!
Courser + 1 + 1 用心讨论,共获提升!
cdj68765 + 2 + 1 用心讨论,共获提升!
ps122 + 1 + 1 用心讨论,共获提升!
Pojie1999.0909 + 2 + 1 用心讨论,共获提升!
Patches + 1 + 1 用心讨论,共获提升!
百年抉择 + 1 + 1 热心回复!
Monitor + 3 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

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

来自 2#
 楼主| pjy612 发表于 2023-5-18 15:14 |楼主
本帖最后由 pjy612 于 2023-5-18 16:12 编辑

发现漏了个函数没说,但是 问题不大。。。。




===================================
自己的沙发~
来自 174#
 楼主| pjy612 发表于 2023-5-22 19:51 |楼主
graper 发表于 2023-5-22 19:28
看起来是这个,不过我试过好像还有试用警告
https://www.52pojie.cn/forum.php?mod=redirect&goto=findp ...


1.这个是另一种 Hook 的思路
2.这个和RSA没半毛钱关系。。。
3.那个后端组件的帖子比较有用。。。
来自 181#
 楼主| pjy612 发表于 2023-5-23 09:02 |楼主
本帖最后由 pjy612 于 2023-5-23 09:05 编辑
15129150532 发表于 2023-5-23 08:39
大佬,生成许可证那段是java嘛?不像C#(我是菜鸡),我改不过来。。。还有,你生成的那个license不可以直接 ...

不可以 还得 Hook RSA的验签。
我 不发成品。成品没有锻炼机会。
所有的帖子 基本都得上手自己试试 才行的。不然 没啥用。

拿了,用了,爽了,忘了。没必要。。。
来自 186#
billpeace 发表于 2023-5-23 12:11
graper 发表于 2023-5-22 19:27
看起来是这个,不过我试过好像还有试用警告
https://www.52pojie.cn/forum.php?mod=redirect&goto=findp ...

我发现 仅支持 net6,暂时还不支持 net7

所以我之前一直测试 不成功

Harmony 目前只支持 Net 6
推荐
Elaineliu 发表于 2023-5-18 15:27
在国人的努力下,老外渐渐学会了各种混淆加壳
推荐
zxsbk 发表于 2023-5-18 15:21
这是用什么语言,什么编辑器,语法高亮很给力呀。
3#
无敌小儿 发表于 2023-5-18 15:17
这个厉害的很,分析透彻
5#
马潇洒 发表于 2023-5-18 15:21
看了下,逻辑清晰,学习一下
6#
vipcrack 发表于 2023-5-18 15:22
这个很强大,新版本的patchkeygen好像一直没有出现
7#
ghui 发表于 2023-5-18 15:25
非常详细啊
9#
Monitor 发表于 2023-5-18 15:31
嗯,赚了$2999
10#
百年抉择 发表于 2023-5-18 15:37
刚才看不了,设置级别太高。还好楼主改了,可以看到这么好的文章学习。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

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

GMT+8, 2023-6-2 04:03

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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