A successful download proves that a request completed. To verify protection, inspect what changed inside the assembly and run the protected build against the same tests as the original.
A measured example
On October 23, 2026, we uploaded our synthetic .NET test library to FreeObfuscator's public free endpoint. We also processed the same library locally with string encryption, control-flow obfuscation and reference proxying enabled. The Pro example below is a local engine run, not a paid-account checkout or API test. Virtualization was not enabled in this example.
| Check | Original | Online Free | Local Pro transforms |
|---|---|---|---|
| Assembly bytes | 25,088 | 24,064 | 26,624 |
| Original type/member signatures absent | Baseline | 23 | 23 |
UTF-16 literal box: present | Yes | Yes | No |
| Compared runtime results | Baseline | 2,003 matched | 2,003 matched |
The runtime comparison uses a fixed random seed for 1,000 calculator calls and 1,000 unsigned divisions, followed by checks of a string result, mutable call count and a generic type. These are sample checks, not exhaustive application tests. File size and a different SHA256 are recorded for artifact identity; neither measures protection strength.
Download the verification sample Read the machine-readable report
The ZIP contains our synthetic original DLL, protected outputs, fixture source, report and ILSpy listings. It contains no customer uploads. Decompiler listings were produced with ILSpyCmd 11.0.0.9375.
1. Compare the decompiled code
Open the original and protected copies in ILSpy, or use ilspycmd. In this library, public APIs remain intact so existing callers continue to bind. Private names change:
Original
private int _callCount;
private readonly int _offset;
private int Combine(int a, int b) => a + b;
Online Free output
private int @b;
private readonly int @c;
private int @d(int @b, int @c) => @b + @c;
That is real name obfuscation. The addition is still easy to understand. Free renaming does not encrypt strings or hide the underlying algorithm. The legacy Block ILDasm attribute does not prevent modern ILSpy from opening the result.
2. Check the transforms you enabled
With string encryption enabled, the example's "calc:" literal becomes a runtime decryptor call. Reference proxying routes the string concatenation through a generated forwarding method. You can inspect both in the included Pro listing. A simple method can still decompile cleanly even when control-flow obfuscation is enabled; unsupported patterns may be skipped.
Searching the binary for a known UTF-16 literal confirms its plaintext is absent in this sample. It does not prove every string was encrypted or that an analyst cannot recover the plaintext at runtime. Code that must execute can ultimately be studied.
3. Run the original and protected builds
Keep dependencies, configuration and test inputs identical. Compare returned values, saved data, exceptions and side effects. Exercise reflection, serialization, dependency injection, plugins and UI bindings. A DLL that loads successfully can still fail on a rarely used path.
For a library, verify public API compatibility with a separate consumer application. For an executable, exercise the published application rather than only a single method. For marked virtualized methods, also measure latency and verify exception behavior.
What this evidence can establish
- The online sample was transformed, with concrete renamed members visible in an independent decompiler.
- The selected local Pro transforms changed the sample's representation and removed a known plaintext literal.
- The tested outputs matched the original on the measured inputs.
It cannot establish a universal “protection percentage,” guarantee an arbitrary application will work, or prove that reverse engineering is impossible. Keep secrets on a server, preserve your original build, and run your own regression suite before shipping.
What can break after renaming · Threat model and limitations · Try your own DLL