What We Do
How We Do
Get Started

eSentire Threat Intelligence Malware Analysis: SolarMarker: To Jupyter and Back

BY eSentire Threat Response Unit (TRU)

November 16, 2023 | 18 MINS READ


Threat Intelligence

Threat Response Unit

TRU Positive/Bulletin

Want to learn more on how to achieve Cyber Resilience?



Key Takeaways

  • SolarMarker uses process injection to run the hVNC and data staging payload.
  • The actors behind SolarMarker primarily utilize .NET for the majority of their payloads, with the notable exception of the observed hVNC backdoor, which is written in Delphi.
  • The initial infection triggers numerous PowerShell processes, resulting in a highly noticeable activity pattern.
  • The threat actor(s) started crafting their own websites to host the landing pages.
  • We are currently seeing versions JN-2, JN-10 and M-VII being deployed.

The eSentire Threat Response Unit (TRU) has been monitoring SolarMarker (also known as Jupyter) since 2021. This malware, written in .NET, possesses a backdoor and is capable of stealing information. The delivery method involves the threat actor(s) compromising vulnerable WordPress websites, which ultimately leads to the distribution of the SolarMarker payload to users.

The threat actor(s) had used MSI and EXE payloads before that were over 200-300 MB in size. eSentire has observed SolarMarker activities since the end of 2022 and the beginning of 2023, targeting healthcare, power and utilities, transportation, legal, software, and finance industries before taking a short break.

SolarMarker threat actor(s) tend to slightly change the format of the second-stage PowerShell decryption script, they went from using XOR encryption to AES, but the logic is still the same.


The decryption routine uses simple XOR on the encrypted Base64-encoded payload saved to the disk as a text file. The decrypted payload is then directly executed via IEX, shown in Figure 1 below.

Figure 1: Decryption routine (2020)


Simple XOR is used to decrypt the payload. The payload is stored under a randomly named file under the %AppData%\Microsoft folder. The resulting decrypted data is then loaded as an assembly using the [Reflection.Assembly]::Load method, shown in Figure 2 below.

Figure 2: Decryption routine (2021)


The payload is encrypted with the AES encryption algorithm. It sets the encryption key using a Base64-encoded string, and the initialization vector (IV) is the first 16 bytes of the encrypted file (Figure 3).

Figure 3: Decryption routine (2022)

January 2023:

The AES key and IV are stored in a byte array. The encrypted payload Base64-encoded payload is stored under C:\Users\<username>\ under a randomly named file (Figure 4).

Figure 4: Decryption routine (January 2023)

May 2023:

The decryption algorithm is the same as the one mentioned above, but the encrypted payload is stored under the randomly created registry name under HKCU:\Software\Classes\ (Figure 5). The payload is written to the registry as bytes instead of in Base64-encoded format.

After loading the decrypted payload into memory, the script enters an infinite loop and includes a delay using the Start-Sleep command. This behavior might be an attempt to evade detection, as the script continues to run indefinitely with periodic pauses.

Figure 5: Decryption routine (May 2023)

January Case

In early January 2023, our Security Operations Center (SOC) received an alert regarding suspicious SearchIndexer usage. This included the detection of a PowerShell script loading processes and outbound network connections to IP addresses flagged as suspicious.

After conducting a thorough investigation, our TRU determined that the infection occurred after the user executed the first stage SolarMarker executable payload that was downloaded from the compromised WordPress website.

The second stage .NET payload was AES-encrypted on disk under %userprofile%. The day after the initial execution, SolarMarker’s third-stage payload was injected into SearchIndexer.exe process, shown in Figure 6.

Figure 6: Infection chain
Figure 7: First stage decryption algorithm (January case)

On the next day after the initial infection, the threat actor(s) pushed the next stage on the infected host which resulted in the searchindexer.exe process injection. We observed over 15k file modification events, which resembled the data staging performed by SolarMarker in the later stages of post-infection as shown in Figure 8.

