LESLIELOADER – Undocumented Loader Observed

Key Takeaways

  • Kroll has observed a new loader for SPARKRAT malware used in ongoing campaigns.
  • While SPARKRAT development has officially ceased, unofficially it has continued to be modified by threat actors as needed.
  • One of these new changes is a previously undocumented loader, identified by the AES key “LeslieCheungKwok”.

Summary

Kroll observed the use of SPARKRAT in conjunction with a previously undocumented loader written in Golang. The loader assists in the initial infection and deployment of the malicious payload, enabling SPARKRAT to execute on a system. This process allows the payload to reach the target system undetected and unquarantined. The loader achieves its goal by decoding and decrypting a secondary payload binary, then injecting it into a notepad.exe instance. This injection allows the malware to blend with legitimate system activity as it shares the memory space of a legitimate application. Despite detection tools’ ability to mitigate process injections, they remain a common evasion tactic.

GitHub developer XZB-1248 wrote and released SPARKRAT, a Golang binary compiled for multiple platforms, as an open-source, feature-rich remote admin tool on GitHub on March 18, 2022. Even though the developer abandoned the project in February 2023, intrusion investigations continue to discover modified versions of SPARKRAT. The “DRAGONSPARK” campaign, notorious for its attacks against organizations in East Asia, frequently uses this malware. SPARKRAT interprets its embedded Golang source code at runtime, which complicates analysis and static detections.

A source code repository very similar to LESLIELOADER has been identified alongside with instructions on how to utilize the loader for any payload necessary, originally timestamped June 7, 2022. Steps include generating a shellcode payload, AES encrypting the payload, and generating the executable. Additionally, the author posted proofs of running the samples against various antivirus and sandbox tools. However, there are some key differences from LESLIELOADER. Unlike the samples observed by Kroll, this loader does not beacon out a network connection. Additionally, this loader does not use process injection for code execution or a secondary file for payload.

leslieloader-article-fig-1

Figure 1: Similar Code Repository

Later forks of this repository show modified versions of the initial loader, which begin to implement Base64 decoding. Continued modification of this original source code likely resulted in the version covered within this article.

leslieloader-article-fig-2

Figure 2: Forked Repository Showing Addition of Base64 Decoding Stage

Kroll has identified and triaged additional LESLIELOADER samples and has observed them to contain Cobalt Strike configurations as well as other payloads, so this loader is not limited to SPARKRAT.

First Loader Stage

The loader begins with two files, Ntmssvc.dll and RemovableStorage.dll. Upon execution of Ntmssvc.dll with the /runcode flag, RemovableStorage.dll is read from C:\\Windows\System32\. Ntmssvc.dll contains the loader functionality, and RemovableStorage.dll functions as the payload.

leslieloader-article-fig-3

Figure 3: RemovableStorage.dll File Read into Memory

RemovableStorage.dll is not a true PE file and does not contain the structure needed by the Windows PE loader to run independently. Instead, it serves as a payload data file that has undergone both Base64 encoding and AES 192-bit encryption.

Ntmssvc.dll initially attempts to beacon out to 209.141.50[.]215:443, however, this execution can be skipped in favor of overwriting the instruction pointer to the storage decoding function.

leslieloader-article-fig-4

Figure 4: HTTP Beacon Attempt

leslieloader-article-fig-5

Figure 5: Jumping to the Loader Function

Stepping through the storage decoding function, the last 32 bytes of RemovableStorage.dll are Base64 decoded and loaded into the RDI register, with LeslieCheungKwok loaded into the RCX register. The system then Base64 decodes RemovableStorage.dll and uses LeslieCheungKwok as the AES key to decrypt the resulting payload of data, with the 32 bytes from the end of RemovableStorage.dll serving as the IV. The resulting payload contains additional Base64 encoded data.

leslieloader-article-fig-6

Figure 6: AES Key and IV are Loaded into Memory

Second Loader Stage

Stepping into the loader for this decrypted and decoded output, we continue to see Base64 decoding occur to portions of our file.

leslieloader-article-fig-7

Figure 7: Further Base64 Decoding

Inspecting this, we see snippets of what appears to be shellcode using CyberChef.

leslieloader-article-fig-8

Figure 8: CyberChef Recipe and Output

To continue observing the loader’s behavior to the memory pages containing these payloads, we set hardware breakpoints for memory access to them. Ultimately, we can observe the final payload for process injection dynamically calculated to have the size of 83DA50 in registers RCX and RDX.

leslieloader-article-fig-9

Figure 9: Preparing for process injection.

leslieloader-article-fig-10

Figure 10: Final Payload Size in RAX and RDX

Process injection to notepad.exe begins with a matching payload size in register r8 when memory is being allocated.

Notepad.exe is launched as a suspended process, however, there are additional artifacts of note within the loader indicating other processes such as calc.exe and cmd.exe. While they do not appear to be used in this sample for injection, the analysis of the use of these processes is out of scope.

leslieloader-article-fig-11

Figure 11: Acquiring Pointer to notepad.exe

Once notepad.exe is created as a suspended process, Ntmssvc.dll overwrites the process memory for notepad.exe to manipulate the entry point. Prior to overwriting the entry point, notepad.exe proceeds as follows:

leslieloader-article-fig-12

Figure 12: Original Entry Point

Once the notepad.exe entry point has been overwritten, the memory address of our SPARKRAT payload is loaded into RAX and jumped to, beginning execution of the malware.

leslieloader-article-fig-13

Figure 13: Modified entry point

This now allows for the injected payload to be executed as notepad.exe.

File Information

FilenameNtmssvc.dll
MD5a8164d4d4c7c0669f01f0cec11db5c23
SHA1524d1042f6834b5d5af6fc8361d25eb3c5e0925c
SHA-256ec45da0ca70a9b71652cc95d51665f7ad568294bd5652c395a119bccd613e9b4
SSDeep49152:NzPXvD233tOrb/TgvO90d7HjmAFd4A64nsfJaZmq59X4uv+J9mqBAhmm9tHaF90V:o3l/1MEUkz6h+
File Size5.2M
Go Version1.19.6
Go Build IDCkXRLYLV5G2q6zLSX2ow/XDMcRiYChHDh4RhVcflB/AvlcOAk9US3h4x7V9sBS/D-1jdZnavCSSXOMBjnmk
FilenameRemovableStorage.dll
MD5d8ed87bccf4ff55b98ee6fd229427a45
SHA11e0d10e17bf5fc2b1dd7cfc717767d87e5fd4489
SHA-256b8cab11421eb4731c16cf3c34ca2b3f2a758d5e112f877b90a18b3e146c8add0
SSDeep49152:wTJSBSikp+WKZvBSVAYk5d606sKhdu6XAPf48ud5cFCz0/cef1Y0Ei7Mt3iyEiYM:O
File Size15M

Additional Samples

During this investigation, Kroll identified other samples with indicators common to this loader. Several of these files notably have indications of Cobalt Strike and shellcode injection payloads. VirusTotal currently has the following list of hashes that have been identified with the yara rule listed below:

SHA-256VT Submissions
f63511dc1d46742a9afb09e51294bcefa6a950326688c6e67b13facbf8ecdcff1
0b77f2dc04fcb24034feb26ed8bb0721da93f55d74ea8347373946abdf245f371
e70aac286c3b320c7cf19a74904c3ff5ecd1795915c98c56c9ff3915875595da1
75a49cd2762810d0e9bd0187e8a29a0ad3e84281028e8aec44723249a5da23631
e8a08771552c29c573f55f6d444d9b9282f331e703fda76110deb124b801d7301
f28f9a11926cfbd08896ee669607ea9ce10f69e217ce10f5ed74db688687cba51
b5ba48002f13975f23851a3ec80547aa71d6953ce7aad42af3ba4a87699c80dd1
05ecd6749aea5cade72b028994e719b3c3315103ef8ba6c46d4dba72575080e02
c9b36dbca2f3260c62c1180720be599886e56191be9d4b1822dacec4d8dd3e991
4741ddd031d4741e9ef92f606753ea4e95b9e161173a2a82c18ffd1f8206d8521
fd557bc84742fa76efd394f0f5f648a889648bd01487c489aa395251b61a7d601
b5d46ffed1ec57b24867499bd15f5a0487443e1f0f4c1fa578d917e851560ba41
24c197844f1275df73f45803b1a740d4dae565f6de06bac388f2cd6df454469c1
fb728d019149bb3dd696c1b417ceea008b88a18baf61b2640bae224ed8148cbe1
0c3cb0a8314e668a65df60800c8075e34b95d1d18fe72fe269f938454543bca91
983e03a0f46cd40a861f7dc3e4efd1397b9b474168dc322a75a551bfb3fa8ded1
db42d41a59e3e5c9bb234479ce05cd1923ef9754911cc14e9b3e5d500e1915111
94445af999055bf7d7cddc0d1d5183ab2776d85285f0522a28fac6c5a61019061
fdea8b01b2597ceafe6f08b5fd12cc603b1e3ce2037731c0b6defde6935b1ce01
25bfed3eb9ebc12604edee0aeb4c8bc2f2a37e9fd1c77ebda33b5756509a726d1
2df61720ffee7a6730c029da45bddba2ec9eace7359e1ee964b44560e9062bb91
12afe1b18b0e7dcc4903fff3a7dc2a2b6c3d111c2f836e7b4d13ed082b8dea891
73d1d42b76e1051c6ad0c832dc1c6bcd7158f4a0687f1f7d84c9c3c513b0e43e1
4ca0d50308013957a3da3fc60a62649c405fd9dbf7b184b18e73333ddf23e0bc1

Additionally, the below Yara rule may be used to search for indications of this loader:

import "pe"

rule leslieloader
{
  meta:
    author = "Marc Messer"
    description = "Checks for the inline string “LeslieCheungKwok” with instructions."
    truepositive = "ec45da0ca70a9b71652cc95d51665f7ad568294bd5652c395a119bccd613e9b4"
  strings:
    $a = {48 b9 4c 65 73 6c 69 65 43 68 48 89 08 48 b9 65 75 6e 67 4b 77 6f 6b}
  condition:
    pe.is_pe and $a
}

https://www.kroll.com/en/insights/publications/cyber/leslieloader-undocumented-loader-observed