typetechniqueconfidencehighcreated2026-06-05updated2026-06-05dotnetcode-injectionload-codeevasionmalware-familymitre-attck

.NET AssemblyResolve Reflective Plugin Loader

What it does A .NET malware sample subscribes to AppDomain.CurrentDomain.AssemblyResolve, intercepts resolution failures for missing plugin DLLs, and returns the assembly from a byte array delivered over the C2 channel. No DLL ever touches disk.

Detection / Fingerprint

  • String CurrentDomain_AssemblyResolve or AssemblyResolve alongside ResolveEventHandler and byte[]
  • .NET metadata tokens for System.AppDomain::add_AssemblyResolve and System.Reflection.Assembly::Load
  • Absence of the expected plugin DLLs on disk despite Assembly.Load references in IL

Implementation patterns observed In XenoRAT the handler is named DllHandler.CurrentDomain_AssemblyResolve; it receives a ResolveEventArgs.Name, maps it to a cached byte buffer, and calls Assembly.Load(byte[]) ^[sample 6133cd0b/strings.txt]. Plugin nodes (DllNodeHandler) traffic actual binary payloads over the existing C2 socket.

Reproduce on your own VMs

  1. Create a .NET Framework console app targeting 4.8
  2. Add AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
  3. In OnAssemblyResolve, read a DLL from a MemoryStream or base64 string and return Assembly.Load(bytes)
  4. Reference a non-existent assembly name from code; watch it resolve in the handler
  5. Verify with ProcMon: no DLL file creation, only Assembly.Load in .NET ETW traces

Defensive countermeasures

  • .NET ETW / CLRv4 provider: monitor AssemblyLoad events with no corresponding file-path
  • EDR userland hooks on Assembly.Load(byte[])
  • Behavioural rule: process with mscoree IAT only + TCP C2 + ManagementObjectSearcher + AssemblyResolve

Pages where observed