Figure 8: Data staging

We obtained the Event Logs file (Figure 9) from the client and were able to correlate the timestamps for the process injection and extracted the PowerShell script.

Figure 9: Event logs containing the PowerShell scripts that ran on the infected host

The PowerShell script unravels the third-stage payload (Figure 10).

Figure 10: Snippet of the PowerShell script containing the third-stage payload


The decryption algorithm used for the third-stage payload is identical to that of the first-stage payload. In this algorithm, the IV consists of the initial 16 bytes obtained after base64 decoding the payload, while the AES key spans 24 bytes. Upon decryption, the script reveals a .NET 32-bit DLL binary, compiled on December 19, 2022 (MD5: 86906856be32fad96e86e7fd6bca89d9). We named the third stage payload as StellarInjector.

Figure 11: Third-stage payload decryption algorithm

SolarMarker employs a string obfuscation technique, where characters are added to a string by subtracting an integer offset from a sequence of numbers. Ultimately, this process yields a resulting string composed of characters (Figures 12-13).

Figure 12: Obfuscated strings
Figure 13: Decoded strings

The threat actor(s) incorporated the inclusion of garbage strings (Figure 14 and 15) with the intention of potentially evading detection by antivirus software, thereby increasing the malware's stealthiness. By introducing such meaningless data, the analysis process can be further complicated, creating challenges for analysts in deciphering the true purpose of the malware.

Figure 14: Garbage data
Figure 15: Output of the junk data

In order to ensure a clear understanding of the sample's functionality, we proceeded with renaming the methods for easy identification (Figure 16).

Figure 16: Renamed methods

Upon examining the majority of the method names, it appears that the process involves the process hollowing. This technique utilizes APIs like ZwUnmapViewOfSection to unmap the process and subsequently resumes execution by utilizing VirtualAllocEx, SetThreadContext, and WriteProcessMemory.

Upon further analysis of the payload, a significant byte array blob was discovered, indicating the presence of an embedded payload, shown in Figure 17.

Figure 17: Embedded payload

Right after the embedded payload, we observe its decryption utilizing the AES CBC algorithm (Figure 18), with the first blob of bytes serving as the key and the second blob as the IV.

Further, we can observe the creation of a new thread with the executable `searchindexer.exe` located at `C:\Windows\SysWOW64\SearchIndexer.exe`, indicating that our embedded payload will be executed from this location (Figure 19).

Figure 19: Payload injection into SearchIndexer.exe

SolarPhantom Backdoor

The extracted payload is written in Delphi and is approximately 520KB in size. Further analyzing the payload, we have found something resembling the hVNC functionality with the hardcoded command and control (C2). We named the hVNC backdoor payload as SolarPhantom.

The code snippets below (Figure 20 and 21) involve operations related to graphics and text rendering; it also involves functions that capture and print the contents of a window, such as PrintWindow and TBitmap.

Figure 20: Graphics and text rendering (1)
Figure 21: Graphics and text rendering (2)

In the code below, the SendMessageA function is used to send the WM_CAP_DRIVER_CONNECT message (0x40Au) to the window specified by the hWnd handle. This message is typically used in video capture applications to connect to a video capture device or webcam (Figure 22).

If the return value of SendMessageA is equal to 1, it means that the capture operation was successful. In this case, the code snippet immediately returns 1, indicating a successful capture.

The function also retrieves the handle of the desktop window via GetDesktopWindow, then it captures the window via capCreateCaptureWindowA, which contains the “CaptureWindow” as the name used for the capture window. The code suggests that its functionality is to capture the footage from web cameras.

Figure 22: Snippet of code that captures webcam footage

Below you can see the APIs being called, such as CreateDesktopA to create a hidden desktop (Figure 23), and SetThreadDesktop, which assigns the hidden desktop to the calling thread, which is the backdoor.

Figure 23: Functions to create a hidden desktop

