ZCShou 发表于 2017-1-21 13:15

嵌入式系统神器 FreeRTOS+Trace 破解分析

本帖最后由 ZCShou 于 2017-1-21 13:19 编辑

本人搞嵌入式的,基本整天和C及汇编打交道,对于C#这个不是很了解,以下分析,仅供学习,如果工作使用还是买正版!

一、准备
首先,下载安装包,直接安装?当然不是!使用UniExtract检查一下,发现直接使用7-zip解压即可!,解压后文件如下:


文件挺多,但是有用没几个,其中,Jlink开头的俩应该是Segger官方的文件,需要处理的应该就是Tracealyzer开头的三个dll和TzForFreeRTOS.exe,使用PEID 检查一下,发现是它们都是.net程序,接着使用.net工具ScanId查询一下,发现有混淆

二、反混淆直接祭出de4dot,只能一次将四个文件全部处理,单个处理后程序无法运行(大神给个解释?)


三、开搞
我在使用 .NET Reflector,因为在保存时提示错误,又不知道如何解决!所以只是用Reflector来查看代码(搜索啥的比较方便),在实际修改时用了GrayWolf!运行一下,看看,直接Enter License 看看,发现网络验证!即便是 Offline 也是创建个本地文件,然后要求将文件以邮件的形式发给厂商!
                  
那怎么搞呢,直接到源码里面找关键字?貌似是可以的!! 还有种方法,界面中有个评估版,点进去后,让填一些信息,点击激活后,会直接跳转到官方网站,然后,你的使用License 就申请成功了!然后在Enter License 在线激活就开启了试用!其会在:系统盘\ProgramData\Tracealyzer for FreeRTOS Data 下生成 License.xml的文件,里面信息还是详细的!

具体,探索过程不说了!直接上关键地方!(这里说明一点,Reflector反编译的代码,明显不如 dnSpy或者GrayWolf整洁)

GClass243.method_11(Byte[], String, DateTime) : GEnum22                        // 这个函数就是取License 中个部分用来校验的
      Depends On
      Used By
                ActivateProductForm.method_4(XmlDocument) : Void                   // 这个看名字就知道,激活窗口,肯定要调用校验License的函数
                GClass105.method_14(String) : Void
                        Depends On
                        Used By
                              GClass105.method_12() : Void                                    // 这个是 处理 License结果的,后面这些和界面有关
                                        Depends On
                                        Used By
                                                GClass105.method_0(String[], Action) : Void
                                                      Depends On
                                                      Used By
                                                                FreeRTOS_Trace.Program.smethod_0(String[]) : Void
                                                                        Depends On
                                                                        Used By
                                                                              FreeRTOS_Trace.Program.Main(String[]) : Void
                                                                                        Depends On
                                                                                        Used By

