Virtual Override Renaming Enterprise
Standard obfuscators cannot rename ToString, Equals, GetHashCode, or interface method implementations because the CLR resolves virtual calls by name. Demeanor Enterprise renames these methods and injects MethodImpl records that wire the renamed methods to the correct vtable slots. The decompiled output produces C# compiler errors and cannot be recompiled.
Usage
| CLI | MSBuild | Default |
|---|---|---|
| (enabled by default at Enterprise) | (enabled by default at Enterprise) | On |
--no-virtual-rename | <ObfuscateNoVirtualRename>true</ObfuscateNoVirtualRename> | Disable |
Before & After
public class User
{
public string Name { get; }
public string Email { get; }
public override string ToString()
=> $"{Name} <{Email}>";
public override bool Equals(object? obj)
=> obj is User other &&
string.Equals(Email, other.Email, ...);
public override int GetHashCode()
=> StringComparer.OrdinalIgnoreCase
.GetHashCode(Email);
}public class j
{
private string m_a;
private string b;
public virtual string u()
{
return a() + l.a("\u0091\u001c") + a()
+ l.a("<");
}
public virtual bool v(object a)
{
return a is j j2 &&
string.Equals(this.a(), j2.a(), ...);
}
public virtual int w()
{
return StringComparer.OrdinalIgnoreCase
.GetHashCode(a());
}
}Real ILSpy output. ToString → u(), Equals → v(), GetHashCode → w(). ILSpy adds comments like "ILSpy generated this explicit interface implementation from .override directive" — revealing the MethodImpl mechanism but not the original names. Attempting to recompile produces 11+ C# compiler errors.
How It Works
Demeanor builds virtual method override groups across the assembly set, identifying methods that override external declarations (System.Object.ToString, interface methods, etc.). After renaming, it injects MethodImpl rows (ECMA-335 II.22.27) that map each renamed method body to its original vtable slot declaration. The CLR uses MethodImpl for virtual dispatch, bypassing the name entirely.
When to Disable
- Reflection on method names —
typeof(T).GetMethod("ToString")will not find the renamed method. The override still works for virtual dispatch. - Expression trees —
Expression.Call(typeof(T), "ToString", ...)uses name-based lookup. - Interop with unobfuscated assemblies — if external code expects a specific method name on your type (beyond the standard virtual dispatch), the renamed name won't match.
Ready to protect your .NET code?