The snippet of code below is handles the mouse input events (Figure 24) and interacts with windows based on that input. It performs actions based on the mouse action requested and sends messages to the appropriate window to simulate those actions using APIs such as WindowFromPoint (retrieves the handle of the window under the mouse cursor), GetWindowRect (retrieves the window’s rectangle) and PostMessageA (posts the messages to the window). It assigns a value to the variable v7 to represent the type of mouse action (e.g., left-click, right-click, wheel-up, wheel-down, move, select).

This could potentially be used to simulate mouse events and interact with windows on the hidden virtual desktop.

Figure 24: Mouse input events

SolarPhantom creates the directories under the %TEMP% folder based on the Browsers that are present on the infected machine (Figure 25 & 26). Each browser will have the following tag names followed by _bkp.

The files from the user’s browsers are copied to the created directories and are exfiltrated to the C2 server.

Figure 26: File copy to the newly created directory (2)

An example of the data copied from Browser folders is shown in the screenshot below (Figure 27). It should be noted that the files include sensitive information, such as cookies and login data.

Figure 27: Example of the exfiltrated browser data

SolarPhantom initially verifies the existence of a specific browser's '_bkp' directory. If found, it further checks for the presence of browser executables by attempting to retrieve their file timestamps. In case the timestamp retrieval fails, the code proceeds to search for the executables in the 'Program Files' directory, which accommodates 64-bit applications, rather than 'Program Files (x86)'.

Subsequently, it customizes the behavior and appearance of the browser process by specifying the initial position and size of its window before launching the browser. These operations are also performed for Microsoft Edge, Firefox, Portable Chrome, and Brave browsers.

Furthermore, SolarPhantom disables browser metrics, hardware acceleration, and window occlusion calculations (Figure 28). This operation is likely intended to prevent any disruptions in the operation of the hVNC module.

Figure 28: Browser executable check and disabling browser metrics

SolarPhantom generates a random 26-character value and passes it to HWID?/ string to send over to C2 (Figure 29).

Figure 29: Random string generator function

During the initial execution, SolarPhantom sends out the host computer name and username along with the randomly generated HWID to C2 in the following format:

Further investigating, we found 42 SolarPhantom samples on VirusTotal tied to the same C2. You can find the hashes in the Indicators of Compromise section.

May Case

In May, our TRU team conducted a comprehensive analysis of the most recent campaign orchestrated by the SolarMarker threat actor(s). In contrast to previously observed campaigns where the threat actor(s) utilized Google Drive and compromised WordPress websites, it appears that the threat actor(s) now employ their own websites to deploy and host the malicious payload.

This strategic shift grants them increased control over the hosting environment, enabling them to swiftly take down the malicious landing page at their discretion, thereby impeding further scrutiny and analysis by researchers. The landing pages resemble other legitimate companies. In our case, threat actor(s) replicated legitimate websites  of BookBaby (self-publishing company) and Arcadis (engineering company).

The threat actor(s) is still using SEO poisoning. SEO attacks are deceptive tactics employed to manipulate search engine rankings, often involving techniques such as keyword stuffing to deceive search engines and drive traffic to the payload hosting websites.

The initial infection chain is similar to the previous campaigns. The user clicks on the first link (Figure 30), which redirects them to a payload download page with a different link generated each time for a different user (Figure 31). After clicking “Open Document,” the payload will be served from the attacker’s server (Figure 33) that is hosted on Hestia Control Panel over port 8083.

Figure 30: Webpage serving the payload, BookBaby clone (1)
Figure 31: Webpage serving the payload, BookBaby clone (2)
Figure 32: Webpage created to likely serve the payloads, Arcadis clone
Figure 33: Initial infection chain

The website in Figure 30 contains other SEO keywords that might potentially be used:

After executing the first stage payload, SolarMarker first connects to the C2. Then it sleeps for a period of time, and then decrypts the second stage payload, loads, and runs it in memory while establishing a connection to another C2. The persistence is achieved via the startup folder after running for 4-10 minutes. SolarMarker creates the handler key in the registry that points to the encrypted payload within the registry under HKCU:\Software\Classes\<random_name>.

