Skip to content
← Todas las publicaciones
· Delta1 Labs Glass.NETDecompiladorSeguridad.NET

Mira de qué depende y qué llama un ensamblado .NET con Glass.NET

Antes de distribuir una DLL de terceros quieres conocer su superficie externa: qué ensamblados y paquetes referencia, para qué framework está compilada, qué bibliotecas nativas invoca por P/Invoke y dónde se conecta a la red, al sistema de archivos o a otro proceso. Así se audita todo eso de forma estática en Glass.NET — el decompilador gratuito que lee el binario y nunca lo ejecuta.

Estás a punto de distribuir una DLL de terceros dentro de tu propio producto, y quieres zanjar una cosa primero: ¿a qué se conecta de verdad? No lo que afirma el README — a qué está cableado el binario. Qué otros ensamblados y paquetes arrastra, para qué framework espera ejecutarse, si llama a código nativo y si abre un socket, escribe un archivo o lanza un proceso en algún punto de su cuerpo. Eso es la superficie externa de una dependencia, y es justo lo que no puedes ver desde la página del paquete.

Puedes verlo todo sin ejecutar la DLL. Un ensamblado .NET compilado registra sus dependencias y sus llamadas en los metadatos y el IL, y Glass.NET lee eso y reconstruye C# legible. Es gratuito, y es estrictamente estático — lee los metadatos y el IL y reconstruye C#, y nunca ejecuta el ensamblado que inspecciona. Esa es toda la razón por la que esto es seguro: auditar una dependencia de la que no estás seguro consiste en leerla, no en ejecutarla, y leer es lo único que Glass hace jamás.

Pongámoslo concreto. Supón que estás evaluando Contoso.ImageKit — un paquete NuGet que redimensiona imágenes — antes de añadirlo a un servicio que gestiona subidas de clientes. Una biblioteca de imágenes pura debería referenciar una pila de imagen y nada alarmante, apuntar a un framework que puedas ejecutar y ceñirse a los píxeles. Si referencia System.Net.Http, invoca por P/Invoke un códec nativo que no esperabas o tiene un Process.Start escondido en un rincón, quieres saberlo antes de distribuirlo, no después. Este es el flujo.

Ábrela y lee primero la información del ensamblado

Encuentra la DLL. Para una dependencia de NuGet está en la caché global de paquetes — %USERPROFILE%\.nuget\packages\<id>\<version>\lib\<tfm>\ en Windows, ~/.nuget/packages/... en el resto. Para una entrega de proveedor está donde haya caído, normalmente en bin/. Ábrela en Glass.NET arrastrándola a la ventana, o Archivo ▸ Abrir ensamblado. Basta con una .dll gestionada corriente — sin PDB, sin código fuente, sin restaurar.

Antes de leer una línea de código, abre la vista de información del ensamblado. Aquí empieza la superficie externa, y responde a dos preguntas de inmediato:

  • ¿A qué apunta? La vista muestra el framework objetivo y los atributos de producto. Una referencia compilada contra un framework que no ejecutas — un ensamblado solo net48 cayendo en un servicio net8.0 sin una compilación compatible en el paquete — es una incompatibilidad que quieres pillar aquí, en el momento de la auditoría, no como un fallo de carga en producción. El framework objetivo es un hecho registrado en el ensamblado, así que es la respuesta autoritativa, no una conjetura a partir del nombre del paquete.
  • ¿Qué referencia? La vista lista los ensamblados referenciados — el conjunto de dependencias directas contra el que se compiló el binario. Para una biblioteca de imágenes esperas una pila de imagen y las bibliotecas base. Si System.Net.Http, System.Net.Sockets o System.Diagnostics.Process aparecen en esa lista, una biblioteca que afirma tocar solo píxeles acaba de decirte que está enlazada contra la red o la API de procesos, y lo has aprendido antes de leer código.

El informe de exposición de Glass es un buen complemento. Pásalo para calibrar cuán legible es el ensamblado. Un paquete de estilo open source corriente debería leerse con claridad; si un ayudante de imagen anodino vuelve muy ofuscado, ese desajuste en sí merece preguntarse — las bibliotecas de utilidades legítimas rara vez necesitan esconderse. (Esa es la vista desde el otro lado del ofuscador hermano Nebula.NET, cuya virtualización de código es una función Pro — pero una dependencia corriente no tiene motivo para verse así.)

La lista de ensamblados referenciados te dice contra qué enlaza el binario; el árbol te dice cuánto de ello te toca vigilar. Despliega el ensamblado en su nodo de referencias y su árbol de espacios de nombres ▸ tipos ▸ miembros. El nodo de referencias es el mismo conjunto de dependencias en forma navegable — y en Glass puedes seguir, abriendo un ensamblado referenciado para inspeccionar a su vez su superficie, que es como sigues una dependencia-de-una-dependencia que la página del paquete nunca mencionó.

