Skip to Content
New release 12 available 🎉
ObfuscatorDynamic Proxy

Dynamic Proxy

Dynamic Proxy protection is a powerful feature offered by Babel Obfuscator that enhances the obfuscation and protection of your application’s code. It allows you to hide method calls to both external and internal code by generating dynamic proxy classes.

When dynamic proxy protection is enabled, Babel Obfuscator creates delegate types or proxy classes that act as intermediaries for method calls. These proxy classes are dynamically built during the obfuscation process and are used to replace the original method calls in your code.

The main advantage of dynamic proxies is that they effectively obscure the actual method calls, making it much more difficult for attackers or reverse engineers to understand and analyze the code flow. By utilizing dynamic proxies, you can prevent direct access to sensitive methods and obscure the application logic.

This section covers:

How Dynamic Proxy Works

At build time, for each protected call Babel Obfuscator generates a small proxy delegate type and rewrites the original call, callvirt or newobj instruction so that it is routed through that proxy. The real target — its declaring type, the method, and the field that will hold the resolved call — is no longer referenced directly by the rewritten code. Instead it is recovered by a tiny injected resolver the first time each proxied call executes, and then cached so that subsequent calls go straight through.

Two properties follow from this design:

  • Static analysis is disrupted. The rewritten call sites no longer carry a direct metadata reference to the target, so decompilers and automated deobfuscators cannot reconstruct the original call graph from metadata alone. The way targets are encoded is also varied from build to build, so tools cannot rely on fixed patterns — see Deobfuscation Resistance.
  • Resolution is lazy and cached. The first call to a given proxied member pays a small one-time cost to resolve the target and wire up the delegate; every later call runs through the cached delegate with negligible overhead — see Performance.

Proxying is purely a managed, build-time transformation: it does not require the .NET Framework, works on .NET and .NET Framework, and does not change the observable behavior of your program (subject to the small set of calls listed under Coverage that are intentionally left direct).

AOT and Platform Compatibility Limitations

Dynamic Proxy is currently not supported on .NET MAUI and Blazor assemblies due to a combination of platform limitations and runtime restrictions that prevent safe or consistent proxy generation and execution in these environments.

Platform Constraints

  • Ahead-of-Time (AOT) Compilation: Platforms such as iOS (used by .NET MAUI) and WebAssembly (used by Blazor WebAssembly) enforce AOT compilation. This eliminates the use of runtime features like reflection-based code emission or runtime type generation. While Babel’s DynamicProxy does not use runtime code generation, its generated proxy logic can depend on metadata and IL constructs that are either stripped or unsupported in AOT-compiled environments.

IL Compatibility Limitations

  • Unsupported Metadata Tokens: The dynamic proxy mechanism injects intermediate call layers through generated proxy types and delegate stubs. These rely on metadata tokens and indirection mechanisms that may not be verifiable or are outright unsupported in certain AOT targets, leading to runtime validation failures or application crashes.

Blazor/WebAssembly Limitations

  • Restricted Reflection Capabilities: In Blazor WebAssembly, reflection is severely limited. Since DynamicProxy often wraps or intercepts method calls, it may result in indirect invocation paths that are incompatible with the linking and tree-shaking process used in WebAssembly publishing workflows.

Recommendation

For full compatibility with AOT environments like .NET MAUI and Blazor, it is recommended to set DynamicProxy=false. This ensures the generated assemblies remain fully verifiable, platform-compliant, and free of features that may fail during native linking or runtime startup.

Last updated on