❌

Reading view

The Odyssey and Trojans again: MovieReaper attacks users in multiple countries through compromised torrents

Introduction

Torrent trackers have long been abused for distributing malicious software, disguised as popular films, games, and other content. Our previous research has shown that cybercriminals repeatedly turn to torrents as an initial infection vector, using trojanized cracks and installers to reach a large number of users. Installation guides for pirated software routinely instruct users to disable their antivirus, conditioning them to ignore the potential threats they are inviting onto their computers.

During our analysis of malware that leverages blockchain networks for its C2 infrastructure, we discovered a previously unknown modular, multi-stage framework that we dubbed MovieReaper. This report details the new crimeware campaign that began with the mass infection of users via compromised torrent tracker file storage. We have identified several hundred victims, including both individual users and organizations in multiple countries, such as Russia, Türkiye, Japan, Kenya, Uganda, and Colombia, as well as in several European countries like Spain, the Netherlands, Belgium, and Germany. We analyze the techniques for evading detection by security and sandbox solutions, and examine the capabilities of the modular framework.

Kaspersky products detect this threat as HEUR:Trojan.Win64.Agent.gen.

Technical details

Background

In mid‑August 2026, during our threat‑hunting efforts, we identified a large‑scale infection campaign involving previously unknown malware disguised as popular movies. The campaign affected both individuals and organizations across multiple countries. Our initial analysis revealed a common denominator: all of the victims had used torrent trackers. This finding prompted us to investigate the campaign further and analyze its distribution mechanism, overall scope, and unknown malware implants.

Initial infection and spread

Compromised torrent trackers are the primary vector used to distribute malware. During our investigation, we identified multiple user reports describing suspicious files being downloaded instead of the intended content.

For example, a user of a popular movie torrent tracker reported the following case on Reddit:

Further analysis of the attack revealed that instead of compromising torrent trackers, the threat actor modified a widely used public repository of torrent files, itorrents[.]org. As a result, the trackers that relied on the repository began inadvertently distributing malicious torrent files to their users. This approach is particularly dangerous because it lets the threat actor reach users of multiple trackers without having to compromise each platform individually.

As of the publication date of this report, the archive remains compromised. When a user attempts to download a torrent via a magnet link, the legitimate torrent archive returns a different torrent file. This malicious torrent leads to the download of the malware loader, used to deploy a framework that we dubbed MovieReaper.

The loader initiates the infection chain shown in the diagram below. Each stage of the chain is described in detail in the following sections.

Malware implants

The infection chain consists of several steps, where only the initial one is dropped on the disk before it is executed to avoid detection. The malware itself is not heavily obfuscated, apart from strings being encrypted with a custom stream cipher. Most of the countermeasures were aimed at avoiding detection by AV sandboxes.

Step 1: Loader

The most popular initial executable was distributed through torrent trackers under many different names (for example, the odyssey (2026) [1080p] [webrip] [5.1].exe), but the file hash (MD5: A0B13781EDD7CFDAB13D79AFFF3C83C1) was identical across all downloads. We have seen multiple different loaders, where the executable file disguises itself with a long filename and an icon of some well-known application. Most of the filenames are rather long, presumably to hide the EXE extension at the end.

After the user manually starts the application, it establishes a global mutex to ensure that only one loader is executed at a time. We have seen several mutex variations in our samples, containing a randomly generated string (in the example Global\fnulSktzSqvVLXHU). This executable then performs a series of operations in order to avoid detection by AV sandbox solutions.

While performing those operations, the malware avoids making LoadLibrary and GetProcAddress calls to acquire the addresses of required functions. Instead, it searches for loaded libraries by traversing the double-linked list taken from the Ldr field of the PEB and then performs manual parsing of the loaded DLL to calculate the function address.

After all initial checks have passed, the binary prepares to establish a network connection to a C2 web server to download the shellcode, map it to the RWX memory and execute. While doing so, the loader decodes the domain name https://deadhub[.]org and if connection to it has failed, it uses the IP address http://193.23.118[.]155 as a fallback and connects to it using plain HTTP. The malware chooses a random group of strings and uses them as a path in the HTTP request to download the parts of the shellcode.

Example URLs:

/cloud/v192.4/ui/sync-status-icons.png
/cloud/v192.4/onboarding/welcome-bg.jpg
/cloud/v192.4/ui/file-preview-placeholder.png
/cloud/v192.4/shared/link-banner.jpg

While mapping the address space and executing the shellcode, the loader registers a vectored exception handler and rewrites the handler address in memory in order to perform a debug break. This, will not crash the program, but instead redirect controlflow to the function that actually makes a raw NtProtectVirtualMemory syscall (via a previously located “0x0F 0x05” syscall instruction inside ntdll). Then it calls the undocumented ntdll function EtwpCreateEtwThread, which is a popular alternative to  CreateThread for code executionm, and executes the shellcode.

Step 2: Shellcode

The second stage of this malware performs an HTTPS request to the Solana blockchain at the endpoint /getAccountInfo endpoint for the account 6pnDGAiHgyPdmckM5Qt1YbanGzrX43WLEU159nRaNLDm. The data in field of the response contains the base64‑encoded address of a second C2, which is encrypted with a static XOR key located within the shellcode itself. To store data in this account, attackers used a simple Solana program (address: CSiY8bQLBYPdfPWkwipBzH6sijTVQVVsA279JQdvwHtL).

