Professional .NET obfuscation tool for protecting C# assemblies and source code.
Obfy helps protect your .NET applications from reverse engineering by applying multiple obfuscation techniques including string encryption, control flow obfuscation, symbol renaming, anti-debugging, anti-tamper, and metadata removal.
These techniques raise the cost of casual reverse engineering. They are not confidentiality: decryption keys live in the output assembly. Do not ship real secrets (API keys, tokens, credentials) inside an assembly and rely on obfuscation.
- Easy to Use - Single command to obfuscate your assemblies
- Configurable - From minimal to aggressive protection levels, plus an interactive
config wizard - Modern - Built for .NET 10; CLI runs cross-platform, WPF UI is Windows
- Extensible - JSON configuration for fine-grained control
- IDE Integration - Visual Studio 2022 and JetBrains Rider extensions with right-click obfuscation
- Fast - Efficient obfuscation with minimal overhead
Free download for Windows. The Store package installs the WPF UI and adds the obfy command to your PATH.
Direct download (no Store): ObfySetup-1.3.0.exe from GitHub Releases.
You can also build a sideload/Store MSIX locally:
.\build\build-msix.ps1See package/README.md for sideload, certificate trust, and Partner Center identity steps. Privacy policy: PRIVACY.md.
Requires the .NET 10 SDK or runtime.
dotnet tool install --global ObfyPer-repo (commit .config/dotnet-tools.json so CI can dotnet tool restore):
dotnet new tool-manifest
dotnet tool install ObfyIf both the Windows installer/MSIX and the global tool are installed, both register the obfy command. Use one or the other on PATH.
# Basic obfuscation with standard protection
obfy MyApp.dll -o output/
# Obfuscate a solution as a closed set
obfy MyApp.sln -o out/
# Aggressive protection (stronger; test thoroughly)
obfy MyApp.dll -l aggressive -o output/
# Using a configuration file
obfy MyApp.dll -c obfy.json -o output/
# Generate a configuration file
obfy config generate -o obfy.json
# Generate an obfuscation report
obfy MyApp.dll -o output/ --report report.html
# Interactive configuration wizard
obfy config wizard -o obfy.jsonObfy also includes a modern WPF desktop application with Fluent Design:
# Run the UI
dotnet run --project Src/Obfy.UI/Obfy.UI.csproj
# Open with files already loaded
dotnet run --project Src/Obfy.UI/Obfy.UI.csproj -- MyApp.dll -o output/Features:
- Three-panel layout (Settings, Files, Output)
- Drag-and-drop assemblies, source files, or a solution/project (expands into included outputs and skipped rows)
- Closed-set protection when two or more included assemblies are listed, or when files came from a solution/project session (the Merge toggle still wins)
- Level presets with expandable advanced settings
- In-app Help (toolbar Help and F1)
- Real-time progress and color-coded output
- Results visualization with symbol map export
For Visual Studio 2022 users, Obfy provides IDE integration from source (not on Marketplace or GitHub Releases yet):
dotnet build Src/Obfy.VisualStudio/Obfy.VisualStudio.csproj -c ReleaseThen in Visual Studio: Extensions → Manage Extensions → Install from VSIX, and pick the .vsix under Src/Obfy.VisualStudio/bin/Release/.
Features:
- Right-click project → Obfuscate to protect your output assembly
- Enable / Disable Post-Build Obfuscation for automatic protection on each build
- Obfy Settings dialog with level presets (Minimal/Standard/Aggressive/Custom)
- Per-project configuration stored in
obfy.json - Output window integration for real-time progress
- Tools → Options → Obfy for global defaults
For JetBrains Rider users, Obfy provides IDE integration from a local Gradle build (the plugin is versioned independently of the 1.3.0 product; it is not attached to GitHub Releases). Requires JDK 21:
cd Src/Obfy.Rider
./gradlew.bat build # Unix: ./gradlew buildThe zip is Src/Obfy.Rider/build/distributions/Obfy.Rider-1.0.1.zip. In Rider: Settings → Plugins → Gear icon → Install Plugin from Disk.
Features:
- Right-click project → Obfy → Obfuscate to protect your output assembly
- Enable / Disable Post-Build Obfuscation for automatic protection on each build
- Settings dialog with level presets (Minimal/Standard/Aggressive/Custom)
- Per-project configuration stored in
obfy.json - Tool window integration for real-time progress
- Settings → Tools → Obfy for global defaults
Src/Obfy.VSCode contributes JSON schema validation for obfy.json and a problem matcher for CLI Error: / ⚠ lines. There is no TaskProvider; add a shell task that runs obfy on PATH. See Src/Obfy.VSCode/README.md.
Original code:
public class UserService
{
public User GetUser(int userId)
{
var status = "Looking up user";
return Database.Query(status, userId);
}
}After obfuscation (conceptual):
public class _
{
public _ _(int _)
{
var _ = _StringDecryptor.Decrypt(encodedIndex);
return _._(_, _);
}
}String/constant “encryption” is obfuscation. The key is in the assembly and is recoverable.
| Level | Description | Use Case |
|---|---|---|
minimal |
Symbol renaming only | Quick protection, debugging easier |
standard |
String encryption + renaming + metadata | Balanced protection (default) |
aggressive |
Most protections on (control-flow intensity 80; method IL encryption on Windows) | Stronger protection; test thoroughly |
custom |
Configure via flags or config file | Fine-tuned control |
Aggressive does not enable watermark, packing, incremental cache, virtualization, dependency embedding, or external call proxies. Those are opt-in in obfy.json.
Encrypts string literals with AES-256 or XOR so they are not stored as plaintext. The key is embedded; this is not secret storage.
Encrypts numeric literals (int, long, float, double) with XOR or AES-256.
Encrypts embedded resources and rewrites GetManifestResourceStream call sites so they decrypt at runtime.
Transforms code structure using switch dispatchers and opaque predicates, making the logic harder to follow.
Renames types, methods, fields, properties, events, namespaces, and parameters to meaningless identifiers while preserving functionality.
Injects debugger detection, wipes in-memory PE headers (Windows), and verifies a whole-file SHA-256 at load.
Injects junk types and methods to clutter decompiler output, plus optional decoy ConfusedBy/Dotfuscator attributes.
Replaces eligible instance and static methods with a bytecode interpreter (--virtualize). Skips EH, generic methods/types/calls, byref, custom structs/Nullable<T>, switch, constructors, typeof (ldtoken), interpolators that allocate DefaultInterpolatedStringHandler, and using / enumerator-struct foreach (array foreach can be encoded). Per-build opcode permutation and XOR. Gated off NativeAOT / Unity IL2CPP / Blazor WASM; off in every preset. Deterrent, not confidentiality.
XOR-encrypts method bodies in the PE (Windows) and hides call targets behind calli trampolines.
Strips debug information, custom attributes, and documentation, reducing attack surface and file size.
Generate detailed HTML or JSON reports with statistics, file size comparison, processing times, and warnings.
obfy MyApp.dll -o output/ --report report.htmlMerge multiple assemblies into a single output before obfuscation. Internalize merged types for better protection.
obfy App.dll Lib1.dll Lib2.dll --merge -o output/With packing.enabled (config-only; off in every preset), Obfy replaces the obfuscated PE with a framework-dependent native Windows host. User IL is AES-256-CBC ciphertext in an overlay. Set packing.rid to portable for the previous managed {name}.launcher.exe. Closed-set / solution runs pack each entry-point output. Not Pre-JIT, not self-contained, not ARM64. Packing hides the managed PE on disk; the key is in the overlay — this is obfuscation, not confidentiality.
Create an obfy.json configuration file:
{
"level": "custom",
"stringEncryption": {
"enabled": true,
"algorithm": "Aes256"
},
"symbolRenaming": {
"enabled": true,
"preservePublicApi": true
},
"controlFlow": {
"enabled": true,
"intensity": 50
},
"metadata": {
"removeDebugInfo": true
}
}A -c file is used as-is (level inside it is not re-applied as a preset). Use obfy config generate -l standard when you want a fully resolved Standard file.
Check out the examples folder:
| Example | Description |
|---|---|
| BasicConsoleApp | Simple console app obfuscation |
| LibraryWithPublicApi | Preserve public API while obfuscating internals |
| MsBuildIntegration | Automatic obfuscation in build process |
| unity | runtimeProfile: UnityIl2Cpp recipe (obfy.json only) |
| blazor | runtimeProfile: BlazorWasm recipe (obfy.json only) |
| maui | MAUI / XAML preserveXaml recipe (obfy.json only) |
| Document | Description |
|---|---|
| CLI Reference | Complete command-line options |
| Configuration | Full JSON schema and examples |
| Techniques | How each obfuscation technique works |
| Advanced | Exclusions, best practices, troubleshooting |
| Platforms | NativeAOT, Blazor WASM, MAUI |
| Unity | Mono / IL2CPP recipe |
| Testing | Test projects and how to add tests |
| Testing roadmap | Scenario coverage plan (WPF solutions, CI, platforms) |
| Roadmap | Feature roadmap and backlog |
| Competitive Analysis | Comparison with other .NET obfuscators |
<Target Name="Obfuscate" AfterTargets="Build" Condition="'$(Configuration)' == 'Release'">
<Exec Command="obfy "$(TargetPath)" -c obfy.json -o "$(TargetDir)"" />
</Target>- uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.x'
- name: Obfuscate
run: |
dotnet tool install --global Obfy
obfy bin/Release/net10.0/MyApp.dll -l aggressive -o dist/We welcome contributions! Please see CONTRIBUTING.md for guidelines.
For security issues, please see SECURITY.md.
MIT License - see LICENSE for details.
Made with ❤️ for the .NET community



