77 KiB
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
- 2. Stage 1 — Enumeration: building the target list
- 3. Stage 2 — Triage: ranking candidates
- 4. Stage 3 — Static reverse engineering
- 5. Stage 4 — Dynamic analysis harness
- 6. Stage 5 — Fuzzing COM interfaces
- 7. Stage 6 — From crash or lead to a proven primitive
- 8. Stage 7 — Weaponization and reporting
- 9. The research backlog: open problems worth hunting
- 10. Appendix A — Master tooling table
- 11. Appendix B — Master reading list
- 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:
- "A service exposes a dangerous method to everyone." DiagHub's SYSTEM service let any user drive
AddAgent(dllPath, guid)intoLoadLibraryExW([3]). UPnP Device Host exposed the undocumentedIUPnPContainerManager(IID6D8FF8D4-730D-11D4-BF42-00B0D0118B56) methodsReferenceContainer,CreateInstance,CreateInstanceWithProgIDto any local user as LOCAL SERVICE — CVE-2019-1405, fixed by adding Administrators-only checks to the dangerous methods ([7]). StorSvc'sSvcMoveFileInheritSecurityimpersonated, moved the file, then reverted and calledSetNamedSecurityInfoas SYSTEM — the late-impersonation pattern ([3]). USO loaded a non-existentwindowscoredeviceinfo.dllfrom System32 on every session creation ([5]). - "The registry is trusted more than it should be." The
HKCRmerged view lets per-user keys silently override system keys ([47]);ProxyStubClsid32shadows inject a DLL into every process that marshals that interface, including SYSTEM servers;TreatAsredirects activation without touching the target'sInprocServer32([28], [29]); andLoadTypeLibparses 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.dllare 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.
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
LocalServer32EXE, a service-hosted class, or a DLL hosted by thedllhost.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/INTERACTIVEshows 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+):
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:
# 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 thatdfsvc.exeregisters 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\CLSIDand...\TypeLibagainst 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:
- OOP server. Registered with
LocalServer32, hosted in a service via its AppID, or running in adllhostsurrogate. In-proc classes count only when the host is privileged (auto-elevated binary, PPL service, another user's process). - Privileged identity. Server runs as
NT AUTHORITY\SYSTEM(direct win),LOCAL SERVICE/NETWORK SERVICE(hop — these holdSeImpersonatePrivilege, the potato entry point), or another user /RunAs=Interactive User(cross-session). - Reachable ACLs.
LaunchPermission+AccessPermission(or machine defaults underHKLM\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]). - 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-suppliedIUnknownimpersonates the SYSTEM caller inside its ownQueryInterface) or return objects (trapped-object pattern: the returned reference stays live in the server ([4])). - Marshaling trust. Class implements
IMarshal(potato criterion ([16])), is marshaled TypeLib-driven viaPSOAInterface{00020424-0000-0000-C000-000000000046}(type-library substitution applies), or itsInterface\{IID}\ProxyStubClsid32can be shadowed per-user (a DLL into both endpoints). - Bonus multipliers.
IDispatch/dualpresent (type-info vector —ITypeInfo::CreateInstanceinstantiates 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
-
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.
-
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+0x36C78for DiagHub. -
Symbolize the vtable. Attach WinDbg to the server process and dump the vtable with
dqs <module>+<offset> L<nMethods>— Microsoft public symbols resolve the slots to real names. DiagHub'sIStandardCollectorService(IID0D8AF6B7-EFD5-4F6D-A834-314740AB8CAA) yieldedCreateSession,GetSession,DestroySession,DestroySessionAsync,AddLifetimeMonitorProcessIdForSessionexactly this way ([3]):0:019> dqs DiagnosticsHub_StandardCollector_Runtime+0x36C78 L8 -
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
SessionConfigurationstruct andCreateSession/AddAgentprototypes the exploit needed. -
Reconcile with disassembly. In IDA/Ghidra: xref command/operation strings (itm4n found
"StartScan"inusosvc.dlland walked the xrefs intoPerformOperationOnSession()/PerformOperationOnManager()([6])); where CFG is present, map_guard_dispatch_icall_fptrindirect 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. -
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/RpcImpersonateClientaround a privileged opClassic privileged-file-operation class Impersonate → check → RevertToSelf→ then writeStorSvc 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])RunAsmismatch / missing client-identity verificationCVE-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 classmeans 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 needdqs.
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).
// 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();
// 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:
CoSetProxyBlanketsets per-proxy security (it wrapsIClientSecurity::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/LoadLibraryExWwith no precedingCoImpersonateClient(missing impersonation), or afterCoRevertToSelf(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
LoadLibraryExWpath or a command line. - Reference leaks: the returned proxy's
Get-ComObjRefshowing 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]).
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
-
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.
-
Typed argument mutation. Higher yield per call, because the arguments are semantically typed:
Argument type Mutations (illustrative test list) Historical rationale BSTRpath/URL stringsOverlong strings, embedded NULs, \??\and device paths, junction/symlink targets, non-existent extensions on valid directoriesDiagHub extension-agnostic load ([3]); USO non-existent DLL ([5]); mock-directory normalization desync SAFEARRAYBounds/count fields desynced from payload size; multidimensional edge cases Conformant-array handling in the NDR engine VARIANTType-tag vs payload confusion (tag says VT_BSTR, payload is a pointer-sized integer); nested arrays;VT_UNKNOWN/VT_DISPATCHcarrying unexpected pointersTLB/proxy type-confusion family ([24], [4]) IStream/IStorageblobsTruncated streams, negative sizes, streams whose content is a second marshaled object CoGetInstanceFromIStorageOBJREF 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]) -
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 → automatedInvoke([2]). OleViewDotNet builds the dynamicIDispatchstubs; 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'sGet-AccessibleFile -AccessRights WriteDacagainst the StorSvc process token ([3])). - Server-side instantiation:
Get-ComObjRefon 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,
OpenThreadTokenand 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
CreateProcessAsUserstep 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.
CreateProcessWithTokenWneeds an impersonate-capable primary-token duplicate;CreateProcessAsUserneedsSeAssignPrimaryTokenPrivilege; 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:
- Primitive — the thing Stage 6 proved (arbitrary file write, server-side instantiation, token capture, type confusion).
- 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 atSprintCSP.dllorprintconfig.dll([14]). - Loader trigger — a COM/RPC method that loads or executes the planted artifact as the privileged identity, ideally outside
DllMain/loader lock: DiagHubAddAgent("license.rtf", guid)(the service callsDllGetClassObjectafter load ([3])); USO'swindowscoredeviceinfo.dllload on Update Session creation, triggered byusoclient.exe StartScanor directly over COM (the service calls a specific export after load ([5], [6]));SprintCSP.dll+SvcRebootToFlashingMode, or overwriteprintconfig.dlland instantiate PrintNotify ([14]). - SYSTEM — payload runs in the service context; if you captured a token instead, apply §7.3's token math.
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.dllfix 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-RPCEID 5/6 records InterfaceUuid/OpNum), which DistributedCOM events appear (10036–10038 for hardening refusals), which registry values change (AllowDCOMReflection/OnlyUseLatestCLRare 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
ExecuteDCOMedge 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.hand theucm*Methodmodules ([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
LoadTypeLibmoniker-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-RPCETW 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