RustemsoftSkater
Skater .NET Obfuscator • Engineering Note

Reflection-Safe Obfuscation in .NET: Keeping Dynamic Code Alive After Protection

Obfuscation is not about renaming everything. It is about renaming what you can prove is safe to rename. This guide shows how to draw that boundary for apps that rely on reflection, DI containers, serializers, and plugins - and how to keep strong protection active on the rest with Skater.

1 The Mental Model: Static Binding vs Dynamic Binding

Direct C# calls use metadata tokens. When you write processor.Process(), the compiler emits callvirt with a token. If an obfuscator renames the method, it rewrites both the declaration and every token reference - safe.

Reflection does not use tokens. It uses strings at runtime:

Type lookup
Type.GetType("Billing.InvoiceService")
Member lookup
GetMethod("Calculate") / GetProperty("Total")
Late activation
Activator.CreateInstance(name)

If you rename Billing.InvoiceService to a.b, reflection still asks for "Billing.InvoiceService". The CLR finds nothing. That is the entire failure mode - a string that outlives its target.

2 Where Reflection Actually Breaks in Production

Not all reflection is equal. In practice, four buckets cause 90% of post-obfuscation crashes:

BucketTypical APISymptom if renamed
Serialization contractsSystem.Text.Json, Newtonsoft.Json, XmlSerializerProperties deserialize as default/null
DI / IoCMicrosoft.Extensions.DependencyInjection, AutofacService not registered / Unable to resolve
Plugin / FactoryAssembly.GetType, CreateInstance, MEFTypeLoadException, null returns
UI BindingWPF BAML, INotifyPropertyChanged string namesXamlParseException, silent binding failure

3 Designing an Exclusion Policy Before You Click Anything

Do not start in the obfuscator UI. Start in code. The question to answer for each type is: Is its name part of a contract observed outside its own assembly?

  • Keep name if: it is a DTO, API model, EF entity mapped by convention, ViewModel bound by name, plugin contract, or service interface resolved by string.
  • Rename aggressively if: it is internal logic, helper, algorithm, licensing, or proprietary business rule - where callers use token references, not strings.
  • Hybrid: keep the type and its public contract properties/methods, but let Skater obfuscate private fields and method bodies.
Practical rule we use at Rustemsoft:

If you could delete the type's name from source and the compiler would still find all usages via typeof or direct references, it is safe to rename. If usage is only discoverable via grep for a string literal, preserve it.

4 Applying the Policy in Skater .NET Obfuscator

Skater lets you apply the policy in two complementary ways. Use both - attributes for boundaries you own, exclusion rules for boundaries you don't.

A. Declarative - ObfuscationAttribute

Ideal for your own domain models. Skater honors standard .NET attributes natively.

using System.Reflection;

[Obfuscation(Exclude = true, ApplyToMembers = false)]
public class PaymentDto
{
  [Obfuscation(Exclude = false)] // allow body obfuscation
  public decimal Amount { get; set; }

  public void Validate() { /* logic still protected */ }
}

B. Configurational - Skater Tree Exclusions

  1. Open assembly in Skater. It builds a full metadata tree.
  2. Navigate to namespace Billing → InvoiceService.
  3. Uncheck Rename Type for contracts; leave Obfuscate Control Flow and Encrypt Strings checked.
  4. For properties used by JSON: right-click → Exclude from renaming but keep body protection.
  5. Save profile as reflection-safe.skproj and use in CI: SkaterCLI.exe --project reflection-safe.skproj
Tip: CLI projects are diff-able. Check them into source control.
What remains protected even when you exclude a name?
Skater continues to transform IL: opaque predicates, block reordering, string literal encryption, anti-tamper injection, and resource encryption. The attacker sees the name InvoiceService but not how Calculate() works.

5 Real-World Scenarios and Fixes

Scenario 1: System.Text.Json DTOs

Fix: either preserve property names or make names explicit with attributes. Preferred for new code is source generation.

[JsonSerializable(typeof(PaymentDto))] // generates metadata, no reflection lookup
public partial class AppJsonContext : JsonSerializerContext {}

Scenario 2: Microsoft.Extensions.DependencyInjection

If you register via services.AddScoped<IInvoiceService, InvoiceService>(), token-based, safe to rename implementation. If you register via Assembly.Scan or string names, exclude service contracts.

Scenario 3: WPF / MVVM

Skater rewrites BAML references automatically. For bindings like {Binding TotalAmount}, keep ViewModel public properties. Alternatively, switch to x:Bind or compiled bindings where possible.

Scenario 4: Plugin Architecture

Define a stable contract assembly that is never obfuscated. Obfuscate plugin implementations heavily, but keep contract interface names and discovery attributes (e.g., [Export]) intact.

6 Verification: How to Prove It Did Not Break

Never trust a green build. Run a post-obfuscation reflection smoke suite.

Smoke checklist
  • Deserialize every DTO from sample JSON
  • Resolve every DI service from provider
  • Load each plugin via factory path
  • Open every WPF window / user control
  • Run dotnet test against obfuscated binaries
Failure fingerprint
Type.GetType returns null → type name renamed
GetMethod returns null → method name renamed
JsonException: property not found → DTO property renamed
XamlParseException → BAML not synchronized

7 Hardening What You Did Not Exclude

Once contracts are stable, turn intensity up on the rest:

  • String Encryption - Always On: Hides connection strings, endpoints, feature flags inside even excluded types' method bodies.
  • Control Flow - High: Skater's virtualization and opaque predicates make decompiled logic unreadable, even if type name is visible.
  • Anti-Tamper / Anti-Debug: Keep enabled; it protects the whole assembly, not just renamed parts.
  • Watermarking: Add assembly watermark to trace leaks without affecting reflection.

Frequently Asked Questions

Continue with Skater Guides