WMI 攻击手法研究 – 探索命名空间、类和方法 (第二部分)

2022-11-23 19:03:17 浏览数 (2)

文章目录[隐藏]

  • 命名空间
    • 列出类
    • 2.2 获取类
    • 2.3 删除类实例
  • 方法
    • 3.1 列出方法
    • 3.2 使用方法
  • 4 设置对象属性
  • 5 结论

本篇文章是 WMI 攻击手法研究的第二篇,主要研究 WMI 中的 3 个组件,在整篇文章中,我们将交替使用 WMI 和 CIM cmdlet,以便熟悉这两种 cmdlet 类型。

命名空间

让我们简单回顾一下命名空间是什么:

命名空间结构信息类似于文件系统中文件夹,但是,与物理位置 (例如磁盘上) 不同,它们本质上更具有逻辑

WMI 中的所有命名空间都是 __Namespace 系统类的实例,要获取 root 命名空间下所有命名空间的列表,可使用以下命令查询同一个类:

代码语言:javascript复制
Get-WmiObject -Namespace root -Class __Namespace

输出的内容包含了许多信息,为了过滤掉 “无用” 信息,可使用 PowerShell 中的 select

代码语言:javascript复制
Get-WmiObject -Namespace root -Class __Namespace | select name

现在我们从系统中得到一个命名空间的列表,许多命名空间会是这样格式出现 root<namespace>,比如 rootDEFAULTrootCIM2 等等,因为它们是 root (本身也是一个命名空间) 下的命名空间。

一个奇怪而有趣的事实是,WMI 中的默认命名空间不是 rootDeFAULT 而是 rootCIMV2 (自 Windows 2000 以来一直是这样)

使用 CIM cmdlet Get-CimInstance 可以实现相同目的:

代码语言:javascript复制
Get-CimInstance -Namespace root -ClassName __Namespace

OK,上面已整整齐齐列出来了,那嵌套的名称空间呢?我们已经看到 root 命名空间下有几个命名空间,只需要编写一个脚本,递归地获取名称空间 (来自 PSMag):

代码语言:javascript复制
Function Get-WmiNamespace {
    Param (
        $Namespace='root'
    )
    Get-WmiObject -Namespace $Namespace -Class __NAMESPACE | ForEach-Object {
            ($ns = '{0}{1}' -f $_.__NAMESPACE,$_.Name)
            Get-WmiNamespace $ns
    }
}

类和命名空间可能因机器而异,具体取决于可用硬件、安装的应用程序和许多其它因素

现在我们有一个可用的命名空间列表,让我们来看看类,那么什么是类?

WMI 类表示系统中的特定项,它可以是从系统进程到硬件 (比如网卡)、服务等任何内容

类分为 3 个主要类型 (这是 CIM 标准的要求):

  • Core classes (核心类):适用于所有管理领域,并提供很少的基本功能,它们通常以双下划线开头 (比如 __SystemSecrity);
  • Common classes (公共类):这些是核心类的扩展,适用于特定的管理领域,以 CIM_ 为前缀 (比如 CIM_TemperatureSensor);
  • Extended classes (扩展类):这些是对基于技术堆栈的常见类的额外添加 (例如 Win32_Process);

类进一步分为以下类型:

  • Abstract classes (抽象类):定义新类的模板;
  • Static classes (静态类):主要用于存储数据;
  • Dynamic classes (动态类):从 Provider 取回数据,代表 WMI 托管资源,我们最感兴趣的是这种类型的类;
  • Association classes (关联类):描述类和托管资源之间的关系;

列出类

有了足够的理论支撑,让我们尝试寻找一些类,我们可以使用 Get-WmiObject cmdlet 列出可用的类:

代码语言:javascript复制
Get-WmiObject -Class * -List

上面这条命令将会列出所有类,但为了举例,假设我们对系统上的用户感兴趣。可以使用以下命令来缩小范围,该命令列出了用于获取或操作用户信息的所有可用类:

代码语言:javascript复制
Get-WmiObject -Class *user* -List

同样也可以使用 Get-CimClass 命令也能实现同样的效果,如下所示:

代码语言:javascript复制
Get-CimClass -ClassName *user*

有关所有 Win32 类的列表,可以参考 Microsoft 的类文档。 Win32 Provider 提供 4 个不同类别的类:计算机系统硬件类、操作系统类、性能计数器类和 WMI 服务管理类

若要获取动态类,可以使用 Get-CimClass cmdlet 的 -QualiferName 参数:

代码语言:javascript复制
Get-CimClass -ClassName "user" -QualifierName dynamic

看起来不错,下一步该如何操作?查询类以从中获取更多东西。

2.2 获取类

我们对 Win32_UserAccount 类感兴趣,通过如下命令可简单获取数据:

代码语言:javascript复制
Get-WmiObject -Class Win32_UserAccount

要获得更详细的输出,可以将上述命令通过管道传输到 Powershell 的 Format-List 或 fl 中,例如:Get-WmiObject -Class Win32_UserAccount | fl *