Utilizing the Solana blockchain as a storage layer for next-stage C2 endpoints substantially complicates infrastructure takedown efforts by defenders.

The second stage payload communicates with its C2 server strictly through HTTPS via a TLS-pinned certificate using the nanopb protobuf library as a container for transferred data. The main logic of the stage 2 implant contains several initial commands, where the most important is the one that parses the COFF file, loads it into memory, and executes the module_init function from it. This provides a convenient interface for extension of the command list, which brings us to the next stage of the payload.

Step 3: UAC Bypass and persistence

Notably, the recovered modules were compiled with symbols, which accelerated reverse engineering.

After receiving the next stage from the second C2 server, the newly loaded module performs several tasks right in the module_init function.

Stage 3 performs UAC Bypass and achieves persistence using public techniques, masquerades the original binary as C:\ProgramData\Microsoft\Windows\Telemetry\msedge.exe, and restarts itself.

The respawned process starts with the initial loader, but with a special command-line argument, which allows it to skip most of the anti-sandboxing checks and proceed straight to downloading the next payload. The executable proceeds with the same steps as before, but this time, instead of downloading the persistence and UAC bypass module, a new one is downloaded from the second C2 server. This is because the malware uses the beacon to send a flag to the remote server, indicating whether the implant is running from the Telemetry folder, which allows the C2 to distinguish between first-run and respawned instances.

Step 4: The final implant

The final module (“file manager”) exposes 21 commands that give the operator filesystem access on the victim host. This allows remote the operator to download, upload, and read files on the system; list and enumerate directories; manipulate files with create, copy, rename, move, delete, chmod, and symlink commands; and use preview and thumbnail commands to exfiltrate previews of images and files before actually extracting them.

We suspect that other modules may be loaded on demand if requested by the operator.

Infrastructure

During this malware campaign, attackers are using various commercial hosting providers for their C2 infrastructure (see the IoC section for details). Furthermore, as noted above, the campaign leverages the legitimate Solana blockchain via the RPC endpoint api.mainnet.solana.com to deliver the address of the second‑stage C2 server to the malware. This approach provides the attackers with decentralized storage for C2 addresses, adding an additional layer of resilience and making it more difficult for defenders to disrupt the campaign by simply blocking the IP addresses of the C2 servers.

Victims

The observed campaign targeted both individuals and organizations across Europe, Asia, Africa, and Latin America, with infection attempts identified in Russia, Spain, Germany, Finland, Türkiye, Japan, Nepal, Kenya, Tanzania, Ghana, Uganda, Colombia, the Netherlands, Belgium, and other countries. The targeted organizations span a wide range of sectors, including enterprise, government, IT, consulting, retail, transportation, and agriculture.

Conclusions

Our research uncovered activity by the same actor dating back to October 2025. Although the campaign has evolved over time, with the malware authors expanding their arsenal and making the loader harder to detect, the pattern remains the same. This includes encoded strings, parts of shellcode downloaded through plain HTTP, and several techniques used to avoid sandboxes and virtual machines. We will continue monitoring this actor’s activity to catch new potential threats.

The first stage offers the clearest opportunity to disrupt this campaign: it relies on a single specific domain name and a single IP address to serve the shellcode, so taking down this server would prevent subsequent infection stages. This includes the second-stage payload, which uses the Solana blockchain network for a C2 and is therefore more resistant to conventional infrastructure takedowns.

However, this framework’s self-containment, modularity and in-memory execution has potential for reuse in later campaigns with minimal rework.

Indicators of compromise

File hashes

4334BBAEA8DE33BF9D45E9B4E4E3BC2
4843F9FAFCAE492F11E2D4D33DBB4CDD
5310CABAE3FBE6DB8742849B588093F9
A0B13781EDD7CFDAB13D79AFFF3C83C1
70060341CAF3338697A7DDFE0FB62875
AD4643EEA15AC286FA47D1131F9EF756
D0B967571AC8A3863C7F324BF5BDE99C
D88D550D0FB8E60CFFFF3EA61FF7A067

File paths

%ProgramData%\Microsoft\Windows\Telemetry\msedge.exe

Mutexes

Global\E4AyDKzvEhe2hgAr
Global\fnulSktzSqvVLXHU

Domains and IPs

First-stage C2:
deadhub[.]org
193.23.118[.]155

Second-stage C2:
208.64.33[.]90
208.94.246[.]53

  •  

New Remote DoS Attacks Against GraphQL Java

Executive Summary 

Imperva Threat Research identified a series of remote denial‑of‑service vulnerabilities in GraphQL Java, one of the most widely used libraries for GraphQL in the Java ecosystem. 

In this blog, we’ll deep dive into these vulnerabilities, analyze their impact, and provide recommendations to protect your environment. If your endpoints are protected by Imperva Web Application Firewall, your systems are already protected against these threats.  

Introduction 

GraphQL Java is the engine beneath Spring for GraphQL, Netflix DGS, and Atlassian’s own products. With over one million downloads per month and ten years of production use, it is a natural choice for any team building a GraphQL API on the JVM. 

Over the last few years, multiple types of DoS attacks have been identified across GraphQL implementations. These vulnerabilities can lead to either denial of service or, in cloud-billed environments, excessive cost consumption. In response, the industry converged on a set of protective controls, like depth limiting, query complexity budgets, and field count caps. Apollo added query cost analysis and depth limiting, GitHub meters its public GraphQL API by computed node cost, and GraphQL Java also introduced additional controls. 

