❌

Normal view

Inside the LiteLLM 1.107.0 supply chain compromise: Credential theft through Python startup hooks

On October 21, 2026, a compromised LiteLLM 1.107.0 release was published to the Python Package Index (PyPI) and distributed through official container images. The malicious package added files that Python could execute during normal interpreter initialization. An application did not need to import LiteLLM for the payload to run: starting Python in an affected environment could be enough.

Microsoft analyzed two execution paths in the affected wheels: a credential collector launched through a path extension, and a Unix-oriented loader persisted through site-specific configuration. The collector targeted authentication material across developer tools, AI applications, cloud environments, browsers, and infrastructure. A separate database module attempted to read selected credential and model-configuration records from the LiteLLM proxy.

Endpoint observations on Windows and macOS matched the recovered collector’s discovery, encryption, and outbound-connection behavior. In one Windows example, a routine Python invocation to install an unrelated dependency activated the collector. This distinction matters for response: investigators should not start Python or pip inside a suspect environment to determine whether the malicious package is present.

This blog explains the startup mechanisms, the credentials the payload could reach, and the evidence defenders can use to investigate exposure. It also provides Microsoft Defender detection information, advanced hunting queries, and recovery guidance. Removing the package or a release tag is not sufficient recovery. Organizations must address the affected Python environment, any surviving processes, and credentials accessible to the compromised identity.

Attack overview

LiteLLM is commonly deployed as a gateway between applications and model providers. In that position it may have access to model-provider API keys, database connection strings, workload identities, routing configuration, and tenant policy data. The same package is also used on developer workstations, build agents, test systems, and containers, which widened the set of environments that could be exposed by the compromised release.

According to LiteLLM maintainers, stolen developer GitHub credentials were used to alter the release workflow and redirect it to the lookalike repository Berri-AI/litellm rather than the legitimate BerriAI/litellm repository. A credential associated with another developer account was then used to satisfy a production approval step. Microsoft has not independently determined how the attacker first accessed the upstream environment or obtained those credentials.

The compromised package used Python startup mechanisms to execute malicious code automatically, meaning exposure was not limited to systems actively using a LiteLLM gateway. Developer workstations, continuous integration and continuous delivery/deployment (CI/CD) agents, test environments, containers, and other systems that started Python with the affected package installed could also execute the payload. The malicious code supported credential collection and, on Unix-based systems, retrieval and execution of additional Python code.

Diagram showing compromised LiteLLM 1.107.0 installing Python startup files that automatically launch a credential collector. Stolen developer, cloud, browser, SSH, environment, and LiteLLM database data is encrypted and sent to an attacker-controlled endpoint. An optional Unix path can retrieve and execute additional Python code; this activity was not confirmed.
Figure 1: Compromised LiteLLM 1.107.0 execution flow.

1. Compromised package distribution

The compromised LiteLLM 1.107.0 release delivered malicious Python startup files to environments where the package was installed.

2. Automatic payload execution

Python startup processing launched the credential collector without requiring the application to actively use LiteLLM gateway functionality.

3. Credential and sensitive-data collection

The collector targeted developer credentials, cloud credentials, browser data, SSH material, environment variables, and LiteLLM database data accessible to the affected process.

4. Encryption and exfiltration

Collected data was encrypted and transmitted to an attacker-controlled endpoint.

5. Conditional retrieval and execution of additional code

On Unix-based systems, the payload supported retrieving and executing additional Python code, although this activity was not confirmed.

Technical details

Compromised package distribution and automatic payload execution

The compromised wheel packaged cook.pth, cook.py, and sitecustomize.py under litellm-1.107.0.data/purelib/. During installation, these files were relocated into the Python environment’s library directory, outside the normal litellm application directory. This placement enabled execution through Python’s normal site initialization, which processes executable import statements in .pth files and later attempts to import the sitecustomize module.

The first execution path began with the single executable line in cook.pth: “import cook”. This loaded cook.py, whose wrapper Base64-decoded and zlib-decompressed an embedded Python program before executing the recovered source. The program identified itself as PRIVCOLLECT and performed credential collection in a daemon thread.

Python code checks the PRIVCOLLECT_ACTIVE flag, then launches the credential collector in a daemon thread or synchronously.
Figure 2. The executable .pth line imports cook, and the recovered collector starts a daemon thread after checking its inherited environment flag.

Before starting the thread, the collector checked the inherited PRIVCOLLECT_ACTIVE environment variable. A nonempty value caused it to return; otherwise, it set the flag, limiting duplicate collection in descendant processes. After an upload returned HTTP 200, it attempted to write /tmp/.pc_once_72129118c59f5636c0bb. These duplicate-suppression gates were not containment controls: startup alone did not prove collection or upload completed, because a short-lived process could exit before the thread finished, while write failures or temporary-storage changes could leave the marker absent.

Python code decodes and executes an embedded Base64- and zlib-encoded payload. The recovered Linux collector configuration specifies an upload endpoint and RSA key, and enables asynchronous collection of system, browser, SSH, shell-history, and cloud-credential data.
Figure 3. Encode Cook.py file and decoded PRIVCOLLECT credential Stealer configuration.

A second startup mechanism used sitecustomize.py, providing a separate Unix-oriented execution path with an embedded collector and functionality to retrieve and execute additional Python code from a remote host. Remote retrieval and execution through this path were not confirmed.

Together, these mechanisms extended potential exposure beyond active LiteLLM deployments: simply starting Python in an affected environment could activate the malicious code, even when LiteLLM itself was never imported. Because the startup files resided outside the litellm application directory, removing only the application files could leave the malicious startup components behind.

Credential and sensitive-data collection

The recovered collector was designed to gather sensitive authentication material across developer tools, AI applications, cloud environments, browsers, and infrastructure. It runs multiple collection modules sequentially with independent error handling, allowing collection to continue even when individual targets are unavailable or inaccessible.

TargetRecovered collection behavior
Developer and AI toolsReads selected authentication and configuration files for AI assistants, integrated development environments (IDEs) , GitHub Copilot, VS Code, and MCP integrations. Collects fixed paths and top-level JSON files in selected tool directories under a collection budget.
Source control and package ecosystemsSearches Git credentials, package-manager configuration, selected dotenv files, and private-key extensions. Shallow directory walks and file-size limits constrain these searches.
Cloud and workload credentialsReads AWS, Azure CLI, and Google Cloud configuration or credential caches; Kubernetes service-account files; Docker configuration; and mounted secrets. It also attempts AWS and GCP metadata credential retrieval.
Browsers and user historiesAccesses Chromium-family and Firefox credential-related data and browsing history, plus shell, database-client, and interactive-tool histories. Password decryption is platform- and format-dependent.
Process environmentsCollects its own environment and, on Linux, other process environments readable through procfs. This can expose secrets beyond variables explicitly configured for the LiteLLM process.
Private keys and infrastructureTargets readable Secure Shell (SSH) material and selected GNU Privacy Guard (GPG), Transport Layor Security (TLS), CI/CD, Vault, and infrastructure-tool configuration. A target appearing in the code does not establish successful access.
LiteLLM proxy dataWhen its prerequisites are satisfied, starts a Python child using Prisma to read selected fields from two proxy database tables, with a 500-row limit for each query

Encryption and exfiltration

After collection, the payload serializes module results and host metadata as JSON. Each run generates a 32-byte AES key and a 16-byte initialization vector. AES-256-CBC encrypts the collection document; an embedded 4,096-bit RSA public key wraps the AES key using OAEP. The OpenSSL path tries SHA-256 and then SHA-1 for OAEP, and the resulting metadata records the selected digest.

Python code encrypts collected data with AES, wraps the key with RSA, packages the results in a gzip archive, and uploads it.
Figure 4. The collector generates a fresh AES key and IV, wraps the key with RSA, and packages the encrypted collection in a gzip tar archive before attempting upload. Selected code excerpts are wrapped for readability.

The collector places three members in a gzip-compressed tar archive: data.bin, containing the initialization vector (IV) and encrypted collection; key.bin, containing the wrapped AES key; and hdr.json, containing plaintext envelope metadata. It then attempts an HTTP POST to hxxp://www[.]litellm[.]dev/healthcheck, using application/octet-stream, a fixed browser-like User-Agent, and a body checksum in an X-SHA256 header. The upload routine retries and treats only HTTP 200 as success.

The OpenSSL backend creates temporary directories beginning with .pc_e_, stages input and output files and removes them after use.

Conditional retrieval and execution of additional code

In addition to the credential collector, the compromised package contained a separate Unix-oriented loader in sitecustomize.py, designed to retrieve and execute additional Python code. When Python starts, the loader takes an exclusive lock on /tmp/remote_code_loader.lock so that only one instance runs per host and detaches into the background. Each cycle reads a GitHub-hosted domain.txt file, which acts as a mutable pointer to an attacker-controlled server.

Figure 5. The remote-loader path checks the pointer and DNS before retrieving code, then compiles and executes the response without a content-signature check.

If a valid server address is returned and successfully resolved, the loader is designed to request /codepy from that server, compile the returned content, and execute it as Python code within the affected environment. This gives the attacker a mechanism to change the second-stage payload without publishing another compromised LiteLLM package. This loader is separate from the credential collector delivered directly in the compromised package.

