天天看點

[C#] 代碼混淆和加殼

目的

對比不同的主流保護工具,針對 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 的根目錄即可:

[C#] 代碼混淆和加殼

混淆效果

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 混淆

混淆效果

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

關鍵的資訊都沒清空了,另外反編譯時多了很多垃圾資料:

[C#] 代碼混淆和加殼

那先混淆再用 vmp 加殼,或者先用 vmp 加殼在混淆會什麼樣子?

經過測試,無論是先混淆再加殼還是先加殼在混淆,都不可以,也就是說(當然可能這隻針對 vmp),殼和混淆應該是不互相相容的。

.NET Reactor

加殼混淆效果:

這個就很離譜了,直接把除 PE 頭外的東西都給幹沒了,我不禁豎起了大拇指 U•ェ•*U

[C#] 代碼混淆和加殼

另外這個 .NET Reactor 還附帶了反調試和其他的功能:

[C#] 代碼混淆和加殼

這就結束了嗎,沒有, 經過測試 被 .NET Reactor 保護過的程式仍可以用 vmp 再保護一次

如下:

[C#] 代碼混淆和加殼

源程式大小 8kb ,加 .NET Reactor 後變成 197kb ,再加上 vmp 後,變成了 0.5M ,并且這并不影響程式的運作:

[C#] 代碼混淆和加殼