However, these enhancements can leave blind spots earlier in the pipeline, before the server has even understood the request. 

The DoS attack we found live in the first half of the pipeline, where the query is parsed and validated, and therefore independent from the schema, the resolvers, and any backend logic.  

They were reported under GHSA-7p4r-9rcc-8vhv (still as draft) and fixed in versions 24.4, 25.1, and 26.1. Several products embedding the library were affected, including Adobe Experience Manager (AEM), Atlassian Confluence, and HAPI FHIR server, a widely used open-source implementation of the HL7 FHIR healthcare interoperability standard. 

Request Processing 

Screenshot 2026 09 23 at 8.36.15 PM

Fig. 1: GraphQL Processing High Level Pipeline 

GraphQL was built around a simple idea: “GraphQL queries mirror their response.” In other words, the client describes exactly the data it needs, while the server determines how to retrieve and resolve that data. The query is then sent to a GraphQL endpoint, where it goes through a series of processing steps before the response is returned: 

  • HTTP Request: The server receives the GraphQL query. 
  • Lexing: The query is broken down into tokens. 
  • Parsing: The tokens are turned into an Abstract Syntax Tree (AST) representing the query structure. 
  • Validation: The query is checked against the GraphQL schema and its rules. 
  • Execution: GraphQL invokes the appropriate resolvers to retrieve the requested data. 
  • JSON Response: The results are assembled and returned to the client. 

The distinction between these stages matters. A request can be rejected before execution because its syntax is invalid or because it does not match the schema. Only after passing these checks does GraphQL reach the resolvers, where the application and its underlying data sources are accessed. 

For security research, this pipeline provides a useful way to understand the attack surface. Each stage processes attacker-controlled input in a different way, making it important to understand not only what GraphQL does, but also when and where it does it. 

Parsing and Validation: A Closer Look 

Before a server decides what data to return, it must first decide whether the request makes sense. Parsing breaks the raw query text into an Abstract Syntax Tree. This involves: 

  • Resolving string literals: block strings go through a dedicated normalization routine that strips leading and trailing blank lines. 
  • Constructing AST nodes for every value encountered: numeric literals are converted to BigInteger or BigDecimal at this point. 

Validation walks the AST and checks it against the schema. This involves: 

  • Field and type checks: do the requested fields exist? Do the argument types match? 
  • Fragment validation: named fragments must not form cycles, directly or transitively 
  • Limit enforcement: in GraphQL Java 26.0, maxDepth and maxFieldsCount are checked here. 

Fragment Cycle Detection 

Validation is where fragment cycle detection takes place. Named fragments are GraphQL’s reuse mechanism. Instead of repeating the same selection set in multiple places, a client defines it once and references it with a spread: 

Screenshot 2026 09 28 at 9.19.01 AM

Fig. 2: Named Fragments in GraphQL 

Fragments can themselves spread other fragments. The spec allows arbitrary nesting, but it forbids cycles: if A spreads B and B spreads A, resolving either one requires resolving the other first. The execution engine would recurse indefinitely. The same applies to indirect cycles across any number of fragments. 

This check happens during validation, after parsing has produced the AST and before execution starts. At this point the server has a complete map of every named fragment in the document and every spread reference between them.  

Cycle detection is pretty straightforward: for each fragment, follow its spread references transitively and check whether any path leads back to the starting node. If it does, the document is rejected with a validation error and execution never starts. 

ValidateNoFragmentCycles is called once per FragmentDefinition in the document. Each call starts with a fresh HashMap. 

For each fragment, it calls buildTransitiveSpreads, a depth-first traversal that follows every spread reference outward, building up the set of fragments reachable from the starting node.  

The traversal tracks its current path in an ArrayList, and at each step calls ArrayList.contains to check whether the next node has already been visited.  

Worst Case Scenario 

We considered a document with the following chain of d fragments: 

Screenshot 2026 09 23 at 8.38.39 PM

Fig. 3: Malicious Payload Structure 

For each fragment, ValidateNoFragmentCycles starts a new traversal with a fresh HashMap. Since the traversal follows the entire chain, and ArrayList.contains iterates over the path of fragments visited so far, the cost of a single validation is O(d²).  

Screenshot 2026 09 23 at 8.39.14 PM

Fig. 4: Processing of the First Fragment 

Since this happens for all fragments, the overall complexity is O(d³), where d is the number of fragments in the document. Within the default 15,000-token limit, a single payload can contain up to around 1,800 fragments (~50 KB), which is sufficient to saturate a CPU core for several minutes at every request. 

Why existing GraphQL protections may not help 

Traditional GraphQL protections such as depth limits and field-count limits operate during validation. However, this attack specifically targets the validation step itself. Therefore, it hits before the protections can prevent the attack. 

Following the reception of our report, graphql-java released a patch that introduces memoization. Once a fragment has been explored, it is marked as done and never re-traversed again. The same malicious payload is processed in a few milliseconds instead. 

This finding was the most impactful, but it wasn’t the only one. 

Additional Remote DoS Vulnerabilities 

We identified the same underlying idea as one of the attack vectors previously identified in React Server Components (BigInt values, CVE-2026-23864), and another vector involving block string normalization routine, more impactful. Both fixed in 24.4, 25.1 and 26.1. 

HAPI FHIR Use Case 

HAPI FHIR is a Java server designed to store and serve medical data (patients, prescriptions, lab results) using the FHIR healthcare standard. Like many modern APIs, it exposes a GraphQL endpoint that clients can use to query this data.  

