NET is a powerful open source assembly obfuscation tool for . It utilizes deep encryption technology and diverse obfuscation strategies to effectively protect the copyright and source code security of .NET software from unauthorized access and tampering.
Projects
NET code encryption tool developed in C#. Many developers are concerned that their software will be cracked and their copyrights infringed, and there are tools available on the market such as PreEmptive dotfuscator, but they may not be able to fully satisfy some specific needs.
Therefore, it has been created, which is capable of deeply encrypting .NET assemblies, thus effectively protecting software copyrights. It is especially worth mentioning that this tool is completely open source and available for free.
1. Name confusion
Rename types and members: make it harder to understand the semantics of the API by changing the names of types and members.
2. Control flow confusion
Obfuscated control flow: randomizes the control flow of IL code, destroying the original syntactic structure and making the code hard to decipher.
3、String encryption
Encrypted String Values: collects all string values defined in the program set, converts them to static read-only fields, and encrypts these values.
4. Resource protection
Encrypt resource files: Encrypt and hide embedded resource files (e.g., .resources files) so that they cannot be easily tampered with.
5. Assigning call stack protection
Hidden allocation call stack: Adjust the allocation call process for key string values to prevent hackers from searching for critical information using memory analysis tools.
Project Effect
1. Encrypted program sets
It is possible to collect all string values defined in a program set, convert them to static read-only fields in a new class, and encrypt the values. This makes it impossible to search for string values directly, making it more difficult to crack.
private string GetLicenseMessage() { return "License authorization for software." + ; }
Use the processed code
private string GetLicenseMessage() { string text = _0._6 + ; 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); } }
2. Confusing the order of class members
When we write code for a large class, it is often the case that fields or methods with the same purpose are placed close together.
Example:
private string _RegisterCode = null; private bool _IsRegisteredFlag = false; public void SetRegisterCode(string code) { } public bool IsRegisterdCodeOK(string code) { } public string GetErrorMessageForRegister(); // Other members
When a hacker captures a key member (e.g. _RegisterCode) and analyzes other members nearby, more useful information may be obtained. However. it is possible to obfuscate the order of class members. like this:
private bool _IsRegisteredFlag = false; // Other members private string _RegisterCode = null; // Other members public string GetErrorMessageForRegister(); // Other members public bool IsRegisterdCodeOK(string code) { } // Other members public void SetRegisterCode(string code) { } // Other members
In this way, other members in the neighborhood may not be related to a key member, which can make cracking more difficult.
3. Hidden array definition
Frequently, arrays are defined in source code, for example:
public static byte[] GetBytes() { return new byte[] { 85, 203, 85, 204, 85, 255, 85, 245, 85 }; }
Code after use
public static byte[] GetBytes() { byte[] array = new byte[18]; ( array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); return array; }
When handled in this way, the definition of the original array is hidden, making reverse engineering more difficult.
4. Simple to use
NET Framework console applications.
It supports the following command line arguments:
-
input
: [Required, default parameter, enter the full path to the .NET assembly file, either an .exe or .dll file, currently only supported for .] -
output
: [Optional, outputs the full path to the .NET assembly file; if empty, the value of the input parameter is used] -
snk
:: [optional, full path to strong name signature file (.snk) used to add strong names to output assemblies] -
switch
: [Optional, multi-switch parameter, separated by commas, can also be defined in []. Support:-
+controlflow
: Enable control flow obfuscation in method bodies. -
-controlflow
: Disable control flow obfuscation in method bodies. -
±strings
: Enable/disable string value encryption. -
±resources
: Enable/disable resource data encryption. -
±memberorder
: Enable/disable obfuscation of the order of the list of members in a type. -
±rename
: Enable/disable renaming of type or member names. -
±allocationcallstack
: Enable/disable encryption of the string value assignment call stack].
-
-
mapxml
: [Optional, name of the XML-formatted file/directory that holds information about the mapping of old and new names of classes/members]. -
pause
: [Optional, to pause the console when processing is complete]. -
debugmode
: [Optional, allows some debugging information text to be displayed]. -
sdkpath
: [Optional, set the full path of the directory where it is located]. -
prefixfortyperename
: [Optional, prefix for type name renaming]. -
prefixformemberrename
: [Optional, prefix for type member name renaming]. -
deletetempfile
: [Optional, delete the template file after the task is completed, default is false]. -
merge
: [Optional, merge some .NET assembly files into the result file.' *' means merge all referenced assembly files]. -
.subsystem
: [Optional, integer value, '2' for GUI-mode applications, '3' for console-mode applications]. -
.corflags
:: [Optional, integer flag, '3' means 32-bit process without strong name signature, '1' means 64-bit without strong name, '9' means 32-bit with strong name, '10' means 64-bit with strong name]. -
[BlazorWebAssembly]
:: [Optional, to handle Blazor WebAssembly assemblies]. -
DeadCode
: [Optional, may beDisabled
、Normal
(all methods are renamed and do not have any custom attributes and are never used) orAll
(All methods renamed and never used).] -
RemoveCustomAttributeTypeFullnames
: [Optional, a complete list of type names for the custom attribute types to be removed].
Example 1: Protect the d:\ file, which will modify the dll file.
> d:\
Example 2: Analyze a d:\ file and write the results to another dll file with a strong name. Enables control flow obfuscation, but does not encrypt the resource.
> input=d:\ output=d:\publish\ snk=d:\source\ switch=+controlflow,-resources
These are the functions of the tool and how to use it.
Project Address
GitHub:
If you found this article helpful, why not support it with a like? Your support is what keeps me motivated to continue sharing my knowledge. Feel free to leave a comment if you have any questions or need further help.
You can also join WeChat[DotNet Technician] community to share ideas and grow with other tech-loving peers!Excellence is a habit, so feel free to leave a comment and learn!