Remote .NET Assembly Loading through WaaSRemediation DCOM Abuse
Last updated
Was this helpful?
Last updated
Was this helpful?
The IDispatch
interface exposed in the WaaSRemediation
COM class, can be manipulated for trapped COM object abuse and .NET code execution. WaaSRemediation
is implemented in the WaaSMedicSvc
service, which executes as a svchost.exe process in the context of NT AUTHORITY\SYSTEM. This technique was discovered In February 2025 by James Forshaw () from Google Project Zero
Fore more information about and DCOM, check .
A trapped COM object is a bug class in which a COM client instantiates a COM class in an out-of-process DCOM server, where the client controls the COM object via a marshaled-by-reference object pointer. Depending on the condition, this control vector may present security-related logic flaws.
The interfaces facilitates late binding to methods and properties of COM objects. Unlike traditional COM clients that use compile-time interface definitions, late binding allows clients to discover and call methods dynamically at runtime
The interface support the following methods:
GetTypeInfoCount
: returns 0 or 1 if the object provides type information.
GetTypeInfo
: Provides access to an ITypeInfo
interface for retrieving type information of an object.
GetIDsOfNames
: takes human-readable names (such as "Workbooks") and returns a number (known as a dispatch identifier or dispID) that maps to the object's associated method or property.
Invoke
: Once you have the dispID number, you use Invoke to call the method or retrieve property data.
Via ITypeLib
from GetTypeInfo->ITypeInfo->GetContainingTypeLib
,a client can retrieve type information of a COM class that use a type library.
In our case, the, WaaSRemediation
references the type library WaaSRemediationLib
, which in turn references stdole
(OLE Automation). WaaSRemediationLib
utilizes two COM classes from that library, StdFont
and StdPicture
. By performing on the StdFont
object via modifying its TreatAs
registry key, the class will point to another COM class of our choosing, such as System.Object
in the .NET Framework.
.NET objects are interesting to us because of System.Object
’s GetType
method. Through GetType
, we can perform .NET reflection to eventually access Assembly.Load
. While System.Object
was chosen, this type happens to be the root of the type hierarchy in .NET. Therefore, any .NET COM object could be used.
To leverage this technique, we need to enable the AllowDCOMReflection
(DWORD) value under the HKLM\Software\Microsoft\.NetFramework
registry key. This setting allows arbitrary reflection to call any .NET method, bypassing the mitigations in MS14-009 that typically prevent .NET reflection over DCOM.
To ensure the correct version of the .NET CLR is loaded, we must also enable the OnlyUseLatestCLR
(DWORD) value under the HKLM\Software\Microsoft\.NetFramework
registry key. This setting ensures the latest .NET CLR (version 4) is loaded, as the default is version 2 unless explicitly enabled.
To leverage the previously explained method, we can use the (C#) proof-of-concept.
In this demo, we will use the below C# code that loads a to retrieve and execute a second-stage payload directly in memory.
Finally we can use the (C#) proof-of-concept to execute GetRev.exe assembly on a remote computer: