|
本篇文章是 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>,比如 root\DEFAULT,root\CIM2 等等,因为它们是 root (本身也是一个命名空间) 下的命名空间。
注意:一个奇怪而有趣的事实是,WMI 中的默认命名空间不是 root\DeFAULT 而是 root\CIMV2 (自 Windows 2000 以来一直是这样)。
使用 CIM cmdlet Get-CimInstance 可以实现相同目的:
- Get-CimInstance -Namespace root -ClassName __Namespace
复制代码
OK,上面已整整齐齐列出来了,那嵌套的名称空间呢?我们已经看到 root 命名空间下有几个命名空间,只需要编写一个脚本,递归地获取名称空间 (来自 PSMag)
- 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 (关联类):描述类和托管资源之间的关系;
2.1 列出类
有了足够的理论支撑,让我们尝试寻找一些类,我们可以使用 Get-WmiObject cmdlet 列出可用的类:
- Get-WmiObject -Class * -List
复制代码
上面这条命令将会列出所有类,但为了举例,假设我们对系统上的用户感兴趣。可以使用以下命令来缩小范围,该命令列出了用于获取或操作用户信息的所有可用类:
- 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 类为我们提供了系统上运行的进程列表:
- Get-WmiObject -Class Win32_Process
复制代码
许多进程在系统上运行,这可能会使终端上显示的内容无休止地滚动,这种情况并不少见!为了避免这种情况,我们可以使用 -Filter 参数来获取我们正在寻找的特定进程 (这里选择了 lsass.exe):
- Get-WmiObject -Class Win32_Process -Filter 'name="lsass.exe"'
复制代码
在这种情况下,CIM cmdlet 替代方法 Get-CimInstance 提供了更短、更全面的输出 (并且它还支持 -Filter 参数):
对 WQL 执行相同操作的表达式如下:
- 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 会发生什么? 进程被杀死!
- Get-CimInstance -ClassName Win32_Process -Filter 'name="calculator.exe"' | Remove-CimInstance
复制代码
这在处理 Registry 时非常有用,或者更好,在我们创建自己的类来存储我们的 Payloads 的情况下,我们可以简单地使用 cmdlet 列出类下的所有项目,从而将它们全部清理干净,一气呵成。
三、方法
方法可操作 WMI 对象,如果向上滚动到我们列出所有可用类的位置,你会注意到一个名为 Methods 的列,其中列出了可用的方法。
3.1 列出方法
要重复我们的工作并列出所有可用的方法,可以执行以下操作:
- Get-CimClass -MethodName *
复制代码
为了过滤掉允许我们执行特定方法的实例,可以传递一个方法名称,例如 Create (这总是很有趣,因为它可能允许我们创建一些东西):
- Get-CimClass -MethodName Create
复制代码
进一步缩小范围,列出特定类的可用方法,需要使用 Powershell 的 select 和 -ExpandProperty 参数:
- Get-WmiObject -Class Win32_Process -List | select -ExpandProperty Methods
- Get-CimClass -ClassName Win32_Process | select -ExpandProperty CimClassMethods
复制代码
注意:传递给 select 语句的值是我们在列出类时得到的列的名称。如果你感到困惑,请向上滚动到我们列出类的部分,并观察 WMI 和 CIM cmdlet 输出之间的差异。
因此,对于 Win32_Process 类,我们有 Create、Terminate、GetOwner、GetOwnerSid 等方法。现在让我们看看如何使用方法。
提示:要使用一个方法,我们需要知道调用该方法时需要提供哪些参数。要列出所有可用参数,我们可以结合使用 Powershell,或者更好地阅读 文档。
3.2 使用方法
Invoke-WmiMethod (WMI) 和 Invoke-CimMethod (CIM cmdlet) 允许我们使用特定类的方法。又是拿计算器开刀 :
- Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList calc.exe
复制代码
要使用 CIM cmdlet,语法略有不同:
- Invoke-CimMethod -ClassName Win32_Process -MethodName create -Arguments @{commandline="calc.exe"}
复制代码
四、设置对象属性
最后但并非最不重要的一点,我们应该看看更新类的实例。但是,重要的是要记住实例应该是可写的。通过编写一些脚本,我们可以编写一个获取类的所有可写属性的方法。这是脚本 (来自 PSMag):
- $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 也可以实现相同的效果,但这留给读者去探索。
五、结论
哇,又是一篇长文!到目前为止,我们已经对 WMI 和 CIM cmdlet 以及如何使用它们实现对系统的重要控制打下了坚实的基础,干杯!
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|