关键点就在看GClass243.method_11这个函数(GrayWolf中代码):
internal GEnum22 method_11(byte[] byte_0, string string_4, DateTime dateTime_1)
{
      int num = 0;
      switch (num)
      {
      }
      XmlElement xmlElement3;
      XmlElement xmlElement9;
      while (true)
      {
                XmlElement xmlElement = this.xmlDocument_0.smethod_7("/SignedLicense/License");
                XmlElement xmlElement2 = this.xmlDocument_0.smethod_7("/SignedLicense/Signature");
                byte[] bytes = Encoding.UTF8.GetBytes(xmlElement.OuterXml);
                byte[] byte_ = Convert.FromBase64String(xmlElement2.InnerText);
                xmlElement3 = this.xmlDocument_0.smethod_7("/SignedLicense/License/ProductId");
                num = 9;
                int num2 = num;
                while (true)
                {
                        string b;
                        string b2;
                        bool flag;
                        IEnumerator enumerator2;
                        DateTime dateTime2;
                        switch (num2)
                        {
                        case 0:

                              {
                                        if (!GClass246.smethod_0(byte_0, bytes, byte_))
                                        {
                                                num = 4;
                                                num2 = num;
                                                continue;
                                        }
                                        XmlElement xmlElement4 = this.xmlDocument_0.smethod_7("/SignedLicense/License/SupportThrough");
                                        DateTime dateTime;
                                        base.method_5(dateTime = DateTime.Parse(xmlElement4.InnerText));
                                        DateTime t = dateTime;
                                        num = 2;
                                        num2 = num;
                                        continue;
                              }
                        case 1:
                              try
                              {
                                        num = 2;
                                        num2 = num;
                                        while (true)
                                        {
                                                num = -25162;
                                                int arg_238_0 = num;
                                                num = -25162;
                                                switch ((arg_238_0 == num) ? 1 : 0)
                                                {
                                                case 0:
                                                case 2:
                                                      break;
                                                case 1:
                                                      goto IL_259;
                                                default:
                                                      goto IL_259;
                                                }
                                                IL_24D:
                                                num = 8;
                                                num2 = num;
                                                continue;
                                                IL_259:
                                                num = 0;
                                                if (num != 0)
                                                {
                                                      goto IL_260;
                                                }
                                                IL_260:
                                                object current;
                                                switch (num2)
                                                {
                                                case 0:

                                                      {
                                                                XmlElement xmlElement5 = (XmlElement)current;
                                                                IEnumerator enumerator = xmlElement5.ChildNodes.GetEnumerator();
                                                                num = 3;
                                                                num2 = num;
                                                                continue;
                                                      }
                                                case 1:
                                                      if (current is XmlElement)
                                                      {
                                                                num = 0;
                                                                num2 = num;
                                                                continue;
                                                      }

                                                      goto IL_54F;
                                                case 2:
                                                      goto IL_54F;
                                                case 3:
                                                      try
                                                      {
                                                                num = 1;
                                                                num2 = num;
                                                                while (true)
                                                                {
                                                                        switch (num2)
                                                                        {
                                                                        case 0:
                                                                              goto IL_3AB;
                                                                        case 1:
                                                                              goto IL_34D;
                                                                        case 2:
                                                                              num = 9;

                                                                              num2 = num;

                                                                              continue;
                                                                        case 3:
                                                                              num = 4;

                                                                              num2 = num;

                                                                              continue;
                                                                        case 4:

                                                                              {
                                                                                        XmlElement xmlElement6;
                                                                                        if (xmlElement6.InnerText == "ANY")
                                                                                        {
                                                                                                num = 17;
                                                                                                num2 = num;
                                                                                                continue;
                                                                                        }
                                                                                        goto IL_34D;
                                                                              }
                                                                        case 5:
                                                                              goto IL_4A3;
                                                                        case 6:

                                                                              {
                                                                                        IEnumerator enumerator;
                                                                                        if (!enumerator.MoveNext())
                                                                                        {
                                                                                                num = 15;
                                                                                                num2 = num;
                                                                                                continue;
                                                                                        }
                                                                                        object current2 = enumerator.Current;
                                                                                        num = 10;
                                                                                        num2 = num;
                                                                                        continue;
                                                                              }
                                                                        case 7:

                                                                              {
                                                                                        XmlElement xmlElement6;
                                                                                        if (xmlElement6.Name == "Id")
                                                                                        {
                                                                                                num = 2;
                                                                                                num2 = num;
                                                                                                continue;
                                                                                        }
                                                                                        break;
                                                                              }
                                                                        case 8:
                                                                              num = 14;

                                                                              num2 = num;

                                                                              continue;
                                                                        case 9:

                                                                              {
                                                                                        XmlElement xmlElement6;
                                                                                        if (!(xmlElement6.InnerText == b))
                                                                                        {
                                                                                                num = 8;
                                                                                                num2 = num;
                                                                                                continue;
                                                                                        }
                                                                                        goto IL_3AB;
                                                                              }
                                                                        case 10:

                                                                              {
                                                                                        object current2;
                                                                                        if (current2 is XmlElement)
                                                                                        {
                                                                                                num = 11;
                                                                                                num2 = num;
                                                                                                continue;
                                                                                        }
                                                                                        goto IL_34D;
                                                                              }
                                                                        case 11:

                                                                              {
                                                                                        object current2;
                                                                                        XmlElement xmlElement6 = (XmlElement)current2;
                                                                                        num = 7;
                                                                                        num2 = num;
                                                                                        continue;
                                                                              }
                                                                        case 12:

                                                                              {
                                                                                        XmlElement xmlElement6;
                                                                                        if (xmlElement6.Name == "Id")
                                                                                        {
                                                                                                num = 3;
                                                                                                num2 = num;
                                                                                                continue;
                                                                                        }
                                                                                        goto IL_34D;
                                                                              }
                                                                        case 13:
                                                                              goto IL_4A8;
                                                                        case 14:

                                                                              {
                                                                                        XmlElement xmlElement6;
                                                                                        if (xmlElement6.InnerText == b2)
                                                                                        {
                                                                                                num = 0;
                                                                                                num2 = num;
                                                                                                continue;
                                                                                        }
                                                                                        break;
                                                                              }
                                                                        case 15:
                                                                              num = 5;

                                                                              num2 = num;

                                                                              continue;
                                                                        case 16:
                                                                              goto IL_4AD;
                                                                        case 17:
                                                                              flag = true;

                                                                              num = 13;

                                                                              num2 = num;

                                                                              continue;
                                                                        default:
                                                                              goto IL_34D;
                                                                        }
                                                                        num = 12;
                                                                        num2 = num;
                                                                        continue;
                                                                        IL_34D:
                                                                        num = 6;
                                                                        num2 = num;
                                                                        continue;
                                                                        IL_3AB:
                                                                        flag = true;
                                                                        num = 16;
                                                                        num2 = num;
                                                                }
                                                                IL_4A3:
                                                                IL_4A8:
                                                                IL_4AD:
                                                                goto IL_55E;
                                                      }
                                                      finally
                                                      {
                                                                while (true)
                                                                {
                                                                        IEnumerator enumerator;
                                                                        IDisposable disposable = enumerator as IDisposable;
                                                                        num = 2;
                                                                        num2 = num;
                                                                        while (true)
                                                                        {
                                                                              switch (num2)
                                                                              {
                                                                              case 0:
                                                                                        disposable.Dispose();

                                                                                        num = 1;

                                                                                        num2 = num;

                                                                                        continue;
                                                                              case 1:
                                                                                        goto IL_4F9;
                                                                              case 2:
                                                                                        if (disposable != null)
                                                                                        {
                                                                                                num = 0;
                                                                                                num2 = num;
                                                                                                continue;
                                                                                        }

                                                                                        goto IL_4F9;
                                                                              }
                                                                              break;
                                                                        }
                                                                }
                                                                IL_4F9:;
                                                      }

                                                      break;

                                                      IL_55E:

                                                      num = 9;

                                                      num2 = num;

                                                      continue;
                                                case 4:
                                                      goto IL_56D;
                                                case 5:
                                                      goto IL_56F;
                                                case 6:
                                                      break;
                                                case 7:
                                                      num = 5;

                                                      num2 = num;

                                                      continue;
                                                case 8:
                                                      num = 4;

                                                      num2 = num;

                                                      continue;
                                                case 9:
                                                      if (!flag)
                                                      {
                                                                goto IL_54F;
                                                      }

                                                      goto IL_24D;
                                                default:
                                                      goto IL_54F;
                                                }
                                                if (!enumerator2.MoveNext())
                                                {
                                                      num = 7;
                                                      num2 = num;
                                                      continue;
                                                }
                                                current = enumerator2.Current;
                                                num = 1;
                                                num2 = num;
                                                continue;
                                                IL_54F:
                                                num = 6;
                                                num2 = num;
                                        }
                                        IL_56D:
                                        IL_56F:;
                              }
                              finally
                              {
                                        while (true)
                                        {
                                                IDisposable disposable = enumerator2 as IDisposable;
                                                num = 1;
                                                num2 = num;
                                                while (true)
                                                {
                                                      switch (num2)
                                                      {
                                                      case 0:
                                                                goto IL_5B8;
                                                      case 1:
                                                                if (disposable != null)
                                                                {
                                                                        num = 2;
                                                                        num2 = num;
                                                                        continue;
                                                                }

                                                                goto IL_5B8;
                                                      case 2:
                                                                disposable.Dispose();

                                                                num = 0;

                                                                num2 = num;

                                                                continue;
                                                      }
                                                      break;
                                                }
                                        }
                                        IL_5B8:;
                              }

                              num = 8;

                              num2 = num;

                              continue;
                        case 2:

                              {
                                        DateTime t;
                                        if (t < dateTime_1)
                                        {
                                                num = 10;
                                                num2 = num;
                                                continue;
                                        }
                                        XmlElement xmlElement7 = this.xmlDocument_0.smethod_7("/SignedLicense/License/ExpiresOn");
                                        num = 1;
                                        if (num == 0)
                                        {
                                                IL_20C:
                                                num = 13;
                                                num2 = num;
                                                continue;
                                        }
                                        goto IL_20C;
                              }
                        case 3:
                              goto IL_1AD;
                        case 4:
                              return GEnum22.const_1;
                        case 5:
                              return GEnum22.const_3;
                        case 6:
                              try
                              {
                                        while (true)
                                        {
                                                XmlElement xmlElement8 = this.xmlDocument_0.smethod_7("/SignedLicense/License/ReactivateOnExpire");
                                                num = 3;
                                                num2 = num;
                                                while (true)
                                                {
                                                      switch (num2)
                                                      {
                                                      case 0:
                                                                base.method_9(true);

                                                                num = 1;

                                                                num2 = num;

                                                                continue;
                                                      case 1:
                                                                goto IL_151;
                                                      case 2:
                                                                goto IL_1A2;
                                                      case 3:
                                                                if (xmlElement8.InnerText == "True")
                                                                {
                                                                        num = 0;
                                                                        num2 = num;
                                                                        continue;
                                                                }

                                                                goto IL_151;
                                                      }
                                                      break;
                                                      IL_151:
                                                      num = 2;
                                                      num2 = num;
                                                }
                                        }
                                        IL_1A2:
                                        goto IL_61D;
                              }
                              catch (Exception)
                              {
                                        goto IL_61D;
                              }

                              goto IL_1AD;

                              IL_61D:

                              num = 3;

                              num2 = num;

                              continue;
                        case 7:
                              return GEnum22.const_5;
                        case 8:
                              if (!flag)
                              {
                                        num = 7;
                                        num2 = num;
                                        continue;
                              }

                              goto IL_694;
                        case 9:
                              if (string_4 != xmlElement3.InnerText)
                              {
                                        num = 11;
                                        num2 = num;
                                        continue;
                              }

                              num = 0;

                              num2 = num;

                              continue;
                        case 10:
                              return GEnum22.const_4;
                        case 11:
                              return GEnum22.const_2;
                        case 12:

                              {
                                        XmlElement xmlElement7;
                                        dateTime2 = DateTime.Parse(xmlElement7.InnerText);
                                        base.method_7(new DateTime?(dateTime2));
                                        num = 6;
                                        num2 = num;
                                        continue;
                              }
                        case 13:

                              {
                                        XmlElement xmlElement7;
                                        if (xmlElement7.InnerText != "Never")
                                        {
                                                num = 12;
                                                num2 = num;
                                                continue;
                                        }
                                        goto IL_77;
                              }
                        }
                        break;
                        IL_77:
                        xmlElement9 = this.xmlDocument_0.smethod_7("/SignedLicense/License/EditionId");
                        XmlElement xmlElement10 = this.xmlDocument_0.smethod_7("/SignedLicense/License/Nodes");
                        b = GClass247.smethod_1();
                        b2 = GClass247.smethod_3();
                        flag = false;
                        enumerator2 = xmlElement10.ChildNodes.GetEnumerator();
                        num = 1;
                        num2 = num;
                        continue;
                        IL_1AD:
                        if (!(dateTime2 < DateTime.Now.Date))
                        {
                              goto IL_77;
                        }
                        num = 5;
                        num2 = num;
                }
      }
      return GEnum22.const_1;
      IL_694:
      base.method_1(xmlElement3.InnerText);
      base.method_3(xmlElement9.InnerText);
      return GEnum22.const_0;
}
分析上面代码,可知:
(1)首先,校验ProductId,失败时直接返回 GEnum22.const_2,而在GClass105.method_14中就是用这些值来区分具体错误类型的!
(2)校验Signature(使用了RSACryptoServiceProvider非对称加密),失败时直接返回 GEnum22.const_1
(3)检验SupportThrough,失败时直接返回GEnum22.const_4
(4)校验ExpiresOn,看看是否到期
          ........