At the time the cited researchers examined domain.txt, it was empty and no second-stage retrieval or execution was confirmed. Because the file could be changed, the loader remained a re-armable remote-code execution mechanism.

Mitigation and protection guidance

Microsoft recommends the following actions for organizations that installed, mirrored, or built images with LiteLLM 1.107.0:

  • Find and contain every affected copy. Identify LiteLLM 1.107.0 across installed environments, uv and pip caches, internal package mirrors, lock files, build outputs, and container images. Scope mutable container tags and the relevant exposure windows once validated and compare artifacts with the customer-ready hashes in the indicators of compromise section. For background, see secure software supply chain practices and Docker image digests. Digests are preferable to mutable tags because they identify immutable image content.
  • Prevent Python execution and investigate from outside the environment. Isolate affected developer workstations, build agents, test systems, containers, and AI gateway hosts. Where operationally safe, stop running Python processes and prevent automation from restarting them. Do not run python, pip, or other commands that invoke the affected interpreter during evidence collection; inspect the environment with trusted tools from a known-clean system. Python normally processes site configuration, including executable import lines in .pth files, during initialization.
  • Rebuild from verified artifacts. Confirm that cook.pth, cook.py, and sitecustomize.py were removed from the environment library path. Rebuilding is more reliable than assuming that deleting the litellm directory cleaned the top-level startup files.
  • Rotate reachable credentials from a known-clean machine. Include model-provider keys, cloud and workload credentials, CI/CD secrets, source-control and registry tokens, SSH and GPG keys, AI coding-tool tokens, and browser sessions available to the affected identity. On proxy hosts, include stored provider credentials and DATABASE_URL. Revoke affected identity sessions rather than assuming password or key rotation immediately invalidates every active token or application session. See revoke user access in Microsoft Entra ID.
  • Correlate before declaring compromise. Combine file hashes, Python process ancestry, .pc_e_ cryptographic staging, network destination, workload identity, and subsequent cloud or identity use. Do not use package presence or a generic filename as the sole verdict.
  • Restrict outbound access. Developer workstations, build agents, test systems, containers, and AI gateway hosts should not have unrestricted outbound HTTP access unless required. Route outbound traffic through managed egress controls, deny unnecessary destinations, and allowlist required services. See control outbound internet access from Azure.
  • Enable Microsoft Defender for Endpoint protections. Onboard supported developer workstations, build agents, and AI gateway servers to Microsoft Defender for Endpoint, and enable Microsoft Defender Antivirus real-time and cloud-delivered protection where supported. See configure always-on protection and configure cloud protection.

Microsoft Defender XDR detections

As of October 22, 2026, the following Microsoft Defender Antivirus signatures and Microsoft Defender for Endpoint alerts were available for activity associated with the compromised LiteLLM 1.107.0 release. Detection names and availability may change as protection is updated.

Tactic Observed activity Microsoft Defender coverage
Initial Access / ExecutionMalicious components associated with the compromised package are detected and blocked; related suspicious script and network activity is identified across endpoints and cloud workloads.Microsoft Defender Antivirus
– Trojan:PyPI/Stealer.SA
– Trojan:PyPI/LiteLlmSupplyChain.A
– Trojan:PyPI/LiteLlmSupplyChain.B
– Backdoor:PyPI/LiteLlmSupplyChain.C

Microsoft Defender for Endpoint
– Suspicious script launched
– Suspicious network connection observed
Command and Control / Credential AccessCredential-like data is staged by Python and followed by network activity to a public destination, including malicious-domain lookups and OpenSSL activity associated with the compromise.Microsoft Defender for Endpoint
– Possible theft of passwords and other sensitive web browser information
– Suspicious OpenSSL command launch

Microsoft Defender for Cloud
Microsoft Defender for Cloud triggers below detections for related activity in Azure App Service and Kubernetes workloads:

– OpenSSL activity associated with possible LiteLLM compromise detected
– DNS lookup of a known malicious domain
Vulnerability ManagementDevices vulnerable to this security issue are surfaced for remediation.Microsoft Defender Vulnerability Management
– Endpoints exposure tab in the Microsoft Defender portal: TVM-2026-0003

Threat intelligence reports

Microsoft customers can use the following reports in Microsoft products to get the most up-to-date information about the threat actor, malicious activity, and techniques discussed in this blog. This report provides intelligence, protection information, and recommended actions to prevent, mitigate, or respond to associated threats found in customer environments.

Microsoft Defender XDR Threat analytics

Inside the LiteLLM 1.107.0 supply chain compromise: Credential theft through Python startup hooks

Advanced hunting

These queries support investigation of the stages discussed above. Select the appropriate lookback in Defender XDR and correlate results with environment, process and identity evidence. They are investigation leads, not standalone verdicts.

Connections to the collector domain

Normalize URL/hostname observations before matching the campaign domain. The query rejects suffix lookalikes such as www[.]litellm[.]dev[.]example; a match still needs process and workload context.

DeviceNetworkEvents
| extend UrlForParsing = iff(RemoteUrl contains "://",
    RemoteUrl, strcat("http://", RemoteUrl))
| extend RemoteHost = trim_end(@"\.",
    tolower(tostring(parse_url(UrlForParsing).Host)))
| where RemoteHost in ("www.litellm.dev", "litellm.dev")
| project Timestamp, DeviceId, DeviceName, ActionType,
    RemoteUrl, RemoteIP, RemotePort, InitiatingProcessFileName,
    InitiatingProcessId, InitiatingProcessCreationTime, ReportId

Known startup-file hashes

The four hashes cover LF and CRLF variants. A missing SHA-256 field limits this hunt; a generic filename is not an equivalent match.

DeviceFileEvents
| where SHA256 in~ (
    "9dd0a3926f96a37eb86cf1ee2310d9be93139cc4ebef3ef9e2efe9531390be25",
    "03ac2a8b752605d1d7710979c17ff18b03dd978203ba23ba97fd8ce3d6f897ea",
    "34bef04fe88ac9d0aae0475630b1738681d15b94f233ac8aa46eacf5968305fa",
    "b6122440d0d9cb1eb1ade9933f49214da8c31288de7710c076c2680dfa528465",
    "7f191632e7320705d154b85204f1ae546b543acbd7e8861229b76f5042b92bdb",
    "84dc8c82c0a4a4a62552ef826b49fcc86d1a5c4a5d0f2c06665723f93d129d7d")
| project Timestamp, DeviceId, DeviceName, ActionType,
    FileName, FolderPath, SHA256, InitiatingProcessFileName,
    InitiatingProcessId, InitiatingProcessCreationTime, ReportId

Inline database-collection program

Look for the sensitive table/field pair together with the query API, serialization and complete output-suppression pattern. Legitimate exports may overlap. The recovered parent’s /proc prerequisite limits its applicability; raw arguments are omitted because they can contain a database secret.

DeviceProcessEvents
| where FileName startswith "python" or FileName startswith "platform-python"
| where strlen(ProcessCommandLine) 

Collector-like encryption staging

The staging prefix plus encryption operation identifies a behavioral lead, not an upload or a uniquely malicious OpenSSL invocation. Alternate backends are outside this query, and key-bearing arguments are not projected.

DeviceProcessEvents
| where FileName in~ ("openssl", "openssl.exe")
| where ProcessCommandLine contains_cs ".pc_e_"
| where (ProcessCommandLine contains_cs " enc "
        and ProcessCommandLine contains_cs "-aes-256-cbc")
    or ProcessCommandLine contains_cs " pkeyutl "
    or ProcessCommandLine contains_cs " rsautl "
| extend CryptoOperation = iff(
    ProcessCommandLine contains_cs " enc ", "AES packaging", "RSA wrapping")
| project Timestamp, DeviceId, DeviceName, FileName, CryptoOperation,
    ProcessId, ProcessCreationTime, InitiatingProcessFileName,
    InitiatingProcessId, InitiatingProcessCreationTime, ReportId

Vulnerability/Posture Check | Is the device potentially exposed to the affected Litellm?

Use this query to identify devices potentially exposed to TVM-2026-0003. A match indicates potential exposure, not confirmed exploitation or compromise.

DeviceTvmSoftwareVulnerabilities
| where CveId == "TVM-2026-0003"

CloudProcessEvents query to detect encryption before exfiltration

Identifies OpenSSL public-key encryption using /tmp/.pc_ staging paths, consistent with key wrapping before potential exfiltration.

CloudProcessEvents
| where ProcessName == 'openssl' and ProcessCurrentWorkingDirectory has_any ('/runner/','/app','/tmp/')
    and ProcessCommandLine has_all ('pkeyutl','-encrypt','-pubin') and ProcessCommandLine contains '/tmp/.pc_'

MITRE ATT&CK techniques observed

Microsoft mapped the following techniques based on observed activity and analysis of the recovered malicious components; individual entries note where behavior was not confirmed. For standard industry documentation, refer to the MITRE ATT&CK framework.

Initial Access

Persistence

Execution

Defense Evasion

Credential Access

Discovery

Collection

Command and Control

Indicators of compromise

URLs are defanged. Use precise roles and context rather than blocking shared infrastructure indiscriminately.

