Skip to content
← Todas las publicaciones
· Delta1 Labs Decompilador.NETRecuperación

Cómo recuperar código fuente perdido a partir de una DLL de .NET

¿Perdiste el repositorio pero aún tienes la DLL? Cómo recuperar código fuente de una DLL de .NET decompilándola de vuelta a un proyecto C# compilable, con advertencias honestas.

Hay un tipo concreto de vuelco en el estómago que todo desarrollador espera no sentir nunca: el repositorio ha desaparecido. Quizá murió un portátil con trabajo sin confirmar. Quizá un contratista se fue y se llevó el código. Quizá una empresa cerró y el servidor de Git se fue con ella. Sea cual sea la causa, estás mirando un .dll o .exe desplegado y pensando: ese binario es la única copia de meses de trabajo.

Aquí van las buenas noticias. Por cómo está construido .NET, esa DLL lleva una descripción casi completa y recuperable de tu programa. No puedes recuperar los archivos originales exactos, pero puedes decompilar el ensamblado a C# preciso y normalmente compilable y reconstruir un proyecto funcional a partir de él. Es una vía de recuperación realista, y te la voy a guiar, con honestidad, incluyendo dónde se queda corta.

Resumen: Abre el ensamblado en un decompilador de .NET como Glass.NET, expórtalo a un proyecto C# compilable y luego arregla el puñado de cosas que la decompilación no puede reconstruir a la perfección. Recuperas tus tipos, métodos, firmas y lógica. No recuperas los comentarios, la mayoría de los nombres de variables locales ni el formato original. Es una gran ventaja de partida, no una máquina del tiempo.

Por qué una DLL de .NET se puede convertir de nuevo en código fuente

Un ensamblado .NET no es código máquina. Cuando compilas un proyecto C#, el compilador emite Lenguaje Intermedio (IL) —un conjunto de instrucciones compacto y basado en pila— más una rica tabla de metadatos que nombra cada tipo, método, campo, propiedad y parámetro por nombre y firma. Todo eso viaja dentro del .dll o .exe. El código nativo no se produce hasta el tiempo de ejecución, cuando el compilador JIT convierte el IL en instrucciones máquina.

La consecuencia práctica: tus nombres públicos e internos sobreviven, las firmas sobreviven y el flujo de control es totalmente recuperable a partir del IL. Un decompilador ejecuta el compilador en reversa: lee el IL, empareja patrones de vuelta a construcciones de C# (un foreach, un método async, una consulta LINQ) y los imprime con formato. Por eso .NET se recupera de forma mucho más legible de lo que lo haría un binario de C++. Hay una explicación más profunda en cómo decompilar una DLL de .NET a C#.

Paso a paso: recuperar tu proyecto

Aquí está el flujo en Glass.NET, con notas que aplican a cualquier decompilador competente.

1. Reúne todo lo que tengas

Recopila el ensamblado que quieres recuperar y todo lo que se entrega junto a él: otras DLL del proyecto, bibliotecas referenciadas y —crucialmente— cualquier archivo PDB (de símbolos). Una DLL por sí sola basta para decompilar, pero un PDB coincidente permite a algunas herramientas restaurar los nombres originales de las variables locales, lo que mejora notablemente la legibilidad. Coge también los archivos de configuración, recursos y archivos de contenido; esos a menudo sobreviven intactos y te ahorran reescribirlos.

2. Abre el ensamblado y confirma que es gestionado

Lanza el decompilador y abre el .dll o .exe (en Glass: Archivo ▸ Abrir ensamblado, o arrástralo a la ventana). Glass lee ensamblados gestionados de .NET Framework y .NET 6, 8, 9 y 10; un binario nativo (no gestionado) no es decompilable a C# y será rechazado con un mensaje claro. Si tu compilación es gestionada, verás cómo se carga en un árbol de espacio de nombres ▸ tipo ▸ miembro.

3. Navega y haz una comprobación de cordura antes de exportar

Antes de exportar en masa, dedica unos minutos a leer. Expande el árbol, haz clic en un par de los tipos que recuerdes haber escrito y confirma que el C# reconstruido se parece a tu código. Esto te dice dos cosas rápidamente: si el ensamblado está ofuscado (identificadores renombrados, ilegibles) y si la decompilación está limpia. Usa Ir a la definición (F12) y Buscar todas las referencias (Mayús+F12) para rastrear cómo se conectan las piezas: una forma rápida de volver a familiarizarte con un código base que no has visto en un tiempo.

4. Exporta a un proyecto compilable

Cuando el código se vea bien, exporta todo el ensamblado a disco. En la GUI esto suele ser Archivo ▸ Exportar a proyecto, que escribe un .csproj más los archivos .cs reconstruidos. Glass también tiene línea de comandos, así que puedes automatizarlo:

# Recuperar un ensamblado en un proyecto C# navegable
glass export MyApp.dll --output ./MyApp.Recovered

(Ejecuta glass --help o un subcomando con --help para ver las opciones exactas en tu compilación.) Repite para cada uno de tus propios ensamblados. Las bibliotecas de referencia de NuGet deberías restaurarlas con normalidad en lugar de recuperarlas: quieres tus dependencias reales de vuelta, no copias decompiladas de ellas.

5. Abre en Visual Studio y haz que compile

Abre el .csproj recuperado en Visual Studio y compila. Un ensamblado pequeño y limpio suele compilar casi de inmediato. Uno más grande normalmente necesita algunos arreglos manuales:

  • Referencias sin resolver: apunta el proyecto a los paquetes NuGet y la versión del framework correctos en lugar de a los sustitutos decompilados.
  • Construcciones generadas por el compilador: ocasionalmente una máquina de estados async, un iterador o una lambda se reconstruye en una forma que necesita un pequeño retoque para compilar.
  • Miembros duplicados o sintéticos: el compilador emite campos de respaldo y tipos auxiliares que pueden necesitar un repaso.

Ve resolviendo los errores de compilación uno a uno. Es genuinamente más rápido de lo que suena, porque la lógica está toda ahí: estás arreglando el andamiaje, no reescribiendo el programa.

Las advertencias honestas

Te haría un flaco favor si pretendiera que la recuperación es sin pérdidas. No lo es.

  • Los comentarios han desaparecido. El compilador los descarta, así que no están en el IL y no se pueden recuperar. Cualquier comentario de documentación XML, TODO y explicación se pierde.
  • La mayoría de los nombres de variables locales se pierden. Sin un PDB verás nombres como num2, flag y text. Los nombres de parámetros y miembros sobreviven; los nombres locales dentro de los cuerpos de los métodos normalmente no.
  • El formato y la estructura cambian. La disposición del archivo, las regiones y las directivas de preprocesador (#if DEBUG) han desaparecido. Es común un archivo decompilado por tipo, sin importar cómo lo organizaras originalmente.
  • El código generado parece generado. Async/await, los iteradores (yield) y LINQ vuelven correctos pero a veces verbosos, porque estás viendo la transformación del compilador reconstruida en lugar de tu azúcar sintáctico original.
  • Las compilaciones ofuscadas son mucho más difíciles. Si el ensamblado estaba protegido, los identificadores renombrados, las cadenas cifradas y el flujo de control aplanado sobreviven todos a la decompilación: obtienes C# válido pero difícil de leer. Si es tu propia compilación ofuscada y conservaste el archivo de mapeo de renombrado, úsalo.

Piensa en la salida como una reconstrucción fiel de lo que tu código hace, que luego recomentas y reorganizas en algo mantenible.

Un ejemplo práctico rápido

Supongamos que la única copia superviviente de un pequeño método auxiliar se decompila así:

public static decimal ApplyDiscount(decimal price, int qty)
{
    decimal num = price * qty;
    if (qty >= 10)
        num *= 0.9m;
    return num;
}

La lógica está intacta y es correcta. Lo que restaurarías a mano es la legibilidad: renombrar num a subtotal, volver a añadir el comentario que explica el umbral de volumen de 10 unidades y colocarlo en la clase a la que pertenece. Multiplica esa pequeña limpieza a lo largo de un proyecto y tienes tu código base de vuelta: como código funcional que refinas, no como un misterio que inviertes desde cero.

Tras la recuperación: protege el código reconstruido

Una vez tengas tu código de vuelta y compilando, merece la pena una reflexión: la razón por la que la recuperación fue posible es la misma por la que cualquiera con un decompilador puede leer tus binarios enviados. Si este código tiene algoritmos, comprobaciones de licencia o secretos que preferirías no entregar a la próxima persona que abra la DLL, para eso está la ofuscación. Incluso puedes verificar el resultado: protege una compilación, luego reábrela en Glass y confirma que los nombres han desaparecido. Para el trabajo de recuperación en sí, sin embargo, un buen decompilador es todo lo que necesitas.

Recupera tu código

Perder el repositorio no es el final del camino cuando aún tienes el binario. Glass.NET es un decompilador de .NET gratuito que lee cualquier ensamblado gestionado y exporta un proyecto C# compilable: sin licencia, sin puestos, sin registro. Descárgalo, abre tu DLL, lee el código que creías perdido y expórtalo. Para flujos de trabajo relacionados, mira cómo decompilar una DLL de .NET a C# y cómo depurar una aplicación .NET cuando no tienes el código fuente.

Prueba Nebula.NET

Endurece tu código .NET en minutos — empieza con la edición gratuita.