Internally, HAPI handles GraphQL requests with its own parser, written specifically for FHIR, which knows how to resolve medical resources. But when a client asks for introspection (a standard GraphQL feature that returns the full list of available queries and types) HAPI delegates directly to graphql-java.  

However, it’s possible to bypass HAPI’s custom FHIR resolver and route a non-introspection query straight to graphql-java. 

This delegation is triggered by a simple string check: it relies on the presence of the string `__schema` in the body.  

Therefore, simply starting the request with the following pattern (see Fig 5.) was enough. 

Screenshot 2026 09 23 at 8.40.46 PM

Fig. 5: bypass HAPI’s custom FHIR GraphQL resolver 

Tested on a fresh c7i.2xlarge instance, with the latest HAPI server with graphql enabled, a single request took 150 seconds of validation. A single wave of multiple small requests could lock the server entirely for several minutes and pin all 8 CPU cores at 100% for more than an hour. 

In this application, this attack vector could represent an alternative avenue for a threat actor lacking authorization to exfiltrate patient data (as HAPI’s authorization model governs GraphQL endpoint access and data read permissions independently), and still willing to cause impact. 

The attack surface is further widened by HAPI’s default CORS configuration (allows any origin, Access-Control-Allow-Origin: *). In environments where no additional network controls are in place, this means the attack could be triggered from a browser: a healthcare worker opening a malicious link while connected to the internal network is sufficient to take down the FHIR server for everyone. 

Who is Affected? 

An application is potentially exposed when: 

  • It uses an affected version of GraphQL Java;  
  • It accepts attacker-controlled GraphQL documents;  
  • The GraphQL endpoint is remotely reachable;  
  • No upstream control blocks the malicious request.  

Remediation 

The fixes are available in GraphQL Java versions 24.4, 25.1, and 26.1 via PRs #4440, #4441. 

For environments where an immediate upgrade is not possible: 

  • Restrict access to affected GraphQL endpoints to authenticated or otherwise trusted clients where the application permits it. 
  • Apply rate limiting and concurrency limits to restrict the number of GraphQL requests that can be processed simultaneously. 
  • Monitor CPU utilization and GraphQL request latency for unusual increases that may indicate resource-exhaustion attempts. 

If your endpoints are protected by Imperva Web Application Firewall, your systems are already protected against these threats. 

Conclusion 

As AI accelerates vulnerability discovery and exploitation, threat actors can increasingly scan a target environment in real time, identify weaknesses across its technology stack, and rapidly turn those findings into attacks. This reduces the time organizations must detect and remediate newly exposed vulnerabilities, making proactive and continuously enforced security controls increasingly important. 

Affected organizations should upgrade to a fixed release as soon as possible. Until patches can be applied, additional controls at the application and network layers can help reduce exposure and limit the impact of potential attacks. 

Imperva customers are protected against exploitation of these vulnerabilities. Imperva Threat Research will continue to monitor this threat and work to ensure that customers remain protected against emerging attack techniques targeting GraphQL and other widely deployed technologies. 

Timeline 

August 11 – We reported the security issue to GraphQL Java. 

August 19 – Report Acknowledged. 

August 23 – Fix released in versions 24.4, 25.1 and 26.1. 

The post New Remote DoS Attacks Against GraphQL Java appeared first on Blog.

  •  

From Debugging to Code Execution: RCE in Microsoft DevLabs’ DebugMCP?

Introduction 

AI-assisted development has crossed a threshold. The question is no longer whether your IDE communicates with an AI, it’s how deeply that AI is now wired into your local environment. The Model Context Protocol (MCP) is one of the plumbing behind this shift: a JSON-RPC-based protocol that lets AI assistants invoke tools running on your machine. From setting a breakpoint, to running tests, or launching a debugger… all from a chat window. 

DebugMCP is one of the extensions leading that charge. Published by Microsoft on GitHub, it exposes a local MCP server that gives any compatible AI agent (GitHub Copilot, Cline, Cursor, Codex, Windsurf, and others) direct control over the VS Code debugger. The value proposition is compelling: instead of pasting stack traces into a chat window and waiting for a suggestion, an AI agent can set breakpoints, step through code, inspect variables, and evaluate expressions autonomously.  

We identified and reported a critical security issue in version 1.1.4. A remote attacker who tricked a developer into visiting a malicious webpage could achieve arbitrary code execution on that developer’s machine, in the background, without any further user interaction (drive by).  

Following our report, the maintainers patched DebugMCP via commit 86776b2m. The fix was silently shipped (no version bump, no advisory) and is included in version 1.2.0 and later. We are publishing this report following the 90-day disclosure period. 

We recommend updating to the latest available version. 

Scope 

The exploitability of this weakness was amplified by the context in which the software evolves.  

Indeed, we’re talking about an opensource MCP server hosted on GitHub, that can be used as a standalone server. But this MCP server is also exposed as an extension in VSCode Marketplace, installable with a single click both in local endpoints, and in shared servers via systems like Github CodeSpaces, OpenVSCode Server, etc. 

From this single installation click, the server is automatically started and listening on port 3001 without authentication, opening the door to RCE. 

First, we’ll explore how this issue could be exploited from a surrounding compromised device, and we’ll then demonstrate how DNS rebinding could be exploited to trigger RCE via simply having a victim browse to a malicious site. 