IndicatorTypeRole
www[.]litellm[.]devDomainExfiltration Domain
hxxp://www[.]litellm[.]dev/healthcheckURLExfiltration URL
hxxps://raw[.]githubusercontent[.]com/letters9813/pythonclient-test/main/domain.txtURLC2 dead-drop URL
9dd0a3926f96a37eb86cf1ee2310d9be93139cc4ebef3ef9e2efe9531390be25SHA-256cook.py, variant
03ac2a8b752605d1d7710979c17ff18b03dd978203ba23ba97fd8ce3d6f897eaSHA-256cook.py, Windows wheel variant
34bef04fe88ac9d0aae0475630b1738681d15b94f233ac8aa46eacf5968305faSHA-256sitecustomize.py, variant
b6122440d0d9cb1eb1ade9933f49214da8c31288de7710c076c2680dfa528465SHA-256sitecustomize.py, Windows wheel variant
7f191632e7320705d154b85204f1ae546b543acbd7e8861229b76f5042b92bdbSHA-256cook.pth
84dc8c82c0a4a4a62552ef826b49fcc86d1a5c4a5d0f2c06665723f93d129d7dSHA-256cook.pth, variant
/tmp/remote_code_loader.lockfileLock file created by the background loader.
/tmp/.pc_once_72129118c59f5636c0bbfileMarker written after stolen data was sent.
7598727f209d717041db37f7dca271d3a7d328a279890e0e1d55375729aeb86dSHA-256litellm-1.107.0-cp310-abi3-macosx_10_12_x86_64.whl
0aaf7ba346d41ef2f40390436738b001180d5a1c03aa093f121078a9969d9a1aSHA-256litellm-1.107.0-cp310-abi3-macosx_11_0_arm64.whl
668169d35b87bf51324080390b1b1c5ab12bd335cfe5f1a99e3689abd5e02ae6SHA-256litellm-1.107.0-cp310-abi3-manylinux_2_28_aarch64.whl
462d0c9f67ca522d9e0e4acd245e90b36ce0d5353604a66bb7c43a1ec4a6fcf7SHA-256litellm-1.107.0-cp310-abi3-manylinux_2_28_x86_64.whl
c2e32d0ce2548aa662c18bf5001911a79fe5b30cf8357132275add02fdcde054SHA-256litellm-1.107.0-cp310-abi3-musllinux_1_2_aarch64.whl
1bbce8caa94f01c0aaa0b7ddae51553a8a32e1ce53d96d44fe583272aff7ad00SHA-256litellm-1.107.0-cp310-abi3-musllinux_1_2_x86_64.whl
12d4ccc5c6f8d35cf4f2cf233b7f3e418e863e657d81ff5f5fc9e210005b9484SHA-256litellm-1.107.0-cp310-abi3-win_amd64.whl

References

Learn More

For the latest security research from the Microsoft Threat Intelligence community, check out the Microsoft Threat Intelligence Blog.

To get notified about new publications and to join discussions on social media, follow us on LinkedIn, X (formerly Twitter), and Bluesky.

To hear stories and insights from the Microsoft Threat Intelligence community about the ever-evolving threat landscape, listen to the Microsoft Threat Intelligence podcast.

Review our documentation to learn more about our real-time protection capabilities and see how to enable them within your organization.  

The post Inside the LiteLLM 1.107.0 supply chain compromise: Credential theft through Python startup hooks appeared first on Microsoft Security Blog.

Impersonating IT support: how threat actors turn a remote session into enterprise-wide access

Microsoft Threat Intelligence has observed a human-operated intrusion campaign that abuses Microsoft Teams external collaboration to impersonate IT or helpdesk personnel and socially engineer users into granting an interactive remote session. Once remote control is established via RMM tools, the threat actor uses PowerShell to download and silently install a malicious MSI package, which in turn stages a portable Node.js runtime and an obfuscated JavaScript implant that provides persistent command execution and command and control (C2).

Unlike commodity phishing that ends with an infostealer, this campaign follows a full hands-on-keyboard playbook. After the implant is deployed, the threat actor performs extensive host and Active Directory reconnaissance, periodically captures screenshots of the victim’s desktop, executes follow-on payloads through trusted Windows binaries, and pivots across the enterprise over Windows Remote Management (WinRM) toward high-value assets such as domain controllers. The intrusion relies heavily on legitimate tooling, including Microsoft Teams, remote support software, Windows Installer, Node.js, and native administrative protocols, allowing the activity to blend into expected enterprise operations at nearly every stage.

This intrusion pattern is especially high-impact because it hands an external operator credential-backed, interactive access to internal infrastructure. The reconnaissance and lateral movement patterns observed: domain enumeration, server discovery, and WinRM pivoting toward identity systems, are consistent with intrusion activity that can precede data theft, extortion, ransomware deployment, or other follow-on objectives, in which threat actors map the environment, escalate privileges, disable security controls, exfiltrate business-relevant data, and ultimately deploy ransomware across the organization.

In this blog, we share our analysis of this attack chain, from initial Microsoft Teams contact through internal lateral movement, along with mitigation and hunting guidance to help defenders detect and disrupt this user-initiated access pathway before it escalates into broader compromise.

Risk to enterprise environments

By abusing enterprise collaboration workflows instead of traditional email-based phishing, the threat actor initiates contact through Microsoft Teams in a way that appears consistent with routine IT support. Microsoft Teams applies multiple security controls at the point of first external contact, including external tenant labeling, Accept/Block prompts, message previews, and phishing indicators, but this attack chain depends on convincing the user to bypass those warnings and voluntarily grant remote access through legitimate support tools.

An approved external Teams interaction, followed by a remote session, can enable the threat actor to:

  • Establish interactive, credential-backed system access through a legitimate remote support tool.
  • Execute threat actor-controlled code (MSI loader and Node.js implant) using trusted installers and runtimes.
  • Map the host and Active Directory environment through automated discovery
  • Move laterally toward high-value infrastructure using WinRM.
  • Capture on-screen activity and create opportunities for follow-on data access or other post-compromise actions.

Attack chain overview

The campaign follows a multi-stage attack chain that progresses from social engineering through payload delivery, execution, reconnaissance, and ultimately lateral movement:

  1. Initial access via Teams (T1566.003): A threat actor operating from an external tenant initiates a Teams chat or call while impersonating IT/helpdesk staff and coaxes the user into handing over their device, for example, approving a “request control” prompt during a Teams screen-share, or opening Quick Assist and reading back the connection code.
  2. Remote session and MSI delivery: During the remote session, the threat actor runs PowerShell to download a malicious MSI from cloud storage and installs it silently with msiexec.
  1. Node.js runtime and implant staging: The MSI installs a script-based loader and a separate encrypted implant file under LocalAppData. If Node.js is not already available, the bootstrap downloads the legitimate portable Node.js runtime from the official distribution. The loader decrypts the implant at runtime, either in memory or into a temporary JavaScript file.
  2. Script-based bootstrap and Node.js execution:The MSI launches hidden bootstrap code through trusted Windows script hosts, including PowerShell, cmd.exe, and WScript. The bootstrap obtains a portable Node.js runtime and uses it to decrypt and execute the JavaScript implant from a user-writable directory.
  3. Command-and-control and operator tasking:The implant uses randomized HTTPS polling to receive JavaScript tasks from its C2 server. Observed operator-issued tasking performed host reconnaissance, security-product and virtualization discovery, and periodic desktop screen capture.
  4. Domain discovery: The operator enumerates domain accounts, servers, and users through native tools and Active Directory Service Interfaces (ADSI) queries.
  5. Follow-on payload execution: Additional payloads are executed through rundll32 loading threat actor-supplied DLLs.
  6. Lateral movement via WinRM:Operator-issued tasking executed through the Node.js backdoor initiates WinRM connections over TCP port 5985 to domain-joined systems, including domain controllers and certificate authorities.
Figure 1. Teams phishing intrusion attack chain overview.

Stage 1: Initial contact via Teams (T1566.003 Spearphishing via Service)

The intrusion begins with abuse of external collaboration features in Microsoft Teams, where a threat actor operating from a separate tenant initiates contact while impersonating internal IT or helpdesk personnel. This activity does not stem from a weakness in Microsoft Teams or its built-in protections; instead, the threat actor abuses legitimate collaboration features by persuading the user to override clearly presented security warnings, highlighting the broader challenge of defending against social engineering rather than technical exploitation.

Because interaction occurs within an enterprise collaboration platform rather than through traditional email, it could bypass the initial skepticism associated with unsolicited external communication. The lure varies, for example “Microsoft Security Update,” “Spam Filter Update,” “Account Verification,” or tasks required to stop deactivation of an account, but the objective is consistent: convince the user to ignore external-contact flags, launch a remote management session, and accept elevation. Voice phishing (vishing) is sometimes layered to increase trust or compliance, or so malicious instructions or URLs never enter the chat logs.

Figure 2. External Teams contact impersonating IT support.

With user consent obtained through social engineering, the threat actor gains interactive control of the device using a remote support tool. From the user’s perspective, they are guided to open the remote-assistance application, enter a short key, and follow prompts to grant access.

Figure 3. Quick Assist with security code.

The urgency and interactivity are the signal: a remote-assist process tree followed immediately by cmd.exe or PowerShell on the same desktop. In vishing scenarios, the threat actor might talk the victim through the process to prevent logging of malicious instructions.

