← Back to Technical Analysis / 3CX Supply Chain Attack — Full Campaign Report
SUPPLY CHAIN TECHNICAL ANALYSIS

3CX Supply Chain Attack — Full Technical Analysis

📅 2026-07-01 ⏱ 30 MIN READ ✍ SalahEldin Fikri (Mr_MaTriX) CRITICAL
A full technical breakdown of the Lazarus Group's 3CX supply chain attack, tracing the intrusion from the X_TRADER initial compromise through the trojanized 3CX Desktop App, the malicious ffmpeg.dll loader, the GitHub-hosted dead-drop resolver, and the VEILEDSIGNAL backdoor — ending with a consolidated IOC set and a full MITRE ATT&CK mapping.

1. Sample Analysis — 3CX Supply Chain Attack Campaign

3CX supply chain attack illustration

The 3CX Supply Chain Attack, publicly disclosed in March 2023, is regarded as one of the most sophisticated software supply chain compromises attributed to the Lazarus Group. Unlike traditional attacks that directly target victims, this operation focused on compromising a trusted software vendor and using its software distribution infrastructure to deliver malware to thousands of organizations worldwide.

Background

3CX is a software company that develops Voice over Internet Protocol (VoIP) communication solutions used by more than 600,000 organizations worldwide. Its desktop application is available for both Windows and macOS and is digitally signed to ensure authenticity and integrity. Because of its widespread adoption in enterprise environments, compromising the 3CX software supply chain provided the attackers with access to a large number of potential victims through a single trusted distribution channel.

Stage 1 — Initial Compromise

The attack did not begin at 3CX. According to the joint investigation conducted by Mandiant and 3CX, the attackers first compromised a 3CX employee's workstation through an earlier supply chain attack involving the X_TRADER financial trading software developed by Trading Technologies International, Inc.

Years before the 3CX incident, Lazarus had compromised the X_TRADER software distribution process, embedding malware within legitimate software updates. A 3CX employee installed the compromised application, unknowingly infecting their workstation. The malware established persistence, collected credentials, and allowed the attackers to maintain long-term access to the employee's system.

Stage 2 — Compromise of the Build Environment

After obtaining access to the employee's workstation, the attackers performed internal reconnaissance and harvested credentials that enabled them to move laterally within the corporate network. Eventually, they compromised the 3CX Continuous Integration and Continuous Delivery (CI/CD) build environment.

The CI/CD infrastructure is responsible for automatically compiling, testing, digitally signing, and publishing official software releases. By compromising this environment, the attackers gained the ability to modify legitimate application components before they were digitally signed and distributed to customers. Rather than stealing the company's code-signing certificate, the attackers inserted malicious components directly into the official build process, allowing the compromised software to retain its trusted digital signature.

Stage 3 — Trojanized Software Distribution

The attackers modified the Windows and macOS versions of the 3CX Desktop Application by replacing legitimate Dynamic Link Libraries (DLLs) with trojanized versions. When users installed or updated the software, the malicious DLLs were executed alongside legitimate application components without raising immediate suspicion. Because the software remained digitally signed by 3CX, endpoint security products and users generally trusted the application. Thousands of organizations unknowingly installed the compromised software during routine software updates.

Stage 4 — Multi-Stage Malware Execution

The trojanized application initiated a carefully designed multi-stage infection chain. During execution, malicious DLLs decrypted embedded shellcode that established communication with attacker-controlled infrastructure. The malware downloaded additional payloads only after performing victim profiling, reducing the likelihood of detection. Researchers identified several malware families associated with the operation, including:

This staged architecture allowed Lazarus to limit exposure by deploying advanced malware only to organizations considered strategically valuable.

Stage 5 — Target Selection

Unlike indiscriminate malware campaigns, the attackers carefully selected follow-on targets. The initial trojanized software acted as a filtering mechanism. Systems meeting predefined criteria received additional malware capable of credential theft, intelligence collection, and long-term remote access. Victims included organizations operating in sectors such as financial services, information technology, government, aerospace, and critical infrastructure.

Discovery

The attack was first identified in March 2023 after security researchers observed suspicious behavior associated with the signed 3CX Desktop Application. Subsequent investigations by multiple cybersecurity vendors, including Mandiant, SentinelOne, CrowdStrike, Sophos, Elastic Security, and Kaspersky, revealed that the application had been compromised during the software build process rather than after distribution.

