你好,這里是 Dotnet 工具箱,定期分享 Dotnet 有趣,實用的工具和組件,希望對您有用!
【JIEJIE.NET - 強大的 .NET 代碼混淆工具】
JIEJIE.NET
JIEJIE.NET 是一個使用 C# 開發(fā)的開源 .NET 代碼加密工具。
很多 .NET 開發(fā)人員擔心他們的軟件被破解,版權受到侵犯,所以他們使用一些工具來混淆 IL 代碼。比如 PreEmptive dotfuscator, 但有些場景的需求,是這些工具不能滿足的。
所以作者寫了 JieJie.NET,它可以深度加密.NET程序集,幫助大家保護版權。重要的是,這個工具是開源的。
界面預覽
功能特性
1.類型和成員重命名
舊代碼:
public abstract class XTextDocumentContentElement : XTextContentElement
{
public override void AfterLoad(ElementLoadEventArgs args);
public override void Clear();
[Obfuscation(Exclude = true, ApplyToMembers = true)]
public override XTextElement Clone(bool Deeply);
[Obfuscation(Exclude = true, ApplyToMembers = true)]
public override XTextDocument CreateContentDocument(bool includeThis);
public XTextSelection CreateSelection(int startIndex, int length);
public override void Dispose();
public override void DrawContent(InnerDocumentPaintEventArgs args);
[Obfuscation(Exclude = true, ApplyToMembers = true)]
public override void EditorRefreshViewExt(bool fastMode);
public float FixPageLinePosition(int pos);
public override void Focus();
[Obfuscation(Exclude = true, ApplyToMembers = true)]
public XTextLineList GetAllLines();
[Obfuscation(Exclude = true, ApplyToMembers = true)]
public virtual XTextRange GetRange(int StartIndex, int EndIndex);
public void InnerGetSelectionBorderElement(ref XTextElement startElement, ref XTextElement endElement);
public void InvalidateSpecifyLayoutElements();
[Obfuscation(Exclude = true, ApplyToMembers = true)]
public virtual bool IsSelected(XTextElement element);
public void RefreshParagraphListState(bool checkFlag, bool updateListIndex);
public XTextParagraphFlagElement RootParagraphFlag();
[Obfuscation(Exclude = true, ApplyToMembers = true)]
public bool SetSelection(int startIndex, int length);
[Obfuscation(Exclude = true, ApplyToMembers = true)]
public bool SetSelectionRange(int firstIndex, int lastIndex);
}
加密后:
public abstract class XTextDocumentContentElement : XTextContentElement
{
public override void Clear();
public override XTextElement Clone(bool Deeply);
public override XTextDocument CreateContentDocument(bool includeThis);
public override void Dispose();
public override void EditorRefreshViewExt(bool fastMode);
public override void Focus();
public XTextLineList GetAllLines();
public virtual XTextRange GetRange(int StartIndex, int EndIndex);
public virtual bool IsSelected(XTextElement element);
public bool SetSelection(int startIndex, int length);
public bool SetSelectionRange(int firstIndex, int lastIndex);
public XTextParagraphFlagElement z0ZzZzbmm1mO001();
public XTextSelection z0ZzZzbmm1mO011(int startIndex, int length);
public void z0ZzZzbmm1mO01O();
public float z0ZzZzbmm1mOOm1(int pos);
public void z0ZzZzbmm1mOOmn(ref XTextElement startElement, ref XTextElement endElement);
public void z0ZzZzbmm1mOOmO(bool checkFlag, bool updateListIndex);
public override void z0ZzZzbmmOO11nn(z0ZzZzbm0mmlm1O args);
public override void z0ZzZzbmmOOl0nO(ElementLoadEventArgs args);
}
可以看到,一些 API 的名稱被混淆了。
2. 混淆代碼流程
JieJie.NET 可以分析 IL 代碼,并且在不丟失任何特性的情況下隨機混淆代碼流程。它可以破壞 foreach/lock/using
, 讓代碼很難閱讀,有時候還會導致破解工具錯誤。
舊代碼:
public int RemoveByControl(object control)
{
if (control == null)
{
throw new ArgumentNullException("control");
}
if (CheckOwner() == false)
{
return -1;
}
int result = 0;
lock (this)
{
for (int iCount = _Tasks.Count - 1; iCount >= 0; iCount--)
{
if (_Tasks[iCount].Control == control)
{
_Tasks.RemoveAt(iCount);
result++;
}
}
if (_CurrentTask != null && _CurrentTask.Control == control)
{
_CurrentTask = null;
}
}
return result;
}
使用 JieJie.NET 后,在 ILSpy 中顯示的代碼如下:
public int RemoveByControl(object control)
{
//Discarded unreachable code: IL_000b, IL_0073
//IL_000b: Incompatible stack heights: 1 vs 0
//IL_0073: Incompatible stack heights: 1 vs 0
int num = z0ZzZzgw.z0kh;
bool flag = default(bool);
int num4 = default(int);
int result = default(int);
while (true)
{
switch (num)
{
default:
{
if (control == null)
{
throw new ArgumentNullException(z0ZzZzow.z0rj);
}
if (!z0rk())
{
goto IL_0049;
}
int num2 = 0;
z0ZzZzjw.z0uk(this);
try
{
int num3 = z0ZzZzgw.z0ah;
while (true)
{
switch (num3)
{
default:
num2++;
goto IL_0097;
case 3:
if (flag)
{
z0ik = null;
}
break;
case 4:
case 5:
{
num4 = z0bk.Count - 1;
goto IL_009e;
}
IL_009e:
if (num4 < 0)
{
flag = z0ik != null && z0ik.Control == control;
num3 = z0ZzZzgw.z0wj;
continue;
}
if (z0bk[num4].Control == control)
{
z0bk.RemoveAt(num4);
num3 = z0ZzZzgw.z0sh;
continue;
}
goto IL_0097;
IL_0097:
num4--;
goto IL_009e;
}
break;
}
}
finally
{
Monitor.Exit(this);
}
result = num2;
break;
}
case 0:
case 1:
case 3:
break;
}
break;
IL_0049:
result = -1;
num = z0ZzZzgw.z0wj;
}
return result;
}
現(xiàn)在代碼流程已經(jīng)被破壞了。
3. 加密所有字符串值
JieJie.NET 可以收集程序集中定義的所有字符串值,然后把它們轉換為新類中的靜態(tài)只讀字段,并對它們的值進行加密。
舊代碼:
private string GetLicenseMessage()
{
return "這是一個密鑰 :" + Environment.UserName;
}
加密后:
private string GetLicenseMessage()
{
string text = _0._6 + Environment.UserName;
return text;
}
// also create a new class, contains all string value in assembly in random order.
internal static class _0
{
public static readonly string _0;
public static readonly string _1;
public static readonly string _2;
public static readonly string _3;
public static readonly string _4;
public static readonly string _5;
public static readonly string _6;
public static readonly string _7;
public static readonly string _8;
public static readonly string _9;
public static readonly string _10;
public static readonly string _11;
public static readonly string _12;
public static readonly string _13;
public static readonly string _14;
public static readonly string _15;
public static readonly string _16;
public static readonly string _17;
public static readonly string _18;
public static readonly string _19;
public static readonly string _20;
public static readonly string _21;
static _0()
{
byte[] datas = _BytesContainer__._0();
_11 = GetStringByLong(datas, 151732605047602L);
_20 = GetStringByLong(datas, 450799767951810L);
_7 = GetStringByLong(datas, 101155071172227L);
_4 = GetStringByLong(datas, 47279000500949L);
_15 = GetStringByLong(datas, 415615395474299L);
_5 = GetStringByLong(datas, 54975582493063L);
_2 = GetStringByLong(datas, 17592187197342L);
_14 = GetStringByLong(datas, 206708198516324L);
_8 = GetStringByLong(datas, 124244814685054L);
_21 = GetStringByLong(datas, 459595860893446L);
_6 = GetStringByLong(datas, 72567769190975L);
_13 = GetStringByLong(datas, 182518931688172L);
_18 = GetStringByLong(datas, 433207581847376L);
_16 = GetStringByLong(datas, 417814419099513L);
_3 = GetStringByLong(datas, 36283884381871L);
_1 = GetStringByLong(datas, 9895605165436L);
_9 = GetStringByLong(datas, 136339442622330L);
_19 = GetStringByLong(datas, 440904163377248L);
_17 = GetStringByLong(datas, 426610511995160L);
_0 = GetStringByLong(datas, 598562L);
_10 = GetStringByLong(datas, 148434069970387L);
_12 = GetStringByLong(datas, 158329675868829L);
}
private static string GetStringByLong(byte[] datas, long key)
{
int num = (int)(key & 0xFFFF) ^ 0xEF83;
key >>= 16;
int num2 = (int)(key & 0xFFFFF);
key >>= 24;
int num3 = (int)key;
char[] array = new char[num2];
int num4 = 0;
while (num4 < num2)
{
int num5 = num4 + num3 << 1;
array[num4] = (char)(((datas[num5] << 8) + datas[num5 + 1]) ^ num);
num4++;
num++;
}
return new string(array);
}
}
項目地址: https://github.com/dcsoft-yyf/JIEJIE.NET
【Dots - 更友好的 .NET SDK 管理器】
什么是 Dots?
Dots 是一個用于管理 .NET SDK 的 GUI 工具,它使用 .NET MAUI 開發(fā)的,可用于 Windows 和 macOS(對不住了,Linux 用戶)。
為什么會開發(fā) Dots?
總所周知, .NET 的小版本更新很快,而我經(jīng)常會試用 SDK 的最新預覽版。甚至嘗試自定義構建。我在我的機器上安裝了幾個不同版本的 SDK,只是方便能夠在它們之間進行切換。通常我會嘗試保留當前的穩(wěn)定版本、最新的預覽版和 LTS 版本。除此之外,我可能需要特定項目的特定 SDK 版本。
當然有 dotnet cli 允許我檢查安裝的版本,dotnet --list-sdks 可以輸出安裝的版本信息。
但我想更好地了解所有已安裝版本的一些細節(jié),并能夠快速卸載它們。
于是,Dots - 更友好的 .NET SDK 管理器來了!歡迎大家嘗試使用!
項目地址: https://github.com/nor0x/Dots
【DotNetCorePlugins- 動態(tài)加載和卸載 .NET 程序插件】
DotNetCorePlugins 是一個 .NET 的開源插件項目,它提供了能夠動態(tài)加載程序集的 API,然后把它們作為 .NET 主程序的擴展程序執(zhí)行。
這個庫主要用到了 AssemblyLoadContext
技術, System.Runtime.Loader.AssemblyLoadContext
,又名 ALC,提供了一些用于定義動態(tài)程序集加載行為的基本 API。這是 .NET Core 中我最喜歡但鮮為人知的 API 之一。
如何使用?
安裝 McMaster.NETCore.Plugins
NuGet 包。
dotnet add package McMaster.NETCore.Plugins
主要使用的 API 是 PluginLoader.CreateFromAssemblyFile
, 它允許從文件中讀取并加載程序集。
PluginLoader.CreateFromAssemblyFile(
assemblyFile: "./plugins/MyPlugin/MyPlugin1.dll",
sharedTypes: new [] { typeof(IPlugin), typeof(IServiceCollection), typeof(ILogger) },
isUnloadable: true)
- assemblyFile = 插件 .dll 的文件路徑
- sharedTypes = 加載程序的統(tǒng)一的類型列表
- isUnloadable = 允許這個插件在將來的某個時候從內存中卸載。
定義接口
這是一個示例,我們定義了一個接口,里面包含了 GetName, 如下
public interface IPlugin
{
string GetName();
}
對于插件,我們直接使用這個接口并進行實現(xiàn),如下
internal class MyPlugin1 : IPlugin
{
public string GetName() => "My plugin v1";
}
對于主程序,我們可以使用 PluginLoader
API 來加載插件,程序需要使用查找磁盤中的插件程序集。一種方式是基于約定的,比如
plugins/
$PluginName1/
$PluginName1.dll
(additional plugin files)
$PluginName2/
$PluginName2.dll
每個插件都發(fā)布到一個單獨的目錄中,這樣可以避免插件之間的爭用和重復的依賴問題。
以通過運行下面的命令,輸出插件到文件夾中。
dotnet publish MyPlugin1.csproj --output plugins/MyPlugin1/
接下來,我們可以通過反射獲取所有的插件,并進行加載, 代碼如下
using McMaster.NETCore.Plugins;
var loaders = new List<PluginLoader>();
// create plugin loaders
var pluginsDir = Path.Combine(AppContext.BaseDirectory, "plugins");
foreach (var dir in Directory.GetDirectories(pluginsDir))
{
var dirName = Path.GetFileName(dir);
var pluginDll = Path.Combine(dir, dirName + ".dll");
if (File.Exists(pluginDll))
{
var loader = PluginLoader.CreateFromAssemblyFile(
pluginDll,
sharedTypes: new [] { typeof(IPlugin) });
loaders.Add(loader);
}
}
// Create an instance of plugin types
foreach (var loader in loaders)
{
foreach (var pluginType in loader
.LoadDefaultAssembly()
.GetTypes()
.Where(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsAbstract))
{
IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType);
Console.WriteLine($"Created plugin instance '{plugin.GetName()}'.");
}
}
支持 MVC 和 Razor
另外插件還支持加載 MVC 的 Controller 和 Razor Pages。通過安裝下面的 Nuget 包。
dotnet add package McMaster.NETCore.Plugins.Mvc
加載程序集的方法如下:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
var pluginFile = Path.Combine(AppContext.BaseDirectory, "plugins/MyRazorPlugin/MyRazorPlugin.dll");
services
.AddMvc()
.AddPluginFromAssemblyFile(pluginFile);
}
}
更多插件的使用方法,作者提供了一些示例項目,可以進行參考。文章來源:http://www.zghlxwxcb.cn/news/detail-427865.html
項目地址:https://github.com/natemcmaster/DotNetCorePlugins文章來源地址http://www.zghlxwxcb.cn/news/detail-427865.html
到了這里,關于【Dotnet 工具箱】JIEJIE.NET - 強大的 .NET 代碼混淆工具的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!