Stage 2: Remote session and malicious MSI delivery

Immediately after establishing control, the threat actor uses PowerShell within the remote session to download a malicious MSI package from threat actor-controlled cloud storage and installs it silently. The installer is disguised with benign, update-themed names such as “devfix” or “Hotfix,” reinforcing the helpdesk pretext.

The payload is hosted on a widely used cloud storage platform, allowing the download to blend in with legitimate traffic and benefit from a trusted domain reputation. The /qn switch suppresses all installer UI so the victim sees no indication that software is being installed.

Stage 3: MSI staging and Node.js runtime acquisition

Upon installation, the MSI retrieves a portable Node.js runtime directly from the official Node.js distribution and extracts it into a randomly named directory under the user’s local application data. Downloading a legitimate, signed runtime from a trusted source lets the threat actor run a full JavaScript execution environment without deploying custom binaries that might attract scrutiny.

The MSI installs a script-based loader and a separate encrypted implant file in the current user’s LocalAppData directory. The encrypted implant is packaged within the MSI rather than downloaded separately. At runtime, the loader decrypts the JavaScript implant either in memory or into a temporary JavaScript file. This separation of a legitimate runtime from the malicious script allows the initial backdoor to execute as interpreted JavaScript while additional native payloads can be delivered later through operator tasking.

Stage 4: Script-based bootstrap and encrypted implant execution

The MSI schedules a deferred, asynchronous custom action immediately after installing its files. The action starts hidden bootstrap code through PowerShell, cmd.exe, or WScript and then launches Node.js from LocalAppData. The loader decrypts a separate high-entropy data file and executes the resulting JavaScript either through standard input or by loading a temporary JavaScript file.

Endpoint activity shows Node.js, or a renamed copy whose original file metadata identifies it as Node.js, executing a staged script loader from LocalAppData. The loaders and encrypted payload files use nonstandard extensions such as .tmp, .ini, .dat, .bin, or .cfg. After decrypting the payload, the loader either provides JavaScript to Node.js through standard input or writes a temporary .js file and loads it into the running Node process.

By using a signed Node.js runtime, including renamed copies of the runtime, to execute nonstandard-extension loaders or JavaScript supplied through standard input, the threat actor can evade controls focused only on unsigned executables and conventional script extensions.

Stage 5: Per-user persistence

The analyzed MSI packages established per-user persistence using update-themed entries. Observed installers created either an HKEY_CURRENT_USER Run value or a shortcut in the current user’s Startup folder. Both mechanisms used the name EdgeUpdate and launched a Node.js loader from LocalAppData when the user signed in.

The Startup-folder implementation launched WScript with the staged JScript wrapper, portable Node.js runtime, and nonstandard-extension loader. The Run-key implementation invoked the portable Node.js runtime directly.

Stage 6: Command-and-control and operator tasking

Once running, the implant establishes communication with its C2 server and begins receiving JavaScript tasking. Observed threat actor issued tasks launched short-lived cmd.exe and PowerShell processes to perform a burst of host reconnaissance, hardware and locale details, installed antivirus products, and disk information.

The querying of the display adapter name and installed antivirus is characteristic of sandbox and defense evasion checks. Generic virtual display adapters and analysis tooling are common tells of an automated analysis environment.

The recovered implant communicates through randomized HTTPS long-polling requests. Responses from the C2 server are treated as JavaScript source and executed dynamically with access to Node.js module loading, process execution, environment variables, buffers, and the file system.

Through JavaScript tasking delivered by the C2 server, operators repeatedly captured the victim’s screen, resized the image, encoded it as Base64, and wrote it to a temporary file before exfiltration. Screenshots are captured at varying scale factors to balance image quality against transfer size.

Representative screen-capture command (sanitized).

Dormant blockchain-based C2 discovery

The analyzed implants also contained dormant logic capable of querying an Ethereum smart contract for an updated C2 URL. This functionality was disabled in the recovered builds, which instead used a hard-coded fallback server. The contract stores only a URL string and does not contain or execute the malware payload.

Stage 7: Domain discovery and reconnaissance

With a foothold validated, the operator uses C2-delivered tasking to expand reconnaissance into Active Directory. Native commands enumerate specific domain accounts, while ADSI searches identify domain-joined servers and collect user description attributes, which can contain operational notes, privileged-account context, or other sensitive information.

An ADSI-based sweep enumerates Windows Server computer objects, resolves their addresses, and probes each for administrative reachability, effectively building a live map of high-value targets:

A second ADSI query enumerates all user objects and their description attributes:

The use of randomized sleep jitter and CIM-based reachability checks indicates a deliberate, operator-driven effort to enumerate the domain quietly rather than through noisy, high-volume scanning.

Stage 8: Follow-on payload execution

Using commands delivered through the Node.js backdoor, the operator executes additional payloads through rundll32.exe, loading threat actor-supplied DLLs by invoking exported functions with a token argument. Using rundll32 to execute malicious DLL exports is a well-established defense-evasion and proxy-execution technique.

The DLLs are given short, innocuous names and are invoked with an exported function (open) and a per-execution token, consistent with modular loaders that gate execution behind a runtime-supplied key.

Stage 9: Lateral movement via WinRM toward high-value assets

Following local execution and discovery, operator-issued tasking executed through the Node.js backdoor initiated internal remote-management connections over WinRM on TCP port 5985 to a large set of domain-joined systems. The target list spans dozens of hosts across multiple regions and roles, including file servers, database and application servers, and, critically, domain controllers and certificate authorities.

The use of WinRM from a non-administrative application context strongly suggests credential-backed lateral movement directed by an external operator. Targeting identity-centric infrastructure, domain controllers and certificate authorities, at this stage reflects a shift from initial foothold toward broader enterprise control, and is a hallmark of intrusions that precede large-scale data theft or ransomware deployment.

Mitigation and response recommendations

This campaign relies less on platform exploitation and more on persuading users to initiate trusted remote-access workflows within legitimate collaboration tools. Organizations should treat any unsolicited external support contact as inherently suspicious and implement layered defenses across the identity, endpoint, and collaboration layers.

  • Reinforce user education. Establish internal helpdesk authentication phrases and train employees to recognize external-tenant indicators and to never grant remote access or run commands provided by an unsolicited contact.
  • Verify unsolicited support contact. Treat any unsolicited external Microsoft Teams chat or call claiming to be IT or helpdesk as suspicious, and verify the request through a known internal channel before granting remote access. Restrict Teams external access to trusted domains only.
  • Harden Microsoft Teams and email against social engineering. Use Microsoft Defender for Office 365 with Safe Links and Zero-hour auto purge (ZAP) so malicious messages and URLs are neutralized at time of click and removed after delivery.
  • Microsoft Teams: Apply the Security best practices for Microsoft Teams, revisit your external collaboration policies, and make sure users see clear external sender notifications when engaging with cross-tenant contacts. Require device- or identity-based access checks before any remote support session is granted.
  • Enforce phishing-resistant access controls. Require MFA and compliant or managed devices through Microsoft Entra Conditional Access to limit the value of credential-backed remote sessions established through social engineering.
  • Deploy attack surface reduction rules. Enable ASR rules that block executable content from email and scripting interpreters, process creation from PowerShell/WScript/cmd, and execution of downloaded content to disrupt MSI- and script-based staging.
  • Restrict administrative protocols. Limit WinRM (TCP 5985) to authorized management workstations and alert on WinRM initiated from user-context or non-administrative processes.
  • Turn on network and web protection. Enable network protection and web protection in Microsoft Defender for Endpoint to block connections to threat actor infrastructure and cloud-hosted staging endpoints used for payload delivery and C2.
  • Enable cloud-delivered protection. Turn on cloud-delivered protection in Microsoft Defender Antivirus to cover rapidly evolving threat actor tooling; cloud-based machine learning helps detect and block newly observed threats.
  • Control remote support tooling. Limit or monitor remote monitoring and management (RMM) and interactive remote-support software, and control which remote-assistance tools are permitted in the environment.
  • Investigate and rotate credentials. Organizations that find indicators of this campaign should assume the operator obtained network-level access through the compromised host and prioritize credential rotation for any credentials accessible from the affected machine, including domain admin accounts if the host was domain-joined.

Microsoft Defender XDR detections

Microsoft Defender XDR coordinates detection, prevention, investigation, and response across endpoints, identities, email, and apps. The representative alerts below can surface activity associated with this campaign. Alert titles are illustrative and may vary by environment and product version.

Tactic Observed activity Microsoft Defender coverage
Initial access External Teams chat or call from an IT/helpdesk persona operating in a separate tenant Microsoft Defender for Cloud Applications / Office 365
– Microsoft Teams chat initiated by a suspicious external user
– IT Support Teams Voice phishing following mail bombing activity
– A user clicked through to a potentially malicious URL.
– A potentially malicious URL click was detected.
– Suspicious Teams Chat likely involved in remote management and dangerous commands

Microsoft Defender for Endpoint
– Possible initial access from an emerging threat
Execution PowerShell downloads and silently installs an MSI Microsoft Defender Antivirus
– Trojan:PowerShell/PowExec.MX!MTB
– Trojan:Win32/FakeAll!MTB
– Trojan:JS/FakeAll.DA!MTB
– Trojan:JS/FakeAll.DB!MTB

