Skip to Content
New release 12 available 🎉
ObfuscatorEnhancing Code Security

Enhancing Code Security

Best practices for enhanced code security.

Babel Obfuscator is a powerful tool that offers robust protection for your code. While delving into all the intricacies of obfuscation may be time-consuming, we have compiled a set of tips that will help you achieve optimal obfuscation results with minimal effort. By following these recommendations, you can significantly enhance the security of your code without getting lost in the details.

Strong protection comes from defense in depth: no single transformation is meant to stop an attacker on its own. Renaming hides intent, encryption hides data, control flow and dynamic proxies hide logic, and runtime checks deter tampering and debugging. Combine several layers so that defeating one still leaves the others in place. The tips below are grouped by what each layer protects.

Rename and Restructure Your Symbols

Consider Internalizing Types in C# or Marking Them as Friend In VB

Declaring types as internal or Friend (in VB terminology) ensures they are not visible to external assemblies and can be safely renamed during obfuscation. This step effectively shields your code from prying eyes.

Babel Obfuscator allows the renaming of public types or symbols externally visible to the assembly by using XML Rules. However, this must be carefully reviewed because if the symbol is consumed by external assemblies, this will break the application. Therefore, while internalizing or marking types as Friend is a straightforward way to enhance security, forcing renaming of public symbols requires thorough consideration and testing.

Strengthen Renaming

Beyond the default symbol renaming, a few options make the renamed metadata considerably harder to read:

  • Overloaded renaming reuses a single obfuscated name for many unrelated members, so the metadata no longer maps one-to-one to your members.
  • Flatten namespaces collapses your namespace hierarchy, erasing the structural hints a decompiler relies on.
  • Virtual member renaming renames virtual and interface members consistently across the type hierarchy.

Babel CLI

babel.exe myapp.dll --overloaded --flatns --virtualmembers

Merge Dependencies Whenever Possible

Babel Obfuscator allows you to merge referenced assemblies into the target assembly. By internalizing all merged types, you increase the number of renamed symbols, making it harder for potential attackers to decipher your code.

Hide Constant Data

Utilize Hash Algorithm for String Encryption

Employing the hash string encryption algorithm provides strong protection while reducing the size of the obfuscated assembly on the disk. You can enable this feature using the following command:

Babel CLI

babel.exe myapp.exe --stringencryption hash

MSBuild Babel Task

<PropertyGroup> <StringEncryption>hash</StringEncryption> </PropertyGroup>

Encrypt Inline Values and Arrays

Numeric constants and inline arrays frequently carry sensitive data — thresholds, keys, magic numbers, lookup tables. Value and Array Encryption removes those literals from the IL and decrypts them at runtime, so a decompiler no longer sees the real numbers or array contents.

Babel CLI

babel.exe myapp.exe --values int32=on --values int64=on --values single=on --values double=on --values array=on

Encrypt Managed Resources

Resource Encryption hides embedded resources within your assembly while compressing them, providing an additional layer of protection. Carefully consider the performance impact before enabling this feature.

Obscure Program Logic

Enable Control Flow Obfuscation

Control Flow Obfuscation adds complexity to if statements, inserts irrelevant branches and introduces multiple switch instructions without altering the method’s behaviour. Enabling specific control flow algorithms like goto, if, switch, case, and call ensures the best code scramble. The following recommended settings will help you achieve effective control flow obfuscation:

Babel CLI

babel.exe myapp.exe --controlflow goto=on --controlflow if=on --controlflow switch=on --controlflow case=on --controlflow call=on

MSBuild Babel Task

<PropertyGroup> <ControlFlowObfuscation>goto=true;if=true;switch=true;case=true;call=true;true</ControlFlowObfuscation> <ControlFlowIterations>3</ControlFlowIterations> </PropertyGroup>

By enabling the above control flow obfuscation settings, you ensure a robust and effective obfuscation of your code. The different algorithms (goto, if, switch, case, and call) contribute to making the control flow more convoluted and challenging to analyze, enhancing the security of your application.

Use Dynamic Proxy Generation for External Method Calls

Dynamic Proxies effectively hide calls to external and internal methods. Enabling dynamic proxy generation for external calls is often sufficient to achieve a high level of obfuscation.

babel.exe myapp.exe --proxy external

