简单破解 Syncfusion
2024-11-05 23:57:22

本文根据 Syncfusion v27.1.58 编写。


根据官方关于 许可证说明 得知一些信息:

  • 在任何控件使用前(最好是在程序入口处),调用Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense添加密钥。
  • 验证全程离线完成,无需联网。


这里有一个全家桶Key,启动时注册一下即可。(根据后面的分析,这个Key只支持27这个大版本)

1
Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("MTU4NUAzMjM3MkUzMTJFMzluT08wbzRnYm4zUlFDOVRzWVpYbUtuSEl0aUhTZmNMYjQxekhrV0NVRnlzPQ==");

简单破解

未注册时,启动后会弹出这样的窗口:

我这里用了一个按钮控件。用 dnSpy 分析,发现控件在构造函数中会调用LicenseHelper.ValidateLicense方法来验证:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public SfButton()
{
Application.AddMessageFilter(this);
this.drawHelper = new ButtonDrawingHelper(this);
base.UseCompatibleTextRendering = true;
this.style = new ButtonVisualStyle(new ButtonStyleInfoIdentity(this));
this.Font = new Font("Segoe UI Semibold", 9f);
this.defaultFont = new Font("Segoe UI Semibold", 9f);
this.TextImageRelation = TextImageRelation.ImageBeforeText;
this.AccessibilityEnabled = true;
LicenseHelper.ValidateLicense(true); // 这里
if (SkinManager.IsThemeChanged)
{
SkinManager.SetVisualStyle(this, SkinManager.ApplicationVisualTheme);
}
}

继续跟踪

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static void ValidateLicense(bool isInternalDependentControl = false)
{
string licenseType = FusionLicenseProvider.GetLicenseType(Platform.WindowsForms, out LicenseHelper.shouldQuit, isInternalDependentControl);
if (LicenseHelper.shouldQuit && !string.IsNullOrEmpty(licenseType) && LicenseHelper.exitLicenseMessage == null)
{
if (LicenseHelper.licenseMessage != null)
{
LicenseHelper.licenseMessage.msgbox.Close();
LicenseHelper.exitLicenseMessage = new LicenseMessage();
LicenseHelper.exitLicenseMessage.ExceedControlCount = true;
LicenseHelper.exitLicenseMessage.DisplayMessage("Syncfusion License", licenseType);
return;
}
}
else if (LicenseHelper.licenseMessage == null && !string.IsNullOrEmpty(licenseType))
{
LicenseHelper.licenseMessage = new LicenseMessage();
LicenseHelper.licenseMessage.DisplayMessage("Syncfusion License", licenseType);
}
}

调用了FusionLicenseProvider.GetLicenseType验证,返回值为不为空表示验证失败,并且根据shouldQuit决定是否要退出程序。

1
2
3
4
5
6
7
8
9
10
11
12
13
public static string GetLicenseType(Platform platform, out bool shouldQuit, bool isInternalDependentControl)
{
shouldQuit = false;
if (!isInternalDependentControl)
{
FusionLicenseProvider.licenseValidatedEffectiveControlsCount++;
if (FusionLicenseProvider.licenseValidatedEffectiveControlsCount > 5 && FusionLicenseProvider.isLicenseExceptionShown)
{
shouldQuit = true;
}
}
return FusionLicenseProvider.GetLicenseType(platform, null, false);
}

