Analysis of Native Process CLR Hosting Used by AgentTesla

A Word document with a VBA macro delivered a 64-bit Rust binary that performed in-memory decryption and fileless injection of an AgentTesla MSIL payload into its own native process via CLR hosting, while patching ETW and AMSI to evade detection. #AgentTesla #SonicWall

Keypoints

  • Initial vector: malicious Word document prompts user to enable a VBA macro that downloads and runs a 64-bit Rust binary.
  • The Rust binary patches EtwEventWrite in ntdll and later patches AMSI functions to evade detection before executing payloads.
  • The binary downloads an encoded shellcode blob from a remote URL, moves it into RW memory, and executes it via EnumSystemLocalesA callback.
  • Shellcode dynamically resolves APIs via PEB parsing and API hashing, allocates memory, and decrypts a 0x3E184-byte encoded AgentTesla payload using a variable single-byte XOR routine.
  • After loading required DLLs (ole32, oleaut32, wininet, mscoree, shell32) and further API resolution, the shellcode performs CLR hosting to load the MSIL payload into the default AppDomain.
  • CLR hosting steps include CLRCreateInstance, locating a runtime, obtaining ICorRuntimeHost, creating a SafeArray for the MSIL, calling Load_3 to load the assembly, and Invoke_3 to execute the AgentTesla entry point in-process.

MITRE Techniques

  • [T1204.002] User Execution: Malicious File – Word macro tricked the user into enabling VBA, which then downloaded and executed a 64-bit binary. (‘Upon opening this document, it will ask the user to enable a VBA macro. If enabled, this VBA macro downloads a 64-bit executable from the internet and executes it.’)
  • [T1105] Ingress Tool Transfer – Malware fetched additional components from remote URLs, including an encoded shellcode blob and a signed_*.exe. (‘This 64-bit malware process downloads an encoded shellcode from the following URL…’)
  • [T1055] Process Injection – Shellcode writes the encoded AgentTesla payload into allocated RW memory, changes protections and executes it within the host process (using EnumSystemLocalesA as a callback). (‘Next, the malware starts the execution of the downloaded shellcode using the “EnumSystemLocalesA” API by passing the address of the shellcode to the API as the callback function argument.’)
  • [T1106] Native API – The binary patches EtwEventWrite and uses NtProtectVirtualMemory, WriteProcessMemory and FlushInstructionCache to modify memory and apply hooks. (‘…patches the “EtwEventWrite” API from NTDLL using the NtProtectVirtualMemory, WriteProcessMemory and FlushInstructionCache APIs.’)
  • [T1562] Impair Defenses – The shellcode patches AMSI functions (AmsiScanBuffer/AmsiScanString) and re-patches EtwEventWrite (0xCC) to bypass AMSI and disable Event Tracing. (‘…patches the “AmsiScanBuffer” and “AmsiScanString” API…’ and ‘…patches “EtwEventWrite” API with a single byte “0xCC” (return instruction).’)
  • [T1620] Reflective Code Loading – The payload is decrypted in memory (single-byte XOR in 0x10-byte blocks) and executed filelessly via CLR hosting without writing the managed assembly to disk. (‘The shellcode uses a customized decryption routine… It decrypts the 0x3E184 bytes of the memory buffer to get the final payload.’)
  • [T1027] Obfuscated Files or Information – The shellcode employs API hashing and a multi-key XOR decryption routine to hide strings and the managed payload until runtime. (‘…it will resolve the VirtualAlloc, VirtualFree, and RtlExitUserProcess APIs using an API hashing technique.’ and ‘single-byte XOR decryption… every time the malware uses a different encryption key derived from a combination of XOR and arithmetic operations.’)

Indicators of Compromise

  • [Document file hashes] initial Word document – MD5: D99020C900069E737B3F4AB8C6947375, SHA256: A6562D8F34D4C25A94313EBBED1137514EED90B233A94A9125E087781C733B37
  • [64-bit downloaded executable] Rust binary – MD5: 4521162D45EFC83FA76C4B5C0D405265, SHA256: F00ED06A1D402ECF760EC92F3280EF6C09E76036854ABACADCAC9311706ED97D
  • [Shellcode blob] downloaded payload – MD5: CD485BF146E942EC6BB51351FA42B1FF, SHA256: 02C03E2E8CA28849969AE9A8AAA7FDE8A8B918B5A29548840367F3ECAC543E2D
  • [Injected AgentTesla payload] in-memory assembly – MD5: 6999D02AA08B56EFE8B2DBBD6FDC9A78, SHA256: 7B6867606027BFCA492F95E2197A3571D3332D59B65E1850CB20AA6854486B41
  • [URLs] download hosts – https[:]//New-Coder[.]cc/Users/signed_20240329011751156[.]exe (64-bit exe), https[:]//New-Coder[.]cc/Users/shellcodeAny_20240329011339585[.]bin (shellcode)

On execution, the Rust-compiled 64-bit binary first patches EtwEventWrite in ntdll (using NtProtectVirtualMemory, WriteProcessMemory, FlushInstructionCache) to disable ETW and then downloads an encoded shellcode blob from a remote URL. The shellcode parses the PEB/PEB_LDR_DATA to resolve APIs via hashing, allocates RW memory (VirtualAlloc), copies ~0x3E3C0 bytes (encoded AgentTesla payload) into that buffer, and executes the shellcode by passing its address as a callback to EnumSystemLocalesA.

The shellcode decrypts the payload in-place using a custom loop that applies single-byte XOR decryption in 0x10-byte blocks with a changing key derived from XOR and arithmetic operations, producing a ~0x3E184-byte MSIL assembly. It enumerates required DLLs (ole32; oleaut32; wininet; mscoree; shell32), loads any missing ones with LoadLibraryA, and resolves additional functions (VirtualProtect, SafeArrayCreate, CLRCreateInstance, etc.) dynamically.

After applying AMSI bypass patches to AmsiScanBuffer/AmsiScanString and re-confirming ETW disabling, the shellcode performs CLR hosting: CLRCreateInstance → enumerate runtimes and GetRuntime → GetInterface to obtain ICorRuntimeHost → Start and GetDefaultDomain to retrieve the _AppDomain. It creates a SAFEARRAY, copies the decrypted MSIL into it, calls defaultAppDomain->Load_3(safeArray) to get an Assembly object, retrieves the EntryPoint via get_EntryPoint, and invokes Invoke_3 with the SafeArray arguments to execute AgentTesla inside the 64-bit process; finally it zeroes the decrypted region and destroys the SAFEARRAY.

Read more: https://blog.sonicwall.com/en-us/2024/04/analysis-of-native-process-clr-hosting-used-by-agenttesla/