CIM cmdlet Get-CimInstance 能获取相同的信息:

代码语言:javascript复制
Get-CimInstance -ClassName Win32_UserAccount

现在我们有了系统上所有用户帐户的列表!

让我们将注意力转向系统上运行的进程,Win32_Process 类为我们提供了系统上运行的进程列表:

代码语言:javascript复制
Get-WmiObject -Class Win32_Process

许多进程在系统上运行,这可能会使终端上显示的内容无休止地滚动,这种情况并不少见!为了避免这种情况,我们可以使用 -Filter 参数来获取我们正在寻找的特定进程 (这里选择了 lsass.exe):

代码语言:javascript复制
Get-WmiObject -Class Win32_Process -Filter 'name="lsass.exe"'

在这种情况下,CIM cmdlet 替代方法 Get-CimInstance 提供了更短、更全面的输出 (并且它还支持 -Filter 参数):

代码语言:javascript复制
Get-CimInstance -ClassName Win32_Process

对 WQL 执行相同操作的表达式如下:

代码语言:javascript复制
Get-WmiObject -Query 'select * from win32_process where name="lsass.exe"'

现在我们知道在 WMI 中列出、获取和过滤类的实例,让我们看看在 WMI 中删除实例是如何工作的。

2.3 删除类实例

Remove-WmiObject (WMI cmdlet) 和 Remove-CimInstance (CIM cmdlet) 是两个具有删除实例功能的 cmdlet。可以将相关命令的输出通过管道传输到 cmdlet。为了快速演示,运行计算器应用程序并列出过程。

如果我们通过管道将命令传递给 Remove-CimInstance 会发生什么? 进程被杀死!

代码语言:javascript复制
Get-CimInstance -ClassName Win32_Process -Filter 'name="calculator.exe"' | Remove-CimInstance

这在处理 Registry 时非常有用,或者更好,在我们创建自己的类来存储我们的 Payloads 的情况下,我们可以简单地使用 cmdlet 列出类下的所有项目,从而将它们全部清理干净,一气呵成。

方法

方法可操作 WMI 对象,如果向上滚动到我们列出所有可用类的位置,你会注意到一个名为 Methods 的列,其中列出了可用的方法。

3.1 列出方法

要重复我们的工作并列出所有可用的方法,可以执行以下操作:

代码语言:javascript复制
Get-CimClass -MethodName *

为了过滤掉允许我们执行特定方法的实例,可以传递一个方法名称,例如 Create (这总是很有趣,因为它可能允许我们创建一些东西):

代码语言:javascript复制
Get-CimClass -MethodName Create

进一步缩小范围,列出特定类的可用方法,需要使用 Powershell 的 select-ExpandProperty 参数:

代码语言:javascript复制
Get-WmiObject -Class Win32_Process -List | select -ExpandProperty Methods
代码语言:javascript复制
Get-CimClass -ClassName Win32_Process | select -ExpandProperty CimClassMethods

传递给 select 语句的值是我们在列出类时得到的列的名称。如果你感到困惑,请向上滚动到我们列出类的部分,并观察 WMI 和 CIM cmdlet 输出之间的差异

因此,对于 Win32_Process 类,我们有 CreateTerminateGetOwnerGetOwnerSid 等方法。现在让我们看看如何使用方法。

要使用一个方法,我们需要知道调用该方法时需要提供哪些参数。要列出所有可用参数,我们可以结合使用 Powershell,或者更好地阅读

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/invoke-wmimethod?view=powershell-5.1#parameters

3.2 使用方法

Invoke-WmiMethod (WMI) 和 Invoke-CimMethod (CIM cmdlet) 允许我们使用特定类的方法。又是拿计算器开刀:

代码语言:javascript复制
Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList calc.exe

要使用 CIM cmdlet,语法略有不同:

代码语言:javascript复制
Invoke-CimMethod -ClassName Win32_Process -MethodName create -Arguments @{commandline="calc.exe"}

4 设置对象属性

最后但并非最不重要的一点,我们应该看看更新类的实例。但是,重要的是要记住实例应该是可写的。通过编写一些脚本,我们可以编写一个获取类的所有可写属性的方法。这是脚本 (来自 PSMag):

代码语言:javascript复制
$class = [wmiclass]'<class_name>'
$class.Properties | ForEach-Object 
{
foreach ($qualifier in $_.Qualifiers) 
{
if ($qualifier.Name -eq "Write") {
 $_.Name
}
}
}

对于我们的示例,我们将使用 Win32_OperatingSystem 类,该类具有一个名为 Description 的可写属性。

让我们使用 Set-WmiInstance 将属性名称更新为 PewOS

使用 Set-CimInstance 也可以实现相同的效果,但这留给读者去探索。

5 结论

哇,又是一篇长文!到目前为止,我们已经对 WMI 和 CIM cmdlet 以及如何使用它们实现对系统的重要控制打下了坚实的基础,干杯!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

0 人点赞