【Dotnet 工具箱】JIEJIE.NET - 强大的 .NET 代码混淆工具

这篇具有很好参考价值的文章主要介绍了【Dotnet 工具箱】JIEJIE.NET - 强大的 .NET 代码混淆工具。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

你好,这里是 Dotnet 工具箱,定期分享 Dotnet 有趣,实用的工具和组件,希望对您有用!

【JIEJIE.NET - 强大的 .NET 代码混淆工具】

JIEJIE.NET

JIEJIE.NET 是一个使用 C# 开发的开源 .NET 代码加密工具。

很多 .NET 开发人员担心他们的软件被破解,版权受到侵犯,所以他们使用一些工具来混淆 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;
}

现在代码流程已经被破坏了。

3. 加密所有字符串值

JieJie.NET 可以收集程序集中定义的所有字符串值,然后把它们转换为新类中的静态只读字段,并对它们的值进行加密。

旧代码:

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 开发的,可用于 Windows 和 macOS(对不住了,Linux 用户)。

为什么会开发 Dots?

总所周知, .NET 的小版本更新很快,而我经常会试用 SDK 的最新预览版。甚至尝试自定义构建。我在我的机器上安装了几个不同版本的 SDK,只是方便能够在它们之间进行切换。通常我会尝试保留当前的稳定版本、最新的预览版和 LTS 版本。除此之外,我可能需要特定项目的特定 SDK 版本。

当然有 dotnet cli 允许我检查安装的版本,dotnet --list-sdks 可以输出安装的版本信息。

但我想更好地了解所有已安装版本的一些细节,并能够快速卸载它们。

于是,Dots - 更友好的 .NET SDK 管理器来了!欢迎大家尝试使用!

项目地址: https://github.com/nor0x/Dots

【DotNetCorePlugins- 动态加载和卸载 .NET 程序插件】

DotNetCorePlugins 是一个 .NET 的开源插件项目,它提供了能够动态加载程序集的 API,然后把它们作为 .NET 主程序的扩展程序执行。

这个库主要用到了 AssemblyLoadContext 技术, System.Runtime.Loader.AssemblyLoadContext,又名 ALC,提供了一些用于定义动态程序集加载行为的基本 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 = 加载程序的统一的类型列表
  • isUnloadable = 允许这个插件在将来的某个时候从内存中卸载。

定义接口

这是一个示例,我们定义了一个接口,里面包含了 GetName, 如下

public interface IPlugin
{
    string GetName();
}

对于插件,我们直接使用这个接口并进行实现,如下

internal class MyPlugin1 : IPlugin
{
    public string GetName() => "My plugin v1";
}

对于主程序,我们可以使用 PluginLoader API 来加载插件,程序需要使用查找磁盘中的插件程序集。一种方式是基于约定的,比如

plugins/
    $PluginName1/
        $PluginName1.dll
        (additional plugin files)
    $PluginName2/
        $PluginName2.dll

每个插件都发布到一个单独的目录中,这样可以避免插件之间的争用和重复的依赖问题。

以通过运行下面的命令,输出插件到文件夹中。

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);
    }
}

更多插件的使用方法,作者提供了一些示例项目,可以进行参考。

项目地址:https://github.com/natemcmaster/DotNetCorePlugins文章来源地址https://www.toymoban.com/news/detail-427865.html

到了这里,关于【Dotnet 工具箱】JIEJIE.NET - 强大的 .NET 代码混淆工具的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • VBA代码宝工具箱(陈表达)

    工具箱: xlam 类型工具箱 数据源:存放在隐藏工作簿的xlam文件的表里,可通过代码读取和写入,读取和写入功能源码在excel的VBA工程模块,代码全部开源 使用窗体: listbox列表框控件 和 textbox文本框控件 和 Button按钮控件等等 菜单部分,最重要部分是VBA代码宝、和VBE代码助手

    2024年02月15日
    浏览(80)
  • BP神经网络预测实例(matlab代码,神经网络工具箱)

    参考学习b站资源: 数学建模学习交流 bp神经网络预测matlab代码实现过程 神经网络简介 可在github下载(含原始样品数据): https://github.com/chenshunpeng/BP-neural-network 最早的神经网络模型, 单层感知器perceptron,结构如下: 这是一个两层的神经网络,第一层为输入层,第二层为输

    2024年02月12日
    浏览(29)
  • 基于MATLAB的最小二乘法拟合与拟合工具箱使用教程(附完整代码与算法)

    给定一组数据满足某一函数模型,其中a为待定系数向量。 那么,最小二乘曲线拟合的目标就是:求出一组待定系数的值,使得以下表达式子最小: 在MATLAB中格式如下: 由以下MATLAB代码生成一组数据: 该组数据满足y(x),求出待定系数,使得目标函数的值为最小。 解: MATL

    2024年01月17日
    浏览(31)
  • 密码算法工具箱

    这是一个密码算法工具箱软件,包含大多数密码键盘的算法,您可以利用他做加解密、校验或者其他功能。 ①本工具包含对称密钥算法、MAC算法、PINBLOCK算法、Hash算法、非对称密钥算法的常用功能。 ②支持国际(RSA、DES、3DES)和国密(SM2、SM3、SM4)算法。 ③支持windows和l

    2024年01月19日
    浏览(44)
  • Matlab 优化工具箱

    语法:[x,fval,exitflag,output,lambda] = linprog(f,A,b,Aeq,beq,lb,ub,options) f、x、b、beq、lb 和 ub 是向量,A 和 Aeq 是矩阵。 示例1-1 : 语法:[x,fval,exitflag,output] = intlinprog(f,intcon,A,b,Aeq,beq,lb,ub,x0,options) f、x、intcon、b、beq、lb 和 ub 是向量,A 和 Aeq 是矩阵。 语法:x = fmincon(fun,x0,A,b,Aeq,beq,lb,ub

    2024年02月02日
    浏览(46)
  • PDF 工具箱

    PDF 工具箱 V9.0.0.1 程序:VB.net  运行库: NET Framework 4.5 下载:https://download.csdn.net/download/polloo2012/88399029 功能简介: 1、PDF文件多文件合并,可调整顺序。 2、PDF文件拆分,将每页拆分成独立的PDF文件。 3、PDF文件添加水印,文字或图片水印,图片水印可选择位置。 4、word/exce

    2024年02月09日
    浏览(35)
  • 29 旋转工具箱

    实现了一个菜单按钮的动画效果,当鼠标悬停在菜单按钮上时,菜单按钮会旋转315度,菜单按钮旋转的同时,菜单按钮旋转的8个小圆圈也会依次旋转360度,并且每个小圆圈的旋转方向和菜单按钮的旋转方向相反,当鼠标悬停在某个小圆圈上时,该小圆圈的旋转方向会变为顺时

    2024年01月18日
    浏览(43)
  • Python工具箱系列(三十)

    MySQL的口号是“世界上最流行的开源关系型数据库”,而PostgreSQL的Slogan则是“世界上最先进的开源关系型数据库(PostgreSQL: The World\\\'s Most Advanced Open Source Relational Database)”,一看这就是一对老冤家了。这两个口号很好的反映出了两者的形象特质:PostgreSQL是功能丰富,高大上的严

    2024年02月03日
    浏览(45)
  • Python工具箱系列(三十七)

    二进制文件操作(上) python比较擅长与文本相关的操作。但现实世界中,对于非文本消息的处理也很普遍。例如: ◆通过有线、无线传递传感器获得的测量数据。 ◆卫星通过电磁波发送测量数据。 ◆数据中心的数万台服务器发送当前CPU的占用率信息、内存占用量等众多指标

    2024年02月11日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包