从中,可以分析出,只要返回GEnum22.const_0 ,就是校验成功!看看函数最后,

IL_694:
base.method_1(xmlElement3.InnerText);
base.method_3(xmlElement9.InnerText);
return GEnum22.const_0;

最简单办法直接,跳转到IL_694就OK了!,这样,随便改改License都无所谓了! License中EditionId表示版本类型:
AAE8DBC5-A985-4BC8-819D-5DDABEE7F448 表示 Academic Edition(这个版本官网没看到,但是源码中存在)
E2BB2BF3-507C-44F2-B250-F5734C63C1BD 表示 Professional Edition
2A5BC2B2-177E-4421-AB65-9683EEF175AC 表示 Standard Edition
D0C8EF57-8402-4264-9BBE-4FA2FD3A50B9 表示 Evaluation Edition
133C03FE-FB99-4B25-8FBD-BCD06711018B 表示 Free Edition
程序会读取 License中的 EditionId以区分版本,上面的修改直接将校验返回为了真,所以,改成相应的字符串什么就是对应的版本!
至于具体算法啥的,谁愿意搞谁搞吧!!上面该有的都有了,算法应该不难!










wf2000cn 发表于 2017-9-25 13:09

再努力搞下也发篇文章讲讲如何破解Tracealyzer for uCOSIII的。{:1_900:}