The investigation also uncovered the connection between the 3CX compromise and the earlier X_TRADER supply chain attack, demonstrating how Lazarus leveraged one software supply chain compromise to facilitate another.

The campaign remains one of the most significant examples of a modern software supply chain attack and illustrates the growing importance of securing software development pipelines, code-signing processes, and CI/CD infrastructure against nation-state adversaries.

2. Technical Analysis

PHASE COMPONENT PURPOSE ANALYSIS
0 Attack Execution Overview Complete execution chain of the 3CX supply chain attack. Attack Flow
1 X_TRADER Supply Chain Initial compromise that led to the infection of a 3CX employee workstation. Full Reverse Engineering
2 3CXDesktopApp.exe Legitimate signed application abused to initiate the malicious execution chain. Static Analysis
3 Trojanized ffmpeg.dll First malicious DLL loaded by the application via DLL side-loading. Full Reverse Engineering
4 GitHub Dead Drop Resolver Retrieves the encrypted configuration and C2 information from GitHub. Reverse Engineering
5 VEILEDSIGNAL Primary modular backdoor deployed during the campaign. Full Malware Analysis
6 Campaign IOC Summary Consolidated indicators extracted from every analyzed component. IOC Table
7 MITRE ATT&CK Mapping Complete mapping of the campaign to MITRE ATT&CK techniques. ATT&CK

Phase 0 — Attack Execution Overview

Before analyzing the individual malware components, it is important to understand how they interact throughout the 3CX supply chain attack. Unlike conventional malware campaigns that rely on a single executable, the 3CX attack employed a multi-stage execution chain in which each component was responsible for loading or enabling the next stage.

The attack originated from a previously compromised X_TRADER installation, which provided the attackers with initial access to a 3CX employee's workstation. After compromising the company's CI/CD build environment, Lazarus inserted malicious components into the signed 3CX Desktop Application. When the application was executed, a sequence of malicious DLLs, shellcode, and payloads were loaded, ultimately leading to the deployment of advanced backdoors on selected victim systems.

The following sections analyze each component in the order it executes during the attack.

Phase 1 — X_TRADER Supply Chain

The first stage of the attack begins with the trojanized X_TRADER application, which served as the initial access vector into the 3CX environment. By compromising the software supply chain of X_TRADER, Lazarus Group was able to execute malicious code on a 3CX employee's workstation while the application appeared legitimate.

This initial compromise provided the attackers with a foothold inside the corporate network, allowing them to establish persistence, collect system information, and ultimately obtain access to the 3CX CI/CD build environment. The following analysis examines the malicious X_TRADER sample to identify its execution flow, capabilities, and role in the overall attack chain.

Starting the analysis of X_TRADER

X_TRADER sample static properties

Figure 1: X_TRADER sample static properties

The analyzed sample is a 32-bit Portable Executable (PE32) designed to run on Microsoft Windows. The executable targets the x86 architecture and uses the Windows GUI subsystem, indicating that it is intended to execute as a graphical application rather than a console program.

Compiled using Microsoft VS Code, it only imports four libraries: Kernel32.dll, SHELL32.dll, ole32.dll, OLEAUT32.dll. From these libraries, some of its functionalities can be inferred:

It also has data stored in the resource section with a size of 001e1048.

Moving to IDA to confirm this functionality: uploading the sample to IDA and starting at the WinMain function, the function has only three calls. The program begins execution by calling a function that, based on its return value, decides whether to proceed to the next function or jump to the third.

WinMain control flow in IDA

Figure 2: WinMain control flow in IDA

