[C#] 代码混淆和加壳

发布时间 2023-04-01 21:34:33作者: DoubleLi

目的

对比不同的主流保护工具,针对 dnSpy 反编译出的效果。

非混淆代码:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace test_winform
{
	// Token: 0x02000002 RID: 2
	public class Form1 : Form
	{
		// Token: 0x06000001 RID: 1 RVA: 0x00002050 File Offset: 0x00000250
		public Form1()
		{
			this.InitializeComponent();
		}

		// Token: 0x06000002 RID: 2 RVA: 0x0000207A File Offset: 0x0000027A
		private void button1_Click(object sender, EventArgs e)
		{
			MessageBox.Show("123");
		}

		// Token: 0x06000003 RID: 3 RVA: 0x00002088 File Offset: 0x00000288
		protected override void Dispose(bool disposing)
		{
			bool flag = disposing && this.components != null;
			if (flag)
			{
				this.components.Dispose();
			}
			base.Dispose(disposing);
		}

		// Token: 0x06000004 RID: 4 RVA: 0x000020C0 File Offset: 0x000002C0
		private void InitializeComponent()
		{
			this.button1 = new Button();
			base.SuspendLayout();
			this.button1.Location = new Point(394, 156);
			this.button1.Name = "button1";
			this.button1.Size = new Size(75, 23);
			this.button1.TabIndex = 0;
			this.button1.Text = "button1";
			this.button1.UseVisualStyleBackColor = true;
			this.button1.Click += this.button1_Click;
			base.AutoScaleDimensions = new SizeF(6f, 12f);
			base.AutoScaleMode = AutoScaleMode.Font;
			base.ClientSize = new Size(800, 450);
			base.Controls.Add(this.button1);
			base.Name = "Form1";
			this.Text = "Form1";
			base.ResumeLayout(false);
		}

		// Token: 0x04000001 RID: 1
		private int a = 1;

		// Token: 0x04000002 RID: 2
		private string b = "asd";

		// Token: 0x04000003 RID: 3
		private IContainer components = null;

		// Token: 0x04000004 RID: 4
		private Button button1;
	}
}

eazfuscator 混淆

下载安装,网上有基于 2018 的破解版,需要最新功能就购买正版。安装后如果提示这个错误:

Unable to find tool "ildasm.exe". Ensure .NET Framework SDK is installed.

就用 everything 搜一下这个文件,然后放在 eazfuscator 的根目录即可:

混淆效果

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

// Token: 0x02000018 RID: 24
public sealed class \u0008\u2000 : Form
{
	// Token: 0x0600003D RID: 61 RVA: 0x0000313C File Offset: 0x0000133C
	public \u0008\u2000()
	{
		this.\u0002();
	}

	// Token: 0x0600003E RID: 62 RVA: 0x00003168 File Offset: 0x00001368
	private void \u0002(object \u0002, EventArgs \u0003)
	{
		MessageBox.Show(\u000F\u2000.\u0002(1645278435));
	}

	// Token: 0x0600003F RID: 63 RVA: 0x0000317C File Offset: 0x0000137C
	protected override void Dispose(bool \u0002)
	{
		bool flag = \u0002 && this.\u0005 != null;
		if (flag)
		{
			this.\u0005.Dispose();
		}
		base.Dispose(\u0002);
	}

	// Token: 0x06000040 RID: 64 RVA: 0x000031B0 File Offset: 0x000013B0
	private void \u0002()
	{
		this.\u0008 = new Button();
		base.SuspendLayout();
		this.\u0008.Location = new Point(394, 156);
		this.\u0008.Name = \u000F\u2000.\u0002(1645278441);
		this.\u0008.Size = new Size(75, 23);
		this.\u0008.TabIndex = 0;
		this.\u0008.Text = \u000F\u2000.\u0002(1645278441);
		this.\u0008.UseVisualStyleBackColor = true;
		this.\u0008.Click += this.\u0002;
		base.AutoScaleDimensions = new SizeF(6f, 12f);
		base.AutoScaleMode = AutoScaleMode.Font;
		base.ClientSize = new Size(800, 450);
		base.Controls.Add(this.\u0008);
		base.Name = \u000F\u2000.\u0002(1645278235);
		this.Text = \u000F\u2000.\u0002(1645278235);
		base.ResumeLayout(false);
	}

	// Token: 0x0400000C RID: 12
	private int \u0002 = 1;

	// Token: 0x0400000D RID: 13
	private string \u0003 = \u000F\u2000.\u0002(1645278461);

	// Token: 0x0400000E RID: 14
	private IContainer \u0005 = null;

	// Token: 0x0400000F RID: 15
	private Button \u0008;
}

Dotfuscator 混淆

配置参考:https://www.cnblogs.com/tianguook/archive/2012/10/06/2713105.html

混淆效果

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

// Token: 0x02000003 RID: 3
public class a : Form
{
	// Token: 0x06000005 RID: 5 RVA: 0x000020B4 File Offset: 0x000002B4
	public a()
	{
		int bxt_1235 = 14;
		this.ᜀ = 1;
		this.ᜁ = a.b("吴䐶崸", bxt_1235);
		this.ᜂ = null;
		base..ctor();
		this.ᜀ();
	}

	// Token: 0x06000006 RID: 6 RVA: 0x000020FC File Offset: 0x000002FC
	private void ᜀ(object A_0, EventArgs A_1)
	{
		int bxt_1241 = 11;
		short num = (short)310378496;
		short num2 = num;
		num = (short)445213688;
		short num3 = num;
		num = (short)1576758264;
		switch (num3 == num)
		{
		}
		num = (short)2146107393;
		if (num != 0)
		{
		}
		num = (short)1721237504;
		if (num != 0)
		{
		}
		MessageBox.Show(a.b("̱سԵ", bxt_1241));
	}

	// Token: 0x06000007 RID: 7 RVA: 0x000021C4 File Offset: 0x000003C4
	protected override void Dispose(bool disposing)
	{
		switch (0)
		{
		case 0:
			goto IL_2C;
		}
		int SW_LOCALVAR;
		short num;
		for (;;)
		{
			IL_0A:
			bool flag;
			bool flag2;
			switch (SW_LOCALVAR)
			{
			case 0:
				num = (short)2070282241;
				if (num != 0)
				{
				}
				num = (short)532611077;
				SW_LOCALVAR = (int)((IntPtr)num);
				continue;
			case 1:
				if (disposing)
				{
					num = (short)62652416;
					SW_LOCALVAR = (int)((IntPtr)num);
					continue;
				}
				num = (short)1510670339;
				SW_LOCALVAR = (int)((IntPtr)num);
				continue;
			case 2:
				goto IL_F7;
			case 3:
				flag = false;
				goto IL_FC;
			case 4:
				this.ᜂ.Dispose();
				num = (short)703332354;
				SW_LOCALVAR = (int)((IntPtr)num);
				continue;
			case 5:
				flag = (this.ᜂ != null);
				goto IL_FC;
			case 6:
				if (flag2)
				{
					num = (short)2086338564;
					SW_LOCALVAR = (int)((IntPtr)num);
					continue;
				}
				goto IL_19E;
			}
			goto IL_2C;
			IL_FC:
			flag2 = flag;
			num = (short)1361661929;
			short num2 = num;
			num = (short)547377129;
			switch ((num2 == num) ? 1 : 0)
			{
			case 0:
			case 2:
				goto IL_2C;
			default:
				num = (short)1285357568;
				if (num != 0)
				{
				}
				num = (short)174129158;
				SW_LOCALVAR = (int)((IntPtr)num);
				break;
			}
		}
		IL_F7:
		IL_19E:
		base.Dispose(disposing);
		return;
		IL_2C:
		num = (short)1859125248;
		short num3 = num;
		num = (short)108331009;
		SW_LOCALVAR = (int)((IntPtr)num);
		goto IL_0A;
	}

	// Token: 0x06000008 RID: 8 RVA: 0x00002378 File Offset: 0x00000578
	private void ᜀ()
	{
		int bxt_1243 = 1;
		short num = (short)1557069824;
		short num2 = num;
		num = (short)2136700257;
		short num3 = num;
		num = (short)389313889;
		switch (num3 == num)
		{
		}
		num = (short)1568669696;
		if (num != 0)
		{
		}
		num = (short)652345345;
		if (num != 0)
		{
		}
		this.ᜃ = new Button();
		base.SuspendLayout();
		this.ᜃ.Location = new Point(394, 156);
		this.ᜃ.Name = a.b("䨧弩堫娭弯就Գ", bxt_1243);
		this.ᜃ.Size = new Size(75, 23);
		this.ᜃ.TabIndex = 0;
		this.ᜃ.Text = a.b("䨧弩堫娭弯就Գ", bxt_1243);
		this.ᜃ.UseVisualStyleBackColor = true;
		this.ᜃ.Click += this.ᜀ;
		base.AutoScaleDimensions = new SizeF(6f, 12f);
		base.AutoScaleMode = AutoScaleMode.Font;
		base.ClientSize = new Size(800, 450);
		base.Controls.Add(this.ᜃ);
		base.Name = a.b("渧䔩師䌭į", bxt_1243);
		this.Text = a.b("渧䔩師䌭į", bxt_1243);
		base.ResumeLayout(false);
	}

	// Token: 0x06000009 RID: 9 RVA: 0x00002550 File Offset: 0x00000750
	internal static string b(string A_0, int A_1)
	{
		char[] array = A_0.ToCharArray();
		int num = (int)((IntPtr)(1927699470 + A_1) + (IntPtr)44 + (IntPtr)14 + (IntPtr)52 + (IntPtr)83 + (IntPtr)87);
		int num3;
		int num2;
		if ((num2 = (num3 = 0)) < 1)
		{
			goto IL_6A;
		}
		IL_37:
		int num5;
		int num4 = num5 = num2;
		char[] array2 = array;
		int num6 = num5;
		char c = array[num5];
		byte b = (byte)((int)(c & 'ÿ') ^ num++);
		byte b2 = (byte)((int)(c >> 8) ^ num++);
		byte b3 = b2;
		b2 = b;
		b = b3;
		array2[num6] = (ushort)((int)b2 << 8 | (int)b);
		num3 = num4 + 1;
		IL_6A:
		if ((num2 = num3) >= array.Length)
		{
			return string.Intern(new string(array));
		}
		goto IL_37;
	}

	// Token: 0x04000004 RID: 4
	private int ᜀ;

	// Token: 0x04000005 RID: 5
	private string ᜁ;

	// Token: 0x04000006 RID: 6
	private IContainer ᜂ;

	// Token: 0x04000007 RID: 7
	private Button ᜃ;

	// Token: 0x04000008 RID: 8
	[NonSerialized]
	string ᜄ = "";
}

感觉这个的混淆效果是要强于第一个的。


VMP 3.5 加壳

加壳后反编译效果:

using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace test_winform
{
	// Token: 0x02000002 RID: 2
	public class Form1 : Form
	{
		// Token: 0x06000003 RID: 3 RVA: 0x0000207A File Offset: 0x0000007A
		private void button1_Click(object sender, EventArgs e)
		{
		}

		// Token: 0x06000004 RID: 4 RVA: 0x00002088 File Offset: 0x00000088
		protected override void Dispose(bool disposing)
		{
		}

		// Token: 0x06000005 RID: 5 RVA: 0x000020C0 File Offset: 0x000000C0
		private void InitializeComponent()
		{
		}

		// Token: 0x04000001 RID: 1
		private int a;

		// Token: 0x04000002 RID: 2
		private string b;

		// Token: 0x04000003 RID: 3
		private IContainer components;

		// Token: 0x04000004 RID: 4
		private Button button1;
	}
}

关键的信息都没清空了,另外反编译时多了很多垃圾数据:

那先混淆再用 vmp 加壳,或者先用 vmp 加壳在混淆会什么样子?

经过测试,无论是先混淆再加壳还是先加壳在混淆,都不可以,也就是说(当然可能这只针对 vmp),壳和混淆应该是不互相兼容的。


.NET Reactor

使用教程:https://linxinfa.blog.csdn.net/article/details/109442027

加壳混淆效果:

这个就很离谱了,直接把除 PE 头外的东西都给干没了,我不禁竖起了大拇指 U•ェ•*U

另外这个 .NET Reactor 还附带了反调试和其他的功能:

这就结束了吗,没有, 经过测试 被 .NET Reactor 保护过的程序仍可以用 vmp 再保护一次
如下:

源程序大小 8kb ,加 .NET Reactor 后变成 197kb ,再加上 vmp 后,变成了 0.5M ,并且这并不影响程序的运行:

ok,那其混淆和 .NET Reactor 会不会冲突呢?
答案是否定的,原因大概是 .NET Reactor 认为被混淆后的程序不是一个合法的 c# 程序。