这里可以看到如果验证失败了,非内部依赖控件超过5个则会退出程序。
继续。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
public static string GetLicenseType(Platform platform, string version, bool fromExtension)
{
FusionLicenseProvider.claimLicenseKeyURL = FusionLicenseProvider.GetClaimLicenseURL(platform);
if (!FusionLicenseProvider.IsBoldLicenseValidation)
{
if (!FusionLicenseProvider.isDesignerModeValidated)
{
FusionLicenseProvider.isAppDesignerMode = FusionLicenseProvider.IsDesignerMode();
FusionLicenseProvider.isDesignerModeValidated = true;
}
if (!fromExtension)
{
if (FusionLicenseProvider.IsDesigner() || FusionLicenseProvider.isAppDesignerMode)
{
return null;
}
if (!FusionLicenseProvider.isSyncfusionApp && platform == Platform.Utility && FusionLicenseProvider.IsSyncfusionPFXSigned())
{
FusionLicenseProvider.isSyncfusionApp = true;
return null;
}
}
if (platform == Platform.FileFormats && !string.IsNullOrEmpty(FusionLicenseProvider.fileFormatExceptionMessage) && !FusionLicenseProvider.isSyncfusionApp)
{
if (FusionLicenseProvider.Platforms != null && FusionLicenseProvider.Platforms.Count > 0)
{
FusionLicenseProvider.Platforms.Clear();
}
return FusionLicenseProvider.fileFormatExceptionMessage;
}
if (((LicenseManager.UsageMode == LicenseUsageMode.Runtime && !FusionLicenseProvider.isLicenseExceptionShown) || platform == Platform.FileFormats || (FusionLicenseProvider.licenseValidatedEffectiveControlsCount > 5 && FusionLicenseProvider.isLicenseExceptionShown)) && !FusionLicenseProvider.isSyncfusionApp)
{
if (FusionLicenseProvider.isSinglePlatform)
{
FusionLicenseProvider.Platforms.Add(platform);
}
FusionLicenseProvider.isSinglePlatform = true;

// 如果验证过了就跳过,这里是破解点!
if ((!FusionLicenseProvider.isLicensed && !FusionLicenseProvider.isTrial) || platform == Platform.FileFormats)
{
LicenseType licenseType;
if (!fromExtension)
{
licenseType = FusionLicenseProvider.GetModeOfLicense(platform); // 解密Key,获取许可证类型
}
else
{
licenseType = FusionLicenseProvider.GetModeOfLicense(platform, version); // 解密Key,获取许可证类型
}
FusionLicenseProvider.Platforms.Clear();
if (licenseType != LicenseType.Licensed && licenseType != LicenseType.Trial)
{
FieldInfo field = licenseType.GetType().GetField(licenseType.ToString());
DescriptionAttribute[] array = (DescriptionAttribute[])field.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (array != null && array.Length > 0)
{
string text = array[0].Description;
text = text.Replace("##LicenseVersion", FusionLicenseProvider.invalidVersion);
if (!fromExtension)
{
text = text.Replace("##Requireversion", CoreAssembly.StudioCoreVersion);
}
else
{
text = text.Replace("##Requireversion", version);
}
if (!fromExtension && platform != Platform.FileFormats)
{
FusionLicenseProvider.isLicenseExceptionShown = true;
}
if (!string.IsNullOrEmpty(text) && string.IsNullOrEmpty(FusionLicenseProvider.fileFormatExceptionMessage))
{
FusionLicenseProvider.fileFormatExceptionMessage = text;
}
return text;
}
}
}
FusionLicenseProvider.Platforms.Clear();
}
}
return null;
}

该控件用一个静态私有变量来记录验证状态,这里有可趁之机,将这个变量改为true,直接验证通过。

1
2
3
4
5
6
7
8
9
10
private static bool CrackSyncfusion()
{
var t = typeof(FusionLicenseProvider);
var fi = t.GetField("isLicensed", BindingFlags.NonPublic | BindingFlags.Static);
if (fi == null)
return false;

fi.SetValue(null, true);
return true;
}

这个破解方式比较通用,无视验证算法,只要这判断条件不变就能一直用。
另外注意看第二行,竟然可以用FusionLicenseProvider.IsBoldLicenseValidation这个静态属性跳过验证,而且这个属性是公开的。
那么可以这样破解。。。

1
FusionLicenseProvider.IsBoldLicenseValidation = true;

离谱。


到这就破解完成了,继续随便看看。。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
private static LicenseType GetModeOfLicense(Platform platform, string assemblyVersion)
{
try
{
string text = CoreAssembly.StudioCoreVersion;
if (!string.IsNullOrEmpty(assemblyVersion))
{
text = assemblyVersion;
}

// 需要先添加密钥,否则直接验证失败
if (FusionLicenseProvider.registeredLicenses.Count == 0)
{
return LicenseType.NoLicense;
}
List<LicenseType> list = new List<LicenseType>();
for (int i = 0; i < FusionLicenseProvider.registeredLicenses.Count; i++)
{
// 获取授权类型
list.Add(FusionLicenseProvider.GetProjectKeyType(FusionLicenseProvider.registeredLicenses[i].Trim(), text, platform));
}
if (list.Contains(LicenseType.Licensed)) // 验证成功
{
FusionLicenseProvider.isLicensed = true;
return LicenseType.Licensed;
}
if (list.Contains(LicenseType.Trial)) // 试用期
{
FusionLicenseProvider.isTrial = true;
return LicenseType.Trial;
}
if (list.Contains(LicenseType.NoLicense)) // 密钥过期
{
return LicenseType.NoLicense;
}
if (list.Contains(LicenseType.Invalid)) // 无效密钥
{
return LicenseType.Invalid;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
return LicenseType.Invalid;
}
return LicenseType.NoLicense;
}

整个验证的核心就在FusionLicenseProvider.GetProjectKeyType这个方法,没精力继续分析了。
密钥中包含支持的产品版本、产品类型、许可证过期时间、注册用户的email的checksum信息。

相关阅读

Wpf
WinForms
Syncfusion Essential Studio