kingdjh 发表于 2018-4-25 17:18

本帖最后由 kingdjh 于 2018-4-27 09:12 编辑

ZCShou 发表于 2018-4-23 12:51
破解方法时完全一样的啊,4 的 版本我也试过了!就是4 的验证逻辑不太一样
4 我看了下,把RSA校验去掉,然后就可以为所欲为了。

下面是根据离线文件生成注册文件的代码
using System;
using System.Xml;

namespace TracealyzerCoder
{
    class Program
    {
      static void Main(string[] args)
      {
            Console.Write("input offline request file name: ");
            string filename = Console.ReadLine();

            try
            {
                XmlDocument requestXml = new XmlDocument();
                requestXml.Load(filename);

                RequestInfo info = XmlGetRequestInfo(requestXml);
                GenerateActivationFile(info);

                Console.WriteLine("OK");
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            Console.Read();
      }

      static RequestInfo XmlGetRequestInfo(XmlDocument xmlDocument)
      {
            string[] nodeNames = new[] { "Key", "ProductId", "Id", "Name" };
            RequestInfo info = new RequestInfo();

            foreach (string name in nodeNames)
            {
                XmlNodeList nodes = xmlDocument.GetElementsByTagName(name);
                if (nodes.Count == 0)
                {
                  throw new Exception("bad format of request file.");
                }
                else
                {
                  string text = nodes.InnerText;
                  switch (name)
                  {
                        case "Key":
                            info.key = text;
                            break;

                        case "ProductId":
                            info.productId = text;
                            break;

                        case "Id":
                            info.id = text;
                            break;

                        case "Name":
                            info.name = text;
                            break;
                  }
                }
            }

            return info;
      }

      static void GenerateActivationFile(RequestInfo info)
      {
            Random rd = new Random();
            XmlDocument root = new XmlDocument();

            XmlElement signedLicense = root.CreateElement("SignedLicense");
            root.AppendChild(signedLicense);

            XmlElement license = root.CreateElement("License");
            signedLicense.AppendChild(license);

            byte[] haskkeyBytes = new byte;
            rd.NextBytes(haskkeyBytes);
            XmlElement hashKey = root.CreateElement("HashedKey");
            hashKey.InnerText = Convert.ToBase64String(haskkeyBytes);
            license.AppendChild(hashKey);

            XmlElement product = root.CreateElement("Product");
            product.InnerText = "Tracealyzer - Standard Edition";
            license.AppendChild(product);

            XmlElement productId = root.CreateElement("ProductId");
            productId.InnerText = info.productId;
            license.AppendChild(productId);

            XmlElement editionId = root.CreateElement("EditionId");
            editionId.InnerText = "{050C587E-D34F-4361-B344-F8FCC4473477}";
            license.AppendChild(editionId);

            XmlElement licenseTo = root.CreateElement("LicensedTo");
            licenseTo.InnerText = info.name;
            license.AppendChild(licenseTo);

            XmlElement expiresOn = root.CreateElement("ExpiresOn");
            expiresOn.InnerText = "Never";
            license.AppendChild(expiresOn);

            XmlElement supportThrough = root.CreateElement("SupportThrough");
            supportThrough.InnerText = "2099-12-31";
            license.AppendChild(supportThrough);

            license.AppendChild(XmlAddComponents(root));

            XmlElement nodes = root.CreateElement("Nodes");
            license.AppendChild(nodes);

            XmlElement node = root.CreateElement("Node");
            nodes.AppendChild(node);

            XmlElement id = root.CreateElement("Id");
            id.InnerText = info.id;
            node.AppendChild(id);
            XmlElement name = root.CreateElement("Name");
            name.InnerText = info.name;
            node.AppendChild(name);

            byte[] licenseBytes = new byte;
            rd.NextBytes(licenseBytes);
            XmlElement signature = root.CreateElement("Signature");
            signature.InnerText = Convert.ToBase64String(licenseBytes);
            signedLicense.AppendChild(signature);

            root.Save("result.xml");
      }

      static XmlElement XmlAddComponents(XmlDocument root)
      {
            ComponentXml[] components = new ComponentXml[]
            {
                new ComponentXml("{B1CF5B88-ADA5-4B2A-81AF-257054106205}", "Tracealyzer Application"),
                new ComponentXml("{469D108A-B824-4C27-99ED-98B8629BFCE0}", "FreeRTOS Support"),
                new ComponentXml("{95F4ED62-6F8E-4EE3-8ED2-1A6F68B63A50}", "Keil RTX5 Support"),
                new ComponentXml("{629259CF-458D-4F05-9545-99DA60198B26}", "µC/OS-III Support")
            };

            XmlElement componentsXml = root.CreateElement("Components");
            foreach (ComponentXml component in components)
            {
                XmlElement componentXml = root.CreateElement("Component");
                XmlElement idXml = root.CreateElement("Id");
                idXml.InnerText = component.id;
                XmlElement nameXml = root.CreateElement("Name");
                nameXml.InnerText = component.name;
                componentXml.AppendChild(idXml);
                componentXml.AppendChild(nameXml);
                componentsXml.AppendChild(componentXml);
            }

            return componentsXml;
      }
    }

