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

CLIMSBuildDefault
(enabled by default at Enterprise)(enabled by default at Enterprise)On
--no-virtual-rename<ObfuscateNoVirtualRename>true</ObfuscateNoVirtualRename>Disable

Before & After

YOUR CODE
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);
}
AFTER OBFUSCATION
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. ToStringu(), Equalsv(), GetHashCodew(). 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 namestypeof(T).GetMethod("ToString") will not find the renamed method. The override still works for virtual dispatch.
  • Expression treesExpression.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?

View Pricing All Options