Intermedio.NETdnSpyILSpydecompilacionC#ofuscacion

Analisis de Binarios .NET: dnSpy, ILSpy y Decompilacion

Analisis de malware .NET con dnSpy e ILSpy. Estructura de assemblies .NET, codigo IL, decompilacion a C#, ofuscacion con ConfuserEx y Dotfuscator, deobfuscacion con de4dot y herramientas especializadas.

MalwareIntel Research··10 min lectura
Serie: Análisis de Binarios — Parte 11

.NET: el paraiso del analista de malware

Analizar malware .NET es fundamentalmente diferente a analizar malware nativo. Mientras que un binario C++ compilado pierde casi toda la informacion de alto nivel, un assembly .NET conserva metadatos completos: nombres de clases, metodos, campos, tipos de parametros y hasta el flujo de control. Los decompiladores modernos reconstruyen codigo C# que es casi identico al original.

Esto convierte a .NET en un territorio privilegiado para el analista. Las familias mas populares de malware .NET (Agent Tesla, AsyncRAT, QuasarRAT, NanoCore, RedLine Stealer, Formbook variantes .NET) se pueden analizar leyendo codigo C# decompilado, sin necesidad de ensamblador.

El desafio viene cuando el autor usa ofuscadores como ConfuserEx o .NET Reactor. Pero incluso ahi, las herramientas de deobfuscacion automatica como de4dot resuelven la mayoria de los casos.

Estructura de un assembly .NET

Un assembly .NET es un archivo PE con una estructura especifica:

ComponenteContenido
PE HeaderHeaders estandar con CLR flag
CLR HeaderMetadatos .NET, entry point de IL
Metadata TablesClases, metodos, campos, strings
IL CodeInstrucciones Intermediate Language
ResourcesRecursos embebidos (archivos, configuraciones)
Strong Name SignatureFirma opcional del assembly

Identificacion de un assembly .NET

import pefile

pe = pefile.PE("sample.exe")

# Verificar CLR header (Data Directory indice 14)
if len(pe.OPTIONAL_HEADER.DATA_DIRECTORY) > 14:
    clr = pe.OPTIONAL_HEADER.DATA_DIRECTORY[14]
    if clr.VirtualAddress > 0 and clr.Size > 0:
        print("Es un assembly .NET")
        print("CLR header en RVA:", hex(clr.VirtualAddress))
    else:
        print("No es .NET")

Otros indicadores:

  • Referencia a mscoree.dll en imports (funcion _CorExeMain).
  • Seccion .text con IL code en lugar de instrucciones x86/x64.
  • Detect It Easy lo identifica como ".NET assembly".

Codigo IL (Intermediate Language)