Root Cause 

DNS Rebinding 

DNS Rebinding is a recurrent risk issue when it comes to MCP servers’ development (See our previous blogpost: Another Critical RCE Discovered in a Popular MCP Server).   

At the end of 2025, probably following a series of vulnerabilities identified in multiple MCP servers, Anthropic added an additional layer of security to prevent this risk (CVE-2025-66414) that adds a default security layer in most MCP server cases.  

Version 1.24.0 of modelcontextprotocol introduces createMcpExpressApp, a preconfigured express server instance that automatically registers validateHostHeader and validateOriginHeader. Together, these functions prevent the risk of DNS rebinding.  

However, the library still relies on maintainers to use header validation middleware functions in case of custom express configuration. And in the case of DebugMCP, this is lacking. 

That was the first node of our attack chain. 

Combined with the lack of host and origin definition and validation, the custom express server defined (identical to CVE-2025-53967), exposed the MCP tools far beyond the intended reach.  

But independently from the broad network exposure, an LLM could be tricked via indirect prompt injection to access a file outside VSCode workspace trust, and the fix produced by the maintainers doesn’t answer this question.

Uncontrolled File Path 

To further explore the attack chain, let’s review the tools exposed. 

The README lists the available tools, including: 

  • start_debugging: launches a debugging session for a given file path 
  • get_debugger_state: returns the current state of an active debugging session 
  • add_breakpoint / remove_breakpoint: manage breakpoints 
  • step_over / step_into / step_out: stepping controls 
  • get_variables: inspect local variables in the current stack frame 
  • evaluate_expression: evaluate an arbitrary expression in the debugger context 
  • continue_execution: resume execution

From reading the tool definitions, start_debugging jumped out immediately since it accepted a fileFullPath argument and instructs VS Code to launch a debugger session for that file. That’s a file execution primitive. 

But to obtain an efficient RCE chain, a few more steps were required. 

The UNC Path Primitive 

At first glance, because the vulnerability requires knowing the full path of an executable on the victim’s machine, it seems difficult to weaponize reliably in the wild. 

However, on Windows, the Universal Naming Convention (UNC) path format allows programs to reference files on network shares using paths of the form: 

\\SERVER\SHARE\path\to\file 

This feature enabled us to make DebugMCP pass the path to VS Code’s debugging infrastructure, which passed it to the Python launcher, which reached out to the attacker’s SMB share and loaded the file. The file executed under the victim’s user context. 

Screenshot 2026 09 23 at 8.22.07 PM

Fig. 1: SMB endpoint to fetch payload 

The proof-of-concept payload was intentionally benign: 

import os
os.system(“calc.exe”) 

After a few seconds, Calculator opened. The attacker’s code was running on the victim’s machine via a single HTTP request. 

At this point we had a working local exploit, if we could send one HTTP request to port 3001 with an attacker-controlled UNC path and get code execution.  

The remaining question was how to deliver that request from a remote attacker’s position to a victim’s localhost, across the same-origin policy that is supposed to make this impossible. 

Stateless MCP session 

One part of the answer lies in the MCP itself. You can find a detailed introduction to the protocol here. 

What matters here is one implementation detail that significantly reduced the attack complexity. 

MCP over HTTP is built on JSON-RPC 2.0. The protocol specification describes a lifecycle: a client must send an initialize request, receive the server’s capability response, then send an initialized notification (only after this handshake can tool calls be made). This sequence implies a minimum of two round-trips before any tool is invoked, and it gives a server the opportunity to establish authenticated session state. 

The MCP TypeScript SDK’s StreamableHTTPServerTransport enforces this lifecycle through a validateSession function called on every non-initialize request. The enforcement is conditional: 

Screenshot 2026 09 23 at 8.22.55 PM

Fig. 2: Stateless MCP mode 

When sessionIdGenerator is undefined, validateSession returns immediately without checking anything. The entire initialization lifecycle is bypassed. In DebugMCP v1.1.4, the transport was explicitly configured in stateless mode.  

The consequence for the attack chain is direct: a single no-cors HTTP request was sufficient to trigger the attack. 

Browser Local Network Protections 

However, there was a last ingredient we needed to incorporate to obtain a frictionless exploit. 

Indeed, Local Network Access’s aim is to protect users from cross-site request forgery (CSRF) attacks targeting routers and other devices on private networks, and to reduce the ability of sites to use these requests to fingerprint the user’s local network. 

Combined with the same-origin policy (that prevents a piece of JavaScript from one domain  and make cors requests to a different one and get the response), in modern browsers, there is a good chance a warning popup would be displayed and halt the execution of the malicious content if a threat actor tries to scan the local network.  

But DNS rebinding is a technique that can potentially circumvent this boundary by exploiting the way browsers cache DNS records. And as we explained earlier, DebugMCP doesn’t include MCP default mitigation added by Anthropic against this risk. 

Here is the attack flow: 

Screenshot 2026 09 23 at 8.24.01 PM

Fig. 3: Attack Flow 

The sequence unfolds in six steps: 

Step 1: Victim visits the page. The attacker’s domain resolves to the attacker’s public IP (Phase 1 DNS). The browser loads the initial page content.  

Step 2: DNS Rebinding. The domain was registered with a very short TTL: 1 to 2 seconds. Firefox enforces an internal minimum cache duration of ~60 seconds regardless of the declared TTL, so the page polls in a JavaScript loop until the entry expires and Firefox re-resolves the name: at which point the attacker’s DNS server returns 127.0.0.1. 

