¿De verdad funcionó tu ofuscación? Compruébalo en Glass.NET
Una compilación limpia no demuestra que tu código esté protegido. Abre el ensamblado ofuscado en Glass.NET — el decompilador de .NET gratuito y de solo análisis estático — y léelo como lo hará un atacante: confirma que el renombrado, el cifrado de cadenas, el flujo de control y la virtualización aguantaron, y que no sobreprotegiste tu API pública.
Pasaste tu ofuscador. La compilación tuvo éxito, las pruebas están en verde, el paquete está firmado. Así que tu código ya está protegido, ¿verdad?
Quizá. Una compilación con éxito te dice que el ofuscador no se cayó. No te dice nada sobre si el resultado es realmente difícil de leer. La única forma de saberlo es mirar el ensamblado como lo mirará un atacante: meterlo en un decompilador y ver qué devuelve. Si el C# sigue siendo legible, enviaste una falsa sensación de seguridad.
La herramienta adecuada para esa comprobación es un decompilador en el que confíes y que nunca ejecute el binario. Glass.NET es gratuito, y es estrictamente estático — lee los metadatos y el IL y reconstruye C#, y nunca ejecuta el ensamblado que inspecciona. Eso lo convierte en el compañero natural de un ofuscador como Nebula.NET: proteges con uno, verificas con el otro, y nunca tienes que ejecutar una compilación de la que no estás seguro.
Por qué «la compilación tuvo éxito» no es verificación
La ofuscación es un conjunto de transformaciones aplicadas al IL. Cualquiera de ellas puede estar mal configurada, tener un alcance demasiado estrecho o saltarse en silencio. Una regla de renombrado que excluye demasiado, un paso de cifrado de cadenas que nunca se ejecutó, una opción de flujo de control desactivada, un método que pretendías virtualizar pero olvidaste marcar — nada de eso produce un error de compilación. Producen un binario que parece protegido en tu carpeta de salida y se lee como código fuente en un decompilador.
Así que trata la verificación como un paso obligatorio, no como algo de última hora. El procedimiento es simple: decompila el ensamblado antes y después de protegerlo, y compara.
Prepara una comparación antes-y-después
Guarda una copia de la compilación sin ofuscar. Ábrela primero en Glass.NET y navega hasta una clase que te importe — una comprobación de licencia, una rutina de precios, cualquier cosa que no quieras que copien. Casi con seguridad te sorprenderá lo legible que es; para un ensamblado sin proteger, el C# reconstruido suele estar lo bastante cerca como para recompilarlo.
Ahora abre la compilación protegida. Glass.NET tiene una comparación de ensamblados en paralelo con diff línea a línea, así que puedes poner las dos versiones una al lado de la otra y leer la diferencia directamente en vez de ir saltando entre ventanas. Recorre, método a método, el código que esperabas que el ofuscador tocara y, para cada uno, hazte las preguntas concretas de abajo.
1. ¿Aguantó el renombrado?
La protección más barata es el renombrado de identificadores — convertir ValidateLicenseKey, _customerBalance y ComputeDiscount en símbolos sin sentido. En la compilación sin proteger verás tus nombres reales. En la protegida, los tipos y miembros internos deberían leerse como a, b, c o ruido similar:
// antes
internal sealed class LicenseValidator
{
public bool ValidateLicenseKey(string key) { ... }
}
// después
internal sealed class a
{
public bool b(string A_0) { ... }
}
Confirma dos cosas. Primera, que el renombrado ocurrió — si tus nombres sobrevivieron, el paso no se ejecutó o tus reglas de exclusión son demasiado amplias. Segunda, e igual de importante, que no fue demasiado lejos: tu API pública, los objetivos de reflexión y los contratos de serialización deben quedar intactos, o tu biblioteca se rompe para quien la llame. Usa Ir a todo (Ctrl+T) y la vista de información del ensamblado para confirmar que tu superficie pública conserva sus nombres reales mientras todo lo interno desapareció. La sobreofuscación es un error tan real como la infraofuscación; Glass te deja ver ambos.
2. ¿Desaparecieron las cadenas?
El código decompilado se filtra mucho a través de los literales de cadena — URLs, SQL, mensajes de error, cadenas de formato, nombres de feature flags. El cifrado de cadenas las almacena cifradas y las descifra solo al usarlas. Para verificarlo, busca en la salida decompilada un literal que sepas que estaba en el código — una URL, un mensaje de error, una constante mágica. En una compilación cifrada correctamente no lo encontrarás como texto; en su lugar encontrarás una llamada que devuelve la cadena en tiempo de ejecución.
Sé honesto sobre lo que esto demuestra. El literal se sigue descifrando en memoria cuando el código se ejecuta, así que un atacante decidido con un depurador puede recuperarlo. Lo que has confirmado es que el ataque trivial — greppear el binario o la fuente decompilada en busca de una palabra clave — ahora no devuelve nada. Eso ya elimina una gran cantidad de exposición de bajo esfuerzo.
3. ¿Es el flujo de control una maraña?
El renombrado oculta cómo se llaman las cosas; la ofuscación de flujo de control oculta lo que hace el código. Un método protegido ya no debería decompilarse como C# limpio y lineal. En vez de un if/else legible, deberías ver lógica aplanada — un switch sobre una variable de estado, ramas opacas, gotos — la forma que produce un decompilador cuando ya no puede recuperar la estructura original:
// tras la ofuscación de flujo de control, decompilado
int num = 0;
while (true)
{
switch (num)
{
case 0: num = (cond ? 2 : 1); continue;
case 1: result = a(); num = 3; continue;
case 2: result = b(); num = 3; continue;
case 3: return result;
}
}
Si el cuerpo sigue leyéndose como la fuente que escribiste, la protección de flujo de control no está alcanzando ese método. El listón al que vale la pena apuntar no es solo «confunde a un humano», sino «sobrevive a los desofuscadores automáticos», así que es razonable pasar también un desofuscador sobre la compilación — pero la primera comprobación, y gratuita, es simplemente leerlo en Glass.
4. ¿De verdad se virtualizaron tus métodos sensibles?
La virtualización de código es la protección común más fuerte, y en Nebula.NET es una función Pro. Convierte el IL de un método en bytecode para una pequeña máquina virtual incrustada en el ensamblado, de modo que no queda IL ordinario que un decompilador pueda reconstruir. Esta es la comprobación en la que el resultado es inconfundible. Cambia Glass.NET a su vista de IL sobre un método que virtualizaste. No deberías ver tu algoritmo. Deberías ver una llamada al intérprete de la VM con un argumento de datos opaco — el bytecode que no significa nada sin el runtime correspondiente:
// vista de IL de un método virtualizado
IL_0000: ldarg.0
IL_0001: ldsfld uint8[] '<VM>'::'data_7f3a'
IL_0006: call object '<VM>'::Run(object, uint8[])
IL_000b: ret
La vista de C# del mismo método también se reduce a una única llamada opaca. Si, en cambio, todavía puedes leer tu lógica en cualquiera de las dos vistas, ese método nunca se virtualizó — comprueba que marcaste los métodos correctos, porque la virtualización se aplica de forma selectiva (es más lenta en tiempo de ejecución, así que la reservas para tu código más sensible, no para todo el ensamblado).
Lee el informe de exposición y luego decide
Glass.NET también produce un informe de exposición que resume cuánto de un ensamblado es legible — un indicador rápido y de alto nivel para pasar sobre ambas compilaciones. Es una señal útil de triaje, pero no sustituye a leer los métodos que más te importan. Un informe puede decirte que la proporción mejoró; solo tus propios ojos sobre el ValidateLicenseKey decompilado pueden decirte que aquello que de verdad intentabas proteger ya no está a la vista.
Nada de esto hace tu código imposible de revertir — nada lo hace, y cualquier herramienta que prometa «indescifrable» te está vendiendo algo. Lo que este flujo de trabajo te da es la verdad: puedes ver exactamente cuánto subiste el listón, cazar los pasos que en silencio no hicieron nada, y confirmar que no renombraste por accidente tu API pública hasta hacerla desaparecer. Protege con Nebula.NET, verifica con Glass.NET — que es gratuito, de solo análisis estático, y la segunda opinión honesta sobre tu propia compilación. ¿Nuevo en la parte del decompilador? Empieza por cómo decompilar una DLL de .NET a C#.
Prueba Nebula.NET
Endurece tu código .NET en minutos — empieza con la edición gratuita.