IL (tambien llamado CIL o MSIL) es el lenguaje intermedio al que compilan todos los lenguajes .NET (C#, VB.NET, F#). Es un lenguaje de stack (como Java bytecode) que se compila a codigo nativo por el JIT compiler en runtime.

Ejemplo de IL vs C#:

// C# original
public int Add(int a, int b)
{
    return a + b;
}
// IL equivalente
.method public hidebysig instance int32 Add(int32 a, int32 b) cil managed
{
    .maxstack 2
    ldarg.1          // push a
    ldarg.2          // push b
    add              // a + b
    ret              // return
}

Normalmente no es necesario leer IL directamente. Los decompiladores lo convierten a C# automaticamente.

dnSpy / dnSpyEx: la herramienta de referencia

dnSpy (y su fork activo dnSpyEx) es el decompilador y debugger .NET preferido para analisis de malware. Combina decompilacion, edicion de codigo y debugging en una sola herramienta.

Funcionalidades clave

Decompilacion:

  • Decompila assemblies a C# o VB.NET con alta fidelidad.
  • Navega clases, metodos y campos con arbol jerarquico.
  • Resalta dependencias y referencias cruzadas.
  • Busqueda global de strings, tipos y metodos.

Debugging:

  • Debug de assemblies .NET sin el codigo fuente original.
  • Breakpoints, watches, call stack, variables locales.
  • Modificar valores de variables en runtime.
  • Step into/over/out como cualquier debugger.

Edicion:

  • Editar codigo C# directamente y recompilar el assembly.
  • Modificar metadatos, IL code y recursos.
  • Util para parchear anti-debug o bypass de checks.

Flujo de analisis con dnSpy

  1. Abrir el assembly: File, Open. dnSpy parsea toda la metadata.
  2. Explorar la estructura: Navegar el arbol de namespaces y clases.
  3. Buscar el entry point: Buscar Main() o el metodo marcado como entry point.
  4. Identificar funcionalidad: Buscar clases relacionadas con red, archivos, registro, criptografia.
  5. Buscar strings: Edit, Search Assemblies, buscar URLs, IPs, paths.
  6. Analizar comunicacion C2: Buscar HttpClient, WebClient, TcpClient, Socket.
  7. Extraer configuracion: Buscar campos estaticos con URLs, puertos, claves de cifrado.

Busquedas utiles en dnSpy

BusquedaQue encuentra
"http://" o "https://"URLs de C2 o descarga
Socket, TcpClientComunicacion de red raw
Registry, RegistryKeyAcceso al registro (persistencia)
Process.StartEjecucion de procesos
File.Write, File.CopyOperaciones de archivo
ClipboardAcceso al portapapeles (clipboard stealer)
Screenshot, CaptureScreenCaptura de pantalla
Keylog, GetAsyncKeyStateKeylogger
Crypto, AES, DES, RijndaelOperaciones criptograficas
base64, Convert.FromBase64Datos codificados

ILSpy: alternativa open source

ILSpy es la alternativa open source a dnSpy, mantenida activamente. No tiene debugger integrado, pero su decompilador es excelente:

  • Decompilacion a C# de alta calidad.
  • Soporte para assemblies .NET Core y .NET 5+.
  • Plugins para funcionalidad adicional.
  • Disponible como extension de Visual Studio Code (ILSpy for VS Code).
# ILSpy desde linea de comandos
ilspycmd sample.exe -o output_directory/
# Genera archivos .cs decompilados

Ofuscacion en malware .NET

ConfuserEx

El ofuscador open source mas popular en malware. Aplica multiples protecciones:

ProteccionEfecto
RenameRenombra clases, metodos y campos a caracteres no legibles
String encryptionCifra todos los strings con funciones de descifrado en runtime
Control flowOfusca el flujo de control con switch dispatchers
Ref proxyReemplaza llamadas directas con proxies indirectos
Anti-tamperDetecta modificaciones del assembly
Anti-debugDetecta debuggers
Constants protectionProtege constantes numericas
Resource encryptionCifra recursos embebidos

Deteccion:

  • Metadata con nombres como caracteres Unicode no imprimibles.
  • Metodo de inicializacion con nombre ofuscado que se ejecuta en el static constructor.
  • Strings "#ConfuserEx" o "Confuser" a veces presentes en la metadata.
  • Detect It Easy lo identifica automaticamente.

.NET Reactor

Protector comercial que va mas alla de la ofuscacion:

  • Cifra el IL code completo (no solo ofuscacion superficial).
  • Native code generation (convierte parte del IL a codigo nativo).
  • Merge de assemblies (combina multiples DLLs en uno).
  • Licenciamiento integrado.

Dotfuscator

Incluido en Visual Studio. Menos agresivo que ConfuserEx:

  • Renaming de identificadores.
  • String encryption basico.
  • Control flow ofuscation leve.
  • Pruning de codigo no usado.

Otros ofuscadores

OfuscadorTipoFrecuencia en malware
SmartAssemblyComercialMedia
Agile.NET (CliSecure)ComercialBaja
Babel.NETComercialBaja
EazfuscatorComercialBaja
Crypto ObfuscatorComercialMedia
CustomPropioAlta (en malware sofisticado)

de4dot: deobfuscacion automatica

de4dot es la herramienta de referencia para deobfuscacion automatica de assemblies .NET. Detecta el ofuscador y aplica las transformaciones inversas.

# Deobfuscar automaticamente (detecta el ofuscador)
de4dot sample_obfuscated.exe

# Resultado: sample_obfuscated-cleaned.exe

# Especificar ofuscador manualmente
de4dot sample.exe -p cr    # ConfuserEx (Confuser (r)ex)
de4dot sample.exe -p dr    # .NET Reactor
de4dot sample.exe -p sa    # SmartAssembly

# Solo renombrar (sin descifrar strings)
de4dot sample.exe --dont-restore-strings

# Preservar tokens de metadata
de4dot sample.exe --preserve-tokens

Que hace de4dot:

  1. Detecta el ofuscador usado.
  2. Descifra strings protegidas.
  3. Renombra clases y metodos a nombres legibles (Class0, Method1, etc.).
  4. Elimina proxy calls.
  5. Simplifica el control flow.
  6. Elimina anti-tamper y anti-debug.
  7. Genera un assembly limpio.

Limitaciones:

  • No soporta todos los ofuscadores (especialmente custom).
  • Algunos protectores modernos no se desofuscan completamente.
  • El renaming automatico (Class0, Method1) es mejor que caracteres ilegibles pero no recupera los nombres originales.

Analisis de recursos en assemblies .NET

Los assemblies .NET pueden embeber recursos como streams accesibles programaticamente. El malware los usa para ocultar payloads:

// Patron comun en malware .NET: cargar payload desde recursos
var assembly = Assembly.GetExecutingAssembly();
var stream = assembly.GetManifestResourceStream("Payload.bin");
var data = new byte[stream.Length];
stream.Read(data, 0, data.Length);

// Descifrar
for (int i = 0; i < data.Length; i++)
{
    data[i] ^= 0x55;  // XOR con clave
}

// Cargar assembly desde memoria
var payload = Assembly.Load(data);
payload.EntryPoint.Invoke(null, null);

En dnSpy: Resources, examinar cada recurso embebido. Extraer y analizar por separado si tienen entropia alta.

Tecnicas especificas de malware .NET

Reflection para evasion

El malware usa System.Reflection para invocar metodos sin referenciarlos directamente:

// En lugar de llamar directamente a Process.Start:
Type t = Type.GetType("System.Diagnostics.Process");
MethodInfo m = t.GetMethod("Start", new Type[] { typeof(string) });
m.Invoke(null, new object[] { "cmd.exe" });

Esto oculta la dependencia de Process.Start del analisis estatico.

Assembly.Load desde memoria

Cargar un assembly completo desde un array de bytes en memoria, sin tocar el disco:

byte[] payload = DecryptResource("EmbeddedPayload");
Assembly asm = Assembly.Load(payload);
asm.EntryPoint.Invoke(null, new object[] { new string[0] });

El assembly cargado no existe como archivo, dificultando el analisis forense.

AppDomain para aislamiento

Crear un AppDomain separado para ejecutar el payload, con la capacidad de descargarlo despues:

AppDomain domain = AppDomain.CreateDomain("PayloadDomain");
domain.ExecuteAssembly(payloadPath);
AppDomain.Unload(domain);  // Descargar despues de ejecutar

Costura.Fody: merge de assemblies

Herramienta legitima que embebe todas las dependencias dentro del ejecutable principal. El malware la usa para crear un solo archivo sin DLLs externas. Los assemblies embebidos se comprimen y se cargan en runtime.

Flujo de trabajo completo

  1. Identificar .NET: file o pefile verifica CLR header.
  2. Verificar ofuscacion: Abrir en dnSpy, examinar nombres de clases.
  3. Deobfuscar si necesario: de4dot sample.exe.
  4. Abrir en dnSpy: Navegar el arbol de clases.
  5. Buscar entry point: Main() o punto de entrada del CLR.
  6. Identificar funcionalidad clave:
    • C2: buscar HttpClient, Socket, WebClient.
    • Persistencia: Registry, ScheduledTask.
    • Robo: Clipboard, Keylogger, Screenshot.
    • Cifrado: AES, RSA, XOR.
  7. Extraer configuracion: Campos estaticos con URLs, puertos, claves.
  8. Extraer recursos: Verificar si hay payloads embebidos.
  9. Debugging si necesario: Breakpoints en funciones de descifrado o C2.

Familias .NET comunes

FamiliaTipoOfuscador comun
Agent TeslaInfostealerConfuserEx, .NET Reactor
AsyncRATRATConfuserEx, custom
QuasarRATRATConfuserEx
NanoCoreRATConfuserEx, Eazfuscator
RedLine StealerInfostealerCustom, ConfuserEx
njRATRATNinguno o ConfuserEx basico
LimeRATRATConfuserEx
Formbook/.NET variantInfostealerCustom
Snake KeyloggerKeyloggerConfuserEx
RemcosRAT.NET Reactor, custom

Conclusion

El malware .NET es mas accesible para el analisis que cualquier otro tipo gracias a la riqueza de los metadatos IL y las herramientas de decompilacion. El flujo estandar (de4dot para deobfuscar, dnSpy para decompiliar y debuggear) resuelve la mayoria de las muestras en minutos. Las familias mas populares de RATs y infostealers usan .NET precisamente por la facilidad de desarrollo, pero esa misma facilidad beneficia al analista.

El desafio real aparece con ofuscadores avanzados o protectores que cifran el IL code completo. En esos casos, el analisis dinamico con dnSpy como debugger y breakpoints en funciones de descifrado es el camino mas eficiente.

Preguntas frecuentes

Artículos relacionados

Este contenido tiene fines exclusivamente educativos y de investigación en ciberseguridad defensiva. No se proporcionan binarios maliciosos ni payloads ejecutables. El uso indebido de esta información es responsabilidad exclusiva del usuario. Leer disclaimer completo.