Это третья часть серии «Offensive WMI» (вторая здесь https://0xinfection.github.io/posts/wmi-classes-methods-part-2/), и эта статья будет посвящена взаимодействию с реестром Windows. Прежде чем мы начнем, полезно знать, что MITER ATT & CK классифицирует запросы значений реестра в соответствии с T1012 https://attack.mitre.org/techniques/T1012/ и его модификацию в соответствии с T1112 https://attack.mitre.org/techniques/T1112/.
Давайте погрузимся в реестр.
Что такое реестр Windows?
Проще говоря, реестр - это база данных, в которой хранятся параметры конфигурации и параметры операционной системы: ядро, драйверы устройств, службы, SAM, пользовательский интерфейс и сторонние приложения используют реестр. Это делает реестр очень привлекательным ресурсом для злоумышленников.
Реестр состоит из разделов, известных как ульи, например HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER и т. д. При проверке реестра в regedit.exe они выглядят так же, как файловая система. У каждого улья есть несколько ключей. Ключи могут иметь несколько подключей. Ключ или подраздел действует как хранилище значений. Элемент реестра состоит из пары имени и значения.
Реестр и WMI
WMI предоставляет класс StdRegProv https://docs.microsoft.com/en-us/previous-versions/windows/desktop/regprov/stdregprov для взаимодействия с реестром Windows. Имея это под рукой, мы можем делать множество вещей, включая извлечение, создание, удаление и изменение ключей и значений. Здесь важно отметить, что нам нужно использовать пространство имен root\DEFAULT для работы с реестром.
Начнем с изучения доступных нам методов:
Get-WmiObject -Namespace root\default -Class StdRegProv -List | select -ExpandProperty methods
Из выходных данных выше мы видим такие методы, как CreateKey, DeleteKey, EnumKey, EnumValues, DeleteValues и т. д. для взаимодействия с реестром. Интересно.
Перед тем как приступить к делу, необходимо знать две важные вещи:
1. Во-первых, WMI использует постоянные числовые значения для идентификации различных кустов в реестре. В таблице ниже перечислены константы для доступа к кустам реестра:
2. Во-вторых, реестр имеет разные типы данных, и к каждому типу данных можно получить доступ с помощью определенного метода в WMI. В таблице ниже общие типы данных сопоставляются с их методами:
Запрос реестра
Перечисление ключей
Теперь, когда мы знаем константы, давайте попробуем перечислить доступные подразделы в хорошо известном пути реестра HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion. Объединив все, что мы знаем до сих пор, мы можем использовать эту команду, чтобы получить все ключи в элементе реестра:
Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name EnumKey @(2147483650, "software\microsoft\windows nt\currentversion") | select -ExpandProperty snames
ПРИМЕЧАНИЕ. То же самое можно сделать и с путями реестра более высокого уровня. Если вы не знаете абсолютный путь, вы можете изучить реестр, просто заменив путь в приведенной выше команде.
Перечисление значений
Теперь, когда мы знаем, как перечислить ключи, доступные в элементе реестра, давайте перечислим значения в разделе Drivers32:
Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name enumvalues @(2147483650, "software\microsoft\windows nt\currentversion\drivers32")
Как мы видим, выходные данные содержат имена подключей в sNames и связанный тип данных в свойстве Types. Конечно, мы можем использовать переключатель Powershell select -ExpandProperty для расширенного просмотра значений свойств, возвращаемых в выводе.
Чтение значений
Теперь попробуем прочитать значения подключей. В нашем примере мы будем читать значения подраздела Drivers32 (который определяет библиотеки DLL Windows NT для приложений). В прошлом было замечено несколько вариантов вредоносных программ, использующих этот ключ (смотри - https://www.trendmicro.com/vinfo/us/threat-encyclopedia/malware/troj_riern.sma- ).
Следующая команда считывает значение подключей aux и midi под ключом Drivers32. Обратите внимание, что имя метода, передаваемое командлету (с помощью переключателя -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
СОВЕТ: Вот хорошая шпаргалка https://www.dfir.training/ultimate-registry-forensics-cheat-sheet с интересными местами в реестре, которые могут быть полезны злоумышленнику. Вы можете попробовать изучить их.
Изменение реестра
Теперь мы знаем о чтении пар ключ и значение из реестра с помощью WMI. Однако пока для этого не требовались административные привилегии - для создания, удаления и обновления ключей и значений могут потребоваться повышенные привилегии.
Попробуем создать новые ключи и подключи. Но перед этим нам нужно проверить, есть ли у нас доступ к конкретному элементу реестра. И снова есть константы, определяющие уровни доступа к ключам. В следующей таблице приведены разрешения для связанных констант:
Проверка разрешений ключа
В нашем примере мы сначала выберем ключ Run под кустом HKEY_CURRENT_USER, а затем 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)
Свойство bGranted в выходных данных сообщает нам, есть ли у нас доступ к определенному элементу реестра. Из приведенного выше примера мы можем ясно видеть, что наш пользователь в настоящее время имеет доступ к ключу Run в HKEY_CURRENT_USER, но не HKEY_LOCAL_MACHINE.
Создание записей в реестре
Теперь, когда мы знаем, что у нас есть доступ для записи в раздел реестра Run под HKEY_CURRENT_USER, мы добавим наше любимое приложение-калькулятор в этот элемент реестра. Это приведет к тому, что калькулятор будет появляться каждый раз при загрузке системы - очень распространенный метод, используемый вредоносными программами для обеспечения устойчивости.
Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name SetStringValue @(2147483649, "software\microsoft\windows\currentversion\run", "C:\Windows\System32\calc.exe", "Calculator")
Бум, наше приложение-калькулятор добилось персистентности. : D
ПРИМЕЧАНИЕ. Существующий подраздел в разделе реестра также можно обновить, используя ту же самую команду, что и выше.
Удаление записей реестра
Чтобы удалить подраздел реестра, нам не нужно значение:
Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name DeleteValue @(2147483649, "software\microsoft\windows\currentversion\run", "Calculator")
Создание новых ключей
В некоторых случаях нам может потребоваться создать ключи в основной древовидной иерархии. Допустим, мы хотим создать новый ключ с именем CustomAgent в элементе реестра HKEY_LOCAL_MACHINE\Software\OpenSSH. Процесс выглядит предельно просто:
Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name DeleteValue @(2147483649, "software\microsoft\windows\currentversion\run", "Calculator")
Удаление ключей
Удалить ключ так же просто:
Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name DeleteKey @(2147483650, "software\openssh\CustomAgent")
Дополнительные инструменты
- Registry.ps1 https://github.com/darkoperator/Posh-SecMod/blob/master/Registry/Registry.ps1 - имеет простые в использовании функции Powershell для перечисления, создания, удаления, обновления ключей и т. д. Очень полезно при работе с вещами вручную.
- Get-Information.ps1 https://github.com/samratashok/nishang/blob/master/Gather/Get-Information.ps1 - от Nishang собирает интересную информацию о системе через реестр.
- Invoke-WmiCommand.ps1 https://github.com/PowerShellMafia/PowerSploit/blob/master/CodeExecution/Invoke-WmiCommand.ps1 - от Powersploit - очень полезный скрипт, который помогает в выполнении кода, сохраняя полезные данные в реестре с использованием WMI в качестве чистого канала C2.
- Invoke-SessionGopher.ps1 https://github.com/EmpireProject/Empire/blob/master/data/module_source/credentials/Invoke-SessionGopher.ps1 - из Powershell Empire ищет и расшифровывает RDP, WinSCP, FileZilla, PuTTY и т. д. информацию о сеансе из системы.
Заключение
Реестр - настоящая находка для злоумышленников, когда дело доходит до сбора полезных данных. Кроме того, реестр также может использоваться для хранения полезных данных, служа идеальным вектором безфайловых атак и механизмом устойчивости. В более поздней части этой серии мы рассмотрим, как создать всю нашу инфраструктуру C2, используя только WMI и реестр. Теперь, когда мы закончили с основами, в нашем следующем блоге мы начнем с базовой разведки с помощью WMI.
Давайте погрузимся в реестр.
Что такое реестр Windows?
Проще говоря, реестр - это база данных, в которой хранятся параметры конфигурации и параметры операционной системы: ядро, драйверы устройств, службы, SAM, пользовательский интерфейс и сторонние приложения используют реестр. Это делает реестр очень привлекательным ресурсом для злоумышленников.
Реестр состоит из разделов, известных как ульи, например HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER и т. д. При проверке реестра в regedit.exe они выглядят так же, как файловая система. У каждого улья есть несколько ключей. Ключи могут иметь несколько подключей. Ключ или подраздел действует как хранилище значений. Элемент реестра состоит из пары имени и значения.
Реестр и WMI
WMI предоставляет класс StdRegProv https://docs.microsoft.com/en-us/previous-versions/windows/desktop/regprov/stdregprov для взаимодействия с реестром Windows. Имея это под рукой, мы можем делать множество вещей, включая извлечение, создание, удаление и изменение ключей и значений. Здесь важно отметить, что нам нужно использовать пространство имен root\DEFAULT для работы с реестром.
Начнем с изучения доступных нам методов:
Get-WmiObject -Namespace root\default -Class StdRegProv -List | select -ExpandProperty methods
Из выходных данных выше мы видим такие методы, как CreateKey, DeleteKey, EnumKey, EnumValues, DeleteValues и т. д. для взаимодействия с реестром. Интересно.
Перед тем как приступить к делу, необходимо знать две важные вещи:
1. Во-первых, WMI использует постоянные числовые значения для идентификации различных кустов в реестре. В таблице ниже перечислены константы для доступа к кустам реестра:
| Variable | Value | Hive |
|---|---|---|
| $HKCR | 2147483648 | HKEY_CLASSES_ROOT |
| $HKCU | 2147483649 | HKEY_CURRENT_USER |
| $HKLM | 2147483650 | HKEY_LOCAL_MACHINE |
| $HKUS | 2147483651 | HKEY_USERS |
| $HKCC | 2147483653 | HKEY_CURRENT_CONFIG |
2. Во-вторых, реестр имеет разные типы данных, и к каждому типу данных можно получить доступ с помощью определенного метода в WMI. В таблице ниже общие типы данных сопоставляются с их методами:
| Method | Data Type | Type Value | Function |
|---|---|---|---|
| GetStringValue | REG_SZ | 1 | Returns a string. |
| GetExpandedStringValue | REG_EXPAND_SZ | 2 | Returns expanded references to env variables. |
| GetBinaryValue | REG_BINARY | 3 | Returns array of bytes. |
| GetDWORDValue | REG_DWORD | 4 | Returns a 32-bit number. |
| GetMultiStringValue | REG_MULTI_SZ | 7 | Returns multiple string values. |
| GetQWORDValue | REG_QWORD | 11 | Returns a 64-bit number. |
Запрос реестра
Перечисление ключей
Теперь, когда мы знаем константы, давайте попробуем перечислить доступные подразделы в хорошо известном пути реестра HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion. Объединив все, что мы знаем до сих пор, мы можем использовать эту команду, чтобы получить все ключи в элементе реестра:
Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name EnumKey @(2147483650, "software\microsoft\windows nt\currentversion") | select -ExpandProperty snames
ПРИМЕЧАНИЕ. То же самое можно сделать и с путями реестра более высокого уровня. Если вы не знаете абсолютный путь, вы можете изучить реестр, просто заменив путь в приведенной выше команде.
Перечисление значений
Теперь, когда мы знаем, как перечислить ключи, доступные в элементе реестра, давайте перечислим значения в разделе Drivers32:
Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name enumvalues @(2147483650, "software\microsoft\windows nt\currentversion\drivers32")
Как мы видим, выходные данные содержат имена подключей в sNames и связанный тип данных в свойстве Types. Конечно, мы можем использовать переключатель Powershell select -ExpandProperty для расширенного просмотра значений свойств, возвращаемых в выводе.
Чтение значений
Теперь попробуем прочитать значения подключей. В нашем примере мы будем читать значения подраздела Drivers32 (который определяет библиотеки DLL Windows NT для приложений). В прошлом было замечено несколько вариантов вредоносных программ, использующих этот ключ (смотри - https://www.trendmicro.com/vinfo/us/threat-encyclopedia/malware/troj_riern.sma- ).
Следующая команда считывает значение подключей aux и midi под ключом Drivers32. Обратите внимание, что имя метода, передаваемое командлету (с помощью переключателя -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
СОВЕТ: Вот хорошая шпаргалка https://www.dfir.training/ultimate-registry-forensics-cheat-sheet с интересными местами в реестре, которые могут быть полезны злоумышленнику. Вы можете попробовать изучить их.
Изменение реестра
Теперь мы знаем о чтении пар ключ и значение из реестра с помощью WMI. Однако пока для этого не требовались административные привилегии - для создания, удаления и обновления ключей и значений могут потребоваться повышенные привилегии.
Попробуем создать новые ключи и подключи. Но перед этим нам нужно проверить, есть ли у нас доступ к конкретному элементу реестра. И снова есть константы, определяющие уровни доступа к ключам. В следующей таблице приведены разрешения для связанных констант:
| Method | Value | Function |
|---|---|---|
| KEY_QUERY_VALUE | 1 | Query the values of a registry key |
| KEY_SET_VALUE | 2 | Create, delete, or set a registry value |
| KEY_CREATE_SUB_KEY | 4 | Create a subkey of a registry key |
| KEY_ENUMERATE_SUB_KEYS | 8 | Enumerate the subkeys of a registry key |
| KEY_NOTIFY | 16 | Change notifications for a registry key or for subkeys of a registry key |
| KEY_CREATE | 32 | Create a registry key |
| DELETE | 65536 | Delete a registry key |
| READ_CONTROL | 131072 | Combines the STANDARD_RIGHTS_READ, KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS and KEY_NOTIFY values |
| WRITE_DAC | 262144 | Modify the DACL in the object’s security descriptor |
| WRITE_OWNER | 524288 | Change the owner in the object’s security descriptor |
Проверка разрешений ключа
В нашем примере мы сначала выберем ключ Run под кустом HKEY_CURRENT_USER, а затем 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)
Свойство bGranted в выходных данных сообщает нам, есть ли у нас доступ к определенному элементу реестра. Из приведенного выше примера мы можем ясно видеть, что наш пользователь в настоящее время имеет доступ к ключу Run в HKEY_CURRENT_USER, но не HKEY_LOCAL_MACHINE.
Создание записей в реестре
Теперь, когда мы знаем, что у нас есть доступ для записи в раздел реестра Run под HKEY_CURRENT_USER, мы добавим наше любимое приложение-калькулятор в этот элемент реестра. Это приведет к тому, что калькулятор будет появляться каждый раз при загрузке системы - очень распространенный метод, используемый вредоносными программами для обеспечения устойчивости.
Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name SetStringValue @(2147483649, "software\microsoft\windows\currentversion\run", "C:\Windows\System32\calc.exe", "Calculator")
Бум, наше приложение-калькулятор добилось персистентности. : D
ПРИМЕЧАНИЕ. Существующий подраздел в разделе реестра также можно обновить, используя ту же самую команду, что и выше.
Удаление записей реестра
Чтобы удалить подраздел реестра, нам не нужно значение:
Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name DeleteValue @(2147483649, "software\microsoft\windows\currentversion\run", "Calculator")
Создание новых ключей
В некоторых случаях нам может потребоваться создать ключи в основной древовидной иерархии. Допустим, мы хотим создать новый ключ с именем CustomAgent в элементе реестра HKEY_LOCAL_MACHINE\Software\OpenSSH. Процесс выглядит предельно просто:
Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name DeleteValue @(2147483649, "software\microsoft\windows\currentversion\run", "Calculator")
Удаление ключей
Удалить ключ так же просто:
Invoke-WmiMethod -Namespace root\default -Class stdregprov -Name DeleteKey @(2147483650, "software\openssh\CustomAgent")
Дополнительные инструменты
- Registry.ps1 https://github.com/darkoperator/Posh-SecMod/blob/master/Registry/Registry.ps1 - имеет простые в использовании функции Powershell для перечисления, создания, удаления, обновления ключей и т. д. Очень полезно при работе с вещами вручную.
- Get-Information.ps1 https://github.com/samratashok/nishang/blob/master/Gather/Get-Information.ps1 - от Nishang собирает интересную информацию о системе через реестр.
- Invoke-WmiCommand.ps1 https://github.com/PowerShellMafia/PowerSploit/blob/master/CodeExecution/Invoke-WmiCommand.ps1 - от Powersploit - очень полезный скрипт, который помогает в выполнении кода, сохраняя полезные данные в реестре с использованием WMI в качестве чистого канала C2.
- Invoke-SessionGopher.ps1 https://github.com/EmpireProject/Empire/blob/master/data/module_source/credentials/Invoke-SessionGopher.ps1 - из Powershell Empire ищет и расшифровывает RDP, WinSCP, FileZilla, PuTTY и т. д. информацию о сеансе из системы.
Заключение
Реестр - настоящая находка для злоумышленников, когда дело доходит до сбора полезных данных. Кроме того, реестр также может использоваться для хранения полезных данных, служа идеальным вектором безфайловых атак и механизмом устойчивости. В более поздней части этой серии мы рассмотрим, как создать всю нашу инфраструктуру C2, используя только WMI и реестр. Теперь, когда мы закончили с основами, в нашем следующем блоге мы начнем с базовой разведки с помощью WMI.