Encrypt Code

Code Encryption provides robust protection for methods that handle sensitive data, such as license key verification. However, be mindful of performance implications, as code encryption can have an impact on application speed — apply it selectively to the methods that need it.

With the integration of Babel Licensing Service, you have the flexibility to utilize Activation or Floating Licenses to enable feature-based licensing. This means that you can securely deliver encryption keys through the licensing service, unlocking specific features of your application for authorized users.

By leveraging Babel Licensing Service in combination with Code Encryption, you ensure that only licensed users have access to the encrypted code segments. The encryption key is securely delivered through the licensing service, preventing unauthorized usage and ensuring the integrity of your application’s features.

Detect and Deter Runtime Attacks

Enable Anti Tampering Protection

Anti Tampering Protection detects any unauthorized modification to your assembly. Choose appropriate actions, such as stopping execution or reporting an error to the user, to deter attackers. Opting for silent actions makes it more challenging to bypass the anti-tampering mechanism.

babel.exe myapp.exe --tamperingdetection

Enable Anti Debugging Protection

Anti-Debugging detects when your application is run under a debugger or profiler — the tools an attacker uses to observe secrets as they are decrypted at runtime. Combined with the encryption layers above, it closes the gap left by static analysis.

babel.exe myapp.exe --antidebugging

Block Disassembly and Reflection Tools

Two lightweight switches make casual inspection harder: --ildasm marks the assembly so the MSIL Disassembler (ildasm.exe) refuses to open it, and --reflection stops reflection-based tools from listing the assembly’s metadata.

babel.exe myapp.exe --ildasm --reflection

Strip What You Don’t Need to Ship

Every piece of metadata you leave behind is a hint. Remove what the running application does not need:

  • Clean attributes — --cleanattrs removes custom attributes that only served the compiler or your tooling.
  • Remove dead code — --deadcode drops unreachable methods and members.
  • Remove enums — --enumremoval replaces enum types with their underlying constants.
  • Seal internal classes — --seal seals internal types that are never inherited.
  • Do not ship debug symbols — deploy without the .pdb file (avoid --debug) so line numbers and local names are not available to an attacker.

The following command combines the layers above into a strong, general-purpose configuration. Add --msilencryption for the specific sensitive methods that warrant it.

babel.exe myapp.dll ` --overloaded --flatns --virtualmembers ` --stringencryption hash ` --values int32=on --values int64=on --values single=on --values double=on --values array=on ` --controlflow if=on --controlflow switch=on --controlflow case=on --controlflow chain=on ` --proxy external ` --resourceencryption ` --tamperingdetection --antidebugging --ildasm ` --cleanattrs --seal

The equivalent MSBuild task properties:

<PropertyGroup> <OverloadedRenaming>true</OverloadedRenaming> <FlattenNamespaces>true</FlattenNamespaces> <VirtualFunctions>true</VirtualFunctions> <StringEncryption>hash</StringEncryption> <ValueEncryption>int32=true;int64=true;single=true;double=true;array=true;true</ValueEncryption> <ControlFlowObfuscation>if=true;switch=true;case=true;chain=true;true</ControlFlowObfuscation> <DynamicProxy>external=true;true</DynamicProxy> <ResourceEncryption>true</ResourceEncryption> <TamperingDetection>true</TamperingDetection> <DebuggingProtection>true</DebuggingProtection> <SuppressIldasm>true</SuppressIldasm> <CleanAttributes>true</CleanAttributes> <SealClasses>true</SealClasses> </PropertyGroup>

Keep a Map File for Support

Aggressive obfuscation makes production stack traces unreadable. Keep the obfuscation map file produced for each build so you can decode stack traces back to the original names when diagnosing customer issues — without weakening the shipped assembly.

Test the Obfuscated Application: It is crucial to thoroughly test your obfuscated application to identify and address any potential issues introduced by the obfuscation process. Testing ensures the stability and proper functioning of your code. When deploying on FIPS-enabled hosts, also review FIPS Compliance, since several encryption layers decrypt through the platform crypto provider at runtime.

By following these obfuscation tips, you can leverage Babel Obfuscator effectively and bolster the security of your code. For more detailed information and comprehensive guidance, we recommend consulting the Babel Obfuscator user’s guide.

Last updated on