Step 3: Local Network Access. The attacker’s JavaScript, issues a fetch to http://evil.attacker.com:3001/mcp?transport=streamable_http. The browser considers this request same-origin and sends it. The DNS entry now points to 127.0.0.1, so the request arrives at the victim’s local DebugMCP server. 

Step 4: DebugMCP Execution. The request reaches the Microsoft DebugMCP server running locally on the victim’s machine. DebugMCP processes the request and triggers its Python launcher, which is responsible for starting the debugging workflow. 

Step 5: Malicious Payload Download. The Python launcher connects to a publicly accessible SMB share controlled by the attacker and downloads the malicious Python script onto the victim’s machine. 

Step 6: Code Execution. The launcher passes the downloaded script to the start_debugging() function. DebugMCP then executes the attacker-controlled payload, ultimately giving the attacker code execution on the victim’s machine. 

Demonstration 

Although the exploit triggers error messages in the VS Code console, the payload is still successfully executed. We used Firefox version 150.0.3, the latest at the time of our research. 

Note: After the research, Firefox enforced a Local Network Access Protections (version 153). This prevents the a request originating from a domain associated with a public IP to reach more private address networks. This recent feature, currently existing in Chrome and Firefox, isn’t yet generalized to all browsers.  

Impact 

The target is a developer. That means the compromised machine holds live credentials, source code, and trusted access to internal infrastructure. 

In practice: AWS keys, SSH keys, GitHub tokens in VS Code’s secret storage, active cloud CLI sessions, VPN tunnels open to the internal network, and push access to production branches would be likely available: a payload that runs as the developer inherits all of it silently. 

The delivery requires no interaction beyond visiting a page, it’s a drive-by attack. 

Recommendations 

Developers using this tool should update to the latest available version. The fix ships after 1.1.4 (version 1.2.0 and later).  

In addition, it’s recommended to regularly audit which servers are listening on loopback. 

Use authentication in your MCP servers and enforce governance to control which MCP server is running in your network and be able to remove it if necessary. 

Regarding MCP development more specifically: 

Use middleware that enforce validation (like createMcpExpressApp Since SDK v1.23.0). 

Validate file path inputs. Reject UNC paths and remote schemes before passing any path to an execution primitive. 

Disclosure Timeline 

  • May 19: Issue reported to Microsoft  
  • May 24: Fix shipped in commit 86776b2, released as version 1.2.0 
  • September 25: Public disclosure (this blogpost) 

Conclusion 

AI-assisted development is quietly rewriting the developer machine’s threat model. To give an agent useful capabilities, extensions expose local servers, wire in execution primitives, and grant broad access to the filesystem and the debugger.  

Each of these is a reasonable engineering decision on its own. Together, they turn the workstation into a dense collection of automation endpoints, and those same endpoints, built to be driven by a trusted agent, are equally drivable by an attacker who reaches them. The productivity story and the attack surface story are the same story. 

Developer environments are where source code, signing keys, pipeline credentials, and cloud sessions converge; compromising one is often a shorter path to production than attacking production directly.  

This vulnerability was not sophisticated. The techniques here are not new; what’s new is the rate at which capable, unvetted local servers are being deployed onto high-value machines, and the growing ability of AI agents to discover and chain weaknesses autonomously. 

The post From Debugging to Code Execution: RCE in Microsoft DevLabs’ DebugMCP? appeared first on Blog.

  •  

A Decision Model Breaks Like Any Other Language Model: A First Look at Jev

A new kind of AI model returns decisions instead of text. We spent a day trying to change its mind. It cost about 50 cents. In this article Jev is a new kind of AI model that returns typed decisions instead of text, built for software to call rather than for people to read. We put it inside a realistic application and tried to change its verdict from the outside. →every configuration we tested was broken: risk downgraded to low and investment advised, on a document that flags every warning sign →about 50 cents per successful break, with our strongest […]

The post A Decision Model Breaks Like Any Other Language Model: A First Look at Jev appeared first on Check Point Blog.

  •  

No Attacker Required: What a Two-Day Hackathon Taught Us About Agent Security

In this article Nineteen Check Point AI Security R&D teams spent two days on one prompt: build the demo customers would ask to see twice. Three of the results tell a single story about securing AI agents, and none of it starts with an attacker. →an autonomous agent took dangerous actions with no attacker involved, it simply hit a wall and improvised →a single poisoned file in a code repository turned a popular coding agent into a data exfiltration channel →questioning an off-track agent prevented as many attacks as blocking it, and completed more legitimate work →the lesson for anyone […]

The post No Attacker Required: What a Two-Day Hackathon Taught Us About Agent Security appeared first on Check Point Blog.

  •  

The Odyssey and Trojans again: MovieReaper attacks users in multiple countries through compromised torrents

Introduction

Torrent trackers have long been abused for distributing malicious software, disguised as popular films, games, and other content. Our previous research has shown that cybercriminals repeatedly turn to torrents as an initial infection vector, using trojanized cracks and installers to reach a large number of users. Installation guides for pirated software routinely instruct users to disable their antivirus, conditioning them to ignore the potential threats they are inviting onto their computers.

