目的
对比不同的主流保护工具,针对 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# 程序。