Raw .NET Metadata Staging
A staging technique where a .NET Framework assembly is stored inside another executable not as a complete PE file, but as raw Common Intermediate Language (CIL) bytecode and .NET metadata streams stripped of the DOS/PE header. The outer loader reconstructs or directly hosts the assembly at runtime.
How it works
A standard .NET PE contains:
- DOS header (
MZ) - PE header (
PE\0\0) - Section headers
- CLR directory entry pointing to the COR20 header
- Metadata root (
BSJB) with streams (#~,#Strings,#US,#GUID,#Blob) - CIL bytecode in
.text
In raw metadata staging, only items 5 and 6 are preserved. The outer loader either:
- Reconstructs a PE header and maps the assembly into memory for
Assembly.Load - Uses
ICLRRuntimeHostor_CorExeMainto host the raw metadata directly - Writes the raw bytes to a temp file and spawns a new process (observed in
0ce2a9be)
Why attackers use it
- Evasion: Standard PE embed scanners (
pefile,binwalk,sigcheck) miss the payload because there is noMZ+PEsignature. - Size reduction: Removing the DOS stub and PE headers saves ~512 bytes per payload (minor, but adds up in multi-payload droppers).
- Builder simplicity: The outer stub only needs to copy the raw bytes and add a header or launch them; no need to preserve a valid nested PE.
Detection
| Method | Technique |
|---|---|
| Static | Search overlay for BSJB without a preceding MZ within 0x400 bytes |
| Static | Entropy scan of overlay — raw CIL has lower entropy than encrypted data (~4.5–6.0) |
| Dynamic | Monitor child processes spawned by Delphi/VB6/native droppers with .NET runtime loaded |
Observed in this corpus
- Sample
0ce2a9be— Delphi VCL native stub stores AgentTesla .NET assembly as raw metadata in overlay. No MZ+PE precedes theBSJBroot. ^[/intel/analyses/0ce2a9bef251a42648a4ef198c4da7cb4c707b9635b13036d3d552fc87ac1566.html]
Related
- delphi-vcl-dotnet-loader — specific Delphi VCL delivery chain observed here
- dotnet-assemblyresolve-plugin-loader — another .NET loading technique
- xored-dotnet-in-memory-assembly — in-memory .NET loading without file drop