Attack Chain Déjà-vu: The infection vector used by SVCReady, Gozi and IcedID

DCSO CyTec Blog
5 min readJul 25, 2022

--

Early June 2022, HP Threat Research published a blog post about a newly discovered malware named SVCReady, notable for using Word document properties to store shellcode used in its attack chain.

DCSO CyTec has been observing similar attack chains since the beginning of March 2022 at the earliest, previously used to deliver IcedID instead of the later discovered SVCReady malware. In addition, a tweet by Cert AgID in April 2022 seems to document a very similar attack chain resulting in the distribution of Gozi (aka Ursnif) malware.

It thus appears the attack chain, common to all 3 instances, predates the appearance of the SVCReady malware itself and is independent of the distributed malware. This implies that the same attack chain may be utilized to distribute other malware in the future, which is why we decided to investigate and take a closer look.

This blogpost was authored by Johann Aydinbas

Layer 1 — Word Macros

As is often the case, the attack chain starts with a lure document using macros in order to infect a client. The macro code varies slightly between samples, sometimes employing minor obfuscation techniques such as reversing strings or storing them in document properties instead of hardcoding them into the macro code.

Document properties containing 32/64bit shellcode highlighted in red

In general the macro:

  • defines environment variables to communicate with the final stage of the attack chain
  • extracts and decodes appropriate (32/64bit) shellcode from document properties
  • executes the shellcode via SetTimer API call

All macros use two fixed environment variables for communicating with RemoteDllLoader, an as of now undocumented (though mentioned by Cert AgID) component appearing later in the execution chain.

RemoteDllLoader has two execution modes. It can either be supplied a URL from where to fetch the final payload, or it can be pointed to a custom archive format file from which to extract the final payload.

For this purpose, the macro signals which mode to operate in by setting one or both environment variables. The variable names itself resemble a GUID and have remained unchanged since the beginning.

If the macro sets both, {FCF2382A-4DD7–4FBE-9E77–0EE3DD66379A} specifies the full path to the Word document itself, which contains the embedded custom archive, while {1F79AEE7–7F65–4B80-A1C6-E5C90A7BE6CF} contains the name of the embedded archive file.

Otherwise, the macro only sets {FCF2382A-4DD7–4FBE-9E77–0EE3DD66379A} which will contain a URL to fetch the payload from.

Finally, the shellcode embedded in the document properties is executed using the SetTimer API.

Unobfuscated macro setting up URL for RemoteDllLoader before executing shellcode

Layer 2 — Shellcode Decoder

The shellcode extracted from the document properties is encrypted. It is prefixed by a small custom decoding routine which appears multiple times throughout the attack chain and involved components.

The decoder expects the trailing encrypted payload in the following format:

[DWORD type]
[DWORD xor key length]
[DWORD payload length]
[* xor key]
[* payload]
Example of an encrypted blob with header

It then proceeds with decrypting the payload with a cyclic xor using the embedded key. After decryption, the decoder checks if the “type” DWORD is set to 0xE8 — if this is the case, the decoder executes the decrypted data as code, otherwise it just returns.

At this point, the type is set to 0xE8 and thus the decoder continues with executing the just decoded code.

This stage is a result of the ongoing development process. It was missing in the earliest sample used to drop IcedID, and later samples also started to include minor variations such as adding a fixed key (xor 0xAA) on top.

Layer 3 — DLL Loader

The DLL loader consists of another shellcode stub and payload.

Here, the code stub is responsible for loading the appended RemoteDllLoader DLL file via manual mapping. Manual mapping is the process of loading a PE file without using common API functions like LoadLibrary in order to stay under the radar of security products.

Once the PE file has been mapped, the code executes the entry point as specified in the image header, to which it passes a magic number 0x54E1C0DE as the first argument (in place of fdwReason as expected for DLL entry points).

Shellcode calling RemoteDllLoader with magic number

At its entry point, RemoteDllLoader verifies the presence of this magic number. This prevents sandboxes from properly executing the malware. If the magic number is not supplied, as would be the case in a sandbox loading the DLL the normal way, the DLL quits without further action.

RemoteDllLoader checking for magic number at entry point

Layer 4 — RemoteDllLoader

PDB path found in RemoteDllLoader

RemoteDllLoader finally is the component responsible for either fetching and executing the final payload, or extracting it from a previously specified custom archive format before execution.

URL Mode

In URL mode, RemoteDllLoader fetches the URL as specified in the environment variable {FCF2382A-4DD7–4FBE-9E77–0EE3DD66379A} by the Word macro, using the API URLDownloadToFileA to a temporary path.

If the downloaded file is a DLL, a copy of rundll32.exe is used to execute its DllRegisterServer export whereas EXE files are executed using the WinExec API.

Archive Mode

Despite its name, RemoteDllLoader does not have to fetch its payload from a URL.

The initial Word macro can point RemoteDllLoader to a zip file and a file name of a custom archive contained in that zip file, from where the payload will be extracted.

As .docx files are essentially zip files, the custom archive is distributed embedded inside the .docx itself, and the initial macro points RemoteDllLoader to a specific file inside the lure document via environment variables.

Custom payload archive embedded in lure .docx file

The custom archive uses the same format as used in Layer 2 with the same shellcode stub responsible for decrypting the payload.

Custom archive with the same header as before (type, key length, payload length)

In this case the “type” is set to 0xEA so the decoder stub does not execute the decrypted payload directly. Execution then proceeds as documented for URL mode, concluding the attack chain with the execution of the payload.

IoCs

You can grab the raw IoCs from our GitHub.

MISP

If you prefer MISP, you can find the IoCs in form of a MISP event on our GitHub as well.

MITRE ATT&CK

T1027       Obfuscated Files or Information
T1566 Phishing
T1001 Data Obfuscation
T1059.005 Visual Basic
T1497 Virtualization/Sandbox Evasion

--

--

DCSO CyTec Blog

We are DCSO, the Berlin-based German cybersecurity company. On this blog, we share our technical research.