DCOM绕过PPL反射调用.Net原理
本篇只是记录James Forshaw, Google Project Zero提供的文章进行学习笔记,并非复现过程。具体细节还是去观摩大佬的文章学习比较好(参考链接1)。
攻击原理
Windows COM (Component Object Model) 架构是 Windows 操作系统的核心技术之一,它允许不同组件之间进行通信和交互。James Forshaw文章分析的攻击技术展示了如何利用 COM 架构中的特性,创建跨权限边界的攻击通道,实现对高权限服务的影响或权限提升。
COM 对象可以在不同的位置运行,这由其在注册表中的注册方式决定:
本地进程 (In-Process):通过
InprocServer32注册表项指定 DLL,在调用者进程内运行。服务进程 (Service):通过
LocalServer32和AppID注册表项配置,在独立的服务进程中运行。远程服务器 (Remote Server):在单独的进程中运行,但不是作为服务。
这种注册位置的差异对安全边界和攻击可行性有重大影响(攻击点)。
某些进程会加载InprocServer32类型的COM组件且暴露出一些公共接口(IDispatch),然后利用DCOM方式与COM组件公开的接口进行交互,碰巧微软有一个机制:允许使用DCOM方式进行.Net反射执行。这个同样在James Forshaw文章中提到(这个大佬是真牛逼)。这个机制在微软2014 年 2 月 11 日的时候进行了修复(https://learn.microsoft.com/en-us/security-updates/SecurityBulletins/2014/ms14-009),但依然留下了缺口,用户可对注册表下的AllowDCOMReflection写值,允许再次将其打开。因此若想要操作起来需要满足下列条件:
注册为在本地进程中运行,而不是在服务中。
开启
AllowDCOMReflection项。TreatAs注册表重定向,这个用于将传统COM对象视为.NET对象,从而允许在 COM 上下文中调用 .NET 对象。这个与.Net与COM交互有关,可看一下CCW、RCW内容。
当这些条件同时满足时,攻击者可以在自己的进程中创建该 COM 类的实例,完全控制其内存和行为,同时利用它与高权限服务建立特权通信。这种攻击绕过了PPL保护,因为它利用了 COM 类型系统本身的特性。
分析
文章中,作者通过遍历本地服务实现的所有COM类,并过滤有暴露接口的类。
1 | |
根据作者所述,存在可利用的是第一个WaaSRemediation,接着查询该类所运行在的进程
1 | |
这里发现COM组件类运行在svchost.exe进程中,接着解析对象使用的类型库。
1 | |
解析类。
1 | |
到这里解释一下为什么作者说了这么一段话。
这里手动查看一下两个类的注册方式。
1 | |
Key都是LocalServer32,意味着当创建COM类实例时,实例将在服务进程中运行,而不是在目标进程中运行,导致代码执行的环境为**服务进程**上下文。因此不符合作者的目的。作者的初衷是找到某个类并且当这个类被实例的时,代码的执行环境是在目标进程上下文。(类似于LoadLibrary函数总是执行在进程上下文)
作者这里提到说,类型库也会引用到其他类型库,类似DLL中import了其他DLL。因此这里查询WaaSRemediationLib引用的库。
1 | |
这里可以看到非常有意思的点,WaaSRemediationLib类型库引用了stdole类库,而stdole中的StdFont类注册为InProcServer32类型。这意味着StdFont COM组件会在调用者的进程上下文中运行,而不是在远程服务中。当进程创建StdFont实例时,系统会将oleaut32.dll加载到该进程的地址空间,使攻击者能够完全控制对象的内存和行为。
这种情况创造了一个独特的攻击路径:攻击者可以在自己的进程中创建并操控StdFont对象,同时利用它与高权限WaaS服务共享的类型定义和接口,建立一个特权通信通道。通过这种方式,攻击者能够在本地进程上下文中执行COM反射(Reflection)操作,绕过了通常的进程边界保护,实现对高权限服务的影响。
接着作者查询该类库被运行在的进程:
1 | |
巧了,运行在svchost.exe,说明可以利用这个东西对svchost.exe注入。查看一下接口
1 | |
(这里不知道为什么查询到的接口和文章的不同=。=),再看一下WaaSRemediationAgent的保护等级。
1 | |
查询到的Level为WindowsLight,表明目标服务是被PPL进行了保护。意味着通过这种方式可以对高权限进程进行注入。具体的代码实现是在参考三中。
总结
作者这一套下来,我认为主要的难点就是如何去找到进程中引用了一个COM组件,并且组件对外暴露了接口,使得可以用DCOM与.NET进行交互,通过reflection进行执行攻击代码。
如果拓展到自己在实际使用场景,我认为可以让自己的程序加载一个拥有暴露接口的com组件,接着外部进程可以通过com组件进行反射调用代码,可以对目标执行类似于脚本化的功能。
参考
googleprojectzero.blogspot.com
googleprojectzero.blogspot.com
Abusing IDispatch for Trapped COM Object Access & Injecting into PPL Processes | Red Teaming’s Dojo