https://mp.weixin.qq.com/s/Sgvpc7dKUZ8iZr7tHx5jNw
项目地址
https://github.com/dcsoft-yyf/JIEJIE.NET
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 的名称被混淆了。
- 混淆代码流程
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;
}
现在代码流程已经被破坏了。
- 加密所有字符串值
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);
}
}
往期推荐:
开源的 .NET 数据库迁移框架
胡桃工具箱, 基于 .NET 开源的多功能原神工具箱
使用 C# 开源的微信/QQ/TIM 防撤回神器
推荐 3 个 .NET 流行的 Redis 客户端库
推荐一个开源的现代化的 PDF 生成组件
文档更新时间: 2023-11-18 13:19 作者:admin