本帖最后由 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中代码):
[C#] 纯文本查看 复制代码 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 ,就是校验成功!看看函数最后,
[C#] 纯文本查看 复制代码
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以区分版本,上面的修改直接将校验返回为了真,所以,改成相应的字符串什么就是对应的版本!
至于具体算法啥的,谁愿意搞谁搞吧!!上面该有的都有了,算法应该不难!
|