Entering the first function, sub_401090, the malware begins by allocating and initializing several buffers used throughout the routine. It then retrieves the full path of the running executable and locates the last directory separator ('\') to isolate the installation directory. Using this path, it constructs the full path to X_TRADER-ja.mst.

Next, the malware opens X_TRADER-ja.mst, moves the file pointer to offset 0x167000, and reads the embedded encrypted payload. It then creates a new directory named TPM under C:\ProgramData. After creating the directory, the malware copies immersivetpmvscmgrsvr.exe into the newly created location and renames it to TpmVscMgrSvr.exe. Finally, it creates a new DLL named devobj.dll within the same directory, which is later populated with the decrypted payload extracted from X_TRADER-ja.mst.

Payload staging under C:\ProgramData\TPM

Figure 3: Payload staging under C:\ProgramData\TPM

The malware proceeds to decrypt an embedded payload from X_TRADER-ja.mst into a temporary memory buffer. Once the decryption process is complete, the recovered payload is written to devobj.dll, preparing it for execution in the next stage of the attack.

Payload decryption routine

Figure 4: Payload decryption routine writing devobj.dll

At this point, the first function completes its execution, and control is transferred to the second function, sub_4013C0. The function begins by constructing the full path C:\ProgramData\TPM\TpmVscMgrSvr.exe. It then initializes the COM library and creates an instance of the Task Scheduler COM object using the CLSID {0F87369F-A4E5-4CFC-BD3E-73E6154572DD}, while requesting the ITaskService interface identified by the IID {2FABA4C7-4DA9-4013-9697-20CC3FD40F85} through CoCreateInstance().

Since COM methods are invoked through a virtual function table (vtable), the imported interface can be reconstructed using the ITaskService method offsets shown below. This mapping allows the indirect calls observed during reverse engineering to be resolved to their corresponding COM methods.

OFFSET INDEX METHOD
0x00 0 QueryInterface
0x04 1 AddRef
0x08 2 Release
0x0C 3 GetTypeInfoCount
0x10 4 GetTypeInfo
0x14 5 GetIDsOfNames
0x18 6 Invoke
0x1C 7 GetFolder
0x20 8 GetRunningTasks
0x24 9 NewTask
0x28 10 Connect
0x2C 11 get_Connected
0x30 12 get_TargetServer
0x34 13 get_ConnectedUser
0x38 14 get_ConnectedDomain
0x3C 15 get_HighestVersion
ITaskService COM interface acquisition

Figure 5: ITaskService COM interface acquisition

The malware initializes four empty VARIANT structures using VariantInit(). These VARIANTs are later passed as arguments to the first method retrieved from the ITaskService COM interface. Before the call, the compiler copies each VARIANT onto the stack, after which the malware invokes the function located at offset 0x28 in the ITaskService vtable, corresponding to ITaskService::Connect(). By passing empty VARIANTs, the malware connects to the local Task Scheduler service using the current user's security context without explicitly specifying a server, username, domain, or password.

ITaskService::Connect call with empty VARIANTs

Figure 6: ITaskService::Connect() call with empty VARIANTs

The malware abuses the COM object to establish persistence by creating a scheduled task within the \Microsoft\Windows\TPM folder. It sets the task author to "Microsoft Corporation" to imitate a legitimate Microsoft task and configures an execution action that launches C:\ProgramData\TPM\TpmVscMgrSvr.exe. The task also uses the identifier Tpm-VscMgr, further reinforcing the appearance of a legitimate TPM-related scheduled task.

Task Scheduler

Name:        Tpm-VscMgr
Author:      Microsoft Corporation
Action:      C:\ProgramData\TPM\TpmVscMgrSvr.exe
Scheduled task creation for persistence

Figure 7: Scheduled task creation for persistence

Moving to the third function, the malware begins by searching the resource section for an embedded payload. After locating the appropriate resource, it loads the encrypted data into memory. The malware then retrieves the full path of X_TRADER.exe, opens the executable, and decrypts the embedded payload using the XOR key 0x0DA39F274. The decrypted code is written into the target executable, effectively patching it with the malicious payload extracted from the resource section. Once the modification is complete, the malware executes the newly patched X_TRADER.exe and finally deletes its original executable from disk to remove traces of the initial infection.

XOR decryption and patching of X_TRADER.exe

Figure 8: XOR decryption and patching of X_TRADER.exe, followed by self-deletion

Phase 2 — 3CXDesktopApp.exe

Unlike the previously analyzed X_TRADER sample, 3CXDesktopApp.exe does not contain the primary malicious functionality. Static and dynamic analysis, along with multiple public threat intelligence reports, show that the executable remains a legitimate, digitally signed 3CX application. Its role in the attack is to act as a trusted loader for the malicious components deployed by the attackers.

During startup, the application follows its normal initialization process and loads its required dynamic-link libraries (DLLs). Due to the supply-chain compromise, the legitimate ffmpeg.dll included with the application was replaced with a trojanized version. As a result, when 3CXDesktopApp.exe starts, the Windows loader automatically loads the malicious ffmpeg.dll, transferring execution to the attacker's code while the application continues to function normally from the user's perspective.

Therefore, the analysis of 3CXDesktopApp.exe focuses primarily on its role in initiating the execution chain rather than implementing the malicious logic itself. The actual payload execution begins inside the trojanized ffmpeg.dll, which is analyzed in the next phase.

Phase 3 — Trojanized ffmpeg.dll

Trojanized ffmpeg.dll analysis illustration

Starting the analysis of the trojanized ffmpeg.dll, the DLL was loaded into IDA for static analysis. The entry point contains only a single function call, which immediately transfers execution to the DLL's primary initialization routine. As a result, the remainder of the analysis focuses on this function, where the malicious behavior is implemented.

ffmpeg.dll entry point transferring to initialization routine alt="ffmpeg.dll entry point transferring to initialization routine" />

Figure 9: ffmpeg.dll entry point transferring to initialization routine

Going deeper into the primary initialization routine to determine the purpose of the trojanized ffmpeg.dll, the malware begins by creating a named event called AVMonitorRefreshEvent using CreateEventW(). Immediately afterward, it calls GetLastError() to determine whether the event already exists. If GetLastError() returns ERROR_ALREADY_EXISTS (0xB7), the malware concludes that another instance is already running and terminates its execution. This mechanism acts as a single-instance check, ensuring that only one instance of the DLL executes at a time.

Single-instance check via AVMonitorRefreshEvent

Figure 10: Single-instance check via the AVMonitorRefreshEvent named event

Moreover, the malware retrieves the full path of the running module and locates the last directory separator ('\') to obtain the application's installation directory. It then appends the string d3dcompiler_47.dll to construct the full path to the target DLL. The file is opened using CreateFileW() with GENERIC_READ access, OPEN_EXISTING disposition, and FILE_ATTRIBUTE_NORMAL attributes. The malware then reads the DLL from disk into memory.

Reading d3dcompiler_47.dll into memory

Figure 11: Reading d3dcompiler_47.dll into memory

Afterward, the malware parses the contents of d3dcompiler_47.dll in search of the byte sequence FE ED FA CE, which serves as a marker indicating the beginning of the embedded shellcode. Once this signature is located, the malware extracts the encrypted payload and decrypts it using the RC4 stream cipher with the hardcoded key 3jB(2bsG#@c7. The decrypted shellcode is a downloader that retrieves icon files from a GitHub repository at https://raw.githubusercontent[.]com/IconStorages/images/main/, which are later used to download the final payload.

RC4 decryption of embedded shellcode marked by FE ED FA CE

Figure 12: RC4 decryption of embedded shellcode, marked by the FE ED FA CE signature

Phase 4 — GitHub Dead Drop Resolver

ICO file parsing for embedded C2 configuration

Figure 13: ICO file parsing for embedded, encoded C2 configuration

Each downloaded ICO file contains an embedded, encoded configuration rather than a standard icon resource. The malware parses the files, extracts the hidden data, and decodes it to recover the command-and-control (C2) configuration used by the final-stage payload. This technique enables the attackers to distribute updated C2 information through seemingly benign icon files hosted on remote servers.

ICON FILE URL
icon0.ico https://www.3cx[.]com/blog/event-trainings/
icon1.ico https://msstorageazure[.]com/window
icon2.ico https://officestoragebox[.]com/api/session
icon3.ico https://visualstudiofactory[.]com/workload
icon4.ico https://azuredeploystore[.]com/cloud/services
icon5.ico https://msstorageboxes[.]com/office
icon6.ico https://officeaddons[.]com/technologies
icon7.ico https://sourceslabs[.]com/downloads
icon8.ico https://zacharryblogs[.]com/feed
icon9.ico https://pbxcloudeservices[.]com/phonesystem
icon10.ico https://akamaitechcloudservices[.]com/v2/storage
icon11.ico https://akamaitechcloudservices[.]com/v2/storage
icon12.ico https://azureonlinestorage[.]com/azure/storage
icon13.ico https://msedgepackageinfo[.]com/microsoft-edge
icon14.ico https://glcloudservice[.]com/v1/console
icon15.ico https://pbxsources[.]com/exchange

Phase 5 — VEILEDSIGNAL

Moving to the final phase, VEILEDSIGNAL, the malware begins by retrieving workstation network information using the NetWkstaGetInfo() API, obtaining both the hostname and the domain name. It then loads ntdll.dll and resolves the RtlGetVersion API to retrieve the operating system version. Afterward, the malware obtains the path to the AppData\Roaming directory and appends \3CXDesktopApp\config.json to construct the full path to the configuration file. The malware then opens config.json, reads its contents into memory, and constructs a new JSON object by appending the previously collected system information, including the hostname, domain name, operating system version, and the data from the config.json file.

Collection of host information and config.json contents

Figure 14: Collection of host information and config.json contents into a JSON buffer

The malware targets the browsing history of several Chromium- and Gecko-based web browsers, including Google Chrome, Microsoft Edge, Brave, and Mozilla Firefox. It locates each browser's profile directory and accesses the corresponding history database (History for Chromium-based browsers and places.sqlite for Firefox). The malware then executes SQL queries to retrieve the 500 most recent visited URLs and their associated page titles, appending the extracted information to the in-memory JSON buffer for later use.

Browser history harvesting via SQL queries

Figure 15: Browser history harvesting via SQL queries against History and places.sqlite

3. Campaign IOC Summary

All indicators extracted across every analyzed component of the 3CX supply chain attack.

IOCs — THIS REPORT
TYPE INDICATOR DESCRIPTION CONFIDENCE
SHA256 DDE03348075512796241389DFEA5560C20A3D2A2EAC95C894E7BBED5E85A0ACC 3CXDesktopApp.exe HIGH
SHA256 7290A9AEFBB759C9B40EF8A197CF20FD098FD74DD413C4D9D81E77A31E643F49 Trojanized ffmpeg.dll HIGH
SHA256 11BE1803E2E307B647A8A7E02D128335C448FF741BF06BF52B332E0BBF423B03 Trojanized d3dcompiler_47.dll HIGH
SHA256 8AB3A5EAAF8C296080FADF56B265194681D7DA5DA7C02562953A4CB60E147423 Final-stage payload (VEILEDSIGNAL) HIGH
MD5 00a43d64f9b5187a1e1f922b99b09b77 X_TRADER initial-access sample HIGH
DIRECTORY C:\ProgramData\TPM\ Staging directory created by the first-stage malware MEDIUM
FILE C:\ProgramData\TPM\TpmVscMgrSvr.exe Dropped executable used for persistence MEDIUM
FILE C:\ProgramData\TPM\devobj.dll Decrypted second-stage DLL MEDIUM
FILE X_TRADER-ja.mst Installer transform containing the encrypted payload MEDIUM
FILE %AppData%\3CXDesktopApp\config.json Configuration file read by VEILEDSIGNAL MEDIUM
TASK Tpm-VscMgr Scheduled task created for persistence MEDIUM
EVENT AVMonitorRefreshEvent Named event used as a single-instance check MEDIUM
KEY RC4: 3jB(2bsG#@c7 RC4 key used to decrypt the embedded shellcode MEDIUM
KEY XOR: 0x0DA39F274 XOR key used by X_TRADER to decrypt the embedded DLL MEDIUM
DOMAIN raw.githubusercontent[.]com/IconStorages/images/main/ GitHub dead-drop repository hosting encoded ICO configs HIGH
DOMAIN msstorageazure[.]com icon1.ico dead-drop host MEDIUM
DOMAIN officestoragebox[.]com icon2.ico dead-drop host MEDIUM
DOMAIN visualstudiofactory[.]com icon3.ico dead-drop host MEDIUM
DOMAIN azuredeploystore[.]com icon4.ico dead-drop host MEDIUM
DOMAIN msstorageboxes[.]com icon5.ico dead-drop host MEDIUM
DOMAIN officeaddons[.]com icon6.ico dead-drop host MEDIUM
DOMAIN sourceslabs[.]com icon7.ico dead-drop host MEDIUM
DOMAIN zacharryblogs[.]com icon8.ico dead-drop host MEDIUM
DOMAIN pbxcloudeservices[.]com icon9.ico dead-drop host MEDIUM
DOMAIN akamaitechcloudservices[.]com icon10 / icon11.ico dead-drop host MEDIUM
DOMAIN azureonlinestorage[.]com icon12.ico dead-drop host MEDIUM
DOMAIN msedgepackageinfo[.]com icon13.ico dead-drop host MEDIUM
DOMAIN glcloudservice[.]com icon14.ico dead-drop host MEDIUM
DOMAIN pbxsources[.]com icon15.ico dead-drop host MEDIUM

In addition to the network and host-based indicators above, VEILEDSIGNAL targets the following browser profile paths and databases for history collection:

BROWSER PROFILE PATH DATABASE
Google Chrome AppData\Local\Google\Chrome\User Data History
Microsoft Edge AppData\Local\Microsoft\Edge\User Data History
Brave AppData\Local\BraveSoftware\Brave-Browser\User Data History
Mozilla Firefox AppData\Roaming\Mozilla\Firefox\Profiles places.sqlite
-- Chromium-based browsers
SELECT url, title FROM urls ORDER BY id DESC LIMIT 500

-- Firefox
SELECT url, title FROM moz_places ORDER BY id DESC LIMIT 500

4. MITRE ATT&CK Mapping — Full Campaign

Complete mapping of the 3CX supply chain campaign to MITRE ATT&CK techniques.

TACTIC TECHNIQUE ATT&CK ID EVIDENCE
Initial Access Compromise Software Supply Chain T1195.002 3CX DesktopApp distributed with trojanized DLLs.
Initial Access Trusted Relationship T1199 Attack leveraged the trust relationship between 3CX and its customers.
Execution Shared Modules T1129 3CXDesktopApp.exe loads the trojanized ffmpeg.dll.
Execution User Execution: Malicious File T1204.002 Malware executes when the victim launches the legitimate 3CX DesktopApp.
Execution Command and Scripting Interpreter T1059 Later-stage payloads execute downloaded commands/scripts.
Persistence Scheduled Task/Job: Scheduled Task T1053.005 Creates the Tpm-VscMgr scheduled task.
Persistence DLL Search Order Hijacking T1574.001 Trojanized ffmpeg.dll is loaded by the legitimate application.
Persistence Event Triggered Execution T1546 Persistence established through Task Scheduler.
Privilege Escalation DLL Search Order Hijacking T1574.001 Malicious DLL executes inside a trusted process.
Defense Evasion Deobfuscate/Decode Files or Information T1140 RC4 and XOR decrypt embedded payloads and shellcode.
Defense Evasion Masquerading T1036 Uses legitimate filenames, Microsoft task names, and trusted application components.
Defense Evasion Indicator Removal on Host: File Deletion T1070.004 Initial dropper deletes itself after execution.
Defense Evasion Hide Artifacts T1564 Payloads stored in legitimate-looking locations.
Defense Evasion System Binary Proxy Execution T1218 Abuses Windows Task Scheduler COM interfaces.
Discovery System Information Discovery T1082 Collects operating system version.
Discovery System Owner/User Discovery T1033 Collects hostname and domain/workgroup information.
Discovery File and Directory Discovery T1083 Enumerates browser profile directories and user files.
Collection Data from Local System T1005 Collects browser history and configuration files.
Collection Data from Information Repositories T1213 Reads SQLite browser history databases.
Collection Archive Collected Data T1560 Aggregates collected information into an in-memory JSON buffer.
Credential Access Credentials from Password Stores T1555 Later-stage payloads target browser credentials.
Command and Control Application Layer Protocol: Web Protocols T1071.001 Uses HTTP/HTTPS for C2 communication.
Command and Control Dynamic Resolution T1568 Retrieves encrypted configuration from remote resources.
Command and Control Dead Drop Resolver T1102.001 Uses GitHub and remote ICO files as dead-drop resolvers.
Exfiltration Exfiltration Over Web Service T1567 Sends collected victim information to the C2 infrastructure.

5. Conclusion & Recommendations

The 3CX supply chain attack illustrates how Lazarus Group leverages a chain of trust — compromising one vendor (X_TRADER) to reach another (3CX) — to gain scalable initial access without directly touching the end victim. Because the trojanized components were inserted during the signed build process rather than after distribution, traditional signature and reputation-based trust models failed to flag the malicious DLLs.

References