It’s worth noting that eSentire TRU has observed SolarMarker storing the encrypted payload under C:\<username>\<encrypted_payload> (November campaign) or under the %TEMP% folder in previous intrusions.

The latest SolarMarker payloads are dropping decoys such as SumatraPDF and pdf files. The latest decoy at the time of this writing is shown below (Figure 34).

Figure 34: PDF decoy

Upon analyzing one of the recent unobfuscated first-stage payloads (MD5: 3fd9d81c06743c2eaffce6995ff1e46c) which is written in .NET, we noticed an embedded blob of base64-encoded text. The blob contains the base64-encoded PDF decoy file and an AES-encrypted payload as shown in the image below (Figure 35).

Figure 35: Embedded PDF decoy and second stage payload

The “powerShell.BeginInvoke” line starts the execution of the PowerShell script that's been constructed. The "while (!mainApp.ShouldExit && !mre.WaitOne(100))" line causes the main program to wait in a loop until either the PowerShell script finishes executing (signaled by mre being set), or until the main application is supposed to exit (mainApp.ShouldExit becomes true). The WaitOne(100) call causes the loop to check these conditions every 100 milliseconds (Figure 36).

Figure 36: Beautified and decoded Base64 blob
Figure 37: Decrypted first-stage payload
Figure 38: Persistence via registry

Numerous PowerShell processes are spawned under the parent process of the first stage payload every 10-15 seconds, which makes it very noisy (Figure 39).

Figure 39: Initial payload spawning multiple PowerShell processes

If the infected machine has StartUp notifications enabled, they might notice the new StartUp apps created every 4 minutes with a random name. Navigating to the Startup folder under C:\Users\<username>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup, we notice many shortcuts with randomly-generated names. Each of them would point to a PowerShell file under the %AppData% folder.

But why would files in the %AppData% have 0 bytes in size? (Figure 40). That is right, the files have the extension keys registered under Computer\HKEY_CURRENT_USER\Software\Classes\. We also described similar behavior in our previous SolarMarker blog. Each registered extension points to the handler key that contains a PowerShell one-liner to decrypt the payload.

Figure 40: PowerShell files under %AppData%
Figure 41: StartUp Apps
Figure 42: Startup shortcuts

The decrypted second stage payload (MD5: 5fd6c3722eeb7a3c1d54e46c28a020b3) is 567KB in size. The backdoor configuration is shown below.

Figure 44: Payload configuration

Where the version tag is M-VII (we have observed versions JN-2, JN-10 and M-VII in the ongoing campaign so far). The RSA key is:


The method shown below is used to retrieve information about the operating system, including the version and product name by querying the registry path Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion and CurrentBuild, ProductName values.

The backdoor sends out the basic information on the infected machine, including the configuration using this template with the placeholders for HWID (unique value generated based on the hardware of the infected machine), pc_name, Win (Windows version), arch (architecture), rights (IsAdmin check), and version:

Some of the information parsing is shown below:

Figure 45: Snipper of the info parsing

The code snippet below creates a new instance of WindowsPrincipal using WindowsIdentity.GetCurrent() to get the current Windows user identity. It checks if the current user is in the Administrator role using the IsInRole method with the WindowsBuiltInRole.Administrator parameter. If the user is in the Administrator role, the ‘+’ is applied; if not – the ‘-‘ is applied for the placeholder {4}.

Figure 46: IsAdmin check

The constructor below initializes a ProcessStartInfo object with the command powershell, indicating the execution of a PowerShell process. The ProcessStartInfo object is then used to start the PowerShell process in the call_it method, where the PowerShell script is written to the standard input of the process.

Figure 47: PowerShell script execution function

