Skip to content
← All posts
· Delta1 Labs Guide.NETObfuscation

How to obfuscate a .NET assembly (step-by-step, 2026)

A practical guide to obfuscating .NET assemblies — what to protect, how to do it with Nebula.NET, and how to verify your app still runs identically afterward.

.NET assemblies are easy to decompile. Tools like ILSpy, dnSpy and dotPeek can turn your compiled DLL back into near-original C# in seconds, exposing your algorithms, license checks, API keys and business logic. Obfuscation raises the cost of that by rewriting the compiled IL so it’s hard to read — without changing how your program runs.

This guide walks through obfuscating a .NET assembly the right way, using Nebula.NET.

Before you start

Obfuscate your release build, not debug, and keep a copy of the original. Decide what must keep its public names — for libraries and plugins, your public API and any members hit by reflection or serialization should be preserved.

Step 1 — Install the tool

Download the Windows installer from the download page and run it. It installs both a command-line tool (nebula) and a desktop GUI. No .NET runtime is required on the machine running it.

Step 2 — Create a configuration

Nebula is driven by a small JSON file. Create nebula.config.json next to your build output:

{
  "schemaVersion": 1,
  "inputs": ["bin/Release/net8.0/MyApp.dll"],
  "outputDirectory": "protected",
  "preservePublicApi": true,
  "encryptStrings": true,
  "controlFlowObfuscation": true
}
  • preservePublicApi keeps public types/members named — essential for libraries.
  • encryptStrings encrypts literal strings so keys and messages don’t sit in plain text.
  • controlFlowObfuscation rewrites your methods so the original logic is obscured.

Step 3 — Run it

nebula --config nebula.config.json

You’ll see a summary of what was renamed, flattened and encrypted, and a protected copy of your assembly appears in protected/.

Step 4 — Verify it still works

This is the step most people skip — and it’s the most important. Obfuscation must never change behavior. Run your app or your full test suite against the protected build and confirm everything behaves exactly as before. Nebula validates output automatically and is tested to preserve runtime behavior across .NET Framework 4.8 and .NET 6–10, but you should always run your own tests too.

What each transform does

  • Identifier renaming replaces meaningful type/method/field names with meaningless ones, while preserving anything that must keep its name.
  • Control-flow flattening rewrites methods into dispatcher-driven state machines, so a decompiler can’t show your original structure.
  • String encryption encrypts literals with a per-build key, decrypted at runtime by an inlined routine.
  • Anti-tamper and anti-debug detect a modified assembly or an attached debugger and react as you configure.

Read more in how it works.

Watch out for reflection and serialization

If your code looks up types or members by string name (reflection, dependency injection, JSON/XML serialization, some ORMs), renaming those members will break it. Preserve them with preservePublicApi and Nebula’s include/exclude rules. When something misbehaves after obfuscation, this is almost always the cause — narrow down which transform is involved and exclude the affected members.

Automate it in CI

Once it works locally, protect on every build. Nebula returns meaningful exit codes and takes a --json summary, so it drops into any pipeline:

nebula --config nebula.config.json --json nebula-summary.json

See MSBuild & CI for details.

Summary

To obfuscate a .NET assembly: install a tool, write a config that preserves your public API, enable the transforms you need, run it, and — crucially — verify your app still runs identically. Start with the free edition; it’s enough to protect small projects and evaluate the full suite.

Try Nebula.NET

Harden your .NET code in minutes — start with the free edition.