前言
之前研究过Crackmapexec这款工具,对这个工具基于smb协议的wmiexec执行方法产生的流量进行了分析,网上似乎还没有相关的文章,这里旨在抛砖引玉,简单梳理下整个过程,以初学者的视角,探索流量当中存在的奥妙之处。
前序知识
OPC协议
OPC协议:OPC是一种利用微软的COM/DCOM技术来达成自动化控制的协定,采用典型的C/S模式,针对硬件设备的驱动程序由硬件厂商完成,提供统一OPC接口标准的Server程序,软件厂商只需按照OPC标准接口编写Client程序就访问Server程序进行读写,即可实现与硬件设备的通信。与大多数应用层协议不同,OPC的基础协议DCOM协议使用动态端口机制,在真正建立数据连接之前通讯双方还需要协商需要使用的端口。
用一张网上的图来表示下:
上图中,OPC客户端使用5568作为源端口首先向OPC服务器的135端口发起连接,连接成功后再经过OPC服务器分配新端口1118,并通过接口ISystemActivator的方法RemoteCreateInstance的应答报文返回给客户端,之后客户端使用5569作为源端口向服务器的1118端口发起新的连接用来后面的真正数据的传输。为什么会是这个流程那是因为在Windows当中有一个运行在135端口的rpcss服务也就是dcom的激活服务负责协调本机所有com对象的激活,当本机激活时采用通过内核通信,无法捕获数据包,属于内部操作,只有当远程激活或远程重定向到本机激活这种方式才可以捕获到数据包.远程激活有2种方式,一种是采用CoCreateInstanceEx方式指定远程服务器和激活身份等参数调用rpscss的IRemoteSCMActivator接口的RemoteCreateInstance方法激活,或者CoGetClassObject等于调用rpscss的IRemoteSCMActivator接口的RemoteGetClassObject方法激活同样可选指定远程服务器和激活身份等参数,这里就是采取了调用rpscss的IRemoteSCMActivator接口的RemoteCreateInstance方法激活的方式
DCERPC
RPC是一种编程模型,主要用于应用程序实现远程过程调用,微软的DCEPRC即是对远程过程调用的一种实现和扩展,实际上Windows上的很多服务以RPC的形式对外提供调用接口,外部应用程序可以通过调用这些PRC接口来实现对特定服务的访问。DCERPC有多种不同的承载方式,如TCP、UDP、HTTP、SMB命名管道等,客户端通过不同的承载协议连接到指定的服务端,由UUID绑定(Bind)到需要使用的终端接口(endpoint/interface)上,再传递所需参数来调用接口上指定的方法(operation),服务端随后将执行结果封装到协议数据包中返回。当使用TCP作为承载协议时DCERPC的知名端口号为135。
在RPC中,不同的终端定义了各自的一系列操作方法以供被调用,这些终端由各自唯一的UUID作为标识,在DCERPC的Bind操作中指定UUID,以告诉服务端使用哪个终端接口,TCP三次握手连接建立之后,例如DCERPC的绑定操作中通过指定UUID为367ABB81-9844-35F1-AD32-98F038001003,该UUID对应的终端是SVCCTL(ServiceControl,与服务管理相关的调用)。
SMB协议可以由多种命令来承载DCE/MS RPC层数据,同样是139、445/TCP上的通信,因不同的SMB命令而导致不同的SMB层解码。
环境
攻击者:MAC-192.168.56.1受害者:Win7-192.168.56.3
执行命令方式
sudo cme smb 192.168.56.3 -u Administrator -p '123456' –exec-method wmiexec -x whoami
流量特征简要分析
1、Crackmapexec基于wmiexec执行命令,首先也是先建立smb连接,首先攻击者发送一个SMB negotiate protocolrequest请求数据包
在用户级共享(与之相对的是共享级共享)中"NTLM 0.12"是首选SMB dialect,也就是NTLM版本为0.12,如果在NEGTIATE Request中说了,我可以支持Dialect:202、210、300、302、311,对应版本即为SMB 2.02 2.1 3.0 3.0.2 3.1.1
3、受害者机器发起响应,返回一个NTLM Server Challenge
4、然后攻击者机器发送User Name、Host Name、Domain Name和response给受害者机器
6、我们会发现它是先进行了smb v1的认证之后,然后又进行了smb v2的认证
7、当攻击者和受害者完成了磋商和认证之后,它会发送一个tree connect andx rerquest SMB数据报并列出它想访问网络资源的名称
8、受害者机器会发送一个tree connect andx response应答数据报以表示此次连接是否被接受或拒绝,下图可以看到没有提示错误,说明连接成功
9、下面是攻击者去告诉受害者这台机器,它想去连接svcctl服务
11、接下来我们的攻击者机器开始进行DCERPC的绑定操作,通过指定UUID为367ABB81-9844-35F1-AD32-98F038001003,该UUID对应的终端是SVCCTL(ServiceControl,与服务管理相关的调用)
12、接着我们攻击者机器收到了Bindack(12)报文,但是并不意味着BIND操作成功,要检查Ack result字段,解析Bindack报文时,务必判断Ack result字段是否 等于Acceptance(0),此时意味着BIND操作成功,Bind_ack(12)报文的RPC层大小与协议序列有关
13、绑定操作完成后,将对选用的终端接口执行指定方法调用,调用方法通过opnum指定,调用SVCCTL中编号为15的方法,即OpenSCManagerW(调用参数已经过编码加密)
14、然后受害者机器返回相应的响应信息,这里还没有用到OpenSCManagerW的返回的句柄只是流量当中存在这个过程所以做了下分析
15、AUTH3之前的Bind的UUID为ISystemActivator(000001a0-0000-0000-c000-000000000046)代表协商的服务为IRemoteSCMActivator方式,因为后面将会调用RemoteCreateInstance就是属于IRemoteSCMActivator当中的方法
17、然后攻击者机器使用RemoteCreateInstance(Opnum 4)方法为实际对象创建对象引用
18、接下来查看下受害者机器的响应,此处回复加密数据当中回复1030端口
19、所以后面我们的攻击者机器开始于受害者机器利用1030端口进行通信
20、然后再去进行了DCERPC的绑定操作进行绑定相应的UUID:f309ad18-d86a-11d0-a075-00c04fb68820也就是我们的IWbemLevel1Login
21、接着我们攻击者机器收到了Bindack(12)报文,但是并不意味着BIND操作成功,要检查Ack result字段,解析Bindack报文时,务必判断Ack result字段是否 等于Acceptance(0),此时意味着BIND操作成功
23、然后调用了IWbemLevel1Login接口当中的Opnum为6的NTLMLogin方法,下面可以看到我们传递的参数的//./root/cimv2命名空间
HRESULT NTLMLogin( [in, unique, string] LPWSTR wszNetworkResource, [in, unique, string] LPWSTR wszPreferredLocale, [in] long lFlags, [in] IWbemContext* pCtx, [out] IWbemServices** ppNamespace );
25、接着调用了alter_context进行添加新的安全上下文,其实也就是新绑定了一个IRemUnknown UUID: 00000131-0000-0000-c000-000000000046
26、下面就是alert_context回复以及我们受害者机器发送AUTH3包进行认证
27、然后调用了RemRelease方法请求在对象的指定接口数量上递减指定数量的引用计数,此处对我们之前引用的IWbemLevel1Login接口对象进行了销毁
HRESULT RemRelease( [in] unsigned short cInterfaceRefs, [in, size_is(cInterfaceRefs)] REMINTERFACEREF InterfaceRefs[] );
28、接着又去添加新的安全上下文,Interface UUID: 9556dc99-828c-11cf-a37e-00aa003240c7,这个接口对象其实就是IWbemServices,然后下面日常的响应、认证等操作
29、然后之后调用了Opnum为6的方法也就是GetObject方法,GetObject方法检索CIM类或CIM实例。此方法必须从与当前IWbemServices接口关联的名称空间中检索CIM对象,取得我们想要调用的Provider类型实例,他以一个IWbemClassObject类型指针返回,微软在WMI核心部件和微软WMI软件开发工具中包括了很多提供程序。我们最常用的是Win32提供程序(核心WMI),他用于处理Win32系统特征。CIM存储库把这些信息存储为以"Win32"为前缀的类中,他包含在root\CIMV2名字空间中。例如,Win32BIOS、Win32Service、Win32Process等等,所以下面的图当中可以看到,我们传入的是Win32_Process类
HRESULT GetObject( [in] const BSTR strObjectPath, [in] long lFlags, [in] IWbemContext* pCtx, [out, in, unique] IWbemClassObject* ppObject, [out, in, unique] IWbemCallResult* ppCallResult );
31、然后我们就会调用Opnum为24的ExecMethod来调用函数,下面可以看到调用的参数传递,之后在我们的Windows当中就会利用Wmiprvse来调用cmd执行命令
HRESULT ExecMethod( [in] const BSTR strObjectPath, [in] const BSTR strMethodName, [in] long lFlags, [in] IWbemContext* pCtx, [in] IWbemClassObject* pInParams, [out, in, unique] IWbemClassObject* ppOutParams, [out, in, unique] IWbemCallResult* ppCallResult );
总结
此处通过对自己使用Crackmapexec的wmiexec模式过程当中产生的流量分析,对于DCOM激活的过程,以及基于DCERPC调用WMI程序的流程进行了梳理,如有错误之处还请指出,喜欢我们就关注我们吧
参考文章
https://www.anquanke.com/post/id/167057