Multi-stage APT attack drops Cobalt Strike using Malleable C2 feature

This blog post was authored by Hossein Jazi and Jérôme Segura On June 10, we found a malicious Word document disguised as a resume that uses template

Microsoft took down 18 Azure AD apps used by Chinese Gadolinium APT
Iran-linked APT is exploiting the Zerologon flaw in attacks
US Agencies and FireEye were hacked with a supply chain attack on SolarWinds Software

This blog post was authored by Hossein Jazi and Jérôme Segura

On June 10, we found a malicious Word document disguised as a resume that uses template injection to drop a .Net Loader. This is the first part of a multi-stage attack that we believe is associated to an APT attack. In the last stage, the threat actors used Cobalt Strike’s Malleable C2 feature to download the final payload and perform C2 communications.

This attack is particularly clever for its evasion techniques. For instance, we observed an intentional delay in executing the payload from the malicious Word macro. The goal is not to compromise the victim right away, but instead to wait until they restart their machine. Additionally, by hiding shellcode within an innocuous JavaScript and loading it without touching the disk, this APT group can further thwart detection from security products.

Lure with delayed code execution

The lure document was probably distributed through spear phishing emails as a resume from a person allegedly named “Anadia Waleed.” At first, we believed it was targeting India but it is possible that the intended victims could be more widespread.

Figure 1: Resume

The malicious document uses template injection to download a remote template from the following url:


Figure 2: Template injection

The domain used to host the remote template was registered on February 29, 2020 by someone from Hong Kong. Creation time for the document is 15 days after this domain registration.

The downloaded template, “indexa.dotm”, has an embedded macro with five functions:

  • Document_Open
  • VBA_and_Replace
  • Base64Decode
  • ChangeFontSize
  • FileFolderExist.

The following shows the function graph of the embedded macro.

Figure 3: Macro functions graph

The main function is Document_open which is executed upon opening the file. This function drops three files into the victim’s machine:

  • Ecmd.exe: UserForm1 and UserForm2 contain two Base64 encoded payloads. Depending on the version of .Net framework installed on the victim’s machine, the content of UserForm1 (in case of .Net v3.5) or UserForm2 (other versions) is decoded and stored in “C:\ProgramData”.
  • cf.ini: The content of the “cf.ini” file is extracted from UserForm3 and is AES encrypted, which later on is decrypted by ecmd.exe.
  • ecmd.exe.lnk: This is a shortcut file for “ecmd.exe” and is created after Base64 decoding the content of UserForm4. This file is dropped in the Startup directory as a trigger and persistence mechanism.

Ecmd.exe is not executed until after the machine reboots.

Figure 4: Document_Open Figure 5: Custom Base64 decode function

ChangeFontSize and VBA_and_Replace functions are not malicious and probably have been copied from public resources [1, 2] to mislead static scanners.

Intermediary loader

Ecmd.exe is a .Net executable that pretends to be an ESET command line utility. The following images show the binary certificates, debugger and version information.

The executable has been signed by “ESET, spol. s r.o.” and its version information shows that this is an “Eset command line interface” (Figure 6-8).

Figure 6: Certificate information Figure 7: Version information Figure 8: Debugger information

ecmd.exe is a small loader that decrypts and executes the AES encrypted cf.ini file mentioned earlier. It checks the country of the victim’s machine by making a HTTP post request to “http://ip-api.com/xml“. It then parses the XML response and extracts the country code.

Figure 9: Getcon function: make http post request to “ip-api.com” Figure 10: ip-api.com output

If the country code is “RU” or “US” it exits; otherwise it starts decrypting the content of “cf.ini” using a hard-coded key and IV pair.

Figure 10: ecmd.exe main function

The decrypted content is copied to an allocated memory region and executed as a new thread using VirtualAlloc and CreateThread APIs.

Figure 11: runn function

ShellCode (cf.ini)

A Malleable C2 is a way for an attacker to blend in command and control traffic (beacons between victim and server) with the goal of avoiding detection. A custom profile can be created for each target.

The shell code uses the Cobalt Strike Malleable C2 feature with a jquery Malleable C2 profile to download the second payload from “time.updateeset[.]com”.

Figure 12: Malleable C2 request

This technique has been used by two other recent Chinese APTs—Mustang Panda and APT41.  

The shellcode first finds the address of ntdll.exe using PEB and then calls LoadLibrayExA to load Winint.dll. It then uses InternetOpenA, InternetConnectA, HttpOpenRequestA, InternetSetOptionA and HttpSendRequestA APIs to download the second payload.
The API calls are resolved within two loops and then executed using a jump to the address of the resolved API call.

Figure 13: Building API calls

The malicious payload is downloaded by InternetReadFile and is copied to an allocated memory region.

Figure 14: InternetReadFile

Considering that communication is over HTTPS, Wireshark is not helpful to spot the malicious payload. Fiddler was not able to give us the payload either:

Figure 15: Fiddler output

Using Burp Suite proxy we were able to successfully verify and capture the correct payload downloaded from time.updateeset[.]com/jquery-3.3.1.slim.min.js. As can be seen in Figure 16, the payload is included in the jQuery script returned in the HTTP response:

Figure 16: Payload happened to the end of jquery

After copying the payload into a buffer in memory, the shellcode jumps to the start of the buffer and continues execution. This includes sending continuous beaconing requests to “time.updateeset[.]com/jquery-3.3.1.min.js” and waiting for the potential commands from the C2.  

Figure 17: C2 communications

Using Hollow Hunter we were able to extract the final payload which is Cobalt Strike from ecmd’s memory space.


A precise attribution of this attack is a work in progress but here we provide some insights into who might be behind this attack. Our analysis showed that the attackers excluded Russia and the US. The former could be a false flag, while the latter may be an effort to avoid the attention of US malware analysts.

As mentioned before, the domain hosting the remote template is registered in Hong Kong while the C2 domain “time.updateeset[.]com” was registered under the name of an Iranian company called Ehtesham Rayan on Feb 29, 2020. The company used to provide AV software and is seemingly closed now. However, these are not strong or reliable indicators for attribution.

Figure 11: updateeset.com whois registration information

In terms of TTPs used, Chinese APT groups such as Mustang Panda and APT41 are known to use jQuery and the Malleable C2 feature of Cobalt Strike. Specifically, the latest campaign of Mustang Panda has used the same Cobalt Strike feature with the same jQuery profile to download the final payload which is also Cobalt Strike. This is very similar to what we saw in this campaign, however the initial infection vector and first payload are different in our case.


Anadia Waleed resume.doc

Remote Template: indexa.dotm

Remote Template Url:




Cf.ini shell-code after decryption:

Cobalt Strike downloaded shellcode:

Cobalt Strike payload


%d bloggers like this:
Close Bitnami banner