> ## Content Index
> Fetch the complete content index at: https://f4n6.co.uk/llms.txt
> Use this file to discover other available public pages before exploring further.

# Unknown APT uses NetamLoader to compromise Asian government Windows builds via supply chain
- URL: https://f4n6.co.uk/security-feed/unknown-apt-uses-netamloader-to-compromise-asian-government-windows-builds-via-supply-chain/
- Published: 2026-10-29T10:52:15.000Z
- Updated: 2026-10-29T10:52:15.000Z
- Author: Jeff Davies
- Tags: #security-feed

## 1\. Executive summary

Kaspersky has published analysis of NetamLoader, a .NET assembly-loading framework delivered through a tampered Patch My PC update package that sat in the Windows update download directory (`C:\Windows\SoftwareDistribution\Download\`) of a single victim in Asia. The loader chains AppDomainManager injection, a BinaryFormatter deserialization flaw in a Microsoft-signed assembly, and multiple XAML stages to reach a final .NET plugin that beacons to `openaigpt4v[.]com` over AES-128-CBC with HMAC-SHA256\. Kaspersky assesses the target as a Windows build customised for government use in Asia and states it could not link the activity to any known APT group. No CVE has been assigned and no entry exists in NVD, EPSS or CISA KEV, so there is no patch to apply and no exploitation deadline to track. The direct risk to EMEA financial services is low: no victim, no targeting and no infrastructure overlap with the sector has been reported. The exposure that matters is architectural. The chain runs entirely through signed Microsoft binaries and a legitimate patch-management tool, so signature-based controls do not see it, and any firm running third-party patch tooling inside `SoftwareDistribution` should assume the same delivery path is available to it.

## 2\. Regulatory framing

No specific DORA/NIS2 article is directly engaged by this item.

## 3\. Technical analysis & attack chain

Kaspersky did not observe delivery. The first artefact is a CAB archive named `e4537a1762fcafd2fd96bfc825bad34f9db9a24d` sitting in `C:\Windows\SoftwareDistribution\Download\`, the directory Windows uses for operating system update packages. The archive extracts seven files to `C:\Windows\SoftwareDistribution\Download\Install\`, and the chain begins when `PatchMyPC-ScriptRunner.exe` runs with the arguments `-updatepackage -applicationid=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`. Six of the seven files are clean. Only `Resources.resx` carries the payload. The rest are legitimate Patch My PC components and Microsoft-signed .NET assemblies, which is why the initial triage of the CAB found nothing.

The confirmed execution sequence:

1. `PatchMyPC-ScriptRunner.exe` starts and the CLR reads `PatchMyPC-ScriptRunner.exe.config` from the same directory before the executable's entry point runs. The config sets `appDomainManagerAssembly` to `Microsoft.HostIntegration.Connectors, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` and `appDomainManagerType` to `Microsoft.ApplicationServer.Caching.DataCacheFactoryConfiguration`. Both are Microsoft-signed.
2. `DataCacheFactoryConfiguration` is the Windows Server AppFabric Cache Client configuration class. On instantiation it looks for `fabric.config` in the same directory and reads it. The planted `fabric.config` sets `className` to `System.Resources.ResXResourceSet, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089(Resources.resx)`, so a `ResXResourceSet` is constructed against `Resources.resx`.
3. `Resources.resx` holds a Base64-encoded object serialised with `BinaryFormatter`. Parsing it calls `BinaryFormatter.Deserialize()`, which Kaspersky describes as a TypeConfuseDelegate deserialization attack. The delegate invokes `XamlReader.Parse()` on an embedded XAML payload (XAML-1).
4. XAML-1 acts as a loader for XAML-2 and then calls `Environment.Exit(0)` to kill the host process before any error dialog can appear.
5. XAML-2 carries two Base64-encoded, ZIP-compressed XAML files, XAML-2-1 and XAML-2-2, each loaded in memory with `XamlReader.Load()`.
6. XAML-2-1 is 796 lines whose only job is AMSI bypass. It checks `IntPtr.Size == 8` and aborts if the host is not 64-bit. It patches `Console.Clear()` in memory with the bytes `41 C7 00 01 00 00 00 33 C0 C3`. It then walks the `IUnknown` virtual method table of the AMSI object, adds `0x18` to reach the `CAmsiAntimalware::Scan` pointer, calls `VirtualProtect()` to make it writable, and overwrites it with the address of a patched routine returning `AMSI_RESULT_CLEAN` (0). Sensitive strings are split into short fragments and reassembled at parse time. One patch lands in the memory of an existing legitimate module and the other only alters AMSI virtual tables, so code integrity checks pass.
7. XAML-2-2 carries the .NET 1 Loader assembly and a JSON configuration (JSON-1), both ZIP-compressed and Base64-encoded. The loader is instantiated with `Assembly.CreateInstance()` and JSON-1 is passed to its `m.C()` method.
8. .NET 1 Loader parses JSON-1, which contains a nested configuration (JSON-1-p) with the C2 URL `https://openaigpt4v.com/model_v4/`, a trusted certificate thumbprint field `tp` set to `*` (any certificate accepted, so certificate pinning is disabled), the AES master key `9fT04e03tAiZAPogcDWt0w==`, and the encrypted XAML-3 template set in `ibi` with its key in `ibk`.
9. .NET 1 Loader reads `SusClientId` from `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate` and derives a per-victim identifier `si` from it. It sets the environment variable `COMPlus_ETWEnabled` to `0` through `WScript.Shell` (CLSID `41904400-BE18-11D3-A28B-00104BD35090`), which stops the CLR registering the .NET ETW provider and hides the associated events.
10. XAML-3 is decrypted from the `ibi`/`ibk` material and loaded in a new process, `dllhost.exe`, reached through COM. The plugin writes `DllSurrogate = ""` under `HKCU\Software\Classes\appid\{ff259bcd-2f0a-44de-b34a-0092fec1d8a2}`, creates the COM object, and calls `CoLockObjectExternal()` so the surrogate is not released. The AMSI bypass from XAML-2-1 is re-applied in the new process through the `__P1__` placeholder.
11. The .NET 2 Plugin (hash `CFB8B281BDF5D9390E64B10C312FB2C1`) runs in `dllhost.exe`. It collects host reconnaissance: the .NET Framework version from `HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\full` value `Version`, and the build string from `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion` value `BuildLab` (the example given is `4.7.03190\n17763.rs5_release.180914-1434`). Failed queries are replaced with a hyphen.
12. The plugin resolves proxy configuration three ways (WinHTTP, `WebProxy.GetDefaultProxy()`, and impersonation of the current user) so it can reach the internet from proxied networks. It then beacons to `https://openaigpt4v[.]com/model_v4/<si>?b=<encrypted>&c=<si>` with a `ServerCertificateValidationCallback` that accepts any certificate because `tp` is `*`.

Traffic is AES-128-CBC with Encrypt-then-MAC: a random 16-byte IV, the ciphertext, then a 32-byte HMAC-SHA256 over IV plus ciphertext. Per-direction keys are derived from the master key with HMAC using single-byte seeds 0 to 3\. The C2 response is parsed by a second-stage XAML loaded through a `CrossAppDomainDelegate` whose `_invocationList` is rewritten by reflection to point at `XamlReader.Parse()`, keeping the downloaded payload out of the main AppDomain.

Timing is deliberate. The plugin waits 100801 seconds (about 28 hours) before its first callback and then exits. If the C2 does not answer, polling backs off to 79200 to 100800 seconds (22 to 28 hours). The initial connection delay is 1200 to 2400 seconds (20 to 40 minutes). These intervals defeat sandboxes that run for minutes.

Persistence is not described in the source. Kaspersky documents the loader chain and the C2 protocol but does not state a run key, scheduled task or service. Treat persistence as unknown rather than absent.

The C2 domain `openaigpt4[.]com` resolved to `104.18.14[.]219`, first seen 27 September 2023, registered through Cloudflare and hosted on Cloudflare's CDN (ASN 15169). Kaspersky notes the use of commercial hosting infrastructure.

Confidence caveats. All of the above is single-sourced to Kaspersky. Kaspersky reports one victim in Asia identified from KSN telemetry and infers government targeting from the customised Windows build, not from confirmed victim identity. The attribution is unconfirmed: Kaspersky states it could not link the TTPs, code or infrastructure to any known APT group, and no MITRE ATT&CK profile exists for this activity. The `tp` field is described by Kaspersky as suspected to be a trusted SSL certificate thumbprint. The delivery vector is unknown; the CAB's presence in `SoftwareDistribution` is consistent with a supply-chain or update-path compromise but Kaspersky does not confirm how it got there.

## 4\. Mitigation & containment

P1 (within 24 hours)

- Hunt for the CAB filename `e4537a1762fcafd2fd96bfc825bad34f9db9a24d` and for any `.config` file in `C:\Windows\SoftwareDistribution\Download\` or its `Install\` subdirectory that contains `appDomainManagerAssembly` or `appDomainManagerType`. Legitimate Windows update packages do not ship CLR AppDomainManager configuration there.
- Block `openaigpt4[.]com` and `104.18.14[.]219` at egress proxy, DNS and firewall. The domain is Cloudflare-fronted, so block by full hostname and by the resolved address rather than by CDN range.
- Alert on `dllhost.exe` making outbound HTTPS to a host it has no COM activation history with, and on `dllhost.exe` writing to `HKCU\Software\Classes\appid\{ff259bcd-2f0a-44de-b34a-0092fec1d8a2}`.
- If Patch My PC is deployed, confirm the publisher's binaries and their `.config` files against a known-good hash set from the vendor. Any `PatchMyPC-ScriptRunner.exe.config` that is not the vendor's own file is a compromise indicator.

P2 (within 72 hours)

- Audit which accounts and processes can write to `C:\Windows\SoftwareDistribution\Download\`. Restrict write access to SYSTEM and the Windows Update service. A non-Microsoft process placing files there is the precondition for this chain.
- Enable PowerShell script block logging, module logging and AMSI logging to a collector that does not depend on the local AMSI provider, since the loader patches AMSI in memory. Forward `Microsoft-Windows-DotNETRuntime` events off-host; the loader sets `COMPlus_ETWEnabled=0` to suppress them locally, so local-only collection will be blind.
- Deploy the YARA rule in §6 to EDR and file-scanning tiers, scoped to `.config`, `.resx` and `.cab` files under `SoftwareDistribution` and to user-writable paths.

P3 (within 7 days)

- Review third-party patch-management tooling for update integrity: signed manifests, hash verification before execution, and execution from a directory the tool controls rather than from `SoftwareDistribution`.
- Add a detection for `BinaryFormatter.Deserialize()` reachable from `ResXResourceSet` parsing in processes that should never deserialise untrusted `.resx` files. .NET 4.6 does not enable the safer `BinaryFormatter` switch by default; where the application allows it, set `Switch.System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization` to `false` in `runtimeconfig` or via `AppContext`, and test that Patch My PC and other managed tools still function.
- No vendor fix exists for this chain. There is no CVE, so there is no patch to schedule. The controls above are the remediation.

## 5\. Indicators of compromise

All indicators are single-sourced to Kaspersky; verify before enforcement. Hashes are MD5 as published.

| type     | value                                                                                   | confidence | source               |
| -------- | --------------------------------------------------------------------------------------- | ---------- | -------------------- |
| md5      | f2458ed133f8d0ca19e22c10f577e98e                                                        | high       | Kaspersky Securelist |
| md5      | e4537a1762fcafd2fd96bfc825bad34f9db9a24d                                                | high       | Kaspersky Securelist |
| md5      | e1dc6f1ed193594f2284be22ae08dfa4                                                        | high       | Kaspersky Securelist |
| md5      | ab81564bcb8ca7e710c66832de747556                                                        | high       | Kaspersky Securelist |
| md5      | cfb8b281bdf5d9390e64b10c312fb2c1                                                        | high       | Kaspersky Securelist |
| md5      | 67e3617f8709d34f806f8e02badba8a5                                                        | high       | Kaspersky Securelist |
| md5      | 514ac0d73b8a1b73488ef5e2e55a75c3                                                        | high       | Kaspersky Securelist |
| md5      | 514117d536e347560d049cfe0c609632                                                        | high       | Kaspersky Securelist |
| md5      | 9000820d8153c24cd60d53001d3a97b6                                                        | high       | Kaspersky Securelist |
| md5      | b3c4a635179680edafb5d006cf0cffc6                                                        | high       | Kaspersky Securelist |
| md5      | 4f28622c5e60c01319bf48cf742fe1a5                                                        | high       | Kaspersky Securelist |
| md5      | c86d53392a87dd3f3e62d62c9b92a9bd                                                        | high       | Kaspersky Securelist |
| domain   | openaigpt4\[.\]com                                                                      | high       | Kaspersky Securelist |
| ipv4     | 104.18.14\[.\]219                                                                       | high       | Kaspersky Securelist |
| url      | hxxps://openaigpt4\[.\]com/model\_v4/                                                   | high       | Kaspersky Securelist |
| filepath | C:\\Windows\\SoftwareDistribution\\Download\\e4537a1762fcafd2fd96bfc825bad34f9db9a24d   | high       | Kaspersky Securelist |
| filepath | C:\\Windows\\SoftwareDistribution\\Download\\Install\\PatchMyPC-ScriptRunner.exe.config | high       | Kaspersky Securelist |
| filepath | C:\\Windows\\SoftwareDistribution\\Download\\Install\\fabric.config                     | high       | Kaspersky Securelist |
| filepath | C:\\Windows\\SoftwareDistribution\\Download\\Install\\Resources.resx                    | high       | Kaspersky Securelist |
| registry | HKCU\\Software\\Classes\\appid{ff259bcd-2f0a-44de-b34a-0092fec1d8a2}                    | high       | Kaspersky Securelist |

The hash-to-file mapping published by Kaspersky is: `f2458ed133f8d0ca19e22c10f577e98e` is the CAB archive `e4537a1762fcafd2fd96bfc825bad34f9db9a24d`; `e1dc6f1ed193594f2284be22ae08dfa4` is `Resources.resx`; `ab81564bcb8ca7e710c66832de747556` is the .NET 1 Loader; `cfb8b281bdf5d9390e64b10c312fb2c1` is the .NET 2 Plugin; `67e3617f8709d34f806f8e02badba8a5` is `fabric.config`; `514ac0d73b8a1b73488ef5e2e55a75c3` is `PatchMyPC-ScriptRunner.exe.config`; `514117d536e347560d049cfe0c609632` is XAML-1; `9000820d8153c24cd60d53001d3a97b6` is XAML-2; `b3c4a635179680edafb5d006cf0cffc6` is XAML-2-1; `4f28622c5e60c01319bf48cf742fe1a5` is XAML-2-2; `c86d53392a87dd3f3e62d62c9b92a9bd` is XAML-3.

```iocs
md5  f2458ed133f8d0ca19e22c10f577e98e
md5  e4537a1762fcafd2fd96bfc825bad34f9db9a24d
md5  e1dc6f1ed193594f2284be22ae08dfa4
md5  ab81564bcb8ca7e710c66832de747556
md5  cfb8b281bdf5d9390e64b10c312fb2c1
md5  67e3617f8709d34f806f8e02badba8a5
md5  514ac0d73b8a1b73488ef5e2e55a75c3
md5  514117d536e347560d049cfe0c609632
md5  9000820d8153c24cd60d53001d3a97b6
md5  b3c4a635179680edafb5d006cf0cffc6
md5  4f28622c5e60c01319bf48cf742fe1a5
md5  c86d53392a87dd3f3e62d62c9b92a9bd
domain  openaigpt4[.]com
ipv4  104.18.14[.]219
url  hxxps://openaigpt4[.]com/model_v4/
filepath  C:\Windows\SoftwareDistribution\Download\e4537a1762fcafd2fd96bfc825bad34f9db9a24d
filepath  C:\Windows\SoftwareDistribution\Download\Install\PatchMyPC-ScriptRunner.exe.config
filepath  C:\Windows\SoftwareDistribution\Download\Install\fabric.config
filepath  C:\Windows\SoftwareDistribution\Download\Install\Resources.resx
registry  HKCU\Software\Classes\appid\{ff259bcd-2f0a-44de-b34a-0092fec1d8a2}

```

Behavioural indicators, since the atomic set above is small and the loader's value is in its behaviour:

| behaviour                                                                                                                                                                                | where to observe                         | confidence |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | ---------- |
| CLR AppDomainManager configuration in a .config file under SoftwareDistribution                                                                                                          | file creation events, EDR file telemetry | high       |
| PatchMyPC-ScriptRunner.exe spawning dllhost.exe that then makes outbound HTTPS                                                                                                           | process creation and network telemetry   | high       |
| dllhost.exe writing DllSurrogate under HKCU\\Software\\Classes\\appid\\{ff259bcd-2f0a-44de-b34a-0092fec1d8a2}                                                                            | registry auditing                        | high       |
| COMPlus\_ETWEnabled set to 0 in a process environment                                                                                                                                    | process environment capture, EDR         | high       |
| Console.Clear() and AMSI Scan patched in memory                                                                                                                                          | memory scanning, not file scanning       | high       |
| outbound HTTPS to openaigpt4\[.\]com with a path of /model\_v4/<GUID> and query parameters b and c                                                                                       | proxy and TLS logs                       | high       |
| reads of SusClientId under HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate by a non-Windows-Update process                                                             | registry auditing                        | medium     |
| %LOCALAPPDATA%\\Microsoft\\CLR\_v4.0\\UsageLogs\\PatchMyPC-ScriptRunner.exe.log and %WINDIR%\\Prefetch\\PATCHMYPC-SCRIPTRUNNER.EXE-\*.pf created on a host that does not run Patch My PC | file creation telemetry                  | medium     |

## 6\. Detection

The YARA rule targets the loader's configuration artefacts and the AMSI patch bytes. The strings are exact values from the Kaspersky report. The `PatchMyPC-ScriptRunner.exe.config` and `fabric.config` strings are specific to the malicious files, not to the legitimate Patch My PC tool, but test against your own Patch My PC deployment before enabling in blocking mode.

```yara
rule APT_NetamLoader_AppDomainManager_Chain
{
    meta:
        author = "Adverse Trace"
        date = "2026-10-29"
        reference = "https://securelist.com/netamloader/121676/"
        description = "Detects NetamLoader AppDomainManager injection config, fabric.config loader and AMSI patch bytes"
        tlp = "AMBER"

    strings:
        $adm_type  = "Microsoft.ApplicationServer.Caching.DataCacheFactoryConfiguration" ascii wide
        $adm_asm   = "Microsoft.HostIntegration.Connectors, Version=1.0.0.0" ascii wide
        $fabric    = "System.Resources.ResXResourceSet, System.Windows.Forms" ascii wide
        $resx      = "Resources.resx" ascii wide
        $amsi_patch = { 41 C7 00 01 00 00 00 33 C0 C3 }
        $etw_off   = "COMPlus_ETWEnabled" ascii wide
        $c2_path   = "/model_v4/" ascii wide
        $c2_host   = "openaigpt4" ascii wide
        $appid     = "{ff259bcd-2f0a-44de-b34a-0092fec1d8a2}" ascii wide nocase

    condition:
        uint16(0) == 0x5A4D and
        (
            (2 of ($adm_type, $adm_asm, $fabric, $resx)) or
            $amsi_patch or
            (2 of ($etw_off, $c2_path, $c2_host, $appid))
        )
}

```

The Sigma rule covers the process and registry behaviour. It assumes Sysmon with process creation, network and registry events, or equivalent EDR telemetry.

```yaml
title: NetamLoader dllhost COM surrogate with AppDomainManager config and C2 beacon
id: 7c1e4b2a-9f3d-4a61-8b0e-2d5c6f7a8b91
status: experimental
description: Detects NetamLoader behaviour - PatchMyPC-ScriptRunner spawning dllhost.exe, DllSurrogate registry write, and outbound HTTPS to openaigpt4 domain
author: Adverse Trace
date: 2026/10/29
references:

    - https://securelist.com/netamloader/121676/
tags:

    - attack.defense_evasion
    - attack.t1218
    - attack.t1055
logsource:
    product: windows
    category: process_creation
detection:
    selection_parent:
        ParentImage|endswith: '\PatchMyPC-ScriptRunner.exe'
        Image|endswith: '\dllhost.exe'
    selection_cmdline:
        CommandLine|contains:

            - '-updatepackage'
            - '-applicationid='
    condition: selection_parent or selection_cmdline
fields:

    - Image
    - ParentImage
    - CommandLine
    - User
falsepositives:

    - Legitimate Patch My PC update runs spawning COM surrogates
level: high
---
title: NetamLoader DllSurrogate registry write
id: 3a8d5e1f-6b2c-4c7d-9e0a-1f2b3c4d5e6f
status: experimental
description: Detects write of DllSurrogate under the NetamLoader appid CLSID
author: Adverse Trace
date: 2026/10/29
references:

    - https://securelist.com/netamloader/121676/
logsource:
    product: windows
    category: registry_set
detection:
    selection:
        TargetObject|contains: '\SOFTWARE\Classes\appid\{ff259bcd-2f0a-44de-b34a-0092fec1d8a2}'
        Details: ''
    condition: selection
falsepositives:

    - Unknown
level: high
---
title: Outbound connection to NetamLoader C2 host
id: 9b4c2d1e-8a7f-4e3b-b6c5-0d9e8f7a6b5c
status: experimental
description: Detects network connections to openaigpt4 domain or 104.18.14.219 used as NetamLoader C2
author: Adverse Trace
date: 2026/10/29
references:

    - https://securelist.com/netamloader/121676/
logsource:
    category: network_connection
    product: windows
detection:
    selection_domain:
        DestinationHostname|endswith: 'openaigpt4.com'
    selection_ip:
        DestinationIp: '104.18.14.219'
    condition: selection_domain or selection_ip
falsepositives:

    - None expected; the domain is not a legitimate service
level: critical

```

## 7\. Sources

- Kaspersky Securelist, "Unknown APT uses NetamLoader to attack a Win10 OS customized for governments in Asia", https://securelist.com/netamloader/121676/, 2026-10-29.

## 8\. Adverse Trace position

Adverse Trace assesses this as a targeted, single-victim intrusion against an Asian government platform, not a sector-wide campaign. No CVE has been assigned, nothing appears in NVD, EPSS or CISA KEV, and there is no exploitation deadline to track. The attribution is unconfirmed: Kaspersky could not link the activity to any known APT group and no MITRE ATT&CK profile exists for it, so we do not attribute it to a named actor. The technical significance for EMEA financial services is the delivery path, not the victim. A legitimate patch-management binary executed from `SoftwareDistribution`, a Microsoft-signed assembly abused for AppDomainManager injection, and an in-memory AMSI patch together defeat file-signature and local AMSI controls. Firms running third-party patch tooling should confirm that tooling verifies update integrity and does not execute from the Windows Update download directory. We will monitor for further Kaspersky reporting, for any CVE assignment against the `DataCacheFactoryConfiguration` or `ResXResourceSet` deserialization path, and for reuse of the `openaigpt4[.]com` infrastructure, and will reissue this advisory if any of those appear. All indicators here are single-sourced to Kaspersky; verify before blocking.

---

[Read the original source →](https://securelist.com/netamloader/121676/?ref=f4n6.co.uk)

*Published via PulseTrace — Adverse Trace threat intelligence.*