During our analysis of malware that leverages blockchain networks for its C2 infrastructure, we discovered a previously unknown modular, multi-stage framework that we dubbed MovieReaper. This report details the new crimeware campaign that began with the mass infection of users via compromised torrent tracker file storage. We have identified several hundred victims, including both individual users and organizations in multiple countries, such as Russia, Türkiye, Japan, Kenya, Uganda, and Colombia, as well as in several European countries like Spain, the Netherlands, Belgium, and Germany. We analyze the techniques for evading detection by security and sandbox solutions, and examine the capabilities of the modular framework.

Kaspersky products detect this threat as HEUR:Trojan.Win64.Agent.gen.

Technical details

Background

In mid‑August 2026, during our threat‑hunting efforts, we identified a large‑scale infection campaign involving previously unknown malware disguised as popular movies. The campaign affected both individuals and organizations across multiple countries. Our initial analysis revealed a common denominator: all of the victims had used torrent trackers. This finding prompted us to investigate the campaign further and analyze its distribution mechanism, overall scope, and unknown malware implants.

Initial infection and spread

Compromised torrent trackers are the primary vector used to distribute malware. During our investigation, we identified multiple user reports describing suspicious files being downloaded instead of the intended content.

For example, a user of a popular movie torrent tracker reported the following case on Reddit:

Further analysis of the attack revealed that instead of compromising torrent trackers, the threat actor modified a widely used public repository of torrent files, itorrents[.]org. As a result, the trackers that relied on the repository began inadvertently distributing malicious torrent files to their users. This approach is particularly dangerous because it lets the threat actor reach users of multiple trackers without having to compromise each platform individually.

As of the publication date of this report, the archive remains compromised. When a user attempts to download a torrent via a magnet link, the legitimate torrent archive returns a different torrent file. This malicious torrent leads to the download of the malware loader, used to deploy a framework that we dubbed MovieReaper.

The loader initiates the infection chain shown in the diagram below. Each stage of the chain is described in detail in the following sections.

Malware implants

The infection chain consists of several steps, where only the initial one is dropped on the disk before it is executed to avoid detection. The malware itself is not heavily obfuscated, apart from strings being encrypted with a custom stream cipher. Most of the countermeasures were aimed at avoiding detection by AV sandboxes.

Step 1: Loader

The most popular initial executable was distributed through torrent trackers under many different names (for example, the odyssey (2026) [1080p] [webrip] [5.1].exe), but the file hash (MD5: A0B13781EDD7CFDAB13D79AFFF3C83C1) was identical across all downloads. We have seen multiple different loaders, where the executable file disguises itself with a long filename and an icon of some well-known application. Most of the filenames are rather long, presumably to hide the EXE extension at the end.

After the user manually starts the application, it establishes a global mutex to ensure that only one loader is executed at a time. We have seen several mutex variations in our samples, containing a randomly generated string (in the example Global\fnulSktzSqvVLXHU). This executable then performs a series of operations in order to avoid detection by AV sandbox solutions.

While performing those operations, the malware avoids making LoadLibrary and GetProcAddress calls to acquire the addresses of required functions. Instead, it searches for loaded libraries by traversing the double-linked list taken from the Ldr field of the PEB and then performs manual parsing of the loaded DLL to calculate the function address.

After all initial checks have passed, the binary prepares to establish a network connection to a C2 web server to download the shellcode, map it to the RWX memory and execute. While doing so, the loader decodes the domain name https://deadhub[.]org and if connection to it has failed, it uses the IP address http://193.23.118[.]155 as a fallback and connects to it using plain HTTP. The malware chooses a random group of strings and uses them as a path in the HTTP request to download the parts of the shellcode.

Example URLs:

/cloud/v192.4/ui/sync-status-icons.png
/cloud/v192.4/onboarding/welcome-bg.jpg
/cloud/v192.4/ui/file-preview-placeholder.png
/cloud/v192.4/shared/link-banner.jpg

While mapping the address space and executing the shellcode, the loader registers a vectored exception handler and rewrites the handler address in memory in order to perform a debug break. This, will not crash the program, but instead redirect controlflow to the function that actually makes a raw NtProtectVirtualMemory syscall (via a previously located “0x0F 0x05” syscall instruction inside ntdll). Then it calls the undocumented ntdll function EtwpCreateEtwThread, which is a popular alternative to  CreateThread for code executionm, and executes the shellcode.

Step 2: Shellcode

The second stage of this malware performs an HTTPS request to the Solana blockchain at the endpoint /getAccountInfo endpoint for the account 6pnDGAiHgyPdmckM5Qt1YbanGzrX43WLEU159nRaNLDm. The data in field of the response contains the base64‑encoded address of a second C2, which is encrypted with a static XOR key located within the shellcode itself. To store data in this account, attackers used a simple Solana program (address: CSiY8bQLBYPdfPWkwipBzH6sijTVQVVsA279JQdvwHtL).

Utilizing the Solana blockchain as a storage layer for next-stage C2 endpoints substantially complicates infrastructure takedown efforts by defenders.

The second stage payload communicates with its C2 server strictly through HTTPS via a TLS-pinned certificate using the nanopb protobuf library as a container for transferred data. The main logic of the stage 2 implant contains several initial commands, where the most important is the one that parses the COFF file, loads it into memory, and executes the module_init function from it. This provides a convenient interface for extension of the command list, which brings us to the next stage of the payload.

Step 3: UAC Bypass and persistence

Notably, the recovered modules were compiled with symbols, which accelerated reverse engineering.

After receiving the next stage from the second C2 server, the newly loaded module performs several tasks right in the module_init function.

