Kaspersky’s Global Research and Analysis Team (GReAT) has published a technical teardown of a .NET loader framework it calls NetamLoader. The malware was built to run on a Windows 10 build customized for government use in Asia. Kaspersky found it through a single detection alert from the Kaspersky Security Network, in the first half of 2026.
The loader stands out for where it hides and what it borrows to run. Kaspersky found it sitting inside the folder Windows itself uses to stage update packages, built mostly from legitimate, signed files that belong to a real patch management tool. After reviewing the code, infrastructure and techniques, Kaspersky says it could not link the activity to any known APT group.
A CAB File Sitting Where Windows Stores Its Own Updates
Kaspersky says it did not observe how the initial CAB file reached the victim. The team only saw a process already running: PatchMyPC-ScriptRunner.exe, launched from inside C:\Windows\SoftwareDistribution\Download\Install, the folder Windows itself uses to hold update packages before it installs them.
Patch My PC is a real third-party patch management tool. Kaspersky’s report says most of the executables in that folder were legitimate Patch My PC components, and that the .NET assemblies used for the injection were Microsoft-signed. Nothing about the folder or the files looks unusual on its own, which is the point.
- Name.
- NetamLoader, a .NET and XAML-based loader framework.
- Found by.
- Kaspersky GReAT, Securelist, 29 Oct 2026.
- Target.
- A government-only customized Windows 10 build in Asia.
- Victims known.
- One, found through Kaspersky Security Network telemetry.
- Entry point.
- A CAB archive in the Windows Update staging folder.
- Attribution.
- Not linked to any known APT group.
A Legitimate Patch Tool Becomes the Injection Point
NetamLoader is a textbook example of a malware loader built to blend in with software the target already trusts. The trick sits in one configuration file, PatchMyPC-ScriptRunner.exe.config. .NET lets an application’s config file name a custom class to load when the program starts, a mechanism called AppDomainManager.
Kaspersky found that this config pointed at Microsoft.ApplicationServer.Caching.DataCacheFactoryConfiguration, a legitimate class from Microsoft’s Windows Server AppFabric Cache Client component. It is one of the Microsoft-signed assemblies the chain reuses, and one most security tools would not flag. That class loads a second file, fabric.config, which in turn parses a third file, Resources.resx.
This is a living-off-the-land technique. The attacker brings almost nothing new. Nearly every file an antivirus engine checks along the way is one Microsoft or Patch My PC already signed.
- CAB archive staged like a Windows Update packageDiskplanted
- PatchMyPC-ScriptRunner.exe startsProcesslaunches
- Signed Microsoft class loads through AppDomainManager.NET Runtimeinjects
- XamlReader.Parse builds the first hidden loader.NET Runtimedecrypts
- AMSI Scan pointer is patchedProcessdisables
- RPC spawns dllhost.exeProcessrelays
- AES channel opens to the operatorNetwork
From a Resource File to a Hidden XAML Loader
Resources.resx holds a Base64-encoded object. When the loader runs BinaryFormatter.Deserialize on it, that object abuses a known weakness called TypeConfuseDelegate to run code instead of just restoring data. That code calls XamlReader.Parse, .NET’s own function for building objects from XAML markup, to construct what Kaspersky labels XAML-1.
XAML-1 does not carry its own decryption key. It takes the command line that started PatchMyPC-ScriptRunner.exe, converts it to lowercase, and hashes it with SHA-256 to generate an AES key on the spot. It uses that key to decrypt a larger payload, which Kaspersky labels XAML-2.
A Second Loader Turns Off the Built-In Antivirus Check
XAML-2 unpacks two more compressed, Base64-encoded XAML files. The first, XAML-2-1, is about 796 lines long and exists for one purpose: disabling AMSI, the Windows interface that lets antivirus engines inspect scripts and in-memory code before they run.
Kaspersky describes the method step by step. The malware gets the native address of Console.Clear(), a harmless .NET function, and overwrites its first bytes with its own code. It then finds the AMSI COM object’s internal function table and uses VirtualProtect to make the Scan() entry writable. It then points that entry at the patched Console.Clear() instead of the real scanner.
The second file, XAML-2-2, carries a loader Kaspersky calls the .NET 1 Loader, plus a JSON configuration block. Once it runs, that loader deletes the files that started the chain: PatchMyPC-ScriptRunner.exe.config, fabric.config and Resources.resx. It also clears CLR usage logs and the Prefetch cache, and filters out matching entries from the Windows event log under the CmitUpdateAgent folder.
The Final Jump Into dllhost.exe
The .NET 1 Loader then uses RPC to create a remote COM object, with class id ab8902b4-09ca-4bb6-b78d-a8f59079a8d5, and exploits the same TypeConfuseDelegate weakness again. This time the deserialization runs inside dllhost.exe, a standard Windows process that hosts COM components. Kaspersky’s chain is, in effect, a form of process injection that lets the next stage run under a trusted system process instead of its own.
Inside dllhost.exe, XAML-3 loads two further components in turn. The second of these, XAML-P2, decodes and loads what Kaspersky calls the .NET 2 Plugin into the process’s current domain. This is the component that finally talks to the attacker’s server.
None of these stages write a fresh executable to disk. Each one is decrypted and run directly in memory, close to the pattern our own library calls reflective code loading.
A Slow, Encrypted Channel Back to the Operator
The .NET 2 Plugin waits between 20 and 40 minutes, a random delay, before its first contact with the command-and-control server. If the server does not answer, it waits again, this time between 22 and 28 hours before trying once more. Both delays make the traffic harder to catch in a short monitoring window.
Every message is encrypted and authenticated with AES-128-CBC and HMAC, built as an encrypt-then-MAC layout: a 16-byte IV, then the ciphertext, then a 32-byte HMAC. Kaspersky’s indicators list the C2 domain as openaigpt4v[.]com, resolving to 104.18.14[.]219 through Cloudflare. The domain itself was first seen on 27 September 2023, more than two years before this detection.
Why Borrowing Trust From a Patch Tool Matters
Kaspersky’s report calls the pattern it found a strong indicator of a supply-chain attack. That phrase does not mean Patch My PC’s own build process was tampered with; Kaspersky found no sign of that. It means the attacker used a trusted tool’s signed, already-installed files as cover, inside a folder Windows itself treats as safe. Security tools that trust signed binaries by default, or that skip deep inspection of the Windows Update folder, are built to miss exactly this.
Kaspersky’s writeup does not name the specific government agency involved, and it does not say how many other customized Windows builds of this kind exist elsewhere. Its closing point is broader. As more governments commission their own hardened Windows builds, each one becomes a separate ecosystem. Its owner must defend that ecosystem alone, including against attacks delivered through the trusted software already running inside it.
What Defenders Can Check For Now
Kaspersky’s products detect the malware family as HEUR:Trojan.MSIL.NetamLoader.gen, Trojan.MSIL.Zapchast and Trojan.Script.Agent, along with related variants of each. Any of these alerts firing on a system that has no reason to run a custom .NET loader is worth a closer look.
The clearest file-based signal is location, not name: PatchMyPC-ScriptRunner.exe.config, fabric.config and Resources.resx sitting together in C:\Windows\SoftwareDistribution\Download\Install on a machine that does not use Patch My PC for patch management. The network indicator Kaspersky lists is the domain openaigpt4v[.]com and the IP address 104.18.14[.]219.
We recommend treating any AppDomainManager configuration entry sitting next to a trusted executable as reason enough to investigate, even when every file involved carries a valid signature. A signature confirms who wrote the code. It says nothing about which files were allowed to sit beside it.
