# 08 · The Zero-Day Research Capstone > **Audience / level:** Advanced red team operators and vulnerability researchers; assumes chapters 01–06. **Prerequisites:** COM activation internals, the impersonation contract, AppID security, OleViewDotNet basics, WinDbg attach/breakpoint fluency. **Estimated reading time:** 90–120 minutes. > After this chapter you will be able to run a repeatable, eight-stage pipeline — enumerate, triage, reverse, harness, fuzz, prove, weaponize, report — that turns the COM attack surface covered by this course into new, original bugs. **Contents** - [1. The research mindset](#1-the-research-mindset) - [2. Stage 1 — Enumeration: building the target list](#2-stage-1--enumeration-building-the-target-list) - [3. Stage 2 — Triage: ranking candidates](#3-stage-2--triage-ranking-candidates) - [4. Stage 3 — Static reverse engineering](#4-stage-3--static-reverse-engineering) - [5. Stage 4 — Dynamic analysis harness](#5-stage-4--dynamic-analysis-harness) - [6. Stage 5 — Fuzzing COM interfaces](#6-stage-5--fuzzing-com-interfaces) - [7. Stage 6 — From crash or lead to a proven primitive](#7-stage-6--from-crash-or-lead-to-a-proven-primitive) - [8. Stage 7 — Weaponization and reporting](#8-stage-7--weaponization-and-reporting) - [9. The research backlog: open problems worth hunting](#9-the-research-backlog-open-problems-worth-hunting) - [10. Appendix A — Master tooling table](#10-appendix-a--master-tooling-table) - [11. Appendix B — Master reading list](#11-appendix-b--master-reading-list) - [12. References](#12-references) --- ## 1. The research mindset COM remains under-explored for structural reasons, not because it is hidden. It is the substrate under OLE, ActiveX, WMI, the shell, Office automation, WinRT, and UAC; practically every Windows process loads `combase.dll`/`ole32.dll`; thousands of classes are registered by default; and activation is driven entirely by the registry, which makes the surface enormous, largely un-audited per class, and almost invisible to file-less-malware defenses. Chapter 01 mapped thirteen fundamental primitives rooted in that design; every technique in chapters 02–06 is an instance of one of them: | # | Primitive (chapter 01) | Attack family it feeds | |---|---|---| | 1 | HKCU shadowing of `CLSID\{X}\InprocServer32`/`LocalServer32` | Persistence / UAC bypass | | 2 | `TreatAs`/`AutoTreatAs` redirect | Persistence | | 3 | Phantom `InprocServer32`/`LocalServer32` paths | Persistence | | 4 | `Interface\{IID}\ProxyStubClsid32` shadow (DLL into *both* endpoints) | LPE / Persistence | | 5 | `TypeLib\{LIBID}\...\win32` path shadow + `LoadTypeLib` moniker quirk | Persistence / Execution | | 6 | ProgID/`CurVer` squatting | Persistence | | 7 | Moniker string injection (`script:`, `new:`, `session:`, `Elevation:`) | Execution | | 8 | ROT squatting/snooping | LPE / Execution | | 9 | Cross-session activation (`RunAs=Interactive User`) | LPE | | 10 | DCOM remote activation of LM-friendly classes | Lateral movement | | 11 | Custom-marshal blob abuse (`OBJREF_CUSTOM` forgery) | Execution / Relay | | 12 | Surrogate abuse (`DllSurrogate`) | Persistence / Execution | | 13 | Reg-free COM manifest hijack | Persistence / Execution | > **Key idea:** Thirteen primitives, six chapters of techniques, and no reason to believe the list is closed. The primitives are *design properties* (merged-view precedence, marshal-by-reference, AppID ACLs, the impersonation contract); design properties do not get patched — individual weaponizations do. ### 1.1 The two root patterns behind almost every find Nearly every bug in this course reduces to one of two root causes: 1. **"A service exposes a dangerous method to everyone."** DiagHub's SYSTEM service let any user drive `AddAgent(dllPath, guid)` into `LoadLibraryExW` ([3]). UPnP Device Host exposed the undocumented `IUPnPContainerManager` (IID `6D8FF8D4-730D-11D4-BF42-00B0D0118B56`) methods `ReferenceContainer`, `CreateInstance`, `CreateInstanceWithProgID` to any local user as LOCAL SERVICE — CVE-2019-1405, fixed by adding Administrators-only checks to the dangerous methods ([7]). StorSvc's `SvcMoveFileInheritSecurity` impersonated, moved the file, then reverted and called `SetNamedSecurityInfo` as SYSTEM — the late-impersonation pattern ([3]). USO loaded a non-existent `windowscoredeviceinfo.dll` from System32 on every session creation ([5]). 2. **"The registry is trusted more than it should be."** The `HKCR` merged view lets per-user keys silently override system keys ([47]); `ProxyStubClsid32` shadows inject a DLL into every process that marshals that interface, including SYSTEM servers; `TreatAs` redirects activation without touching the target's `InprocServer32` ([28], [29]); and `LoadTypeLib` parses a non-TLB path string as a *moniker display name*, so `"script:http://evil/x.sct"` reaches the script moniker from a "data" API ([23]). A third, smaller family is **marshaling trust**: forged `OBJREF`/`IStorage` bindings (CVE-2015-2370 and the whole potato lineage it birthed ([8], [17])) and objects marshaled by reference that were never meant to leave their process (trapped objects ([4])). ### 1.2 Microsoft's mitigation style — and what it teaches Microsoft rarely fixes a whole bug class; it kills the *weaponization primitive* that made the class exploitable: | Mitigation | Year | Primitive killed | Bug class left behind | |---|---|---|---| | 1809 silent `rpcss` fix (`CreateRemoteBindingToOR`, OXID on port 135 only, remote OXID queries as ANONYMOUS LOGON, captured tokens downgraded to Identification, CLSIDs gated to INTERACTIVE) | 2018 | Rotten/JuicyPotato reflection ([9]) | Service-account token capture — re-solved by RoguePotato and JuicyPotatoNG ([12], [13]; conceptual root in Forshaw's DCOM-relay work ([18])) | | DiagHub `ProcessImageLoadPolicy` (Microsoft-signed loads only) | 19H1/1903 | "Load arbitrary extension from System32" via `AddAgent` ([3]) | Arbitrary file-write bugs — re-bridged by USO ([5]) | | oleaut32 `VerifyTrust` (cached signing level ≥ 12 for TLBs in protected processes) | 2019-era | Type-library substitution inside protected processes ([4]) | Trapped-object instantiation — re-bridged via .NET/StdFont ([4]) | | CI.DLL `CipMitigatePPLBypassThroughInterpreters` (blocks `scrobj.dll`, `jscript.dll`, etc. in protected processes) | 1803 | Scriptlet-based PPL injection ([24]) | PPL type-confusion — re-bridged by KnownDlls aliasing, `IRundown::DoCallback` ([24], [25]) | | KB5004442 / CVE-2021-26414 (PKT_INTEGRITY floor for activation) | 2021–2023 | Relay *to* DCOM activation ([10]) | Authenticated admin DCOM LM; relay *from* DCOM ([26], [27]) | Three lessons fall out of that table: - **Chase primitives, not bugs.** When a loader policy or binding builder dies, the underlying file-write/auth-capture bugs usually survive; the researcher who finds the *next* bridge (USO after DiagHub, RoguePotato after JuicyPotato) owns the next CVE family. - **Diff the silent fixes.** The 1809 OXID change was never a CVE; it was found by researchers diffing `rpcss.dll` ([9]). `rpcss.dll`, `combase.dll`, `ole32.dll`, `oleaut32.dll` are the four binaries to BinDiff every Patch Tuesday. - **"Not a boundary" is a hunting license.** Microsoft services UAC and PPL slowly or not at all (no CVEs/bounties for PPL-only issues ([24]; "we don't consider UAC a hard security boundary" — MSRC case 64957, per Kanthak ([43])). Bug density in these zones stays high precisely because fixes ship late. ![Figure 1 — The eight-stage zero-day research pipeline](diagrams/d27-research-pipeline.png) *How to read this figure: the pipeline you will run for the rest of this chapter, left to right — enumerate (OleViewDotNet, registry sweeps), triage (OOP + SYSTEM + ACLs + dangerous methods), static RE, dynamic harness, fuzzing, root-cause, weaponize, report — with the tools named at each stage. Sections 2–8 map one-to-one onto the stages.* > **Legal:** Everything here is for authorized research: your own lab VMs, bug-bounty scope, or systems you are contracted to test. The enumeration and fuzzing stages are indistinguishable from attack behavior on a network you do not own. --- ## 2. Stage 1 — Enumeration: building the target list The goal of Stage 1 is a *complete* candidate list: every COM class on the box that could plausibly execute attacker-influenced logic at a higher privilege, plus every registry path whose trust could be subverted. Completeness matters more than precision — Stage 3 discards. > **Beginner note:** An **out-of-process (OOP) server** is a COM class whose code runs in its own process — a `LocalServer32` EXE, a service-hosted class, or a DLL hosted by the `dllhost.exe /Processid:{AppID}` surrogate. OOP matters because the server process often runs as SYSTEM, so "who may activate it and what methods does it expose" becomes a privilege question. In-process (`InprocServer32`) classes matter when the *host* is privileged (auto-elevated binaries, PPL services, other users' processes). ### 2.1 OleViewDotNet — deep usage OleViewDotNet (Forshaw) is the recon workhorse ([1]). Two front-ends, same data: **GUI views that build target lists:** - `Registry → Local Services` — COM objects hosted in Windows services, with filtering. This is the LPE shortlist. - `Registry → CLSIDs by Server` — group by server binary to see which DLL/EXE carries the most classes. - Object node → **View Launch Permissions / View Access Permissions** — the AppID SDDLs decoded; a class readable by `Authenticated Users`/`INTERACTIVE` shows up immediately. - AppID properties expose `RunAs`, service name, and **ServiceProtectionLevel** (PPL); the class list can be filtered to **"Run as: Interactive User"** — the exact filter that surfaces cross-session candidates such as the PhoneExperienceHost class `{7540C300-BE9B-4C0D-A335-F002F9AB73B7}` behind bohops' CVE-2023-33127 chain ([11]). **PowerShell module** (`Install-Module OleViewDotNet` — **PowerShell 5 only, not 7+**): ```powershell Get-ComClass -Service # all service-hosted classes (the LPE shortlist) Get-ComClass -Clsid 42CBFAA7-A4A7-47BB-B422-BD10E9D02700 $cls.Servers # InProc vs Local server registrations $cls.AppIDEntry # RunAs identity, service name $cls.AppIDEntry.ServiceProtectionLevel # PPL check, e.g. WindowsLight Get-ComInterface -Class $cls # interfaces the class advertises New-ComObject -Clsid 72566E27-1ABB-4EB3-B4F0-EB431CB1CB32 Import-ComTypeLib -Object $obj # pull the object's type library Get-ComObjRef $obj # proves OOP: shows hosting PID/process name ``` Worked example — the exact enumeration behind the trapped-objects research ([4]): `Get-ComClass -Service` → enumerate interfaces → filter `IsDispatch` → **five candidates on a default box**: WaaSRemediation `{72566E27-1ABB-4EB3-B4F0-EB431CB1CB32}`, SearchGatheringManager `{9E175B68-F52A-11D8-B9A5-505054503030}`, SearchGathererNotification `{9E175B6D-F52A-11D8-B9A5-505054503030}`, AutomaticUpdates `{BFE18E9C-6D87-4450-B37C-E02F0B373803}`, and `Microsoft.SyncShare.SyncShareFactoryClass` `{DA1C0281-456B-4F14-A46D-8ED2E21A866F}`. One `IsDispatch` filter turned "thousands of classes" into a weekend-sized list — that is what good enumeration looks like. OleViewDotNet can also invoke arbitrary methods, view the ROT, parse `.winmd` metadata, and spawn elevated instances (`CreateElevated`). ### 2.2 Raw-registry sweeps OleViewDotNet reads the registry; sometimes you want the registry itself: ```powershell # Full CLSID/AppID walk (machine + merged view) Get-ChildItem Registry::HKEY_CLASSES_ROOT\CLSID reg query HKCR\CLSID /s # DCOM-reachable applications and their AppIDs Get-CimInstance Win32_DCOMApplication # Orphan sweep (bohops): registered servers whose binary is missing ([28]) $inproc = Get-WmiObject Win32_COMSetting | ?{ $_.InprocServer32 -ne $null } foreach ($p in ($inproc | %{$_.InprocServer32})) { $p; cmd /c dir $p > $null } # "File Not Found" = orphan # Scheduled tasks with COM handler actions = timed triggers ([34]) foreach ($Task in Get-ScheduledTask) { if ($Task.Actions.ClassId -ne $null -and $Task.Triggers.Enabled -eq $true -and $Task.Principal.GroupId -eq "Users") { Write-Host "$($Task.TaskName) :: $($Task.Actions.ClassId)" } } ``` - **Dangling references:** ProcMon during logon/app launches with `Operation is RegOpenKey` + `Result is NAME NOT FOUND` + `Path ends with InprocServer32` — every hit is a CLSID a live process *tries* to activate that you can register in HKCU ([30]). The ClickOnce phantom-object technique (pre-registering a CLSID that `dfsvc.exe` registers later) is this idea weaponized ([31]). - **Phantom hunting generally:** ProcMon `Path contains InprocServer32/LocalServer32/TreatAs/ProxyStubClsid32`, `Result = NAME NOT FOUND`. - **Per-user shadow audit:** diff `HKCU\Software\Classes\CLSID` and `...\TypeLib` against HKLM; anything present in both with different server paths is an existing hijack or a plant. ### 2.3 The WinRT surface WinRT is COM vNext — same `IUnknown` base, `IInspectable` instead of `IDispatch`, `.winmd` metadata instead of TLBs — but its classes register per-package under `HKLM\SOFTWARE\Microsoft\WindowsRuntime` (with `ActivatableClassId` server mappings), **not** `HKCR\CLSID`. Classic CLSID tooling does not see them; OleViewDotNet parses both worlds. Brokers are just OOP COM servers with sandbox-facing activation permissions — CVE-2019-0555 (XML DOM exposed through WinRT → XSLT sandbox escape) is the canonical find ([4]). Enumerate this hive separately or your target list has a hole. ### 2.4 Automation: the incendium.rocks methodology Manual browsing does not scale. The incendium.rocks methodology ([2]) automates the loop end-to-end: walk the registry/CLSID set → use OleViewDotNet to dump each class's interfaces and methods to **JSON** → build dynamic `IDispatch` stubs at runtime and **automatically `Invoke`** every method with generated arguments → logHRESULTs, crashes, and side effects. OleViewDotNet builds dynamic `IDispatch` stubs at runtime to call arbitrary vtables — the same primitive every COM fuzzer uses (§6). ### 2.5 Standing on corpora Do not re-derive what is published: the JuicyPotato per-OS abusable-CLSID lists (`ohpe.it/juicy-potato/CLSID/`) encode the potato criteria (instantiable by the user, implements `IMarshal`, elevated server identity) per Windows build ([16]); the strontic xcyclopedia CLSID library catalogs classes and their capabilities; the juicy-potato repo README tables map CLSIDs to working OS versions. NCC's acCOMplice ships `masterkeys.csv` of known hijackable shell classes (§10). These are starting sets — your job is to extend them, not worship them. --- ## 3. Stage 2 — Triage: ranking candidates A default Windows box yields thousands of classes; you can reverse perhaps a dozen well. Triage is a scoring pass that answers one question: *if I drive this object, does privileged code do something I control?* Every heuristic below is drawn from the case studies in this course — each is a property that a published bug actually had. ### 3.1 The master checklist A candidate is promising if it checks these boxes, in descending order of importance: 1. **OOP server.** Registered with `LocalServer32`, hosted in a service via its AppID, or running in a `dllhost` surrogate. In-proc classes count only when the host is privileged (auto-elevated binary, PPL service, another user's process). 2. **Privileged identity.** Server runs as `NT AUTHORITY\SYSTEM` (direct win), `LOCAL SERVICE`/`NETWORK SERVICE` (hop — these hold `SeImpersonatePrivilege`, the potato entry point), or another user / `RunAs=Interactive User` (cross-session). 3. **Reachable ACLs.** `LaunchPermission` + `AccessPermission` (or machine defaults under `HKLM\SOFTWARE\Microsoft\Ole`) include your principal: `Authenticated Users` (S-1-5-11), `INTERACTIVE` (S-1-5-4), or AppContainer/LPAC capability SIDs for sandbox escapes. DiagHub's launch SDDL literally contained `(A;;CCDCSW;;;AU)` — Authenticated Users ([3]). 4. **Dangerous methods.** Interface methods that touch: filesystem paths (`CreateFile`, `MoveFile`, delete/rename), the registry, process creation, `LoadLibrary*`/`GetProcAddress`, `SetNamedSecurityInfo`/ACL APIs, token APIs — or that **accept interface pointers** (callback-impersonation pattern: DCOMPotato's attacker-supplied `IUnknown` impersonates the SYSTEM caller inside its own `QueryInterface`) or **return objects** (trapped-object pattern: the returned reference stays live in the server ([4])). 5. **Marshaling trust.** Class implements `IMarshal` (potato criterion ([16])), is marshaled TypeLib-driven via `PSOAInterface` `{00020424-0000-0000-C000-000000000046}` (type-library substitution applies), or its `Interface\{IID}\ProxyStubClsid32` can be shadowed per-user (a DLL into both endpoints). 6. **Bonus multipliers.** `IDispatch`/`dual` present (type-info vector — `ITypeInfo::CreateInstance` instantiates server-side ([4])); .NET COM interop (loads the CLR into the server); `RunAs=Interactive User` (cross-session); `Elevation\Enabled=1` (UAC elevation-moniker surface ([37])); server binary unsigned or third-party (patch-cycle lag). ### 3.2 Scored triage table *(illustrative scoring)* The weights below are a starting heuristic, not ground truth — calibrate them against your own hit rate. | Signal | Where you read it | Points *(illustrative)* | |---|---|---| | OOP server (LocalServer32 / service AppID / surrogate) | OleViewDotNet `.Servers`, AppID entry | +3 | | Runs as SYSTEM | AppID `LocalService`, service config | +3 | | LOCAL/NETWORK SERVICE identity (potato hop) | AppID / service config | +2 | | Launch+Access ACLs include AU / INTERACTIVE / LPAC | OVDN View Permissions | +3 | | Method takes a path/URL/command string | Proxy definition / typelib | +2 | | Method wraps `LoadLibrary*`, process creation, or `SetNamedSecurityInfo` | Static RE (§4) | +3 | | Method accepts an interface-pointer argument | Proxy definition | +2 | | Method returns an object reference | Proxy definition | +2 | | `IDispatch`/dual interface | `Get-ComInterface`, `IsDispatch` | +2 | | Implements `IMarshal` | Interface list | +1 | | TypeLib-driven marshaling (`PSOAInterface` proxy) | `HKCR\Interface\{IID}\ProxyStubClsid32` | +1 | | .NET interop (`mscoree.dll` InprocServer32) | Registry | +1 | | `RunAs = Interactive User` | AppID entry / OVDN filter | +2 | | Server is PPL (`.AppIDEntry.ServiceProtectionLevel`) | OleViewDotNet | +1 (PPL-class impact) | > **Key idea:** Read the table historically: DiagHub scores on rows 1, 2, 3, 4, 5; UPnP CVE-2019-1405 on 1, 2, 3, 4; the StdFont trapped-object chain needed only rows 4 (returns object), 5, and 6 (`IDispatch`). No published bug needed every row — three or four of the heavy ones suffice. Kill anything scoring 0 on rows 1–3 unless you are specifically hunting hijacks. For persistence-style targets (chapter 05) the analogous score is: **trigger frequency x host desirability x breakage risk** — count `RegOpenKey` hits per CLSID per process per hour from a ProcMon boot trace (or hijack several candidates with a logging DLL, acCOMplice `Hijack-MultipleKeys`-style), prefer explorer/browsers/taskhostw over niche hosts, and prefer orphaned/abandoned/undefined classes that a Windows update will not re-register ([31]). --- ## 4. Stage 3 — Static reverse engineering Static RE answers two questions per candidate: **what are the exact method signatures** (so you can call them) and **where does the server mishandle trust** (so you know what to call). The canonical recipe is the one Forshaw used against DiagHub ([3]), generalized below, with itm4n's USO service work ([5], [6]) as the second reference implementation. ### 4.1 The DiagHub recipe, generalized 1. **Instantiate and inspect.** In OleViewDotNet, create an instance of the class → right-click → *Marshal ⇒ View Properties*. Capture the **PID** of the hosting process, the **IPID** (per-interface-pointer GUID), the **OXID** (object exporter), the string bindings, and the authentication services. This proves the object is OOP and names its host. 2. **Get the server-side vtable address.** OleViewDotNet's process view (needs admin plus configured symbols: dbghelp from the WinDbg install and `srv*https://msdl.microsoft.com/download/symbols`) → find your IPID entry → it shows the interface pointer and the **server-side VTable address**, e.g. `DiagnosticsHub_StandardCollector_Runtime+0x36C78` for DiagHub. 3. **Symbolize the vtable.** Attach WinDbg to the server process and dump the vtable with `dqs + L` — Microsoft public symbols resolve the slots to real names. DiagHub's `IStandardCollectorService` (IID `0D8AF6B7-EFD5-4F6D-A834-314740AB8CAA`) yielded `CreateSession`, `GetSession`, `DestroySession`, `DestroySessionAsync`, `AddLifetimeMonitorProcessIdForSession` exactly this way ([3]): ```text 0:019> dqs DiagnosticsHub_StandardCollector_Runtime+0x36C78 L8 ``` 4. **Recover signatures from the wire format.** OleViewDotNet's **View Proxy Definition** decompiles the NDR "stubless" bytecode of the proxy into method signatures; the **Structures tab** gives marshaled struct layouts. Rebuild the interface in C++/C# from these. For DiagHub this produced the `SessionConfiguration` struct and `CreateSession`/`AddAgent` prototypes the exploit needed. 5. **Reconcile with disassembly.** In IDA/Ghidra: xref command/operation strings (itm4n found `"StartScan"` in `usosvc.dll` and walked the xrefs into `PerformOperationOnSession()`/`PerformOperationOnManager()` ([6])); where CFG is present, map `_guard_dispatch_icall_fptr` indirect calls to vtable slots with dynamic breakpoints; match client-side proxy slots (`ObjectStublessClientN`) to server-side symbols so client slot *N* = server function you are reading. 6. **Hunt the failure modes** (this is the actual bug list; every one is a published bug class): | Failure mode in server code | Historical instance | |---|---| | Missing `CoImpersonateClient`/`RpcImpersonateClient` around a privileged op | Classic privileged-file-operation class | | Impersonate → check → `RevertToSelf` → *then* write | StorSvc `SvcMoveFileInheritSecurity` ([3]) | | Accepting an identify-level token where impersonation is required | Potato CLSID hardening regression space ([9]) | | Device-map / symlink / hard-link handling while impersonating | CVE-2019-0841 AppXSvc, StorSvc hard links ([3]) | | Path validation that constrains directory but not extension/content | DiagHub `GetValidAgentPath` ([3]) | | `RunAs` mismatch / missing client-identity verification | CVE-2017-0100 HelpPane ([46]) | | Type-library trust (stub generated from attacker-controlled TLB) | NGEN type confusion, trapped objects ([24], [4]) | | Unmarshal-by-reference of objects never meant to leave the server | CVE-2019-0555, CVE-2017-0211 ([4]) | ### 4.2 The USO variant — when the tool fails, pivot itm4n's USO write-up is the honest version of this workflow ([5], [6]): `symchk` pulled PDBs first (symbols are leverage, always try); string xref on `"StartScan"` located the trigger path; OleViewDotNet then **failed to expand the object** (`ClassFactory cannot supply requested class`) — and the research continued anyway, client-side: breakpoint on `_guard_dispatch_icall_fptr` after `CoCreateInstance`, `dqs` on the client proxy vtable (`usoapi!IUpdateSessionOrchestratorProxyVtbl`), then match `ObjectStublessClientN` slots against server symbols in `usosvc.dll`. The result was the full map of `IUpdateSessionOrchestrator` (`{07F3AFAC-7C8A-4CE7-A5E0-3D24EE8A77E0}`: `CreateUpdateSession`, `GetCurrentActiveUpdateSessions`, `LogTaskRunning`, `CreateUxUpdateManager`, `CreateUniversalOrchestrator`) and the 68-method `IUsoSessionCommon` (`{FCCC288D-B47E-41FA-970C-935EC952F4A4}`), with `VTable[21]` identified as the StartScan trigger. > **Key idea:** OleViewDotNet failing on a class is information, not a dead end. `ClassFactory cannot supply requested class` means the activation path itself is unusual (locked-down factory, wrong CLSCTX, interface-only marshaling) — switch to client-side dynamic analysis of the proxy and read the server from the disassembler. > **Warning:** WinDbg-attaching to a SYSTEM service freezes its threads while broken in; RPCSS garbage-collects OXIDs on missed pings, and some services watchdog-restart. Snapshot the VM first, and prefer non-invasive attach (`-pv`) when you only need `dqs`. --- ## 5. Stage 4 — Dynamic analysis harness Static reading tells you what the server *can* do; the harness tells you what it *actually does when you call it*, under which token, touching which paths. The harness is deliberately minimal: a C++ client you control argument-by-argument, plus observation tooling on the server process. ### 5.1 The minimal client skeleton The shape comes directly from the published DiagHub/USO clients ([3], [6]): initialize, activate OOP, **offer impersonation**, then call methods with controlled inputs. The `CoSetProxyBlanket(... RPC_C_IMP_LEVEL_IMPERSONATE ...)` call is not ceremony — itm4n's StartScan flow required it, because a server can only impersonate a client that lets it (the impersonation contract of chapter 03). ```cpp // Minimal COM method-probing client (after itm4n's USO "StartScan" flow ([6])) CoInitializeEx(0, COINIT_MULTITHREADED); CoCreateInstance(CLSID_TargetClass, nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&service)); service->LogTaskRunning(L"Probe"); // any bookkeeping call service->CreateSession(1, &IID_ISessionItf, &session); // obtain the interesting interface CoSetProxyBlanket(session, RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT, COLE_DEFAULT_PRINCIPAL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, NULL); session->TheMethod(0, 0, L"C:\\Users\\Public\\probe.txt"); // controlled inputs here CoUninitialize(); ``` ```cpp // Generic one-method-per-argument sweep (illustrative) // For each method M and each string argument A: call M with A set to a // canary path; log HRESULT; check ProcMon for the canary appearing in the // server's file/registry operations. HRESULT hr = E_FAIL; for (auto& m : methods) { for (auto& arg : m.stringArgs) { hr = m.invoke(canaryPath(arg)); log(m.name, arg.index, hr); // non-E_INVALIDARG HRESULTs = arg parsed } } ``` > **Beginner note:** `CoSetProxyBlanket` sets per-proxy security (it wraps `IClientSecurity::SetBlanket`): which authentication level and *impersonation level* the server gets on calls through that one proxy. `RPC_C_IMP_LEVEL_IDENTIFY` (2) lets the server only identify you — its token cannot access objects; `RPC_C_IMP_LEVEL_IMPERSONATE` (3) lets it act as you locally. If a bug needs the server to touch your files as you, offer 3. ### 5.2 Observation stack | Tool | Configuration | What it proves | |---|---|---| | ProcMon | Filter: server PID (from §4 step 1); watch file/registry/LoadImage operations | Which paths the server touches **as its own identity**; canary strings reaching `CreateFile` | | API Monitor | Hook the server binary | Parameter-level view of `CreateFileW`/`LoadLibraryExW`/registry calls | | WinDbg breakpoints | `CoImpersonateClient`, `RpcImpersonateClient`, `CoRevertToSelf`, `CreateFileW`, `RegCreateKeyExW`, `LoadLibraryExW`, `SetNamedSecurityInfo` | Whether the server impersonates *at all*, and whether the sensitive call happens **before or after revert** (the late-impersonation bug pattern) | | TokenViewer (Forshaw) | Inspect the token the server captured | Impersonation vs Identification token — the #1 cause of "exploit didn't work" confusion (early RoguePotato experiments captured "useless" Identification tokens ([12])) | | ETW | `Microsoft-Windows-RPC` (`{6AD52B32-D609-4BE9-AE07-CE8DAE937E39}`, Debug — EID 5/6 give InterfaceUuid/OpNum/Protocol/Endpoint), `Microsoft-Windows-RPC-Events` (`{F4AED7C7-A898-4627-B053-44A7CAA12FCD}`), `Microsoft-Windows-RPCSS` (`{D8975F88-7DDB-4ED0-91BF-3ADF48C48E0C}`), `Microsoft-Windows-COMRuntime` (`{BF406804-6AFA-46E7-8A48-6C357E1D6D61}`, verbose) | Activation and call tracing without a debugger; which interface/opnum your client actually reached | Enable the COMRuntime provider (plus the RPC providers) for activation tracing before each run; for cross-checking the wire, Wireshark's `dcom`/`dcerpc` dissectors find the `MEOW` signature of marshaled references. The full ProcMon filter set for hijack-style targets is the phantom set from §2.2 (`Path contains InprocServer32/LocalServer32/TreatAs/ProxyStubClsid32`, `Result = NAME NOT FOUND`). ### 5.3 What you are looking for - **Token sequencing:** breakpoint hits on `CreateFileW`/`SetNamedSecurityInfo`/`LoadLibraryExW` with no preceding `CoImpersonateClient` (missing impersonation), or after `CoRevertToSelf` (late impersonation — the StorSvc pattern ([3])). - **Identity of file ops:** ProcMon shows the op performed as SYSTEM against your canary path in a user-writable directory. - **Reachability of dangerous paths:** your string argument landing verbatim in a `LoadLibraryExW` path or a command line. - **Reference leaks:** the returned proxy's `Get-ComObjRef` showing an object living in the server that the design never intended to expose (trapped-object lead ([4])). > **OpSec:** A harness is noisy by design — rapid-fire activation, odd arguments, debugger processes. Run it in a snapshot-isolated VM. The same telemetry that helps you (ETW RPC EID 5/6, ProcMon canaries) is what a defender uses, so the harness doubles as a detection-engineering data source: record what every probe looks like in the logs for the report (§8). --- ## 6. Stage 5 — Fuzzing COM interfaces Logical bugs (Stages 3–5) pay best, but COM interfaces are also a memory-corruption surface: every OOP call is attacker-controlled NDR bytes being unmarshaled in a privileged process — the exact layer OleViewDotNet decompiles in *View Proxy Definition*. WalletService's CVE-2020-1362 is the proof of concept for the whole category: `Wallet::WalletCustomProperty::SetGroup` OOB write over DCOM → `SetLabel` BSTR pointer write-what-where → fake vtable → virtual call redirected into `dxgi` code whose `LoadLibraryExW` uses a writable global path → SYSTEM ([42]). ![Figure 2 — COM fuzzing harness anatomy](diagrams/d28-fuzzing-harness.png) *How to read this figure: the harness loop — create a valid object, iterate interface/method pairs from the recovered signatures (§4), mutate typed arguments (BSTR paths, SAFEARRAY bounds, VARIANT types, IStream blobs, fake interface pointers), log every HRESULT, and let a crash monitor (page heap + AppVerifier + debugger + WER) catch faults, feeding interesting inputs back into the corpus.* ### 6.1 Mutation strategies that match the marshaling layer 1. **Raw NDR buffer mutation.** Interpose between proxy and channel and mutate the marshaled buffer before it reaches the server's **NDR interpreter stubs** (the stubless-engine layer). Watch for OOB reads/writes in server-side unmarshaling (the WalletService class) and for marshal-by-reference object leaks (§5.3). Because signatures come from §4, you know which bytes are length fields, pointers, and conformant-array bounds. 2. **Typed argument mutation.** Higher yield per call, because the arguments are semantically typed: | Argument type | Mutations *(illustrative test list)* | Historical rationale | |---|---|---| | `BSTR` path/URL strings | Overlong strings, embedded NULs, `\??\` and device paths, junction/symlink targets, non-existent extensions on valid directories | DiagHub extension-agnostic load ([3]); USO non-existent DLL ([5]); mock-directory normalization desync | | `SAFEARRAY` | Bounds/count fields desynced from payload size; multidimensional edge cases | Conformant-array handling in the NDR engine | | `VARIANT` | Type-tag vs payload confusion (tag says `VT_BSTR`, payload is a pointer-sized integer); nested arrays; `VT_UNKNOWN`/`VT_DISPATCH` carrying unexpected pointers | TLB/proxy type-confusion family ([24], [4]) | | `IStream`/`IStorage` blobs | Truncated streams, negative sizes, streams whose content is a second marshaled object | `CoGetInstanceFromIStorage` OBJREF forgery lineage ([8]) | | Interface pointers | Fake/foreign interface pointers, pointers to objects of the wrong class, freed-then-reused pointers | Callback-impersonation (DCOMPotato) and trapped-object classes ([4]) | 3. **Interface brute-calling (poor-man's fuzzer).** The OleViewDotNet PowerShell loop — `New-ComObject` + reflection-driven method invocation with generated arguments — requires zero harness code and is exactly what the incendium.rocks automation formalized: registry → JSON of interfaces/methods → automated `Invoke` ([2]). OleViewDotNet builds the dynamic `IDispatch` stubs; you supply the argument generator and the logging. ### 6.2 What the field already built - **COMRace** (USENIX Security '22) — data-race detection in COM objects; races matter because MTA-hosted objects are called on arbitrary RPC thread-pool threads and must self-synchronize ([39]). - **Black Hat EU 2024, "Enhancing Automatic Vulnerability Discovery for Windows RPC/COM in New Ways"** — harness-generation research for RPC/COM fuzzing ([40]). - **RPC-aware fuzzing driven from IDA-generated clients** — the manual version of the same idea: reverse the interface (§4), generate the client, fuzz through it. ### 6.3 Crash triage setup The monitor stack shown in Figure 2 is page heap + AppVerifier on the server process, a debugger (or time-travel trace) attached for first-chance exceptions, and WER as the collection backstop. The briefs underlying this course do not specify exact configuration flags, so treat the specific `gflags`/AppVerifier settings as **(verify in lab)** against your Windows build before relying on them. What the course case studies do establish: crashes inside `ole32`/`combase` unmarshaling or inside the server method itself are the signal; crashes in your own proxy are harness bugs — filter by faulting module before investing in root cause. > **Warning:** Fuzzing a SYSTEM service will, by design, crash it. Some services are marked critical — a fault can bugcheck the box or leave the service dead until reboot. Snapshot the VM, fuzz one interface at a time, and keep the corpus so every crash is replayable. --- ## 7. Stage 6 — From crash or lead to a proven primitive A crash or an odd HRESULT is not a finding. A finding is a **primitive**: a repeatable statement like "any local user can cause an arbitrary file write as SYSTEM" with a PoC that proves it. The taxonomy below maps raw leads onto this course's bug classes, with the historical proof for each — use it to route your lead to the right proving strategy. ### 7.1 Outcome taxonomy, mapped to the course's bug classes | Lead (what you observed) | Bug class | Proven primitive | Historical proof | |---|---|---|---| | Server touches attacker paths without (or after) impersonation | Missing/late impersonation | Arbitrary file write / ACL set as SYSTEM | StorSvc `SvcMoveFileInheritSecurity` + hard links → `SetNamedSecurityInfo` applies attacker ACEs to any file SYSTEM can `WRITE_DAC` (P0 1427/1428) ([3]) | | Method loads libraries/executables from partially-controlled paths | Dangerous method exposed to everyone | Code execution as server identity | DiagHub `AddAgent` ([3]); UPnP `IUPnPContainerManager` command exec as LOCAL SERVICE, CVE-2019-1405 ([7]) | | Returned proxy references an object still living in the server | Trapped object | Server-side `CoCreateInstance` of attacker-chosen classes | `IDispatch::GetTypeInfo` → `ITypeInfo::CreateInstance` → StdFont planted inside the service; chained to .NET `Assembly.Load` in PPL ([4]) | | Stub built from attacker-influenced type library | TypeLib/proxy confusion | Type confusion in server stub; unsigned code in protected processes | NGEN `ICorSvcPooledWorker::CanReuseProcess` integer-as-pointer → KnownDlls aliasing → PPL injection ([24]) | | Registry shadow/redirect loads attacker code | Registry hijack | Execution inside any process that activates the class, incl. elevated/PPL hosts | Per-user CLSID/`TreatAs`/`TypeLib` hijacks (chapters 04–05); StdFont `TreatAs` → `System.Object` ([4]) | | Server calls into an attacker-implemented callback object | Callback impersonation | Server's token captured in-process | DCOMPotato/PrintNotifyPotato: fake `IUnknown` callback, `CoImpersonateClient()` inside `QueryInterface` impersonates the SYSTEM caller | | `RunAs=Interactive User` class reachable cross-session | Cross-session activation / missing client verification | Code in another user's/session's context | CVE-2017-0100 HelpPane ([46]); CVE-2023-33127 PhoneExperienceHost chain ([11]) | | Memory-corruption crash in unmarshaling or method body | NDR/argument corruption | Controlled write → fake vtable → code exec | CVE-2020-1362 WalletService BSTR write-what-where ([42]) | ### 7.2 How "proven" looks for each class - **File write:** demonstrate creation/content control of a file at a SYSTEM-writable-only path (the DiagHub chain used `C:\Windows\System32\license.rtf`, chosen as a non-TrustedInstaller-owned, non-critical System32 file — candidates enumerated with NtObjectManager's `Get-AccessibleFile -AccessRights WriteDac` against the StorSvc process token ([3])). - **Server-side instantiation:** `Get-ComObjRef` on the returned object must show the hosting PID is the *service* process — that single screenshot is the trapped-object proof ([4]); public third-party PoCs by Fakroud and IBM X-Force reproduce the chain end-to-end ([20], [21]). - **Type confusion:** show the server stub interpreting your controlled input as a pointer (crash with your value in a dereferenced register), then escalate to a controlled write. - **Callback impersonation:** inside your callback, `OpenThreadToken` and print the user — if it reads SYSTEM, the primitive is proven; TokenViewer removes all doubt (§5.2). - **Memory corruption:** faulting address controlled by an input field; then the CVE-2020-1362 template (OOB → write-what-where → fake vtable → loader hijack) ([42]). ### 7.3 Reliability work (where most PoCs actually live) - **STA pumping.** If your client or callback object lives in an STA, you *must* pump messages (`GetMessage`/`DispatchMessage`) or cross-apartment calls hang — and the reentrancy window during an outgoing call is where callback impersonation lands. Raymond Chen's write-up of COM failing to pump in a single-threaded apartment is the canonical failure narrative ([45]). Put exploit threads in the MTA unless you specifically need STA reentrancy. - **Session / window-station issues.** Spawning a process from a captured service token hits Session-0 window-station permission problems; RoguePotato's final `CreateProcessAsUser` step required a Session-0 window-station permission fix ([12]), and its SYSTEM token was kidnapped from the rpcss logon session that NETWORK SERVICE shares with SYSTEM-token-holding threads ([19]). Cross-session activations likewise depend on *which* session is currently interactive ([11]). - **Token type math.** `CreateProcessWithTokenW` needs an impersonate-capable primary-token duplicate; `CreateProcessAsUser` needs `SeAssignPrimaryTokenPrivilege`; an Identification token is a dead end for both — verify the captured token in TokenViewer before writing the spawn code ([12]). - **Ping/liveness.** Holding OBJREFs across long analysis sessions fails silently: missed pings let the server garbage-collect stubs. Re-resolve OXIDs on long runs. --- ## 8. Stage 7 — Weaponization and reporting ### 8.1 The full-chain template The course's two end-to-end chains (DiagHub, USO) share one template; every new primitive you prove should be driven through the same four stages: 1. **Primitive** — the thing Stage 6 proved (arbitrary file write, server-side instantiation, token capture, type confusion). 2. **File write (if not already code execution)** — overwrite a loadable artifact in a privileged location. The canonical target properties: System32-resident, not TrustedInstaller-owned, not system-critical. DiagHub's worked example used `C:\Windows\System32\license.rtf` ([3]); LocalPotato's write primitive was aimed at `SprintCSP.dll` or `printconfig.dll` ([14]). 3. **Loader trigger** — a COM/RPC method that loads or executes the planted artifact *as the privileged identity*, ideally **outside `DllMain`/loader lock**: DiagHub `AddAgent("license.rtf", guid)` (the service calls `DllGetClassObject` after load ([3])); USO's `windowscoredeviceinfo.dll` load on Update Session creation, triggered by `usoclient.exe StartScan` or directly over COM (the service calls a specific export after load ([5], [6])); `SprintCSP.dll` + `SvcRebootToFlashingMode`, or overwrite `printconfig.dll` and instantiate PrintNotify ([14]). 4. **SYSTEM** — payload runs in the service context; if you captured a token instead, apply §7.3's token math. ```text primitive ──► file write ──► loader trigger ──► SYSTEM StorSvc ACL license.rtf DiagHub AddAgent DllGetClassObject as SYSTEM ([3]) any write windowscoredeviceinfo.dll USO session create export call as SYSTEM ([5]) LocalPotato SMB SprintCSP.dll SvcRebootToFlashingMode service as SYSTEM ([14]) ``` > **Key idea:** Microsoft keeps killing stage 3 (`ProcessImageLoadPolicy`, `VerifyTrust`, KnownDlls changes) because stages 1–2 are cheap to find. Budget your research time accordingly: a standing list of *fresh loader triggers* is the reusable asset; the file-write bugs that feed them are renewable. ### 8.2 Reporting norms (as supported by the course's documented cases) - **Know the boundary rules before you write.** Microsoft's servicing criteria decide whether your finding gets a CVE: UAC is explicitly *not* a hard security boundary ("we don't consider UAC a hard security boundary, but rather, a customizable enhancement" — MSRC case 64957, per Kanthak ([43])); PPL-only escapes get no CVEs/bounties, with fixes shipped late in new Windows versions ([4], [24]); integrity levels are not a security boundary either — the lesson of the CVE-2017-0298 bad fix, where HelpPane compared integrity levels instead of verifying the caller's admin membership. The LocalPotato HTTP/WebDAV scenario was left unpatched as an explicit Microsoft decision ([15]). Servicing-criteria link: ([44]). - **Write the report like the ones that landed.** Forshaw's P0 issues are the model: mechanism-first (what trust assumption fails), minimal PoC, affected builds, and — critically — follow-up when the fix is wrong ("Bad Fix for COM Session Moniker EoP" became CVE-2017-0298). Track the fix: the 1809 OXID change was a *silent* `rpcss.dll` fix with no CVE, found by diffing ([9]). - **Coordinated disclosure in practice (from the course corpus):** CVE-2015-2370 reported 2015-04-09 via Project Zero, patched as MS15-076 on 2015-07-14 ([8]); the trapped-COM-objects bug class was published as a *class* write-up after Microsoft declined boundary status ([4]); decoder's "No more rotten/juicy potato?" documented a silent mitigation publicly ([9]); CISA KEV later absorbed CVE-2017-0213 and CVE-2019-1388 — evidence that "not fixed" does not mean "not exploited." - **Detection content is part of the deliverable.** Include the telemetry map with your PoC: which ETW providers fire (`Microsoft-Windows-RPC` EID 5/6 records InterfaceUuid/OpNum), which DistributedCOM events appear (10036–10038 for hardening refusals), which registry values change (`AllowDCOMReflection`/`OnlyUseLatestCLR` are high-fidelity trapped-COM artifacts). A finding that ships with its own detections gets patched — and credited — faster. --- ## 9. The research backlog: open problems worth hunting Every row below is an open direction *stated in the underlying research* — not speculation. The first experiment is sized to one lab day. | Hypothesis | Why it might exist | First experiment | |---|---|---| | **Alternative `IDispatch` classes** beyond the documented five enable trapped-object chains without the PPL CLR-load limitation | Outflank's LLM-assisted enumeration found exactly such alternatives after the WaaSMedicSvc path failed on updated Win11; the failure is target-specific, not class-specific ([22]) | Re-run `Get-ComClass -Service` → `IsDispatch` filter across builds, SKUs, and third-party software; for each hit, walk `ReferencedTypeLibs` and test server-side `CreateInstance` of an in-proc CoClass | | **Trapped-object variants beyond StdFont** | StdPicture has an OOP check; StdFont does not — registration checks are per-class, so other in-proc CoClasses in commonly referenced typelibs may share the gap; `stdole` is virtually always referenced, and Forshaw found no direct EoP in the font object itself, leaving the class under-explored ([4]) | Enumerate every CoClass in the referenced typelibs of each IDispatch server; instantiate each via the remote typelib and confirm host PID with `Get-ComObjRef` | | **Reg-free COM manifest hijack** as a stealth path | Activation-context manifests resolve classes before the registry; entries are invisible to naive `HKCR` hunting and need no registry write at all | Inventory `%WinDir%\WinSxS\Manifests` for `comClass`/`comInterfaceExternalProxyStub` declarations; in a lab, plant an attacker manifest beside a side-loadable binary and observe resolution order | | **WinRT broker surface** hides the next sandbox escape | Brokers are OOP COM servers with sandbox-facing activation permissions, registered under `HKLM\SOFTWARE\Microsoft\WindowsRuntime` where classic CLSID tooling cannot see them; CVE-2019-0555 is the precedent ([4]) | Enumerate `ActivatableClassId` server mappings; run the §3 triage checklist against broker AppIDs, prioritizing AppContainer-reachable ones | | **Session/cross-session activation** still exposes interactive-user classes | `RunAs=Interactive User` instantiates the object in whatever session is interactive; the class produced CVE-2017-0100 and, a decade later, CVE-2023-33127 ([46], [11]) | Apply the OleViewDotNet "Run as: Interactive User" filter per build; activate each from a service session and document what client verification the server performs | | **TypeLib script-moniker paths** survive as a load primitive | `LoadTypeLib` parses a non-TLB path as a moniker display name, so `script:` URLs execute from a "data" API; observed in the wild (ReliaQuest 2025) and in VS poisoning ([23], [35]) | Inventory high-frequency Automation LIBIDs (explorer touches SHDocVw `{EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}` constantly); shadow per-user and record which processes load it and whether the `script:` string survives per-build hardening | | **DCOM relay post-KB5004442** has exploitable boundaries | The floor stops relay *to* activation, but relay *from* DCOM still works (RemoteMonologue's `RunAs` tampering + UNC-dereferencing methods); the LocalPotato HTTP scenario is unpatched by decision; RemotePotato0 was "Won't Fix" ([26], [15], [27]) | Inventory methods that dereference UNC paths (the RemoteMonologue set: `ServerDataCollectorSet`, `FileSystemImage`, `UpdateSession`, MSTSWebProxy); test coercion from each with the PKT_INTEGRITY floor enforced | | **Per-user hijack into PPL** without admin | Forshaw: the general trapped-object technique does not require admin if any suitable IDispatch-exposing server activates user-scope classes — the per-user variant of the StdFont `TreatAs` hijack ([4]) | Find PPL-hosted classes that activate HKCU-scope classes in-session; test `TreatAs` and TypeLib shadows under `HKCU\Software\Classes` against them | > **OpSec:** Several rows (TypeLib shadows, `TreatAs`, `AllowDCOMReflection`) are heavily signatured since 2025. Run backlog experiments on instrumented VMs and diff your own telemetry against the public Sigma/Elastic coverage — the rows where your experiment is invisible are the publishable ones. --- ## 10. Appendix A — Master tooling table Every tool named in the course's research briefs, one row each. `—` means the brief named the tool without a URL (built-in Windows components, or links not given in the sources); retrieve those from their official channels only. | Category | Tool | Author | Purpose | URL | |---|---|---|---|---| | Enumeration & analysis | OleViewDotNet | James Forshaw (tyranid) | The recon workhorse: classes/interfaces/AppIDs/typelibs, decoded ACLs, `RunAs` filters, ROT, method invocation, proxy decompilation, `.winmd` parsing | https://github.com/tyranid/oleviewdotnet | | Enumeration & analysis | oleview.exe | Microsoft (SDK) | Legacy COM/OLE viewer | — | | Enumeration & analysis | dcomcnfg.exe | Microsoft | GUI for AppID Launch/Access ACLs and machine OLE defaults | — | | Enumeration & analysis | RpcView | — | RPC endpoint/interface (IPID) maps | — | | Enumeration & analysis | ProcMon | Microsoft Sysinternals | File/registry/LoadImage tracing; phantom-CLSID hunting | — | | Enumeration & analysis | Autoruns | Microsoft Sysinternals | Autostart enumeration (does not diff the full HKCU CLSID tree — known gap) | — | | Enumeration & analysis | Wireshark | Wireshark project | `dcom`/`dcerpc` dissectors; grep `MEOW` in captures | — | | Enumeration & analysis | API Monitor | — | Parameter-level API logging | — | | Enumeration & analysis | Event Viewer | Microsoft | DistributedCOM 10010/10015/10016/10036–10038 telemetry | — | | Enumeration & analysis | `Win32_DCOMApplication` / `Win32_COMSetting` | Microsoft (WMI) | DCOM app and COM-setting inventory | — | | Enumeration & analysis | incendium.rocks methodology | incendium.rocks | Automated registry → JSON → `Invoke` research pipeline | https://incendium.rocks/posts/Automating-COM-Vulnerability-Research/ | | Enumeration & analysis | JuicyPotato CLSID lists | ohpe / @Giutro & @decoder_it | Per-OS abusable-CLSID corpora | http://ohpe.it/juicy-potato/CLSID/ | | Enumeration & analysis | strontic xcyclopedia | strontic | CLSID library/catalog | — | | Enumeration & analysis | awesome-potatoes | bodik | Potato study notes and link farm | https://github.com/bodik/awesome-potatoes | | Enumeration & analysis | BloodHound (`ExecuteDCOM` edge) | SpecterOps | Graph modeling of DCOM-abusable admin relationships | https://bloodhound.specterops.io/resources/edges/execute-dcom | | Reverse engineering & debugging | WinDbg (`dqs`, `symchk`) | Microsoft | VTable symbolization, server attach, breakpoint harness, PDB retrieval | — | | Reverse engineering & debugging | IDA / Ghidra | Hex-Rays / NSA | Server-binary disassembly; string xref (`"StartScan"` technique) | — | | Reverse engineering & debugging | BinDiff | — | Patch diffing `rpcss.dll`, `combase.dll`, `ole32.dll`, `oleaut32.dll`, `usosvc.dll` | — | | Reverse engineering & debugging | TokenViewer | James Forshaw | Inspect captured tokens — impersonation vs identification | — | | Reverse engineering & debugging | NtObjectManager | — | `Get-AccessibleFile -AccessRights WriteDac` target-file enumeration | — | | Reverse engineering & debugging | ExploitRemotingService | James Forshaw | .NET remoting trapped-object exploitation | — | | Reverse engineering & debugging | IE11SandboxEscapes | James Forshaw | CVE-2014-0257 .NET DCOM reflection PoC (reference for trapped-object PoC) | https://github.com/tyranid/IE11SandboxEscapes | | Reverse engineering & debugging | COMRace | USENIX Security '22 authors | Data-race detection in COM objects | https://www.youtube.com/watch?v=9bBh2YEqVMA | | Local privilege escalation (potato family & bridges) | RottenPotato | FoxGlove Security (@breenmachine, @vvalien1) | BITS DCOM trigger + NTLM reflection (≤1803) | https://github.com/foxglovesec/RottenPotato | | Local privilege escalation (potato family & bridges) | RottenPotatoNG | FoxGlove Security | Standalone C++ port (no Meterpreter) | https://github.com/foxglovesec/RottenPotatoNG | | Local privilege escalation (potato family & bridges) | LonelyPotato | decoder | RottenPotato standalone | https://decoder.cloud/2017/12/23/the-lonely-potato/ | | Local privilege escalation (potato family & bridges) | JuicyPotato | ohpe / @Giutro & @decoder_it | Arbitrary CLSID/port/program reflection (≤1803) | https://github.com/ohpe/juicy-potato | | Local privilege escalation (potato family & bridges) | RoguePotato | @decoder_it & @splinter_code | Fake OXID resolver + named-pipe redirect (1809+) | https://github.com/antonioCoco/RoguePotato | | Local privilege escalation (potato family & bridges) | RogueWinRM | antonioCoco | BITS→WinRM HTTP NTLM capture | https://github.com/antonioCoco/RogueWinRM | | Local privilege escalation (potato family & bridges) | SweetPotato | @_EthicalChaos_ / CCob | C# unified potato toolkit | https://github.com/CCob/SweetPotato | | Local privilege escalation (potato family & bridges) | JuicyPotatoNG | @decoder_it & @splinter_code | Type-9 `LogonUser` + SSPI hook (1809+/Win11) | https://github.com/antonioCoco/JuicyPotatoNG | | Local privilege escalation (potato family & bridges) | LocalPotato | @decoder_it & @splinter_code | NTLM context swap → SYSTEM SMB write (CVE-2023-21746) | https://github.com/decoder-it/LocalPotato | | Local privilege escalation (potato family & bridges) | GodPotato | BeichenDream | Service-DCOM trigger + callback impersonation (Win8–11) | https://github.com/BeichenDream/GodPotato | | Local privilege escalation (potato family & bridges) | DCOMPotato | zcgonvh | Attacker `IUnknown` callback → `CoImpersonateClient` | https://github.com/zcgonvh/DCOMPotato | | Local privilege escalation (potato family & bridges) | PrintNotifyPotato | BeichenDream | PrintNotify CLSID + callback (works with legacy Spooler off) | https://github.com/BeichenDream/PrintNotifyPotato | | Local privilege escalation (potato family & bridges) | PrintSpoofer | itm4n | Spooler pipe-name normalization + impersonation | https://github.com/itm4n/PrintSpoofer | | Local privilege escalation (potato family & bridges) | BadPotato | BeichenDream | PrintSpoofer C# port | https://github.com/BeichenDream/BadPotato | | Local privilege escalation (potato family & bridges) | EfsPotato | zcgonvh | MS-EFSR coercion + pipe impersonation | https://github.com/zcgonvh/EfsPotato | | Local privilege escalation (potato family & bridges) | SharpEfsPotato | bugch3ck | EfsPotato C# variant | https://github.com/bugch3ck/SharpEfsPotato | | Local privilege escalation (potato family & bridges) | CoercedPotato | @Hack0ura & @Prepouce (Hackvens) | Automated multi-coercion (MS-RPRN + MS-EFSR) | https://github.com/Prepouce/CoercedPotato | | Local privilege escalation (potato family & bridges) | PetitPotato | wh0amitz | Local PetitPotam → pipe | https://github.com/wh0amitz/PetitPotato | | Local privilege escalation (potato family & bridges) | RasmanPotato | crisprss | RasMan RPC coercion → pipe | https://github.com/crisprss/RasmanPotato | | Local privilege escalation (potato family & bridges) | CandyPotato | klezVirus | Weaponized pure-C++ RottenPotatoNG | https://github.com/klezVirus/CandyPotato | | Local privilege escalation (potato family & bridges) | MultiPotato | S3cur3Th1sSh1t | Multi-trigger combo | https://github.com/S3cur3Th1sSh1t/MultiPotato | | Local privilege escalation (potato family & bridges) | SigmaPotato | tylerdotrar | Modernized GodPotato-style, in-memory .NET | https://github.com/tylerdotrar/SigmaPotato | | Local privilege escalation (potato family & bridges) | GenericPotato | Micah van Deusen | Generic SeImpersonation → SYSTEM | https://micahvandeusen.com/the-power-of-seimpersonation/ | | Local privilege escalation (potato family & bridges) | GhostPotato | Shenanigans Labs | NTLM challenge-cache SMB relay bypass | https://shenaniganslabs.io/2019/11/12/Ghost-Potato.html | | Local privilege escalation (potato family & bridges) | RemotePotato0 | antonioCoco / SentinelOne | Cross-protocol RPC→HTTP relay (remote user→DA) | https://github.com/antonioCoco/RemotePotato0 | | Local privilege escalation (potato family & bridges) | CertPotato | SensePost | ADCS path from virtual/network service accounts | https://sensepost.com/blog/2022/certpotato-using-adcs-to-privesc-from-virtual-and-network-service-accounts-to-local-system/ | | Local privilege escalation (potato family & bridges) | SpoolSample | Lee Christensen | MS-RPRN coercion PoC | https://github.com/leechristensen/SpoolSample | | Local privilege escalation (potato family & bridges) | UsoDllLoader | itm4n | USO weaponization-bridge PoC | https://github.com/itm4n/UsoDllLoader | | Local privilege escalation (potato family & bridges) | COMahawk | NCC Group / Fox-IT | CVE-2019-1405 + CVE-2019-1322 chain PoC | — | | Local privilege escalation (potato family & bridges) | RpcClient (StorSvc) | BlackArrowSec | `SvcRebootToFlashingMode` trigger client (LocalPotato weaponization) | — | | Local privilege escalation (potato family & bridges) | Trebuchet | NetSPI | MS15-076 → arbitrary file write | https://www.netspi.com/blog/technical-blog/web-application-pentesting/exploiting-ms15-076-cve-2015-2370/ | | Lateral movement | impacket (`dcomexec.py`, `rpcdump.py`, `oxidresolver`) | Fortra (agsolino / byt3bl33d3r) | DCOM exec via MMC20/ShellWindows/ShellBrowserWindow; RPC dumps; OXID resolver interface leak | https://github.com/fortra/impacket | | Lateral movement | NetExec | NetExec project | `--exec-method mmcexec` remote command execution | https://www.netexec.wiki/smb-protocol/command-execution/execute-remote-command | | Lateral movement | SharpCOM | rvrsh3ll | C# DCOM execution | https://github.com/rvrsh3ll/SharpCOM | | Lateral movement | SharpExcel4-DCOM | rvrsh3ll | Excel XLM/shellcode via DCOM | https://github.com/rvrsh3ll/SharpExcel4-DCOM | | Lateral movement | Invoke-DCOM.ps1 | rvrsh3ll | PowerShell DCOM invocation | https://github.com/rvrsh3ll/Misc-Powershell-Scripts | | Lateral movement | CsDCOM / CheeseDCOM | rasta-mouse | C# DCOM tooling | — | | Lateral movement | SharpMove | 0xthirteen | Lateral movement (`action=dcom`/`hijackdcom`) | https://github.com/0xthirteen/SharpMove | | Lateral movement | MoveKit | — | Lateral movement kit | — | | Lateral movement | SharpLateral (`reddcom`) | — | DCOM lateral movement | — | | Lateral movement | LethalHTA | codewhitesec | Remote `htafile` + custom moniker + DotNetToJScript | https://github.com/codewhitesec/LethalHTA | | Lateral movement | Invoke-DCOMPowerPointPivot.ps1 | attactics.org | PowerPoint add-in DCOM pivot | https://attactics.org/2018/02/dcom-lateral-movement-powerpoint/ | | Lateral movement | Empire | — | `invoke_dcom` module (MMC20, ShellWindows, ShellBrowserWindow, ExcelDDE, RegisterXLL) | — | | Lateral movement | Cobalt Strike | — | `remote-exec com-mmc20` via Aggressor | — | | UAC bypass | UACME (Akagi) | hfiref0x | The 82-method UAC-bypass corpus; read `comsup.h` and the `ucm*Method` modules | https://github.com/hfiref0x/UACME | | UAC bypass | Sharp4COMBypassUAC | xz.aliyun.com writeup | ICMLuaUtil UAC bypass PoC | https://xz.aliyun.com/t/16063 | | UAC bypass | Atomic Red Team | Red Canary | T1548.002 / T1546.015 / T1021.003 lab tests | https://github.com/redcanaryco/atomic-red-team | | UAC bypass | Metasploit | Rapid7 | `bypassuac_eventvwr`, `bypassuac_comhijack`, `ms16_075_reflection`, CVE-2019-0841 module | https://github.com/rapid7/metasploit-framework | | Persistence & hijacking | acCOMplice / COMHijackToolkit | David Tulis / NCC Group | `Extract-HijackableKeysFromProcmonCSV`, `Find-MissingLibraries`, `Hijack-CLSID`, `Hijack-MultipleKeys`, `masterkeys.csv` | https://github.com/nccgroup/Accomplice | | Persistence & hijacking | COM-Hunter | @nickvourd + @S1ckB0y1337 | `search`/`persist`/`tasksch`/`treatas`/`remove` modes (.NET + BOF) | https://github.com/nickvourd/COM-Hunter | | Persistence & hijacking | Get-ScheduledTaskComHandler.ps1 | enigma0x3 | Enumerate scheduled tasks with ComHandler actions | https://github.com/enigma0x3/Misc-PowerShell-Stuff | | Persistence & hijacking | COMProxy | leoloobeek | Pass-through hijack DLL PoC (+ TestCOMClient/TestCOMServer) | https://github.com/leoloobeek/COMProxy | | Persistence & hijacking | SharpDllProxy | Flangvik | Export-forwarding stub generator | https://github.com/Flangvik/SharpDllProxy | | Persistence & hijacking | FaceDancer | — | Export-forwarding stub generator (`recon -I target.dll -G`) | — | | Persistence & hijacking | Koppeling | — | Export-forwarding stub generator | — | | Persistence & hijacking | Invoke-OutlookPersistence.ps1 | 3gstudent | Outlook `TreatAs` persistence automation (handles WOW6432Node) | https://github.com/3gstudent/COM-Object-hijacking | | Persistence & hijacking | Invoke-EventVwrBypass.ps1 | enigma0x3 | eventvwr `mscfile` hijack PoC | https://enigma0x3.net/2016/08/15/fileless-uac-bypass-using-eventvwr-exe-and-registry-hijacking/ | | Persistence & hijacking | CS-Situational-Awareness-BOF | TrustedSec | Situational-awareness BOF (COM enumeration) | https://github.com/trustedsec/CS-Situational-Awareness-BOF | | Persistence & hijacking | EVTX-ATTACK-SAMPLES | sbousseaden | COM-hijack Sysmon telemetry samples | https://github.com/sbousseaden/EVTX-ATTACK-SAMPLES | | Execution, injection & evasion | DotNetToJScript | James Forshaw | .NET assembly → JScript/VBScript/HTA via COM-visible mscorlib classes | https://github.com/tyranid/DotNetToJScript | | Execution, injection & evasion | SharpShooter | MDSec | DotNetToJScript-based payload generation | https://www.mdsec.co.uk/2018/06/freestyling-with-sharpshooter-v1-0/ | | Execution, injection & evasion | CACTUSTORCH / GreatSCT / SuperSharpShooter | — | DotNetToJScript-derived frameworks | — | | Execution, injection & evasion | PPLdump / PPLmedic / PPLKiller | itm4n | PPL bypass / injection tooling | https://github.com/itm4n/PPLmedic | | Execution, injection & evasion | PPLFault | gabriellandau | PPL bypass | — | | Execution, injection & evasion | ANGRYORCHARD | — | PPL follow-on tooling | — | | Execution, injection & evasion | IRundown::DoCallback injection | MDSec | COM-based injection into protected processes | https://mdsec.co.uk/2022/04/process-injection-via-component-object-model-com-irundowndocallback/ | | Execution, injection & evasion | ForsHops | IBM X-Force Red | Remote trapped-COM fileless lateral movement | https://github.com/xforcered/ForsHops | | Execution, injection & evasion | ComDotNetExploit | Mohamed Fakroud / T3nb3w | Local trapped-COM PPL-injection PoC | https://github.com/T3nb3w/ComDotNetExploit | | Execution, injection & evasion | RemoteMonologue | IBM X-Force (Andrew Oliveau) | DCOM NTLM coercion via AppID `RunAs` tampering | https://github.com/3lp4tr0n/RemoteMonologue | | Execution, injection & evasion | Koadic / Covenant | — | C2 frameworks using COM scriptlet delivery | — | | Defense validation & detection engineering | RPC Firewall | Zero Networks | Per-call RPC UUID/opnum/source-IP filtering and logging (closes the raw-RPC-ETW remote-IP gap) | https://github.com/zeronetworks/rpcfirewall | | Defense validation & detection engineering | sysmon-config | SwiftOnSecurity | Sysmon baseline configuration | https://github.com/SwiftOnSecurity/sysmon-config | | Defense validation & detection engineering | sysmon-modular | olafhartong | Modular Sysmon configuration | https://github.com/olafhartong/sysmon-modular | | Defense validation & detection engineering | Sigma | SigmaHQ | Rule set incl. COM hijack, MMC20, squiblydoo, RPC-firewall rules | https://github.com/SigmaHQ/sigma | | Defense validation & detection engineering | Elastic detection-rules | Elastic | Prebuilt COM-hijack and DCOM-LM rules | https://github.com/elastic/detection-rules | --- ## 11. Appendix B — Master reading list The further-reading picks from every chapter's Research Lab, deduplicated and grouped. Read in group order if you are new to the field; jump to the row matching your current pipeline stage otherwise. **COM internals & research methodology** - OleViewDotNet — James Forshaw — the tool and its source are the best COM-internals documentation that exists — https://github.com/tyranid/oleviewdotnet - COM in Sixty Seconds — James Forshaw — activation/OBJREF internals talk ([49]) - The Component Object Model — magicsplat — registry keys, HKCR merged view, SCM lookup walkthrough — https://www.magicsplat.com/book/com.html - COM Hijacking in Windows — cyberc0re — per-user vs system hive mechanics — https://www.cyberc0re.in/posts/com-hijacking-in-windows/ - Automating COM/DCOM vulnerability research — incendium.rocks — the IDispatch-JSON automation methodology — https://incendium.rocks/posts/Automating-COM-Vulnerability-Research/ - DCOM Turns 30: Revisiting a Legacy Interface in the Modern Threatscape — hack.lu 2025 slides ([41]) **Privilege escalation** - Windows Exploitation Tricks: Exploiting Arbitrary File Writes for Local Elevation of Privilege — James Forshaw — the DiagHub chain and the file-write template — https://googleprojectzero.blogspot.com/2018/04/windows-exploitation-tricks-exploiting.html - Weaponizing Privileged File Writes with the USO Service, parts 1–2 — itm4n — the USO bridge and honest RE workflow — https://itm4n.github.io/usodllloader-part1/ · https://itm4n.github.io/usodllloader-part2/ - CVE-2019-1405 and CVE-2019-1322 — NCC Group / Fox-IT — "service exposes dangerous API to everyone", with a ready-made OleViewDotNet methodology section — https://www.fox-it.com/be-en/cve-2019-1405-and-cve-2019-1322-elevation-to-system-via-the-upnp-device-host-service-and-the-update-orchestrator-service/ - Giving JuicyPotato a second chance: JuicyPotatoNG — decoder — post-1809 potato design — https://decoder.cloud/2022/09/21/giving-juicypotato-a-second-chance-juicypotatong/ **Trapped objects, PPL & injection** - Windows Bug Class: Accessing Trapped COM Objects with IDispatch — James Forshaw — the newest bug class in this course, with the full OleViewDotNet methodology ([4]) - Injecting Code into Windows Protected Processes using COM, Part 1 — James Forshaw — typelib substitution → type confusion → PPL ([24]) - Process Injection via Component Object Model (COM) IRundown::DoCallback — MDSec — the callback-execution injection primitive ([25]) - Fileless Lateral Movement with Trapped COM Objects — IBM X-Force — taking the class remote ([21]) **Lateral movement** - Lateral Movement via DCOM: Round 2 — enigma0x3 — the ShellWindows/ShellBrowserWindow playbook — https://enigma0x3.net/2017/01/23/lateral-movement-via-dcom-round-2/ - Abusing DCOM for Yet Another Lateral Movement Technique — bohops — abandoned binaries (mobsync) — https://bohops.com/2018/04/28/abusing-dcom-for-yet-another-lateral-movement-technique/ - I Like to Move It: Windows Lateral Movement Part 2 — DCOM — MDSec — XLM and shellcode in DCOM-spawned Excel — https://www.mdsec.co.uk/2020/09/i-like-to-move-it-windows-lateral-movement-part-2-dcom/ - Abuse the Power of DCOM Excel Application — SpecterOps — ActivateMicrosoftApp EOL proxy execution — https://posts.specterops.io/lateral-movement-abuse-the-power-of-dcom-excel-application-3c016d0d9922 - BloodHound `ExecuteDCOM` edge docs — SpecterOps — graph modeling of this attack class ([48]) **UAC** - UAC bypasses from COMAutoApprovalList — swapcontext — enumerating and weaponizing the approved-class list — https://swapcontext.blogspot.com/2020/11/uac-bypasses-from-comautoapprovallist.html - Calling Local Windows RPC Servers — James Forshaw — AppInfo's RPC interface and `RAiLaunchAdminProcess` ([36]) - UACME — hfiref0x — the 82-method corpus; read `comsup.h` and the `ucm*Method` modules ([38]) - UAC Bypass by Mocking Trusted Directories — David Wells / Tenable — the normalization-desync blueprint — https://medium.com/tenable-techblog/uac-bypass-by-mocking-trusted-directories-24a96675f6e - Advanced Windows Task Scheduler Playbook Part 2 — zcgonvh — from COM to UAC bypass to SYSTEM — http://www.zcgonvh.com/post/Advanced_Windows_Task_Scheduler_Playbook-Part.2_from_COM_to_UAC_bypass_and_get_SYSTEM_dirtectly.html - Reading Your Way Around UAC — James Forshaw — deep UAC internals series — https://tyranidslair.blogspot.com/2017/05/reading-your-way-around-uac-part-1.html **Persistence** - Abusing the COM Registry Structure Part 2 — bohops — loading techniques and evasion ([29]) - Revisiting COM Hijacking — SpecterOps — modern hosts, export forwarding, OpSec ([30]) - Proxying COM For Stable Hijacks — leoloobeek — the pass-through pattern ([33]) - New Abuse of the ClickOnce Technology: Part 2 — CrowdStrike — phantom-object persistence ([31]) - acCOMplice — David Tulis / NCC Group — discovery methodology and tooling — https://github.com/nccgroup/Accomplice - Persistence Part 2 – COM Hijacking — Dominic Chell / MDSec — the ComHandler walkthrough ([32]) **Execution, relay & detection** - Attacking Visual Studio for Initial Access — Outflank — the `LoadTypeLib` moniker-parsing quirk ([23]) - RemoteMonologue: Weaponizing DCOM NTLM Authentication Coercions — IBM X-Force — relay-from-DCOM in 2025 ([26]) - Utilizing RPC Telemetry — SpecterOps — turning `Microsoft-Windows-RPC` ETW into call-level visibility — https://posts.specterops.io/utilizing-rpc-telemetry-7af9ea08a1d5 --- ## 12. References [1] OleViewDotNet — James Forshaw (tyranid) — https://github.com/tyranid/oleviewdotnet [2] Automating COM/DCOM vulnerability research — incendium.rocks — https://incendium.rocks/posts/Automating-COM-Vulnerability-Research/ [3] Windows Exploitation Tricks: Exploiting Arbitrary File Writes for Local Elevation of Privilege — James Forshaw, Google Project Zero (2018) — https://googleprojectzero.blogspot.com/2018/04/windows-exploitation-tricks-exploiting.html [4] Windows Bug Class: Accessing Trapped COM Objects with IDispatch — James Forshaw, Project Zero (2025) — https://projectzero.google/2025/01/windows-bug-class-accessing-trapped-com.html [5] Weaponizing Privileged File Writes with the USO Service, Part 1 — itm4n (2019) — https://itm4n.github.io/usodllloader-part1/ [6] Weaponizing Privileged File Writes with the USO Service, Part 2 — itm4n (2019) — https://itm4n.github.io/usodllloader-part2/ [7] CVE-2019-1405 and CVE-2019-1322 — Elevation to SYSTEM via the UPnP Device Host Service and the Update Orchestrator Service — NCC Group / Fox-IT, Langlois & Torkington (2019) — https://www.fox-it.com/be-en/cve-2019-1405-and-cve-2019-1322-elevation-to-system-via-the-upnp-device-host-service-and-the-update-orchestrator-service/ [8] Windows: DCOM DCE/RPC Local NTLM Reflection Elevation of Privilege (Project Zero issue 325) — James Forshaw (2015) — https://bugs.chromium.org/p/project-zero/issues/detail?id=325 [9] No more rotten/juicy potato? — decoder (2018) — https://decoder.cloud/2018/10/29/no-more-rotten-juicy-potato/ [10] KB5004442 — Manage changes for Windows DCOM Server Security Feature Bypass (CVE-2021-26414) — Microsoft Support — https://support.microsoft.com/en-au/topic/kb5004442-manage-changes-for-windows-dcom-server-security-feature-bypass-cve-2021-26414-f1400b52-c141-43d2-941e-37ed901c769c [11] Abusing .NET Core CLR Diagnostic Features (CVE-2023-33127) — bohops (2023) — https://bohops.com/2023/11/27/abusing-net-core-clr-diagnostic-features-cve-2023-33127/ [12] No more JuicyPotato? Old story, welcome RoguePotato! — decoder (2020) — https://decoder.cloud/2020/05/11/no-more-juicypotato-old-story-welcome-roguepotato/ [13] Giving JuicyPotato a second chance: JuicyPotatoNG — decoder (2022) — https://decoder.cloud/2022/09/21/giving-juicypotato-a-second-chance-juicypotatong/ [14] LocalPotato — When Swapping The Context Leads You To SYSTEM — decoder (2023) — https://decoder.cloud/2023/02/13/localpotato-when-swapping-the-context-leads-you-to-system/ [15] LocalPotato HTTP edition — decoder (2023) — https://decoder.cloud/2023/11/03/localpotato-http-edition/ [16] JuicyPotato — abusing the golden privileges (with per-OS CLSID lists) — ohpe / @Giutro & @decoder_it (2018) — http://ohpe.it/juicy-potato/ and http://ohpe.it/juicy-potato/CLSID/ [17] Rotten Potato — Privilege Escalation from Service Accounts to SYSTEM — FoxGlove Security (2016) — https://foxglovesecurity.com/2016/09/26/rotten-potato-privilege-escalation-from-service-accounts-to-system/ [18] Windows Exploitation Tricks: Relaying DCOM Authentication — James Forshaw, Google Project Zero (2021) — https://googleprojectzero.blogspot.com/2021/10/windows-exploitation-tricks-relaying.html [19] Sharing a Logon Session a Little Too Much — James Forshaw (2020) — https://www.tiraniddo.dev/2020/04/sharing-logon-session-little-too-much.html [20] Abusing IDispatch for Trapped COM Object Access & Injecting into PPL Processes — Mohamed Fakroud — https://mohamed-fakroud.gitbook.io/red-teamings-dojo/abusing-idispatch-for-trapped-com-object-access-and-injecting-into-ppl-processes [21] Fileless lateral movement with trapped COM objects — IBM X-Force (2025) — https://www.ibm.com/think/news/fileless-lateral-movement-trapped-com-objects [22] Accelerating Offensive R&D with LLMs — Kyle Avery, Outflank (2025) — https://www.outflank.nl/blog/2025/07/29/accelerating-offensive-research-with-llm/ [23] Attacking Visual Studio for Initial Access — Outflank (2023) — https://www.outflank.nl/blog/2023/03/28/attacking-visual-studio-for-initial-access/ [24] Injecting Code into Windows Protected Processes using COM, Part 1 — James Forshaw, Google Project Zero (2018) — https://googleprojectzero.blogspot.com/2018/10/injecting-code-into-windows-protected.html [25] Process Injection via Component Object Model (COM) IRundown::DoCallback — MDSec (2022) — https://mdsec.co.uk/2022/04/process-injection-via-component-object-model-com-irundowndocallback/ [26] RemoteMonologue: Weaponizing DCOM NTLM Authentication Coercions — IBM X-Force, Andrew Oliveau (2025) — https://www.ibm.com/think/x-force/remotemonologue-weaponizing-dcom-ntlm-authentication-coercions [27] Relaying Potatoes: Another Unexpected Privilege Escalation Vulnerability in Windows RPC Protocol (RemotePotato0) — SentinelOne (2021) — https://www.sentinelone.com/labs/relaying-potatoes-another-unexpected-privilege-escalation-vulnerability-in-windows-rpc-protocol/ [28] Abusing the COM Registry Structure: CLSID, LocalServer32, & InprocServer32 — bohops (2018) — https://bohops.com/2018/06/28/abusing-com-registry-structure-clsid-localserver32-inprocserver32/ [29] Abusing the COM Registry Structure (Part 2): Hijacking & Loading Techniques for Evasion and Persistence — bohops (2018) — https://bohops.com/2018/08/18/abusing-the-com-registry-structure-part-2-loading-techniques-for-evasion-and-persistence/ [30] Revisiting COM Hijacking — SpecterOps (2025) — https://specterops.io/blog/2025/05/28/revisiting-com-hijacking/ [31] New Abuse of the ClickOnce Technology: Part 2 — CrowdStrike (2025) — https://www.crowdstrike.com/en-us/blog/new-abuse-of-the-clickonce-technology-part-two/ [32] Persistence Part 2 – COM Hijacking — Dominic Chell, MDSec (2019) — https://www.mdsec.co.uk/2019/05/persistence-the-continued-or-prolonged-existence-of-something-part-2-com-hijacking/ [33] Proxying COM For Stable Hijacks — leoloobeek (2019) — https://adapt-and-attack.com/2019/08/29/proxying-com-for-stable-hijacks/ [34] Userland Persistence with Scheduled Tasks and COM Handler Hijacking — enigma0x3 (2016) — https://enigma0x3.net/2016/05/25/userland-persistence-with-scheduled-tasks-and-com-handler-hijacking/ [35] Hijacked and Hidden: New Backdoor and Persistence Technique — ReliaQuest (2025) — https://reliaquest.com/blog/threat-spotlight-hijacked-and-hidden-new-backdoor-and-persistence-technique/ [36] Calling Local Windows RPC Servers — James Forshaw, Google Project Zero (2019) — https://googleprojectzero.blogspot.com/2019/12/calling-local-windows-rpc-servers-from.html [37] The COM Elevation Moniker — Microsoft Learn — https://learn.microsoft.com/en-us/windows/win32/com/the-com-elevation-moniker [38] UACME — Defeating Windows User Account Control — hfiref0x — https://github.com/hfiref0x/UACME [39] COMRace: data-race detection in COM objects (USENIX Security 2022 talk) — https://www.youtube.com/watch?v=9bBh2YEqVMA [40] Enhancing Automatic Vulnerability Discovery for Windows RPC/COM in New Ways (Black Hat EU 2024 talk) — https://www.youtube.com/watch?v=VQiQuLo0v58 [41] DCOM Turns 30: Revisiting a Legacy Interface in the Modern Threatscape — hack.lu 2025 slides — https://d3lb3.github.io/assets/hacklu_2025.pdf [42] CVE-2020-1362 WalletService writeup — Q4n (2020) — https://github.com/Q4n/CVE-2020-1362 [43] Mitigate some Exploits for Windows UAC (MSRC case 64957 quote) — Stefan Kanthak — https://skanthak.hier-im-netz.de/uacamole.html [44] Microsoft Security Servicing Criteria for Windows — Microsoft — https://www.microsoft.com/en-us/msrc/windows-security-servicing-criteria [45] The case of COM failing to pump messages in a single-threaded COM apartment — Raymond Chen, The Old New Thing (2025) — https://devblogs.microsoft.com/oldnewthing/20250314-00/?p=110965 [46] CVE-2017-0100 — Windows HelpPane Elevation of Privilege Vulnerability — Microsoft Security Response Center (2017) — https://msrc.microsoft.com/update-guide/vulnerability/CVE-2017-0100 [47] Merged View of HKEY_CLASSES_ROOT — Microsoft Learn — https://learn.microsoft.com/en-us/windows/win32/sysinfo/merged-view-of-hkey-classes-root [48] BloodHound — ExecuteDCOM edge — SpecterOps — https://bloodhound.specterops.io/resources/edges/execute-dcom [49] COM in Sixty Seconds — James Forshaw — https://github.com/tyranid/presentations