文章目录[隐藏]
- 命名空间
- 类
- 列出类
- 2.2 获取类
- 2.3 删除类实例
- 方法
- 3.1 列出方法
- 3.2 使用方法
- 4 设置对象属性
- 5 结论
本篇文章是 WMI 攻击手法研究的第二篇,主要研究 WMI 中的 3 个组件,在整篇文章中,我们将交替使用 WMI 和 CIM cmdlet,以便熟悉这两种 cmdlet 类型。
命名空间
让我们简单回顾一下命名空间是什么:
命名空间结构信息类似于文件系统中文件夹,但是,与物理位置 (例如磁盘上) 不同,它们本质上更具有逻辑
WMI 中的所有命名空间都是 __Namespace
系统类的实例,要获取 root
命名空间下所有命名空间的列表,可使用以下命令查询同一个类:
Get-WmiObject -Namespace root -Class __Namespace
输出的内容包含了许多信息,为了过滤掉 “无用” 信息,可使用 PowerShell 中的 select
:
Get-WmiObject -Namespace root -Class __Namespace | select name
现在我们从系统中得到一个命名空间的列表,许多命名空间会是这样格式出现 root<namespace>
,比如 rootDEFAULT
,rootCIM2
等等,因为它们是 root (本身也是一个命名空间) 下的命名空间。
一个奇怪而有趣的事实是,WMI 中的默认命名空间不是 rootDeFAULT 而是 rootCIMV2 (自 Windows 2000 以来一直是这样)
使用 CIM cmdlet Get-CimInstance
可以实现相同目的:
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
列出可用的类:
Get-WmiObject -Class * -List
上面这条命令将会列出所有类,但为了举例,假设我们对系统上的用户感兴趣。可以使用以下命令来缩小范围,该命令列出了用于获取或操作用户信息的所有可用类:
代码语言:javascript复制Get-WmiObject -Class *user* -List
同样也可以使用 Get-CimClass
命令也能实现同样的效果,如下所示:
Get-CimClass -ClassName *user*
有关所有 Win32 类的列表,可以参考 Microsoft 的类文档。 Win32 Provider 提供 4 个不同类别的类:计算机系统硬件类、操作系统类、性能计数器类和 WMI 服务管理类
若要获取动态类,可以使用 Get-CimClass
cmdlet 的 -QualiferName
参数:
Get-CimClass -ClassName "user" -QualifierName dynamic
看起来不错,下一步该如何操作?查询类以从中获取更多东西。
2.2 获取类
我们对 Win32_UserAccount
类感兴趣,通过如下命令可简单获取数据:
Get-WmiObject -Class Win32_UserAccount
要获得更详细的输出,可以将上述命令通过管道传输到 Powershell 的 Format-List 或 fl 中,例如:Get-WmiObject -Class Win32_UserAccount | fl *
CIM cmdlet Get-CimInstance
能获取相同的信息:
Get-CimInstance -ClassName Win32_UserAccount
现在我们有了系统上所有用户帐户的列表!
让我们将注意力转向系统上运行的进程,Win32_Process 类为我们提供了系统上运行的进程列表:
代码语言:javascript复制Get-WmiObject -Class Win32_Process
许多进程在系统上运行,这可能会使终端上显示的内容无休止地滚动,这种情况并不少见!为了避免这种情况,我们可以使用 -Filter
参数来获取我们正在寻找的特定进程 (这里选择了 lsass.exe
):
Get-WmiObject -Class Win32_Process -Filter 'name="lsass.exe"'
在这种情况下,CIM cmdlet 替代方法 Get-CimInstance
提供了更短、更全面的输出 (并且它还支持 -Filter
参数):
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
参数:
Get-WmiObject -Class Win32_Process -List | select -ExpandProperty Methods
代码语言:javascript复制Get-CimClass -ClassName Win32_Process | select -ExpandProperty CimClassMethods
传递给 select 语句的值是我们在列出类时得到的列的名称。如果你感到困惑,请向上滚动到我们列出类的部分,并观察 WMI 和 CIM cmdlet 输出之间的差异
因此,对于 Win32_Process 类,我们有 Create
、Terminate
、GetOwner
、GetOwnerSid
等方法。现在让我们看看如何使用方法。
要使用一个方法,我们需要知道调用该方法时需要提供哪些参数。要列出所有可用参数,我们可以结合使用 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) 允许我们使用特定类的方法。又是拿计算器开刀:
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 以及如何使用它们实现对系统的重要控制打下了坚实的基础,干杯!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。