Stage 3 performs UAC Bypass and achieves persistence using public techniques, masquerades the original binary as C:\ProgramData\Microsoft\Windows\Telemetry\msedge.exe, and restarts itself.

The respawned process starts with the initial loader, but with a special command-line argument, which allows it to skip most of the anti-sandboxing checks and proceed straight to downloading the next payload. The executable proceeds with the same steps as before, but this time, instead of downloading the persistence and UAC bypass module, a new one is downloaded from the second C2 server. This is because the malware uses the beacon to send a flag to the remote server, indicating whether the implant is running from the Telemetry folder, which allows the C2 to distinguish between first-run and respawned instances.

Step 4: The final implant

The final module (“file manager”) exposes 21 commands that give the operator filesystem access on the victim host. This allows remote the operator to download, upload, and read files on the system; list and enumerate directories; manipulate files with create, copy, rename, move, delete, chmod, and symlink commands; and use preview and thumbnail commands to exfiltrate previews of images and files before actually extracting them.

We suspect that other modules may be loaded on demand if requested by the operator.

Infrastructure

During this malware campaign, attackers are using various commercial hosting providers for their C2 infrastructure (see the IoC section for details). Furthermore, as noted above, the campaign leverages the legitimate Solana blockchain via the RPC endpoint api.mainnet.solana.com to deliver the address of the second‑stage C2 server to the malware. This approach provides the attackers with decentralized storage for C2 addresses, adding an additional layer of resilience and making it more difficult for defenders to disrupt the campaign by simply blocking the IP addresses of the C2 servers.

Victims

The observed campaign targeted both individuals and organizations across Europe, Asia, Africa, and Latin America, with infection attempts identified in Russia, Spain, Germany, Finland, Türkiye, Japan, Nepal, Kenya, Tanzania, Ghana, Uganda, Colombia, the Netherlands, Belgium, and other countries. The targeted organizations span a wide range of sectors, including enterprise, government, IT, consulting, retail, transportation, and agriculture.

Conclusions

Our research uncovered activity by the same actor dating back to October 2025. Although the campaign has evolved over time, with the malware authors expanding their arsenal and making the loader harder to detect, the pattern remains the same. This includes encoded strings, parts of shellcode downloaded through plain HTTP, and several techniques used to avoid sandboxes and virtual machines. We will continue monitoring this actor’s activity to catch new potential threats.

The first stage offers the clearest opportunity to disrupt this campaign: it relies on a single specific domain name and a single IP address to serve the shellcode, so taking down this server would prevent subsequent infection stages. This includes the second-stage payload, which uses the Solana blockchain network for a C2 and is therefore more resistant to conventional infrastructure takedowns.

However, this framework’s self-containment, modularity and in-memory execution has potential for reuse in later campaigns with minimal rework.

Indicators of compromise

File hashes

4334BBAEA8DE33BF9D45E9B4E4E3BC2
4843F9FAFCAE492F11E2D4D33DBB4CDD
5310CABAE3FBE6DB8742849B588093F9
A0B13781EDD7CFDAB13D79AFFF3C83C1
70060341CAF3338697A7DDFE0FB62875
AD4643EEA15AC286FA47D1131F9EF756
D0B967571AC8A3863C7F324BF5BDE99C
D88D550D0FB8E60CFFFF3EA61FF7A067

File paths

%ProgramData%\Microsoft\Windows\Telemetry\msedge.exe

Mutexes

Global\E4AyDKzvEhe2hgAr
Global\fnulSktzSqvVLXHU

Domains and IPs

First-stage C2:
deadhub[.]org
193.23.118[.]155

Second-stage C2:
208.64.33[.]90
208.94.246[.]53

  •  

From Exposure to Lockdown: How AWS Neutralizes Compromised IAM Credentials through Managed Policies

We explore how AWS neutralizes exposed IAM credentials using managed policies, detailing GitHub secret scanning and CloudTrail monitoring strategies.

The post From Exposure to Lockdown: How AWS Neutralizes Compromised IAM Credentials through Managed Policies appeared first on Unit 42.

  •  

A Vault with a Heap-View: The Uncomfortable Space Between AgentCore Harness and Identity

Analysis of how default configurations in AWS AgentCore Harness allow prompt injection to exfiltrate credentials, and key steps to secure your agents.

The post A Vault with a Heap-View: The Uncomfortable Space Between AgentCore Harness and Identity appeared first on Unit 42.

  •  

Unmasking Cloud Identities: From Behavioral Clustering to Automated Detection

We designed a behavioral clustering model to map cloud identity roles from audit logs, enabling continuous threat detection using standard SQL queries.

The post Unmasking Cloud Identities: From Behavioral Clustering to Automated Detection appeared first on Unit 42.

  •  

The Machine With Many Faces: Post-Exploitation Identity Misuse in SPIFFE/SPIRE

Learn how root access on a compromised K8s node allows attackers to utilize SPIFFE/SPIRE metadata to spoof and harvest co-located workload identities.

The post The Machine With Many Faces: Post-Exploitation Identity Misuse in SPIFFE/SPIRE appeared first on Unit 42.

  •  

Untracked Nightmares: The Threats Hiding Behind Commodity Infrastructure

An investigation into how cybercriminals used YouTube gaming lures and SEO poisoning to deliver multi-payload malware to enterprise networks.

The post Untracked Nightmares: The Threats Hiding Behind Commodity Infrastructure appeared first on Unit 42.

  •  
❌