Microsoft Defender for Endpoint
– Possible initial access from an emerging threat
Execution Portable Node.js runtime executes an obfuscated loader from LocalAppData; observed execution includes WScript, nonstandard script extensions, renamed Node.js copies, and standard-input execution. Microsoft Defender Antivirus
– Trojan:JS/SynkLoader.SA
– Trojan:JS/EtherRatz.A!MTB
– Trojan:JS/EtherRatz.B!MTB

Microsoft Defender for Endpoint
– Suspicious Node.js process behavior
– Suspicious JavaScript process
Defense evasion Silent msiexec install and rundll32 loading threat actor-supplied DLLs Microsoft Defender Antivirus
– Trojan:Win32/SynkLoader.SA

Microsoft Defender for Endpoint
– Low-reputation arbitrary code executed by signed executable
– Suspicious process launch by Rundll32.exe
Discovery WMI/ADSI host and Active Directory enumeration and periodic screen capture Microsoft Defender for Endpoint
– Suspicious screen capture activity
– Suspicious LDAP query
– Suspicious Active Directory enumeration
– Possible hands-on-keyboard pre-ransom activity
– Anomalous account lookups
– Possible hands-on-keyboard pre-ransom activity
Lateral movement WinRM (TCP 5985) pivot toward domain controllers and certificate authorities Microsoft Defender for Endpoint
– Suspicious WinRM activity was observed

Microsoft Security Copilot

Security Copilot customers can use the standalone experience to create their own prompts or run prebuilt promptbooks to automate investigation and response tasks related to this threat. Useful promptbooks for this activity include Incident investigation, Microsoft User analysis, Threat actor profile, Threat intelligence 360 report, and Vulnerability impact assessment. Some promptbooks require access to Microsoft Defender XDR, Microsoft Sentinel, or related Microsoft security plugins.

For this campaign, Security Copilot can help analysts summarize affected devices where Node.js or a renamed Node.js runtime executed a staged loader from a user-writable path, reconstruct the Teams-to-remote-session-to-MSI delivery chain, and build containment and credential-rotation plans for affected domain-joined endpoints.

Threat intelligence reports

Microsoft customers can use Microsoft Defender XDR Threat Analytics and related Microsoft threat intelligence reporting to stay current on the malicious activity, indicators, detection coverage, and recommended response actions associated with this campaign.

For campaign-specific intelligence, see Threat Analytics: Teams-based helpdesk impersonation delivers MSI loader and Node.js implant for hands-on-keyboard intrusion (View report). These reports provide investigation context, protection guidance, and updated intelligence that security teams can use to prevent, mitigate, or respond to related activity in their environments.

Advanced hunting queries

Microsoft Defender XDR customers can run the following advanced hunting queries to locate related activity. Tune time windows, tool lists, and filters for your environment.

External Teams activity

Sender, Recipient, and ThreadId can be used for pivoting other useful information. CloudAppEvents is useful for searching first contact information.

CloudAppEvents
| where Timestamp > ago(7d)
// optional time filters between ([_startTime] .. [_endTime])
| where Application == "Microsoft Teams"
| where ActionType == "ChatCreated"
| where IsExternalUser == true
| extend ThreadCreatorUpn = tostring(RawEventData.Members[0].UPN)
    ,ThreadCreatorDisplayName = tostring(RawEventData.Members[0].DisplayName)
    ,ThreadCreatorOrganizationId = tostring(RawEventData.Members[0].OrganizationId)
    ,TRecipient1Upn = tostring(RawEventData.Members[1].UPN)
    ,Recipient1DisplayName = tostring(RawEventData.Members[1].DisplayName)
    ,Recipient1OrganizationId = tostring(RawEventData.Members[1].OrganizationId)
    ,Recipient2Upn = tostring(RawEventData.Members[2].UPN)
    ,Recipient2DisplayName = tostring(RawEventData.Members[2].DisplayName)
    ,Recipient2OrganizationId = tostring(RawEventData.Members[2].OrganizationId)
    ,ThreadId = tostring(RawEventData.ChatThreadId)
| summarize by ThreadCreatorUpn, ThreadCreatorDisplayName, ThreadCreatorOrganizationId,
    TRecipient1Upn, Recipient1DisplayName, Recipient1OrganizationId,
    Recipient2Upn, Recipient2DisplayName, Recipient2OrganizationId,
    ThreadId, tostring(IsExternalUser), tostring(IsImpersonated)

MessageEvents, CallActivityEvents, MessageUrlInfo, and others can be searched alone or in a union to correlate threads with messages and calls.

let _threadIds = pack_array(
      "19:[thread]",
      "19:[thread]",
      "19:[thread]");
union
    MessageEvents,
    CallActivityEvents,
    MessageUrlInfo
    | where ThreadId in (_threadIds)
       or TeamsMessageId has_any (_threadIds)
    | sort by ThreadId, TeamsMessageId asc

PowerShell writing an MSI to a user-writable path

DeviceFileEvents 
| where Timestamp > ago(7d) 
| where InitiatingProcessParentFileName =~ "explorer.exe" 
| where InitiatingProcessFileName =~ "powershell.exe" 
| where FileName endswith ".msi" 
 where
    FolderPath contains @"\Downloads\"
    or FolderPath contains @"\AppData\"
    or FolderPath contains @"\Temp\"

node.exe executing a staged payload from user-writable paths