El árbol de tipos te da la forma del código en sí: tres tipos ordenados o un amasijo de cien, una API pública pequeña sobre un puñado de ayudantes internos o algo mucho más ajetreado de lo que un redimensionador debería necesitar. Aquí lees por proporción — ¿encaja la superficie con el trabajo declarado?

Encuentra los sitios de llamada que se conectan fuera

Ahora la auditoría de verdad: ¿dónde llama el código fuera de sí mismo? Aquí es donde un decompilador centrado en la navegación convierte una lista de comprobación en unos pocos saltos en vez de un recorrido.

El método es el mismo para cada capacidad que te importa: encuentra la API, y luego usa Buscar todas las referencias (Shift+F12) para listar cada sitio de llamada, volcándose al panel de resultados, y lee el método alrededor de cada uno.

  • Red. Busca HttpClient, WebClient, Socket/TcpClient crudos y cualquier URL o dirección codificada a fuego. ¿Por qué abriría un socket un redimensionador? Buscar todas las referencias sobre el constructor o SendAsync te muestra cada punto donde ocurre y te deja leer el código que lo rodea.
  • Lanzamiento de procesos. Process.Start, o cualquier cosa que llame por consola a cmd, powershell o un binario incluido. Una biblioteca pura rara vez necesita lanzar nada.
  • Sistema de archivos. File, FileStream, Directory — lecturas y escrituras más allá del scratch temporal que un redimensionador necesita legítimamente, en especial lecturas de rutas que parecen credenciales o configuración.
  • Bibliotecas nativas. Esta es la superficie de P/Invoke. Un método [DllImport] o [LibraryImport] generado por el origen nombra el módulo nativo al que se enlaza ahí mismo en el atributo, así que se decompila con claridad y la dependencia nativa es visible en el código. Una biblioteca de imágenes que enlaza un códec nativo puede ser del todo esperable — pero un [DllImport("kernel32")] inesperado haciendo trabajo de proceso o memoria es justo lo que auditas para pillar. Para la terminología y por qué el nombre del punto de entrada es crítico, mira ofuscar P/Invoke y DllImport sin romper la interoperabilidad.

Usa Ir a todo (Ctrl+T) para saltar a un tipo o miembro por su nombre, e Ir a definición (F12) para seguir una llamada hasta el ayudante que hace el trabajo real. La jerarquía de llamadas responde a la pregunta que más importa en una auditoría: ¿es esto alcanzable desde la API que de verdad uso, o es código muerto? Un Process.Start al que nada de tu camino de llamada llega es un hallazgo muy distinto de uno al que llega tu primer método.

Una cosa que hay que tener clara: encontrar una llamada a HttpClient o Process.Start es evidencia estática de que la llamada existe en el código y es alcanzable. No es Glass viendo salir una petición — Glass nunca ejecuta el ensamblado. Esa distinción es justo por lo que esto es seguro de hacer sobre una dependencia en la que no confías: lees el cableado, no lo energizas. La misma disciplina sustenta analizar con seguridad un ensamblado .NET sospechoso e inspeccionar un paquete NuGet antes de confiar en él.

Baja al IL donde necesites certeza

La mayoría de las veces el C# decompilado en un sitio de llamada es lo bastante claro para juzgar. A veces no lo es — una llamada encaminada por reflexión, o un método ofuscado donde la reconstrucción de C# es irregular. Cuando la vista de alto nivel redondea un detalle que importa, cambia el mismo miembro a la vista de IL. El IL es lo que de verdad se ejecuta, así que es la verdad de base, y sigue siendo legible incluso donde el C# limpio no se reconstruye. (Leer el IL repasa qué estás mirando.) No hace falta vivir ahí — recurre a él en el puñado de sitios de llamada donde necesitas estar seguro de qué alcanza el código.

La idea

La superficie externa de una dependencia no está oculta — está registrada en el binario, y un lector estático la saca toda a la luz. Abre la DLL, lee la información del ensamblado para su framework objetivo y sus ensamblados referenciados, navega las referencias y el árbol de tipos por proporción, y usa Buscar todas las referencias para aterrizar en cada sitio de llamada de red, archivo, proceso y P/Invoke para juzgar cada uno en contexto. En unos minutos puedes confirmar que Contoso.ImageKit solo habla con lo que una biblioteca de imágenes debería — o encontrar la única llamada que significa que no. Y como Glass.NET es gratuito y estrictamente estático, hiciste toda la auditoría sin ejecutar una sola línea de una dependencia en la que aún no habías decidido confiar. Para el flujo complementario de leer qué hace el código, mira entender código .NET de terceros desconocido. Descarga Glass.NET, abre la DLL que estás a punto de distribuir y mira a qué se conecta.

Prueba Nebula.NET

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