WMI 攻击手法研究 – 与 windows 注册表交互 (第三部分)

WMI 攻击手法研究 – 与 windows 注册表交互 (第三部分)

这是 WMI 攻击手法研究系列第三篇,本文将重点介绍与 Windows 注册表的交互。在开始之前需要了解的一件事情是:MITRE ATT&CK 对查询注册表 (Query Registry) 归类于 T1012 以及它的修改 (Modify Registry) 归类于 T1112

1 Windows 注册表是什么

简单来说,注册表是一个存储操作系统配置设置的数据库:内核、设备驱动程序、服务、SAM、用户界面和第三方应用程序都使用注册表,这使得注册表成为攻击者非常关注的一个点。

注册表由称为 hives 的部分组成,例如 HKEY_LOCAL_MACHINEHKEY_CURRENT_USER 等。检查 regedit.exe 中的注册表后,它们的排列方式似乎与文件系统类似,每个 hive 都有许多键,键可以有多个子键,键或子键用来存储值。注册表项由名称和值组成,成一对。

2 注册表 & WMI

WMI 提供了一个名为 StdRegProv 的类,用于与 Windows 注册表交互。有了这个,我们可以做很多事情,包括检索、创建、删除和修改键和值。这里需要注意的重要一点是,我们需要使用 root\DEFAULT 命名空间来处理注册表。

让我们开始探索吧:

Get-WmiObject -Namespace root\default -Class StdRegProv -List | select -ExpandProperty methods
图片[1]-WMI 攻击手法研究 – 与 windows 注册表交互 (第三部分)-零度非安全

在上图中,我们可以看到一些与注册表交互的方法,比如 CreateKeyDeleteKeyEnumKeyEnumValuesDeleteValues 等,这很有趣。

进入之前需要了解的两件重要事情:首先,WMI 使用常量数值来标识注册表中的不同配置单元。下表列出了访问注册表配置单元的常量:

VariableValueHive
$HKCR2147483648HKEY_CLASSES_ROOT
$HKCU2147483649HKEY_CURRENT_USER
$HKLM2147483650HKEY_LOCAL_MACHINE
$HKUS2147483651HKEY_USERS
$HKCC2147483653HKEY_CURRENT_CONFIG

其次,注册表具有不同的数据类型,并且可以使用 WMI 中的特定方法访问每种数据类型。下表将常见数据类型与它们的方法的对应关系:

MethodData TypeType ValueFunction
GetStringValueREG_SZ1返回一个字符串
GetExpandedStringValueREG_EXPAND_SZ2返回对 env 变量的扩展引用
GetBinaryValueREG_BINARY3返回字节数组
GetDWORDValueREG_DWORD4返回一个 32 位的数值
GetMultiStringValueREG_MULTI_SZ7返回多个字符串值
GetQWORDValueREG_QWORD11返回一个 64 位的数值

2.1 查询注册表

枚举键

现在我们知道了常量,让我们尝试枚举一个众所周知的注册表路径 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion 下的可用子项。把我们目前所知道的放在一起,可以使用以下这个命令来获取注册表项下的所有键:

Get-WmiObject -Namespace root\default -Class StdRegProv -List | select -ExpandProperty methods
图片[2]-WMI 攻击手法研究 – 与 windows 注册表交互 (第三部分)-零度非安全

注意:对于上层层次的注册表路径也可以这样做。如果不知道绝对路径,可以通过简单地替换上面命令中的路径来浏览注册表。例如,如果将上述命令中的路径 software\microsoft\windows nt\currentversion\schedule 替换为 software,则输出将列出 HKEY_LOCAL_MACHINE\Software 下的所有子项。这在探索注册表中的未知嵌套项时很有帮助。

枚举值

现在我们知道如何列出注册表项下可用的键,让我们枚举 Drivers32 键下的值:

Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name enumvalues @(2147483650, "software\microsoft\windows nt\currentversion\drivers32")
图片[3]-WMI 攻击手法研究 – 与 windows 注册表交互 (第三部分)-零度非安全

正如我们所见,输出包含 sNames 下的子项名称和 Types 属性下的关联数据类型。当然也可以使用 Powershell 的 select -ExpandProperty 选项参数来扩展输出中返回的属性值。

读取值

现在让我们尝试读取子键的值,对于示例,将读取 Drivers32 子键 (定义应用程序的 Windows NT DLL) 的值。过去曾观察到几个恶意软件变种使用此子键 (请参阅 Riern Trojan Family)。

以下命令读取 Drivers32 项下子项 auxmidi 的值。请注意,传递给 cmdlet 的方法名称 (通过 -Name 选项参数) 将因注册表数据类型而异 (请参阅上面的数据类型表)。

Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name GetStringValue @(2147483650, "software\microsoft\windows nt\currentversion\drivers32", "aux")
Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name GetStringValue @(2147483650, "software\microsoft\windows nt\currentversion\drivers32", "midi") | select svalue
图片[4]-WMI 攻击手法研究 – 与 windows 注册表交互 (第三部分)-零度非安全