DeviceProcessEvents 
| where Timestamp > ago(7d) 
| where FileName =~ "node.exe" 
| where ProcessCommandLine has @"\AppData\Local\" and ProcessCommandLine !contains ".js" 
| where InitiatingProcessFileName =~ "wscript.exe" 
| where InitiatingProcessCommandLine has_all (@"\AppData\Local\", "node.exe", ".js") 

Screen capture via hidden PowerShell writing Base64 to a temp file

DeviceProcessEvents 
| where Timestamp > ago(7d) 
| where InitiatingProcessParentFileName =~ "node.exe" or InitiatingProcessFileName =~ "node.exe" 
| where FileName in~ ("powershell.exe", "cmd.exe") 
| where ProcessCommandLine has_all ("CopyFromScreen", "ToBase64String", "System.Drawing.Bitmap", "System.Drawing", "WriteAllText") 
| project Timestamp, DeviceName, AccountName, ProcessCommandLine 
| order by Timestamp desc 

WinRM lateral movement from a non-administrative process

DeviceNetworkEvents 
| where Timestamp > ago(7d) 
| where InitiatingProcessFileName =~ "powershell.exe" 
| where InitiatingProcessCommandLine endswith "-NoLogo -NoProfile -ExecutionPolicy Bypass" 
| where RemoteUrl endswith ":5985/wsman" 

MITRE ATT&CK Techniques observed

The following table maps the observed activity to MITRE ATT&CK techniques:

Tactic Technique ID Technique Observed activity
Initial Access T1566.003 Phishing: Spearphishing via Service External Teams chat/call impersonating IT helpdesk
Execution T1059.001 Command and Scripting Interpreter: PowerShell PowerShell used to download and install the MSI
Execution T1059.007 Command and Scripting Interpreter: JavaScript Malicious JavaScript implant run via node.exe
Execution T1218.007 System Binary Proxy Execution: Msiexec Silent MSI installation via msiexec /qn
Execution T1218.011 System Binary Proxy Execution: Rundll32 Follow-on DLL payloads executed via rundll32
Defense Evasion T1036 Masquerading Update/helpdesk-themed MSI names (devfix, Hotfix)
Defense Evasion T1497.001 Virtualization/Sandbox Evasion: System Checks Display adapter and antivirus product queries
Discovery T1082 System Information Discovery systeminfo, MachineGuid, ProductName, disk inventory
Discovery T1016 System Network Configuration Discovery net session, net use, domain membership checks
Discovery T1087.002 Account Discovery: Domain Account net user /domain and ADSI user enumeration
Discovery T1018 Remote System Discovery ADSI server enumeration with reachability probing
Discovery T1518.001 Security Software Discovery Antivirus product enumeration via SecurityCenter2
Collection T1113 Screen Capture Periodic Base64-encoded desktop screenshots
Command and Control T1071.001 Application Layer Protocol: Web Protocols Randomized HTTPS long-polling used for core C2; separate post-compromise tasking installed the ws package for an additional or optional capability.
Command and Control T1105 Ingress Tool Transfer Portable Node.js runtime downloaded and JavaScript tasks received from C2; the initial loader and encrypted implant are extracted from the MSI.
Lateral Movement T1021.006 Remote Services: Windows Remote Management WinRM (5985) pivoting to domain-joined systems

Indicators of Compromise (IOCs)

The following indicator types were observed in this campaign. Environment-specific values (paths, hostnames, and account names) have been generalized; defenders should hunt for the corresponding behaviors and patterns in their own telemetry.

File indicators

Indicator (SHA-256) Description
4cfdcae6dd1d6d98b870c8f0654d504f2bf10479a117dc297de789c249dc389d Malicious MSI loader package (silent msiexec install)
a4d145a6347e47d40b3ca48af5c6dba01bf019d0110e31a44bb70fc77d1d1676 Malicious MSI loader package
cc6d0f3f47afeba018173604e34f527e8413d3a54ffb35caed529bff49055ec5 Malicious MSI loader package
0d2fc28af246f62f27e49207d1f64e236ad9ea029412b27877d1ae6c098e86e3 Second-stage DLL (rundll32-loaded module)
69e10e0cb7bb2137ebea12971adb02c662cf5543a4f8c9530812bcbf7b183a23 Second-stage DLL (rundll32-loaded module)
a135fe4df18c711097e69b4f27ea32a74a955160bf2fb12da841f21866d95d87 Second-stage DLL (rundll32-loaded module)

Payload delivery infrastructure

Indicator Type Description
update1n5[.]blob.core.windows.net Domain Azure Blob Storage endpoint hosting the malicious MSI loader
update1n6[.]blob.core.windows.net Domain Azure Blob Storage endpoint hosting the malicious MSI loader
update1n7[.]blob.core.windows.net Domain Azure Blob Storage endpoint hosting the malicious MSI loader
update1n9[.]blob.core.windows.net Domain Azure Blob Storage endpoint hosting the malicious MSI loader
updatetmp[.]blob.core.windows.net Domain Azure Blob Storage endpoint hosting the malicious MSI loader

Command-and-control infrastructure

Indicator Type Description
synctimes[.]australiaeast[.]cloudapp[.]azure[.]comDomain Hardcoded fallback C2 and latest URL stored in the associated Ethereum contract
webwether[.]eastus[.]cloudapp[.]azure[.]com Domain Earlier URL stored in the Ethereum contract
dssdfvsdfvsdfvsdgbfbdvdzv[.]org Domain Earlier URL stored briefly in the Ethereum contract

Learn more

For the latest security research from the Microsoft Threat Intelligence community, check out the Microsoft Threat Intelligence Blog.

To get notified about new publications and to join discussions on social media, follow us on LinkedIn, X (formerly Twitter), and Bluesky.

To hear stories and insights from the Microsoft Threat Intelligence community about the ever-evolving threat landscape, listen to the Microsoft Threat Intelligence podcast.

Review our documentation to learn more about our real-time protection capabilities and see how to enable them within your organization.  

The post Impersonating IT support: how threat actors turn a remote session into enterprise-wide access appeared first on Microsoft Security Blog.

TerminalFix campaign deploys a reverse tunnel through multistage intrusion

Microsoft Threat Intelligence has observed a TerminalFix campaign, a variant of ClickFix, targeting organizations across multiple industries. The campaign uses compromised websites to display a fake Cloudflare CAPTCHA verification overlay that tricks users into copying and executing a malicious PowerShell command. While traditional ClickFix campaigns direct victims to the Windows Run dialog, TerminalFix campaigns apply the same technique but direct users to Windows Terminal or PowerShell instead, increasing the likelihood that complex, multi-line scripts execute successfully. Unlike earlier ClickFix variants that typically deliver a single infostealer, this TerminalFix campaign deploys a sophisticated multi-stage attack chain that combines DLL sideloading, steganographic payload extraction, extensive Active Directory reconnaissance, and a custom reverse-tunnel implant – giving the attacker persistent, network-level proxy access through the compromised host.

Once executed, the PowerShell command masquerades as a Cloudflare verification process while downloading a ZIP archive containing a legitimate binary (LockScreenContentServer.exe) and a malicious DLL (dui70.dll) used for sideloading. The sideloaded DLL drives an elaborate second stage: downloading payloads concealed inside PNG images using steganography, establishing dual persistence through Registry Run keys and scheduled tasks, conducting thorough domain reconnaissance—including domain trust enumeration, domain admin discovery, Active Directory user description harvesting, and targeted server ping sweeps—and ultimately deploying a Python-based reverse-tunnel C2 implant that tunnels arbitrary TCP traffic back through an encrypted WebSocket channel to attacker infrastructure.

This type of intrusion is particularly dangerous because it provides attackers with direct access to an organization’s internal network through the reverse tunnel. The observed reconnaissance and reverse-tunnel capability could enable an attacker to identify and reach additional systems from a compromised host. Microsoft did not observe the downstream actions described below in the analyzed chain. Organizations should treat affected devices as potential network pivot points and investigate for lateral movement and credential exposure. In the hands-on-keyboard phase that typically follows, attackers leverage this access to escalate privileges, disable security controls, exfiltrate sensitive data, and deploy ransomware across the organization. The combination of stealth techniques (DLL sideloading, steganography, hidden folders) and persistent network access make this TerminalFix campaign a serious threat to enterprise environments.

In this blog, we share our detailed analysis of the TerminalFix attack chain – from initial compromise through network tunneling—along with indicators of compromise, detection details, and hunting guidance to help defenders identify and respond to this threat.

Attack chain overview

The TerminalFix campaign follows a multi-stage attack chain that progresses from social engineering through payload delivery, persistence, reconnaissance, and ultimately network tunneling:

1. Initial access via compromised website – A compromised website displays a fake Cloudflare Turnstile CAPTCHA verification overlay. The user is instructed to copy and paste a “verification” command.

2. PowerShell execution – The pasted command runs a disguised PowerShell script that downloads a ZIP archive from attacker infrastructure, extracts it to C:\ProgramData, and silently launches a batch file.

3. DLL sideloading — The batch file executes LockScreenContentServer.exe, a signed legitimate binary, which automatically loads the co-located malicious dui70.dll.

4. Steganographic payload retrieval – The sideloaded DLL executes PowerShell that downloads PNG images from attacker domains, extracts embedded executables and DLL fragments hidden within pixel data, and reassembles them on disk.

5. Persistence – The malware establishes persistence through both HKCU\…\Run registry keys and scheduled tasks that re-execute LockScreenContentServer.exe every 60 minutes.

6. Reconnaissance – Extensive domain discovery is performed: domain trust enumeration, domain admin group membership, Active Directory computer and user enumeration, targeted server pinging, and system information collection in both English and Spanish locales.

7. Command execution loop – A persistent PowerShell file-watch loop monitors a text file for new commands, executes them via Invoke-Expression, and writes results to an output file-, creating a primitive but effective asynchronous command shell.

8. Reverse tunnel deployment – A Python runtime and a custom client.py tunneling implant are downloaded and launched via pythonw.exe with no visible window, establishing a reverse WebSocket tunnel to gitnow[.]dev:443 that gives the attacker full SOCKS-style TCP proxy access through the victim’s network.

Attack chain

Figure 1. TerminalFix attack chain overview.

1. Initial access: Fake CAPTCHA and the TerminalFix lure

The attack begins when a user visits a compromised website that displays a fake Cloudflare Turnstile verification overlay. The original page is briefly displayed before being replaced by a convincing Cloudflare Turnstile verification overlay. This overlay spoofs the Cloudflare CAPTCHA interface, complete with the Cloudflare logo, “Verify you are human” checkbox, and a spinner animation, tricking users into believing they must complete a verification step to access the site.

Figure 2. Fake Cloudflare Turnstile verification displayed on a compromised website.

When the user interacts with the fake verification prompt, a malicious PowerShell command is silently copied to their clipboard. The on-screen instructions then guide the user to open Windows Terminal or PowerShell and paste the command. The command is carefully crafted to appear legitimate by printing reassuring Cloudflare-themed status messages in color-coded terminal output:

Figure 3. Defanged initial PowerShell command copied to the user’s clipboard by the ClickFix lure.

The command performs the following actions:

  • Clears the terminal and prints a fake “Starting Cloudflare verification…” message in cyan color formatted
  • Downloads a ZIP archive from the attacker’s infrastructure using a custom User-Agent header
  • Extracts the archive to C:\ProgramData\f47f2a8c21c9df4e
  • Launches a batch file (1.bat) that executes LockScreenContentServer.exe silently in the background
  • Prints a convincing “I am not a robot – Cloudflare ID: f47f2a8c21c9df4e” confirmation message in green text

2. Payload delivery: DLL sideloading via LockScreenContentServer.exe

The downloaded ZIP archive (SHA-256: 18c2090e8a0ae0568af9b87e59eaf8270f23d2909600ed9db91a9444fd8b278f) contains two files:

FileDescriptionPurpose
LockScreenContentServer.exeLegitimate signed Windows executableSideloading host; loads dui70.dll from its working directory
dui70.dllMasquerading DLL claiming to be “Windows DirectUI Engine” (unsigned, forged future timestamp 2104)Malicious payload; executes second-stage PowerShell upon sideloading

LockScreenContentServer.exe is a legitimate, signed binary that has a static import dependency on dui70.dll, the Windows DirectUI Engine.

Here is the example view of LockScreenContentServer application importing dui70.dll function:

Figure 4. Example list of imports from dui70.dll

The attacker abuses this dependency by dropping a malicious dui70.dll alongside the executable. Because the Windows loader resolves the application directory before the System32 directory, the planted DLL is loaded in place of the legitimate one, a technique known as DLL sideloading (T1574.001). Execution therefore begins inside a trusted, signed process, allowing the attacker to inherit its reputation and evade controls that key on process identity.

The malicious dui70.dll embeds a heavily obfuscated payload in its resource section. On load, the DLL’s initialization path retrieves this resource, decodes it entirely in memory, and transfers execution to it, staging the next phase of the infection without ever writing the decoded payload to disk (Figures 5 and 6).

Figure 5. Loading a malicious resource (dui70.dll code path).
Figure 6. Heavily obfuscated malicious resource from dui70.dll

3. Second-stage delivery: Steganography and image-based payload extraction

Once sideloaded, the malicious DLL launches an elaborate PowerShell script that retrieves additional payloads concealed within PNG image files, a technique known as steganography. The script downloads three images from attacker-controlled domains, extracts binary data encoded in pixel values, and reassembles the components on disk.

Content domains

The script uses a failover mechanism across two domains:

Figure 7. Attacker content delivery domains with failover.

Steganographic extraction

The Extract-RawFileFromImage function reads each pixel’s RGBA channels and reconstructs an embedded binary. The first 8 bytes encode the payload length as a 64-bit integer, and the remaining bytes contain the file data:

Figure 8. Steganographic extraction function — payload hidden within pixel channel data.

The script downloads three images via POST requests to the content domains, extracts the executable from the first image, extracts two halves of the DLL from the second and third images, and concatenates the DLL fragments:

Figure 9. Payload extraction from three images and DLL reassembly.

Encoding payload data in PNG files can make file type and content inspection more difficult. Splitting the DLL across two images further obscures the complete payload in transit, the payloads aren’t recognizable as executables in transit, and splitting the DLL across two images further complicates detection. After extraction, the source images are deleted to reduce forensic artifacts.

4. Persistence mechanisms

The TerminalFix campaign establishes redundant persistence through two independent mechanisms, ensuring the payload survives reboots and re-executes on a recurring schedule. The dropped batch script takes the payload path as a command-line argument, validates that the file exists, and then configures both mechanisms under the same masquerading name LockScreenContentServer_MuODG5yBM chosen to blend in with the legitimate Windows Lock Screen component abused earlier in the chain.

Registry Run key

The malware creates a Run key entry with a randomized service-like name:

Figure 10. Registry Run key persistence [T1547.001].

Scheduled task

A scheduled task ensures the malware re-executes every 60 minutes:

Figure 11. Scheduled task persistence at 60-minute intervals [T1053.005].

Folder hiding

The malware directory is hidden using system and hidden file attributes:

Figure 12. Directory hiding via attrib [T1564.001].

5. Reconnaissance and domain discovery

After establishing persistence, the sideloaded malware conducts extensive reconnaissance of the victim’s environment. This activity is consistent with a hands-on-keyboard operator or an automated pre-assessment script designed to evaluate whether the compromised host is a valuable target – particularly whether it is domain-joined and near high-value infrastructure.

System information collection

The attacker collects system metadata and the script includes English, Spanish, and German locale variants, indicating an attempt to operate across systems configured in multiple languages:

Figure 13. Bilingual system information enumeration.

Active Directory enumeration

The malware performs domain trust discovery, domain admin enumeration, and Active Directory user and computer searches:

Figure 14. Active Directory enumeration including user description harvesting.

Infrastructure probing

The malware systematically pings named servers to map the internal network topology:

Figure 15. Automated Windows Server enumeration via ADSI combined with targeted ping sweep.

The observed names correspond to common infrastructure roles, including domain controllers, databases, backup, gateways, and mail systems. This probing could help an attacker identify accessible target systems for follow-on activity.

6. Asynchronous command execution loop

The malware deploys a persistent PowerShell file-watch loop that creates an asynchronous command-and-control channel through the local filesystem. This mechanism monitors a “watch” file for changes, executes its contents via Invoke-Expression, and writes results to an output file:

Figure 16. File-watch command execution loop – a primitive but effective asynchronous C2 channel.

This loop provides the attacker with a way to execute arbitrary PowerShell commands by writing them to the watched text file. The output is captured to a separate file, which the attacker can read back through the reverse tunnel. This decoupled execution model allows the attacker to issue commands asynchronously and retrieve results at their convenience.

7. Reverse tunnel deployment: The custom Python-based tunneling implant

The most significant post-compromise capability observed is the deployment of a custom Python-based reverse-tunnel implant. The attacker brings their own interpreter: an unmodified, signed embeddable Python runtime pulled directly from the official python.org distribution. The malicious logic lives entirely in the accompanying client.py, giving the operator a portable, cross-version-tolerant execution environment that inherits the trust of a legitimate open-source runtime.

The deployment is orchestrated in PowerShell. It removes any prior install directory, extracts the implant kit, downloads the embeddable Python 3.14.5 archive over TLS 1.2, unpacks it into the same directory, and launches the tunnel with no visible window via pythonw.exe:

Figure 17. Python runtime deployment and custom tunnel implant launch.

Tunneling implant analysis

The client.py script is a compact but full-featured reverse tunnel. It dials outbound to the C2 over TLS/443, upgrades the session to a WebSocket, and uses that channel to relay arbitrary TCP connections on behalf of the operator. On the wire, the traffic is indistinguishable from an ordinary encrypted web session to a single destination

CapabilityDescription
TLS WebSocket tunnelConnects outbound over TLS port 443, upgrades to WebSocket at /tunnel endpoint. Certificate verification is always disabled (CERT_NONE).
Arbitrary TCP proxyingSOCKS5-style address parsing (IPv4/IPv6/hostname) allows the C2 server to instruct the implant to connect to any internal host and port.
User-Agent rotationRandomly selects from four realistic browser UA strings (Chrome, Firefox, Safari) per connection.
Remote shutdownC2 server can remotely terminate the implant via MSG_SHUTDOWN; uses os._exit() to bypass Python cleanup.
Stream multiplexingCustom 7-byte binary protocol header (type + stream ID + length) multiplexes many tunneled connections over one WebSocket.

The tunnel carries a lightweight custom protocol with eight message types spanning implant identification, connection setup, data relay, keepalive, and remote termination:

Figure 18. custom tunnel protocol message types.

Turning the victim into a network pivot: The implant’s SOCKS5-style address parsing enables the C2 server to reach any host visible from the victim’s network. Combined with the reconnaissance data gathered earlier (domain controllers, SQL servers, backup servers, gateway), this turns the compromised machine into a full network pivot point:

Figure 19. Custom implant’s arbitrary TCP connection capability.

The choice to launch with pythonw.exe (no visible window Python interpreter) means no console window is visible to the user. Combined with DEBUG = False by default and all logging going to stderr, the implant operates completely silently.

Mitigation and protection guidance

Microsoft recommends the following mitigations to reduce the impact of this threat:

  • Restrict PowerShell and Run dialog execution – Use AppLocker, Application Control for Windows, or Group Policy to restrict PowerShell execution for standard users.
  • Consider blocking or auditing the Windows Run dialog (Win+R) where it is not required for daily work.
  • Monitor for DLL sideloading indicators — Alert on LockScreenContentServer.exe executing from non-standard paths (anything other than C:\Windows\SystemApps). Use the LockScreenContentServer.exe sideloading from non-standard paths advanced hunting query provided below to identify this activity across your environment.
  • Educate users about ClickFix tactics – Train employees to recognize fake CAPTCHA verification pages that instruct them to paste commands into Terminal or the Run dialog.
  • Investigate affected hosts thoroughly – Organizations that find indicators of this campaign should assume the attacker has network-level access through the compromised host. Credential rotation should be prioritized for any credentials accessible from the affected machine, including domain admin accounts if the host was domain-joined.
  • Check your Microsoft 365 email filtering settings to ensure spoofed emails, spam, and emails with malware are blocked. Use Microsoft Defender for Office 365 for enhanced phishing protection and coverage against new threats and polymorphic variants. Configure Defender for Office 365 to recheck links on click and delete sent mail in response to newly acquired threat intelligence. Turn on safe attachments policies to check attachments to inbound email.
  • Consider using enterprise-managed browsers, which provide multiple security features including security update requirements and data compliance policies.
  • Block web pages from automatically running Flash plugins.
  • Enable network protection and web protection in Microsoft Defender for Endpoint to safeguard against malicious sites and internet-based threats.
  • Encourage users to use Microsoft Edge and other web browsers that support Microsoft Defender SmartScreen, which identifies and blocks malicious websites, including phishing sites, scam sites, and sites that host malware.
  • Turn on cloud-delivered protection in Microsoft Defender Antivirus, or the equivalent for your antivirus product, to cover rapidly evolving attacker tools and techniques. Cloud-based machine learning protections block a majority of new and unknown variants.
  • Enable PowerShell script block logging to detect and analyze obfuscated or encoded commands, providing visibility into malicious script execution that might otherwise evade traditional logging.
  • Enforce use of PowerShell Constrained Language Mode where possible, in addition to use of execution policies such as setting AllSigned or RemoteSigned to help reduce the risk of malicious execution by ensuring only trusted, signed scripts are executed, adding a layer of control.
  • Use Group Policy to deploy hardening configurations throughout your environment, if certain features are not necessary:
    • Create an App Control policy that prohibits the launch of native Windows binaries from Run. This can be accomplished by defining a rule based on the specific process that is launching binaries like PowerShell.
  • Microsoft Defender XDR customers can also implement the following attack surface reduction rules to harden an environment against PowerShell techniques used by threat actors:

Microsoft Defender XDR detections

Microsoft Defender XDR customers can refer to the list of applicable detections below. Microsoft Defender XDR coordinates detection, prevention, investigation, and response across endpoints, identities, email, and apps to provide integrated protection against attacks like the threat discussed in this blog.

Customers with provisioned access can also use Microsoft Security Copilot in Microsoft Defender to investigate and respond to incidents, hunt for threats, and protect their organization with relevant threat intelligence.

TacticObserved ActivityMicrosoft Defender Coverage
Initial Access / ExecutionUser pastes ClickFix/TerminalFix PowerShell cmdlets from clipboard after interacting with fake Cloudflare CAPTCHAMicrosoft Defender Antivirus
– Trojan:Win32/ClickFix.*
– Trojan:Win32/TermFix.*

Microsoft Defender for Endpoint
– Possible initial access from an emerging threat
– Possible ClickFix activity
– Potential initial access led to ransomware attempt
Defense EvasionLockScreenContentServer.exe DLL sideloading of malicious dui70.dllMicrosoft Defender Antivirus
– Trojan:Win32/Posilod.*
– Trojan:Win64/DLLHijack.DAB!MTB
Microsoft Defender for Endpoint
– An executable file loaded an unexpected DLL file

PersistencePersistence through Registry Run key and Scheduled taskMicrosoft Defender for Endpoint
– Anomaly detected in ASEP registry
– Suspicious Scheduled Task Process Launched
– Suspicious scheduled task
DiscoveryDomain enumeration via nltest, net group, ADSI searcherMicrosoft Defender for Endpoint
– Suspicious LDAP query
– Suspicious Active Directory enumeration
– Possible hands-on-keyboard pre-ransom activity
– Anomalous account lookups
– Possible hands-on-keyboard pre-ransom activity
Command and ControlOutbound TLS WebSocket tunnel to gitnow[.]dev on port 443Microsoft Defender Antivirus
– Trojan:Python/Indigo.SA

Microsoft Defender for Endpoint
– Possibly malicious use of proxy or tunneling tool

Microsoft Security Copilot

Security Copilot customers can use the standalone experience to create their own prompts or run prebuilt promptbooks to automate investigation and response tasks related to this threat. Useful promptbooks for this activity include Incident investigation, Microsoft User analysis, Threat actor profile, Threat Intelligence 360 report based on MDTI intelligence, and Vulnerability impact assessment. Some promptbooks require access to Microsoft Defender XDR, Microsoft Sentinel, or related Microsoft security plugins.

For this campaign, Security Copilot can help analysts summarize affected devices running LockScreenContentServer.exe from non-standard locations, trace the PowerShell steganography extraction chain, and build containment and credential rotation plans for affected domain-joined endpoints.

Threat intelligence reports

Microsoft customers can use Microsoft Defender XDR Threat analytics and related Microsoft threat intelligence reporting to stay current on the malicious activity, indicators, detection coverage, and recommended response actions associated with this compromise. These reports provide investigation context, protection guidance, and updated intelligence that security teams can use to prevent, mitigate, or respond to related activity in customer environments.

Advanced hunting queries

Microsoft Defender XDR customers can run the following advanced hunting queries to find related activity in their networks:

ClickFix PowerShell execution which executes payload

DeviceProcessEvents
| where InitiatingProcessFileName =~ "powershell.exe"
| where FileName =~ "cmd.exe" and ProcessCommandLine has_all (@"\ProgramData\", "1.bat", "LockScreenContentServer.exe")

LockScreenContentServer.exe sideloading from non-standard paths

DeviceImageLoadEvents
| where InitiatingProcessFileName =~ "LockScreenContentServer.exe"
| where FileName =~ "dui70.dll"
| extend path = tostring(parse_path(FolderPath).DirectoryPath)
| where path =~ InitiatingProcessFolderPath
| where not(path has_any (@"\Windows\System32", @"\Windows\SysWOW64", @"\winsxs\", @"\program files", @"\Windows Defender\", @"\Microsoft Security Client\", @"\Program Files\Windows", @"\Program Files\Microsoft", @"\ProgramData\Microsoft\", @"\Microsoft\Windows", @"\amd64_windows-defender-service", @"\Microsoft Defender for Endpoint\"))

Custom reverse tunnel implant execution

DeviceProcessEvents
| where FileName in~ ("pythonw.exe", "python.exe")
| where ProcessCommandLine has_all ("client.py", "--server", "--uuid", “cert.pem”, “gitnow.dev”)

Outbound connections to known C2 domains

DeviceNetworkEvents
| where RemoteUrl has_any ("gitnow.dev", "bestsocialmedianewspapper.com",
                            "offlineupdater.com")
| project Timestamp, DeviceName, RemoteUrl, RemotePort,
          InitiatingProcessFileName

MITRE ATT&CK Techniques observed

The following MITRE ATT&CK mappings reflect behaviors observed during this activity.

Initial Access

  • T1189 Drive-by Compromise | A compromised website delivers a fake CAPTCHA overlay.

Execution

  • T1059.001 Command and Scripting Interpreter: PowerShell | A malicious PowerShell command is pasted by the user into Terminal.
  • T1204.002 User Execution: Malicious File | The user pastes and executes a clipboard-hijacked command.

Persistence

  • T1547.001 Boot or Logon Autostart Execution: Registry Run Keys | An HKCU Run key is set to execute LockScreenContentServer.exe.
  • T1053.005 Scheduled Task/Job: Scheduled Task | A scheduled task is created to execute every 60 minutes.

Defense Evasion

  • T1574.002 Hijack Execution Flow: DLL Side-Loading | Malicious dui70.dll is side-loaded by the legitimate LockScreenContentServer.exe.
  • T1027.003 Obfuscated Files or Information: Steganography | Payloads are hidden in PNG image RGBA pixel data.
  • T1564.001 Hide Artifacts: Hidden Files and Directories | The attrib +h +s command is applied to the payload directory.
  • T1036.005 Masquerading: Match Legitimate Name or Location | The DLL is named dui70.dll to match the legitimate Microsoft DUI framework.

Discovery

  • T1018 Remote System Discovery | An ADSI query identifies Windows Server computers and performs a ping sweep.
  • T1069.002 Permission Groups Discovery: Domain Groups | The net group “domain admins” /domain command is used for enumeration.
  • T1482 Domain Trust Discovery | nltest /domain_trusts and /dclist: are used for domain enumeration.
  • T1087.002 Account Discovery: Domain Account | An ADSI searcher enumerates user descriptions.
  • T1082 System Information Discovery | systeminfo is used with multilingual findstr filters.

Command and Control

  • T1572 Protocol Tunneling | A reverse WebSocket tunnel communicates over TLS with gitnow[.]dev:443.
  • T1071.001 Application Layer Protocol: Web Protocols | Command-and-control communication occurs over HTTPS/WebSocket.
  • T1105 Ingress Tool Transfer | A Python runtime and implant kit are downloaded and extracted.

Indicators of Compromise (IOCs)

File indicators

IndicatorDescription
18c2090e8a0ae0568af9b87e59eaf8270f23d2909600ed9db91a9444fd8b278fInitial ZIP archive (verify_pkg.zip)
b8d107800403b9197e5b7609ceacd8e4cac1b0f9a1d156e6dacd6c3f7794b36aCustom tunnel implant (client.py)
ba77feed86bcda49308746421bdc684a432dd5d68c363975b2a3c6831bda3f07Malicious DLL (dui70.dll)
026478003fe354134c03acf6890e7d3b153ba08a836eca42350db48f213872abMalicious DLL (dui70.dll)
032b529fac61e550f5dc9489686f519b82d64625fa05a8d9ecf8ba8be9b2ad22Malicious DLL (dui70.dll)
df8221a933b38284ebdcb8bffc2df62123c9f5b5f421dd0b070e13e668b3eabfMalicious DLL (dui70.dll)
eb1b4be34d05b394fb74efdeb95faecd1d1963be6ecc1b9db2b4757b491f01f0Malicious DLL (dui70.dll)
5d43abf5c36ea203176d3300ff14af27b4be81810ad2679b3a62b255e3d6e1c8Malicious DLL (dui70.dll)
9a7b4dcd51d9251c177d323d6aaecdfc86674f69bc1af048dc872926d22aaa24Malicious DLL (dui70.dll)
342df92235c9dec81203b837addaa38bb85b64b4a48fe71b5303ca86d991991eMalicious DLL (dui70.dll)
ededeacf30e493dd632d477fe770ba419aa2848f685ea049381a0a8d2cc3e84dMalicious DLL (dui70.dll)

Network indicators

IndicatorTypeDescription
gitnow[.]devDomainC2 server for custom reverse tunnel implant (port 443)
bestsocialmedianewspapper[.]comDomainSteganographic image hosting / payload delivery
offlineupdater[.]comDomainSteganographic image hosting / failover
hxxps://linked-log[.]com/DomainCompromised website

Learn more

For the latest security research from the Microsoft Threat Intelligence community, check out the Microsoft Threat Intelligence Blog.

To get notified about new publications and to join discussions on social media, follow us on LinkedIn, X (formerly Twitter), and Bluesky.

To hear stories and insights from the Microsoft Threat Intelligence community about the ever-evolving threat landscape, listen to the Microsoft Threat Intelligence podcast.

Review our documentation to learn more about our real-time protection capabilities and see how to enable them within your organization.  

The post TerminalFix campaign deploys a reverse tunnel through multistage intrusion appeared first on Microsoft Security Blog.

❌