The method below creates an instance of the class, passing it a dictionary of properties and the ps_script parameter. The dictionary contains three key-value pairs, specifying properties for the ProcessStartInfo object used internally. These properties indicate that the process should not create a window, should redirect the standard input, and should not use the user's shell for execution.

Figure 48: Passing properties to ProcessStartInfo

The code snippet below is responsible for fetching additional payload from C2, specifically exe and ps1 files, and placing them under the %TEMP% folder with a randomly generated name using the GetRandomFileName method.

The following templates are used to communicate with the infected machine, where change_status means the successful execution of the fetched payload:

More on the backdoor commands, you can read in our previous blog.

Figure 49: Payload fetching

The backdoor still uses the unique Base64-encoded value as a hash for communication with C2. Where “idle” means that the infected machine is in the waiting state for the instructions from the C2 server.

Figure 50: C2 communication via unique hash

How eSentire is Responding

Our TRU combines threat intelligence gained from research and security incidents to create practical outcomes for our customers. We are taking a comprehensive response approach to combat modern cybersecurity threats by deploying countermeasures, such as:

Our detection content is supported by investigation runbooks, ensuring our 24/7 SOC (Security Operations Center) Cyber Analysts respond rapidly to any intrusion attempts related to known malware Tactics, Techniques, and Procedures (TTPs).

In addition, TRU closely monitors the threat landscape, constantly addresses capability gaps, and conducts retroactive threat hunts to assess customer impact.

Recommendations from eSentire’s Threat Response Unit (TRU)

We recommend implementing the following controls to help secure your organization against SolarMarker malware:

While the TTPs used by threat actor(s) grow in sophistication, they lead to a certain level of difficulties, at which critical business decisions must be made. To stop attackers using modern attack techniques and tactics from disrupting your business, you need to actively monitor the threat landscape, develop and deploy endpoint detections, and investigate logs and network data during active intrusions.

eSentire’s TRU is a world-class team of threat researchers who develop new detections enriched by original threat intelligence and leverage new machine learning models that correlate multi-signal data and automate rapid response to advanced threats.

If you are not currently engaged with an MDR provider, eSentire MDR can help you reclaim the advantage and put your business ahead of disruption.

Learn what it means to have an elite team of Threat Hunters and Researchers that works for you. Connect with an eSentire Security Specialist.

Indicators of Compromise























































































First stage payload


First stage payload


First stage payload


First stage payload


First stage payload


First stage payload


First stage payload




PowerShell payload











MITRE ATT&CK Technique


Initial Access


Drive-by Compromise

SolarMarker is delivered via malicious websites hosting the payload disguised as a document file (PDF, DOC, XLS, PPT)

User Execution


Malicious File

The user launches the malicious file

Data Staged


Credentials from Password Stores

Credentials from Password Stores: Credentials from Web Browsers

SolarMarker performs data staging of sensitive files from browsers, including credentials, cookies and sends them over to C2



Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder

Persistence is achieved via the Startup folder



Command and Scripting Interpreter: PowerShell

SolarMarker utilizes PowerShell to load the payload in memory as well as to retrieve additional payloads from C2



Exfiltration Over C2 Channel

SolarMarker payloads are capable of uploading the stolen data to the C2 server

Sigma and Yara

You can find Sigma and Yara rules in the GitHub repository: https://github.com/RussianPanda95/Malware-Rules-IOCs/tree/main/SolarMarker



eSentire Unit
eSentire Threat Response Unit (TRU)

The eSentire Threat Response Unit (TRU) is an industry-leading threat research team committed to helping your organization become more resilient. TRU is an elite team of threat hunters and researchers that supports our 24/7 Security Operations Centers (SOCs), builds threat detection models across the eSentire XDR Cloud Platform, and works as an extension of your security team to continuously improve our Managed Detection and Response service. By providing complete visibility across your attack surface and performing global threat sweeps and proactive hypothesis-driven threat hunts augmented by original threat research, we are laser-focused on defending your organization against known and unknown threats.

Read the Latest from eSentire