2.2 修改注册表

现在已经知道如何使用 WMI 从注册表中读取键值对,然而,到目前为止,这些并不需要管理权限 —— 创建、删除和更新键和值可能需要提升权限。

让我们尝试创建新的键和子键,但在此之前,我们需要检查是否可以访问特定的注册表项,还有一个常量定义了对键的访问级别,下表总结了具有关联常量的权限:

MethodValueFunction
KEY_QUERY_VALUE1查询注册表键的值
KEY_SET_VALUE2创建、删除或设置注册表值
KEY_CREATE_SUB_KEY4创建注册表项的子项
KEY_ENUMERATE_SUB_KEYS8枚举注册表项的子项
KEY_NOTIFY16注册表项或注册表项子项的更改通知
KEY_CREATE32创建注册表项
DELETE65536删除注册表项
READ_CONTROL131072结合 STANDARD_RIGHTS_READ、KEY_QUERY_VALUE、KEY_ENUMERATE_SUB_KEYS 和 KEY_NOTIFY 值
WRITE_DAC262144修改对象安全描述符中的 DACL
WRITE_OWNER524288更改对象安全描述符中的所有者

检查键的权限

对于我们的示例,首先选择配置单元 HKEY_CURRENT_USER 下的 Run 键,然后选择 HKEY_LOCAL_MACHINE,以下展示如何做:

Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name CheckAccess @(2147483649, "software\microsoft\windows\currentversion\run", 32)
Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name CheckAccess @(2147483650, "software\microsoft\windows\currentversion\run", 32)
图片[5]-WMI 攻击手法研究 – 与 windows 注册表交互 (第三部分)-零度非安全

上图中的 bGranted 属性告诉我们是否可以访问注册表中的特定项目。从上面的例子中,可以清楚地看到用户当前可以访问 HKEY_CURRENT_USER 下的 Run 键,而不是 HKEY_LOCAL_MACHINE

创建注册表项

现在我们知道对在 HKEY_CURRENT_USER 下运行的注册表项有写访问权限,将计算器应用程序添加到注册表项中。这将导致每次系统启动时都会弹出一个计算器,这是恶意软件中常见的一种获得持久性的技术。

Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name SetStringValue @(2147483649, "software\microsoft\windows\currentversion\run", "C:\Windows\System32\calc.exe", "Calculator")
图片[6]-WMI 攻击手法研究 – 与 windows 注册表交互 (第三部分)-零度非安全

Boom,我们的计算器应用程序实现了持久化。

注意:注册表项下的现有子项也可以使用上述方法进行更新。

删除注册表项

删除注册表子项不需要的值:

Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name DeleteValue @(2147483649, "software\microsoft\windows\currentversion\run", "Calculator")
图片[7]-WMI 攻击手法研究 – 与 windows 注册表交互 (第三部分)-零度非安全

创建键

在少数情况下,我们可能需要在主树层次结构下创建键。假设要在 HKEY_LOCAL_MACHINE\Software\OpenSSH 注册表项下创建一个名为 CustomAgent 的新键,这个过程看起来非常简单:

Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name DeleteValue @(2147483649, "software\microsoft\windows\currentversion\run", "Calculator")
图片[8]-WMI 攻击手法研究 – 与 windows 注册表交互 (第三部分)-零度非安全

删除键

删除键同样也很简单:

Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name DeleteKey @(2147483650, "software\openssh\CustomAgent")
图片[9]-WMI 攻击手法研究 – 与 windows 注册表交互 (第三部分)-零度非安全

3 工具

  • Registry.ps1:具有易于使用的 PowerShell 函数,用于枚举、创建、删除、更新键等,在手动处理问题时非常有用;
  • Get-Information.ps1:Nishang 通过注册表收集系统的有趣信息;
  • Invoke-WmiCommand.ps1:Powersploit 是一个非常有用的脚本,它通过使用 WMI 作为纯 C2 通道将 Payload 存储在注册表中来帮助执行代码;
  • Invoke-SessionGopher.ps1:从 PoweShell Empire 搜索和解密来自系统的 RDP、WinSCP、FileZilla、PuTTY 等会话信息。

4 结论

在收集有用数据时,注册表是攻击者的宝库。此外,注册表还可用于存储 Payload,作为理想的无文件攻击和持久性机制。在本系列的后面部分,我们将了解如何仅使用 WMI 和注册表来创建整个 C2 基础设施。现在已经完成了基础知识,在下一篇文章中,将从 WMI 的基本侦察开始。

敬请期待,我的朋友!

© 版权声明
THE END
喜欢就支持一下吧
点赞14赞赏 分享
评论 抢沙发

请登录后发表评论