    class RequestInfo
    {
      public string key;
      public string productId;
      public string id;
      public string name;
    }

    class ComponentXml
    {
      public string id;
      public string name;

      public ComponentXml(string _id, string _name)
      {
            this.id = _id;
            this.name = _name;
      }
    }
}


去掉RSA校验方法:
用dnSpy打开Tracealyzer.Application.dll,然后搜索"SignedLicense"字符串,一般只有一个方法。
该方法有三个参数,其中一个是个byte[],找到方法内用到这个byte[]的地方(一般只有一个),这个调用就是校验RSA的,NOP掉就行。

kingdjh 发表于 2018-4-27 13:50

sblpp 发表于 2018-4-27 10:18
您好,谢谢您,用您的方法在Tracealyzer.Application.dll中并没有找到SignedLicense字符串,甚至连 icens ...

ghostfire 发表于 2017-1-21 13:53

楼主全才,感谢分享。

1175583503 发表于 2017-1-21 14:06

支持楼主

翰墨云 发表于 2017-1-21 16:26

支持楼主

15067753585 发表于 2017-1-21 16:51

强大~ 支持lz

交王飞也不行 发表于 2017-1-21 20:42

感谢楼主

lxj199610 发表于 2017-1-22 00:35

感谢分析。。。

silverkey 发表于 2017-1-22 07:35

看到了jlink 好熟悉的感觉啊

agasdf 发表于 2017-1-22 08:44

一会就不能用了,好难受

ZCShou 发表于 2017-1-22 08:49

agasdf 发表于 2017-1-22 08:44
一会就不能用了,好难受

哪不能用了?
页: [1] 2 3 4 5 6 7 8
查看完整版本: 嵌入式系统神器 FreeRTOS+Trace 破解分析