Уровень сложностиСредний
Время на прочтение28 мин
Количество просмотров16K
Всем привет! Меня зовут Сергей Кислухин, я работаю аналитиком 3 линии SOC, и мне есть чем поделиться в области реагирования на компьютерные инциденты на хостах под управлением Windows.
Введение
В своей работе, работники ИБ, особенно те, кто связаны с реагированием на инциденты, форензикой или compromise assessment, обязательно сталкиваются с необходимостью копаться в операционной системе глубже и быстрее, чем это делают остальные. Так, при реагировании на аномальное событие (или его поиске), специалисты, в подавляющих случаях, смотрят только журналы событий систем (локально или же через SIEM). И, если информации оттуда оказывается недостаточно, то прибегают к особым мерам, вроде локальных анализа дампа ОЗУ и анализа Amcache, Prefetch, MFT, AppCompatCache, UserAssist и т.д.
К анализу реестра же прибегают, либо для ручного просмотра какой-то уникальной информации о хосте, либо для поиска событий с помощью сторонних автоматизированных утилит (Sysinternals Autoruns, PersistenceSniper, RegRipper), которые смотрят на определенный набор мест, которыми может воспользоваться злоумышленник. Этот вариант анализа реестра, а также прочие методы, в которых требуется просматривать вручную каждую ветку, я считаю неэффективными, и далее в статье я поясню почему, и покажу пример, как я решил эту проблему.
Оглавление
-
Краткая теория
-
Проблема
-
Предложенное решение
-
Демонстрация на примерах
-
Выводы
-
Ссылки на источники
Краткая теория
Реестр Windows это база данных системы, которая отслеживает информацию, касающуюся конфигурации, действий, пользователей и т. д. Состоит он из иерархического набора папок (веток), в которых хранятся другие папки, ключи и их значения. Физически, кусты (корневые ветки) и ветки хранятся в системе, в нескольких местах:
-
В оперативной памяти — куст HKEY_LOCAL_MACHINE\Hardware;
-
%SystemRoot%\System32\Config\*
— основные ветки SYSTEM, SAM, SECURITY, SOFTWARE и DEFAULT куста HKEY_LOCAL_MACHINE; -
C:\Users\%Username%\NTUSER.DAT
— файлы кустов реестра пользователей HKEY_CURRENT_USER; -
%AppData%\Local\Microsoft\Windows\UsrClass.dat
— куст HKEY_CLASSES_ROOT (типы информации из подраздела HKEY_LOCAL_MACHINE\Software\Classes); -
%SystemRoot%\AppCompat\Programs\Amcache.hve
— файл ключа Amcache (содержит информацию о всех исполняемых файлах).
Значение ключа может иметь один из типов данных:
-
Строка (REG_SZ) — Строки с буквенно-цифровыми символами;
-
Многострочное значение (REG_MULTI_SZ) — Список значений, а не однострочный текст;
-
Расширяемое строковое значение (REG_EXPAND_SZ) — Переменные, фактическое значение которых используется операционной системой во время выполнения или при необходимости;
-
Двоичные значения (REG_BINARY);
-
Шестнадцатеричные числа (DWORD и QWORD).
-
…
Так как реестр содержит информацию, связанную с конфигурацией системы, то злоумышленники активно этим пользуются, добавляя или изменяя ветки в своих целях, что бы при определенных действиях выполнялась их злонамеренная программа или предоставлялся несанкционированный доступ к системе. Наиболее популярные ветки реестра, используемые во вредоносных целях описаны распределенно в различных техниках тактики Закрепления в матрице MITRE (Persistence, Tactic TA0003 | MITRE ATT&CK). Так, самой распространенной тактикой считается добавление ссылки на исполняемый файл в ветку реестра автозапуска системы HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
, в результате чего, указанная программа будет выполнятся каждый раз при включении операционной системы.
Для анализа реестра существует несколько утилит и способов:
-
Стандартный, встроенный в систему, для работы с реестром хоста, наживую:
-
%SystemRoot%\regedit.exe
— позволяет просматривать и изменять, а также импортировать и экспортировать ветки и ключи реестра;
-
-
Сторонние аналоги, для работы с выгруженными файлами реестра, других хостов:
-
Registry Explorer — с графическим интерфейсом;
-
RECmd — консольный вариант;
-
-
Анализатор выгруженных файлов или веток реестра, по сторонним алгоритмам:
-
RegRipper;
-
Sysinternals Autoruns (требуется дополнительно выгрузка некоторых библиотек для работы);
-
-
Анализаторы работающей системы, по сторонним алгоритмам:
-
Sysinternals Autoruns;
-
PersistenceSniper;
-
-
Анализ изменений, выполняемых процессами системы в событиях безопасности (требуется дополнительная предварительная настройка):
-
События Sysmon: 12 (Создание/удаление объекта реестра), 13 (Задание значения реестра), 14 (Переименование ключа и значения реестра);
-
События Security: 4657 (Значение реестра изменено);
-
-
Анализ реестра из дампа оперативной памяти:
-
Volatility.
-
Проблема
Потратив несколько вечеров на консолидацию всей информации из матрицы MITRE и дополнительный сбор, не описанных в ней методов автозапуска ПО, можно получить подобную картину по веткам реестра, которые могут использоваться для вредоносных целей (в скобках, при возможности, указано к какой технике MITRE ATT&CK относится данная ветка реестра):
Возможные места закрепления в реестре Windows
-
SOFTWARE\Classes\CLSID\*
(# Event Triggered Execution: Component Object Model Hijacking T1546/015) -
SOFTWARE\Classes\*\shell\*\command
(# Event Triggered Execution: Change Default File Association T1546/001) -
SOFTWARE\Microsoft\Active Setup\Installed Components\
(# Boot or Logon Autostart Execution: Active Setup T1547/014) -
SOFTWARE\Microsoft\Active Setup\Installed Components\*\ShellComponent
() -
SOFTWARE\Microsoft\Command Processor\AutoRun
() -
SOFTWARE\Microsoft\Ctf\LangBarAddin\*\FilePath
() -
SOFTWARE\Microsoft\Internet Explorer\Extensions\*\Exec
() -
SOFTWARE\Microsoft\Internet Explorer\Extensions\*\Script
() -
SOFTWARE\Microsoft\Netsh
(# Event Triggered Execution: Netsh Helper DLL T1546/007) -
SOFTWARE\Microsoft\Office\*\Word\Options\GlobalDotName
(# Office Application Startup: Add-ins T1137/006) -
SOFTWARE\Microsoft\Office\*\Word\Security\Trusted Documents
(# Office Application Startup: Add-ins T1137/006) -
SOFTWARE\Microsoft\Office\*\Word\Security\Trusted Locations\*\AllowSubFolders
(# Office Application Startup: Add-ins T1137/006) -
SOFTWARE\Microsoft\Office\*\Word\Security\Trusted Locations\*\Path
(# Office Application Startup: Add-ins T1137/006) -
SOFTWARE\Microsoft\Office\*\Word\Security\VBAWarning
(# Office Application Startup: Add-ins T1137/006) -
SOFTWARE\Microsoft\Office\*\Common\General\SharedTemplates
(# Office Application Startup: Add-ins T1137/006) -
SOFTWARE\Microsoft\Office\*\Common\General\UserTemplates
(# Office Application Startup: Add-ins T1137/006) -
SOFTWARE\Microsoft\Office test\Special\Perf
(# Office Application Startup: Office Test T1137/002) -
SOFTWARE\Microsoft\Windows CE Services\AutoStartOnConnect\MicrosoftActiveSync
() -
SOFTWARE\Microsoft\Windows CE Services\AutoStartOnDisconnect\MicrosoftActiveSync
() -
SOFTWARE\Microsoft\Windows nt\CurrentVersion\Appcompatflags\Custom
(# Event Triggered Execution: Application Shimming T1546/011) -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Appcompatflags\Installedsdb
(# Event Triggered Execution: Application Shimming T1546/011) -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
(# Event Triggered Execution: Accessibility Features T1546/008) -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\*\VerifierDlls
() -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\IniFileMapping\system.ini\boot
() -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks
(# Scheduled Task/Job: Scheduled Task T1053/005) -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree
(# Scheduled Task/Job: Scheduled Task T1053/005) -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\
(# Event Triggered Execution: Image File Execution Options Injection T1546/012) -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\*
() -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001; # Event Triggered Execution: AppInit DLLs T1546/010) -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001) -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\IconServiceLib
() -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\Load
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001) -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\Run
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001) -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\
(# Boot or Logon Autostart Execution: Winlogon Helper DLL T1547/004) -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\AppSetup
(# Boot or Logon Autostart Execution: Winlogon Helper DLL T1547/004) -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GpExtensions\*\DllName
(# Boot or Logon Autostart Execution: Winlogon Helper DLL T1547/004) -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Taskman
(# Boot or Logon Autostart Execution: Winlogon Helper DLL T1547/004) -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\VmApplet
(# Boot or Logon Autostart Execution: Winlogon Helper DLL T1547/004) -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001) -
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Userinit
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001) -
SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001) -
SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001) -
SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001) -
SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\SYSTEM\Shell
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001) -
SOFTWARE\Microsoft\Windows\CurrentVersion\Run
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001) -
SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001) -
SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001) -
SOFTWARE\Microsoft\Windows\CurrentVersion\RunServices
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001) -
SOFTWARE\Microsoft\Windows\CurrentVersion\RunServicesOnce
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001) -
SOFTWARE\Microsoft\Windows\CurrentVersion\StartupApproved\Run
(# RegRipper run.pl) -
SOFTWARE\Microsoft\Windows\CurrentVersion\StartupApproved\Run32
(# RegRipper run.pl) -
Software\Microsoft\Windows\CurrentVersion\StartupApproved\StartupFolder
(# RegRipper run.pl NTUSER) -
SOFTWARE\Microsoft\Windows\CurrentVersion\ShellServiceObjectDelayLoad
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001) -
SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001) -
SOFTWARE\Microsoft\Windows\Windows Error Reporting\Hangs\ReflectDebugger
() -
SOFTWARE\Policies\Microsoft\Windows\Control Panel\Desktop\SCRNSAVE.EXE
(# Event Triggered Execution: Screensaver T1546/002) -
SOFTWARE\Policies\Microsoft\Windows\System\Scripts
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001) -
SOFTWARE\Policies\Microsoft\Windows\System\Scripts\Logoff\Script
() -
SOFTWARE\Policies\Microsoft\Windows\System\Scripts\Logon\Script
() -
SOFTWARE\Policies\Microsoft\Windows\System\Scripts\Shutdown\Script
() -
SOFTWARE\Policies\Microsoft\Windows\System\Scripts\Startup\Script
() -
SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run\
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001) -
SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run
(# RegRipper run.pl) -
SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\
(# Event Triggered Execution: Image File Execution Options Injection T1546/012) -
SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows
(# Event Triggered Execution: AppInit DLLs T1546/010) -
SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_Dlls
() -
SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Winlogon\
(# Boot or Logon Autostart Execution: Winlogon Helper DLL T1547/004) -
SYSTEM\ControlSet001\Control\BootVerificationProgram\ImagePath
() -
SYSTEM\ControlSet001\Control\Print\Environments\[Windows architecture]\Print Processors\*\Driver
(# Boot or Logon Autostart Execution: Print Processors T1547/012) -
SYSTEM\ControlSet001\Control\Lsa\Notification Packages
(# Modify Authentication Process: Password Filter DLL T1556/002) -
SYSTEM\ControlSet001\Control\Lsa\OSConfig\Security Packages
(# Boot or Logon Autostart Execution: Authentication Package T1547/002; # Boot or Logon Autostart Execution: Security Support Provider T1547/005) -
SYSTEM\ControlSet001\Control\Lsa\Security Packages
(# Boot or Logon Autostart Execution: Authentication Package T1547/002; # Boot or Logon Autostart Execution: Security Support Provider T1547/005) -
SYSTEM\ControlSet001\Control\NetworkProvider\Order
(# Modify Authentication Process: Network Provider DLL T1556/008) -
SYSTEM\ControlSet001\Control\Print\Environments\[Windows architecture]\Print Processors\[user defined]\Driver
(# Boot or Logon Autostart Execution: Print Processors T1547/012) -
SYSTEM\ControlSet001\Control\Print\Monitors
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001; # Boot or Logon Autostart Execution: Port Monitors T1547/010) -
SYSTEM\ControlSet001\Control\SafeBoot\AlternateShell
() -
SYSTEM\ControlSet001\Control\ServiceControlManagerExtension
() -
SYSTEM\ControlSet001\Control\Session Manager
(# Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder T1547/001; # Event Triggered Execution: AppCert DLLs T1546/009) -
SYSTEM\ControlSet001\Control\Session Manager\AppCertDLLs\*
(# Event Triggered Execution: AppCertDLLs T1546/009) -
SYSTEM\ControlSet001\Control\Session Manager\Environment\Path
(# Hijack Execution Flow: Path Interception by PATH Environment Variable T1574/007) -
SYSTEM\ControlSet001\Control\Session Manager\BootExecute
() -
SYSTEM\ControlSet001\Control\Session Manager\Execute
() -
SYSTEM\ControlSet001\Control\Session Manager\S0InitialCommand
() -
SYSTEM\ControlSet001\Control\Session Manager\SetupExecute
() -
SYSTEM\ControlSet001\Services
(# Hijack Execution Flow: Services Registry Permissions Weakness T1574/011; # Create or Modify SYSTEM Process: Windows Service T1543/003) -
SYSTEM\ControlSet001\Services\*\NetworkProvider
(# Modify Authentication Process: Network Provider DLL T1556/008) -
SYSTEM\ControlSet001\Services\W32Time\TimeProviders\
(# Boot or Logon Autostart Execution: Time Providers T1547/003) -
SYSTEM\ControlSet001\Services\servicename\Parameters\ServiceDll
(# Hijack Execution Flow: Services Registry Permissions Weakness T1574/011) -
SYSTEM\ControlSet001\services\TermService\Parameters\
(# Server SOFTWARE Component: Terminal Services DLL T1505/005) -
SYSTEM\ControlSet001\Control\Terminal Server\Wds\rdpwd\StartupPrograms
() -
SYSTEM\ControlSet001\Control\Terminal Server\WinStations\RDP-Tcp\InitialProgram
() -
SYSTEM\Setup\CmdLine
() -
NTUSER.DAT\Environment\UserInitMprLogonScript
(# Boot or Logon Initialization Scripts: Logon Script` (Windows) T1037/001) -
NTUSER.DAT\Control Panel\Desktop\scrnsave.exe
(# Event Triggered Execution: Screensaver T1546/002) -
NTUSER.DAT\Software\*
(Все ключи выше, начинающиеся с SOFTWARE) -
NTUSER.DAT\System\*
(Все ключи выше, начинающиеся с SYSTEM) -
COR_ENABLE_PROFILING, COR_PROFILER и COR_PROFILER_PATH
(# Hijack Execution Flow: COR_PROFILER T1574/012)
Как видно мест много и есть множество способов залезть внутрь реестра для их анализа, но ни один из них (по крайне мере без дополнительных доработок) не является идеальным и универсальным, т.к.:
-
Использовать утилиты для ручного просмотра реестра — неразумно из-за больших времязатрат на анализ каждого ключа, особенно если нужно исследовать много хостов;
-
Используя анализаторы, которые автоматически парсят файлы реестра (RegRipper, Autoruns, PersistenceSniper), у Вас никогда не будет уверенности, что заложенные алгоритмы проверяют все известные Вам места закрепления, особенно учитывая частоту их обновлений (как разработчиком, так и Вами). Как пример, я добавил вручную EICAR тестовый вирус в контекстное меню изменения текстовых файлов и запустил AtomicTest для техники T1546.011, и ни один их этих приемов, Autoruns не показал:
-
Если полагаться на события безопасности с изменениями, то они могут либо вообще отсутствовать (например удалены злоумышленником), либо быть не настроены на определенные ветки.
Таким образом, идеальное и универсальное решение должно подчиняться следующим критериям:
-
Уметь работать с выгруженными файлами реестра (доступ к работающему хосту не всегда будет, а выгрузить файлы можно даже с выключенных систем, с помощью Live CD);
-
Автоматически парсить файлы реестра, в соответствии с легко добавляемыми правилами парсинга (на случай обнаружения новых мест закрепления, которые не были учтены в прошлой версии);
-
Уметь парсить много файлов реестра с разных хостов (как для compromise assessment, так и для массового компьютерного инцидента);
-
Иметь удобный человекочитаемый вид и не требовать много действий для обработки (чтобы не было больно работать).
Предложенное решение
В результате проб и ошибок был реализован следующий автоматизированный конвейер по обработке файлов реестра:
-
С хоста(-ов) выгружаются файлы реестра (в моем случае с помощью KAPE, в каталог
E:\temp\%имя_хоста%\
);
Пример скрипта.bat, лежащего рядом с папкой с KAPE по получению реестра
set “dest_folder=E:\temp\%COMPUTERNAME%
md “%dest_folder%”
cd /d%~dp0
KAPE\kape.exe ‑tsource C: ‑tdest%dest_folder% ‑target RegistryHivesOther,RegistryHivesSystem,RegistryHivesUser
-
Скриптом на Python перемещаются файлы реестра в каталог:
E:\temp\%имя_хоста%\Reg\
, а файлы реестра NTUSER и UsrClass каждого пользователя, переименовываются на имя пользователя владельца и оказываются в каталоге:E:\temp\%имя_хоста%\NTUSER\
иE:\temp\%имя_хоста%\UsrClass\
, соответственно (если хостов немного, то можно и вручную сделать).-
В каталогах должны также лежать файлы
%Реестр%.LOG1
и%Реестр%.LOG2
, для корректного парсинга сырых данных.
-
Пример скрипта по перемещению файлов реестра
import os
import shutil
for host_dir in os.scandir(r'E:\temp'): # Обход всех папок хостов
if host_dir.is_dir():
# Перемещение Реестра
src_path = host_dir.path + '\C\Windows\System32\config'
dst_path = host_dir.path + '\Reg'
if os.path.exists(src_path):
os.makedirs(dst_path, exist_ok=True)
for file in os.scandir(src_path):
shutil.move(file.path, dst_path)
# Перемещение NTUSER
users_folder = host_dir.path + r'\C\Users'
if os.path.exists(users_folder):
for user_dir in os.scandir(users_folder):
if user_dir.is_dir():
for file_name in ["NTUSER.DAT", "ntuser.dat.LOG1", "ntuser.dat.LOG2"]:
file_path = os.path.join(user_dir.path, file_name)
if os.path.exists(file_path):
# Перемещаем файл в \NTUSER\
dst_folder = host_dir.path + r'\NTUSER'
os.makedirs(dst_folder, exist_ok=True)
if file_name == "NTUSER.DAT":
dst_file = os.path.join(dst_folder, user_dir.name + '.' + file_name.split('.')[-1])
else:
dst_file = os.path.join(dst_folder, user_dir.name + '.' + file_name.split('.')[-2].upper() + '.' + file_name.split('.')[-1])
shutil.move(file_path, dst_file)
# Перемещение UsrClass
users_folder = host_dir.path + r'\C\Users'
if os.path.exists(users_folder):
for user_dir in os.scandir(users_folder):
if user_dir.is_dir():
for file_name in ["UsrClass.dat", "UsrClass.dat.LOG1", "UsrClass.dat.LOG2"]:
file_path = os.path.join(user_dir.path, 'AppData\\Local\\Microsoft\\Windows\\', file_name)
if os.path.exists(file_path):
# Перемещаем файл в \UsrClass\
dst_folder = host_dir.path + r'\UsrClass'
os.makedirs(dst_folder, exist_ok=True)
if file_name == "UsrClass.dat":
dst_file = os.path.join(dst_folder, user_dir.name + '.' + file_name.split('.')[-1])
else:
dst_file = os.path.join(dst_folder, user_dir.name + '.' + file_name.split('.')[-2].upper() + '.' + file_name.split('.')[-1])
shutil.move(file_path, dst_file)
-
Далее запускается конвейер скриптов на Python:
-
Вместо сотни веток реестра, указанных выше в статье, выгружается всего несколько десятков, из-за того, что убраны многие ветки, у которых есть общая родительская. Выгружать около сотни веток оказалось довольно долгим занятием (на каждый компьютер тратилось по 20 минут), т.к. на каждую ветку приходится отдельный запуск утилиты и проверка наличия данной ветки в файле реестра.
-
В текущей реализации скриптов, на каждую систему тратится на обработку, в среднем, по 3 минуты.
-
При необходимости, в код программы легко вносятся дополнительные ветки реестра, при обнаружении новых техник, которые ее будут использовать.
-
1. Запуск RECmd для необходимых файлов реестра, который выгружает только необходимые ветки
import os
import subprocess
from pathlib import Path
# Список ключей реестра, которые нужно парсить
registry_keys_software = [
"Classes",
"Microsoft\\Active Setup\\Installed Components",
"Microsoft\\Command Processor\\Autorun",
"Microsoft\\Ctf\\LangBarAddin",
"Microsoft\\Internet Explorer\\Extensions",
"Microsoft\\Netsh",
"Microsoft\\Office",
"Microsoft\\Office test\\Special\\Perf",
"Microsoft\\Windows CE Services\\AutoStartOnConnect\\MicrosoftActiveSync",
"Microsoft\\Windows CE Services\\AutoStartOnDisconnect\\MicrosoftActiveSync",
"Microsoft\\Windows NT\\CurrentVersion",
"Microsoft\\Windows\\CurrentVersion",
"Microsoft\\Windows\\Windows Error Reporting\\Hangs\\ReflectDebugger",
"Policies\\Microsoft\\Windows\\Control Panel\\Desktop",
"Policies\\Microsoft\\Windows\\System\\Scripts",
"Wow6432Node\\Microsoft\\Windows\\CurrentVersion",
"Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion"
]
registry_keys_system = [
"ControlSet001\\Control\\BootVerificationProgram",
"ControlSet001\\Control\\Lsa\\Notification Packages",
"ControlSet001\\Control\\Lsa\\OSConfig\\Security Packages",
"ControlSet001\\Control\\Lsa\\Security Packages",
"ControlSet001\\Control\\NetworkProvider\\Order",
"ControlSet001\\Control\\Print\\Environments",
"ControlSet001\\Control\\Print\\Monitors",
"ControlSet001\\Control\\SafeBoot\\AlternateShell",
"ControlSet001\\Control\\ServiceControlManagerExtension",
"ControlSet001\\Control\\Session Manager",
"ControlSet001\\Control\\Terminal Server\\Wds\\rdpwd\\StartupPrograms",
"ControlSet001\\Control\\Terminal Server\\WinStations\\RDP-Tcp\\InitialProgram",
"ControlSet001\\Services",
"Setup\\CmdLine"
]
registry_keys_ntuserdat = [
"Software\\Microsoft",
"Software\\Policies\\Microsoft\\Windows\\System\\Scripts",
"Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion",
"Software\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion",
"System\\CurrentControlSet\\Control",
"System\\CurrentControlSet\\Services",
"System\\Setup\\CmdLine",
"Environment",
"Control Panel\\Desktop"
]
registry_keys_usrclassdat = [
"ROOT"
]
base_dir = Path('E:/temp') # Базовая папка, где все лежит
reg_dir_name = 'Reg' # В какой папке искать кусты реестра хоста
ntuser_dir_name = 'NTUSER' # В какой папке искать кусты реестра пользователей
usrclass_dir_name = 'UsrClass'
special_regs = ['SOFTWARE', 'SYSTEM'] # Какие кусты реестра хоста парсить
# Обход поддиректорий базовой директории
for host_dir in base_dir.iterdir(): # подкаталог - имя хоста
if host_dir.is_dir():
host_name = host_dir.name
reg_dir = host_dir / reg_dir_name # Поиск папки кустов реестра хоста
ntuser_dir = host_dir / ntuser_dir_name # Поиск папки кустов реестра пользователя
usrclass_dir = host_dir / usrclass_dir_name
if reg_dir.exists():
for reg_name in special_regs: # Обход software и system
reg_file = reg_dir / reg_name
if reg_file.exists():
output_dir = base_dir / 'ToElastic' / host_name # Определение директории куда сливать результаты (закрепеление за именем хоста)
output_dir.mkdir(parents=True, exist_ok=True)
if reg_name == "SOFTWARE": # Парсинг Software
for key in registry_keys_software: # Только нужные ветки реестра
json_file_name = key.replace('\\', '%5C').replace(' ', '') # Замена плохих символов, мешающих работе
# Запуск команды RECmd.exe
cmd = (
f'E:/Scripts/2.Reg/RECmd.exe -f "{str(reg_file)}" --kn "{key}" --details --json "{output_dir}" --jsonf "Reg-Software%5C{str(json_file_name)}.json"'
)
with open(os.devnull, 'w') as FNULL:
subprocess.run(cmd, stderr=subprocess.STDOUT, stdout=FNULL)
if reg_name == "SYSTEM": # Аналогично Software
for key in registry_keys_system: # Только нужные ветки реестра
json_file_name = key.replace('\\', '%5C').replace(' ', '')
cmd = (
f'E:/Scripts/2.Reg/RECmd.exe -f "{str(reg_file)}" --kn "{key}" --details --json "{output_dir}" --jsonf "Reg-System%5C{str(json_file_name)}.json"'
)
with open(os.devnull, 'w') as FNULL:
subprocess.run(cmd, stderr=subprocess.STDOUT, stdout=FNULL)
if ntuser_dir.exists(): # Обход кустов реестра пользователей
for ntuser_file in ntuser_dir.iterdir():
if ntuser_file.is_file() and not ntuser_file.name.endswith(("LOG1", "LOG2")): # Не обходить требующиеся для парсинга .dat.LOG
output_dir = base_dir / 'ToElastic' / host_name # Определение директории куда сливать результаты (закрепеление за именем хоста)
output_dir.mkdir(parents=True, exist_ok=True)
for key in registry_keys_ntuserdat: # Только нужные ветки реестра
json_file_name = f"Reg-Ntuser-{ntuser_file.stem}" # Определение имени нового файла, для сохранения имени пользователя
json_file_name = json_file_name.replace('.dat', '') + "%5C"
json_file_name += key.replace('\\', '%5C').replace(' ', '')
# Запуск команды RECmd.exe
cmd = (
f'E:/Scripts/2.Reg/RECmd.exe -f "{str(ntuser_file)}" --kn "{key}" --details --json "{output_dir}" --jsonf "{json_file_name}.json"'
)
with open(os.devnull, 'w') as FNULL:
subprocess.run(cmd, stderr=subprocess.STDOUT, stdout=FNULL)
if usrclass_dir.exists(): # Обход кустов реестра пользователей
for usrclass_file in usrclass_dir.iterdir():
if usrclass_file.is_file() and not usrclass_file.name.endswith(("LOG1", "LOG2")): # Не обходить требующиеся для парсинга .dat.LOG
output_dir = base_dir / 'ToElastic' / host_name # Определение директории куда сливать результаты (закрепеление за именем хоста)
output_dir.mkdir(parents=True, exist_ok=True)
for key in registry_keys_usrclassdat: # Только нужные ветки реестра
json_file_name = f"Reg-UsrClass-{usrclass_file.stem}" # Определение имени нового файла, для сохранения имени пользователя
json_file_name = json_file_name.replace('.dat', '') + "%5C"
json_file_name += key.replace('\\', '%5C').replace(' ', '')
# Запуск команды RECmd.exe
cmd = (
f'E:/Scripts/2.Reg/RECmd.exe -f "{str(usrclass_file)}" --kn "{key}" --details --json "{output_dir}" --jsonf "{json_file_name}.json"'
)
with open(os.devnull, 'w') as FNULL:
subprocess.run(cmd, stderr=subprocess.STDOUT, stdout=FNULL)
2. Выгруженные ветки приводятся в адекватный вид (удаляются ненужные поля и значения, древовидная структура реестра приводится в ndjson вид, где на один ключ приходится одна строчка) и все файлы объединяются в один для каждого хоста
import json
import os
# Исключения по полям ValueName и ValueData, для удаления
with open("value_name_to_remove.txt", "r") as file:
value_name_to_remove = [line.strip() for line in file.readlines()]
with open("value_data_to_remove.txt", "r") as file:
value_data_to_remove = [line.strip() for line in file.readlines()]
def remove_fields(data): # Удаление ненужных полей "DataRaw" и "Slack", если они присутствуют
if isinstance(data, dict):
data.pop("DataRaw", None)
data.pop("Slack", None)
for key, value in data.items():
data[key] = remove_fields(value)
elif isinstance(data, list):
data = [remove_fields(item) for item in data]
return data
def remove_values(data):# Удаление ненужных значений и оставление нужных (в которых может быть путь/файл)
value_types_to_keep = ["RegSz", "RegExpandSz", "RegMultiSz"] # Указанные типы значения оставляем
if "Values" in data:
values = data["Values"]
filtered_values = [value for value in values if ((value["ValueType"] in value_types_to_keep) and (not value["ValueName"] in value_name_to_remove) and (not value["ValueData"] in value_data_to_remove) and (not (value["ValueData"].isdigit() or not value["ValueData"]))) or value["ValueName"].endswith(".sdb")]
data["Values"] = filtered_values
return data
def is_empty(data): # Удаление пустых значений "Values"
return "Values" in data and not data["Values"]
def process_json(json_data): # Исправление многовложенности словаря
json_data = remove_fields(json_data)
json_data = remove_values(json_data)
# Если есть SubKeys, обработаем их
if 'SubKeys' in json_data:
subkeys = json_data['SubKeys']
del json_data['SubKeys']
yield json_data
for subkey in subkeys:
yield from process_json(subkey)
def flatten_json(data): # Убирание словарей внутри ndjson
if "Values" in data:
values = data["Values"]
if len(values) == 1:
# Если только один набор значений в Values, вставляем его в родительский словарь
value = values[0]
data["ValueName"] = value["ValueName"]
data["ValueType"] = value["ValueType"]
data["ValueData"] = value["ValueData"]
del data["Values"]
yield data
else:
# Если несколько наборов значений в Values, дублируем родительский словарь для каждого набора
for value in values:
new_data = data.copy()
new_data["ValueName"] = value["ValueName"]
new_data["ValueType"] = value["ValueType"]
new_data["ValueData"] = value["ValueData"]
del new_data["Values"]
yield new_data
def process_registry_file(input_file): # Основная функция открытия и обработки
with open(input_file, 'r', encoding='utf-8') as file:
data = json.load(file)
filtered_data = [entry for entry in process_json(data) if not is_empty(entry)]
flattened_data = [new_entry for entry in filtered_data for new_entry in flatten_json(entry)]
return flattened_data
def main(input_directory):
for dir_name in os.listdir(input_directory): # Перебор поддиректорий в указанной директории (Имена хостов)
dir_path = os.path.join(input_directory, dir_name)
if os.path.isdir(dir_path):
registry_data = [] # Обнуление общего json фрейма
for root, dirs, files in os.walk(dir_path): # Перебор файлов в текущей поддиректории (Файлы веток реестра)
for file in files:
if file.startswith("Reg-"): # Поиск только файлов с реестром
registry_file = os.path.join(root, file)
registry_data_temp = process_registry_file(registry_file) # json фрейм для определенного файла (для корректной замены ROOT)
# Замена ROOT на соответствующее значение куста реестра
if file.startswith("Reg-Software"):
for entry in registry_data_temp:
entry["KeyPath"] = entry["KeyPath"].replace("ROOT", "Software")
elif file.startswith("Reg-System"):
for entry in registry_data_temp:
entry["KeyPath"] = entry["KeyPath"].replace("ROOT", "System")
elif file.startswith("Reg-Ntuser"):
username_start = file.find("Reg-Ntuser-") + len("Reg-Ntuser-")
username_end = file.find("%5C", username_start)
username = file[username_start:username_end]
for entry in registry_data_temp:
entry["KeyPath"] = entry["KeyPath"].replace("ROOT", f"NTUSER.DAT-{username}")
elif file.startswith("Reg-UsrClass-"):
username_start = file.find("Reg-UsrClass-") + len("Reg-UsrClass-")
username_end = file.find("%5C", username_start)
username = file[username_start:username_end]
for entry in registry_data_temp:
entry["KeyPath"] = f"UsrClass-{username}-" + entry["KeyPath"]
registry_data += registry_data_temp # Добавлнение скорректированного json фрейма в общий
os.remove(registry_file) # Удаление обработанных файлов
output_file = os.path.join(dir_path, "Registry.json") # Создание отдельного Registry.json в директории хоста
with open(output_file, 'w', encoding='utf-8') as out_file:
for entry in registry_data:
# Запись каждого объекта JSON на новой строке
json.dump(entry, out_file, ensure_ascii=False, separators=(',', ':'))
out_file.write('\n')
if __name__ == "__main__":
input_directory = r'E:\temp\ToElastic' # Папка, в которой находятся файлы для обработки
main(input_directory)
3. Переименование полей, форматирование времени
import os
import json
import jsonlines
from datetime import datetime, timedelta
def process_registry_file(file_path):
updated_data = []
with jsonlines.open(file_path, 'r') as reader:
for entry in reader: # Переименование полей для выгрузки в ELK
entry["reg.key.path"] = entry.pop("KeyPath")
entry["reg.key.name"] = entry.pop("KeyName")
timestamp = entry["LastWriteTimestamp"]
timestamp = int(timestamp[6:-2]) / 1000 # Получение числа секунд из строки времени
timestamp = datetime.fromtimestamp(timestamp) - timedelta(hours=3) # UTC-3
entry["@timestamp"] = timestamp.strftime('%Y-%m-%dT%H:%M:%S') # Формат, понятный ELK
entry.pop("LastWriteTimestamp")
entry["file.name"] = entry.pop("ValueName")
entry["file.path"] = entry.pop("ValueData")
entry.pop("ValueType")
updated_data.append(entry)
return updated_data
def split_json_file(input_file, chunk_size): # Разделение на несколько json файлов
with open(input_file, 'r', encoding='utf-8') as infile:
data = [json.loads(line) for line in infile]
total_records = len(data)
num_chunks = (total_records + chunk_size - 1) // chunk_size # Определение на сколько частей разделять
for i in range(num_chunks): # Создание ограниченных файлов json
input_file_temp = input_file.replace('.json', '')
output_file = f"{input_file_temp}{i + 1}.json"
start = i * chunk_size
end = (i + 1) * chunk_size
chunk_data = data[start:end]
with open(output_file, 'w', encoding='utf-8') as outfile:
for item in chunk_data:
outfile.write(json.dumps(item, ensure_ascii=False) + '\n')
def process_directory(directory_path, chunk_size): # Проверка необходимости разделения на блоки
for root, dirs, files in os.walk(directory_path): # Поиск всех файлов обработанного реестра
for filename in files:
if filename == 'Registry.json':
file_path = os.path.join(root, filename)
with open(file_path, 'r', encoding='utf-8') as file:
line_count = sum(1 for line in file)
if line_count > chunk_size: # Нужно ли разделять
split_json_file(file_path, chunk_size)
os.remove(file_path)
def main(input_directory, chunk_size):
for root, dirs, files in os.walk(input_directory): # Поиск всех файлов обработанного реестра
for file in files:
if file == "Registry.json":
registry_file = os.path.join(root, file)
updated_data = process_registry_file(registry_file) # Переименование полей
with jsonlines.open(registry_file, 'w') as writer:
writer.write_all(updated_data)
process_directory(root, chunk_size) # Разделение на блоки
if __name__ == "__main__":
input_directory = r'E:\temp\ToElastic'
chunk_size = 100000 # По сколько строк разделять json-файлы, для корректной выгрузки в ELK
main(input_directory, chunk_size)
-
В результате мы получаем существенный набор ключей реестра на анализ в следующем виде (названия полей легко меняются по Вашему желанию):
{"reg.key.path": "Software\\Classes\\.htm\\OpenWithList\\Excel.exe\\shell\\edit\\command",
"reg.key.name": "command",
"@timestamp": "2019-10-07T22:49:35",
"file.name": "(default)",
"file.path": "\"C:\\Program Files\\Microsoft Office\\Office15\\EXCEL.EXE\" /dde"}
-
После проверки корректности обработки сырых данных в json файл, все файлы отправляются в ElasticStack (вручную, с помощью API или FileBeat) или другую, удобную Вам SIEM систему.
-
В ElasticStack далее производится анализ:
-
C помощью фильтра по всем местам закрепления, или в котором ищется что-то конкретное (1). В реальных ситуациях можно искать в 3 захода: два захода с самыми шумными фильтрами (
*Software*Classes*CLSID*
(T1546/015) и*Software*Classes*shell*command
(T1546/001)), и один со всем остальным. -
Удобный поиск проводится с помощью визуализации, в которой формируется таблица (2) по полю
file.path
(3), которая равна выполняемой команде / ссылке на файл (Группировка событий). -
Отсортировав по возрастанию количества раз встречаемости (4), можно легко найти исполняемые файлы, которые не должны присутствовать на компьютере (наиболее встречаемые команды = бОльшая вероятность ее легитимности).
-
Затем, поправив фильтр, что бы найти только нужные файлы, можно перейти в список всех событий для более глубокого анализа (5).
-
-
В событиях уже показывается в какой ветке реестра находится нужная ссылка/команда и когда она была добавлена, из чего можно делать выводы — легитимно это или нет.
-
Здесь показан лишь упрощенный поиск для примера, а то время как реальные кейсы поиска ограничены только Вашей фантазией. Кстати, фильтр для поиска не шумных мест закрепления:
Фильтр поиска закрепления в реестре
reg.key.path : (*Software*Microsoft*Active*Setup*Installed*Components
OR *Software*Microsoft*Active*Setup*Installed*Components*ShellComponent
OR *Software*Microsoft*Command*Processor*Autorun
OR *Software*Microsoft*Ctf*LangBarAddin*FilePath
OR *Software*Microsoft*Internet*Explorer*Extensions*Exec
OR *Software*Microsoft*Internet*Explorer*Extensions*Script
OR *Software*Microsoft*NetSh
OR *Software*Microsoft*Office*Word*Options*GlobalDotName
OR *Software*Microsoft*Office*Word*Security
OR *Software*Microsoft*Office*Word*Security*Trusted*Documents
OR *Software*Microsoft*Office*Word*Security*Trusted*Locations
OR *Software*Microsoft*Office*Word*Security*Trusted*Locations*
OR *Software*Microsoft*Office*Word*Security*Trusted*Locations*AllowSubFolders
OR *Software*Microsoft*Office*Word*Security*Trusted*Locations*Path
OR *Software*Microsoft*Office*Word*Security*VBAWarning
OR *Software*Microsoft*Office*Common*General*SharedTemplates
OR *Software*Microsoft*Office*Common*General*UserTemplates
OR *Software*Microsoft*Office*test*Special*Perf
OR *Software*Microsoft*Windows*Services*AutoStartOnConnect*MicrosoftActiveSync
OR *Software*Microsoft*Windows*Services*AutoStartOnDisconnect*MicrosoftActiveSync
OR *Software*Microsoft*Windows*CurrentVersion*AppCompatFlags*Custom*
OR *Software*Microsoft*Windows*CurrentVersion*AppCompatFlags*Installedsdb
OR *Software*Microsoft*Windows*CurrentVersion*Image*File*Execution*Options
OR *Software*Microsoft*Windows*CurrentVersion*Image*File*Execution*Option*VerifierDlls
OR *Software*Microsoft*Windows*CurrentVersion*IniFileMapping*system.ini*boot
OR *Software*Microsoft*Windows*CurrentVersion*Schedule*TaskCache*Tasks
OR *Software*Microsoft*Windows*CurrentVersion*Schedule*TaskCache*Tree
OR *Software*Microsoft*Windows*CurrentVersion*SilentProcessExit*
OR *Software*Microsoft*Windows*CurrentVersion*Terminal*Server*Install*
OR *Software*Microsoft*Windows*CurrentVersion*Windows*AppInit_DLLs
OR *Software*Microsoft*Windows*CurrentVersion*Windows*IconServiceLib
OR *Software*Microsoft*Windows*CurrentVersion*Windows*Load
OR *Software*Microsoft*Windows*CurrentVersion*Windows*Run
OR *Software*Microsoft*Windows*CurrentVersion*Winlogon
OR *Software*Microsoft*Windows*CurrentVersion*Winlogon*AppSetup
OR *Software*Microsoft*Windows*CurrentVersion*Winlogon*GpExtensions*
OR *Software*Microsoft*Windows*CurrentVersion*Winlogon*Taskman
OR *Software*Microsoft*Windows*CurrentVersion*Winlogon*VmApplet
OR *Software*Microsoft*Windows*CurrentVersion*Winlogon*Shell
OR *Software*Microsoft*Windows*CurrentVersion*Winlogon*Userinit
OR *Software*Microsoft*Windows*CurrentVersion*Explorer*Shell*Folders
OR *Software*Microsoft*Windows*CurrentVersion*Explorer*User*Shell*Folders
OR *Software*Microsoft*Windows*CurrentVersion*Policies*Explorer*Run
OR *Software*Microsoft*Windows*CurrentVersion*Policies*System*Shell
OR *Software*Microsoft*Windows*CurrentVersion*Run
OR *Software*Microsoft*Windows*CurrentVersion*RunOnce
OR *Software*Microsoft*Windows*CurrentVersion*RunOnceEx
OR *Software*Microsoft*Windows*CurrentVersion*RunServices
OR *Software*Microsoft*Windows*CurrentVersion*RunServicesOnce
OR *Software*Microsoft*Windows*CurrentVersion*ShellServiceObjectDelayLoad
OR *Software*Microsoft*Windows*CurrentVersion*policies*Explorer*Run
OR *Software*Microsoft*Windows*Windows*Error*Reporting*Hangs*ReflectDebugger
OR *Software*Policies*Microsoft*Windows*Control*Panel*Desktop*SCRNSAVE.EXE
OR *Software*Policies*Microsoft*Windows*System*Scripts
OR *Software*Policies*Microsoft*Windows*System*Scripts*Logoff*Script
OR *Software*Policies*Microsoft*Windows*System*Scripts*Logon*Script
OR *Software*Policies*Microsoft*Windows*System*Scripts*Shutdown*Script
OR *Software*Policies*Microsoft*Windows*System*Scripts*Startup*Script
OR *Software*Wow6432Node*Microsoft*Windows*CurrentVersion*Run*
OR *Software*Wow6432Node*Microsoft*Windows*CurrentVersion*Image*File*Execution*Options*
OR *Software*Wow6432Node*Microsoft*Windows*CurrentVersion*Windows
OR *Software*Wow6432Node*Microsoft*Windows*CurrentVersion*Windows*AppInit_Dlls
OR *Software*Wow6432Node*Microsoft*Windows*CurrentVersion*Winlogon*
OR *System*ControlSet001*Control*BootVerificationProgram*ImagePath
OR *System*ControlSet001*Control*Print*Environments*Print*Processors*Driver
OR *System*ControlSet001*Control*Lsa*Notification*Packages
OR *System*ControlSet001*Control*Lsa*OSConfig*Security*Packages
OR *System*ControlSet001*Control*Lsa*Security*Packages
OR *System*ControlSet001*Control*NetworkProvider*Order
OR *System*ControlSet001*Control*Print*Environments***Print*Processors***Driver
OR *System*ControlSet001*Control*Print*Monitors
OR *System*ControlSet001*Control*SafeBoot*AlternateShell
OR *System*ControlSet001*Control*ServiceControlManagerExtension
OR *System*ControlSet001*Control*Session*Manager
OR *System*ControlSet001*Control*Session*Manager*AppCertDLLs**
OR *System*ControlSet001*Control*Session*Manager*Environment*Path
OR *System*ControlSet001*Control*Session*Manager*BootExecute
OR *System*ControlSet001*Control*Session*Manager*Execute
OR *System*ControlSet001*Control*Session*Manager*KnownDLLs
OR *System*ControlSet001*Control*Session*Manager*S0InitialCommand
OR *System*ControlSet001*Control*Session*Manager*SetupExecute
OR *System*ControlSet001*Services
OR *System*ControlSet001*Services*NetworkProvider
OR *System*ControlSet001*Services*W32Time*TimeProviders*
OR *System*ControlSet001*Services*servicename*Parameters*ServiceDll
OR *System*ControlSet001*services*TermService*Parameters*
OR *System*ControlSet001*Control*Terminal*Server*Wds*rdpwd*StartupPrograms
OR *System*ControlSet001*Control*Terminal*Server*WinStations*RDP-Tcp*InitialProgram
OR *System*Setup*CmdLine
OR *Environment*UserInitMprLogonScript
OR *Control*Panel*Desktop)
Демонстрация на примерах
Пример того как в моем решении видны изменения контекстного меню — представлены выше.
Для дальнейшей демонстрации были взяты 3 техники, применённые с помощью AtomicTests, которые не детектируются с помощью Autoruns:
-
T1546.011 (Злоупотребление подсистемой совместимости приложений), рассмотренная ранее в разделе с Проблемой;
-
T1546.002 (Манипуляция параметрами экранной заставки);
-
T1546.007 (Злоупотребление вспомогательными библиотеками DLL Netsh):
-
Собрав, обработав и отправив в ElasticStack все необходимые данные, при поиске всех мест закрепления (кроме 2 самых шумящих), получаем следующее:
-
Необходимые нам пути к файлам и аномальные ключи находятся наверху списка. Совершив поиск по этим событиям, сразу находим где находятся данные значения в реестре:
-
Для увеличения удобства дальнейшего поиска, все легитимные значения для Вашего «золотого» образа систем Вашей организации легко добавляются в исключения
Выводы
На текущий момент существует множество утилит для анализа реестра Windows на поиск мест закрепления в нем вредоносного ПО. Наиболее удобным и эффективным является Sysinternals Autoruns, однако как было продемонстрировано, даже он не способен детектировать все, что нам нужно.
Для решения этой проблемы был продемонстрирован автоматизированный конвейер скриптов по обработке сырых файлов реестра Windows в SIEM-понятный формат данных. Далее, в SIEM-е, при правильно настроенных исключениях, поиск вредоноса не составит большого труда.
На обратной стороне монеты же, безусловно выделяется бОльшая сложность в подготовке и дальнейшем анализе, по сравнению с тем же Autoruns. Так что если в Вашей работе, скорость анализа играет решающую роль, то предложенное решение можно рассматривать в качестве дополнения к существующим решениям, в которых можно проводить первичный анализ.
Ссылки на источники
-
Изучаем Adversarial Tactics, Techniques & Common Knowledge (ATT@CK). Enterprise Tactics. Часть 3 / Хабр
-
Windows Registry, Data Source DS0024 | MITRE ATT&CK®
-
Uncommon Registry Persistence Change | Elastic Security Solution [8.10] | Elastic
-
Analysis of Malicious Security Support Provider DLLs — PDF Free Download
-
Office Templates and GlobalDotName — A Stealthy Office Persistence Technique — 0xShukruN
-
Windows Registry: Malware Persistence
-
T1546.011 — Explore Atomic Red Team
-
T1546.002 — Explore Atomic Red Team
-
T1546.007 — Explore Atomic Red Team
Бывают ситуации, когда нужно узнать, когда и какие программы запускались на компьютере пользователя. Для этих целей можно использовать Проводник, редактор реестра, а также специальные утилиты вроде ExecutedProgramsList. С этими способами знакомы большинство продвинутых юзеров, но мало кому из них известно, что получить список недавно запускавшихся программ можно, проанализировав системный файл Amcache.hve.
Это файл реестра в формате REGF, расположенный в каталоге %SystemRoot%\AppCompat\Programs и содержащий информацию о запускаемых в системе приложениях.
Структура файла представлена набором записей, включающих в себя пути к исполняемым файлам программ и временные метки установки, запуска и удаления. Кроме того, файл хранит контрольные суммы (SHA1) запущенных программ. Поскольку файл постоянно используется Windows, его нельзя ни открыть напрямую, ни скопировать в другое расположение.
Чтобы его извлечь, вам придется либо загрузить компьютер с LiveCD и скопировать файл вручную, либо воспользоваться программами WinHex или R-Studio, позволяющими получать доступ к используемым системой файлам в обход драйвера NTFS.
В WinHex (запускать этот редактор нужно с правами администратора) необходимо выбрать в меню Tools -> Open Disk.
И указать системный раздел.
После того как программа создаст снапшот, перейдите в расположение C:\Windows\AppCompat\Programs, кликните по файлу Amcache.hve ПКМ, выберите «Recovery/Copy».
И укажите путь сохранения файла.
В R-Studio нужно выбрать системный раздел и создать его карту нажатием F5.
После этого переходим в расположение Amcache.hve, отмечаем его и выполняем восстановление в любой каталог.
В общем, какой из этих способов извлечения покажется вам наиболее удобным, тот и используйте.
Amcache.hve — бинарный файл, для его анализа вам понадобится утилита RegRipper, скачать которую можно со страницы разработчика github.com/keydet89. Если вдруг релиз окажется недоступным, скачиваем инструмент по ссылке yadi.sk/d/oB3_4Dn-Wvpy_A.
Распакуйте архив с утилитой, откройте от имени администратора командную строку, перейдите в расположение файлов RegRipper, а затем выполните команду следующего вида:
rip -r путь-к-файлу-Amcache.hve -p amcache > amcache.txt
В результате в папке RegRipper будет создан текстовый лог amcache.txt.
Который вы сможете просмотреть обычным Блокнотом.
Как можно видеть из примера, отчет содержит пути к исполняемым файлам приложений и дату последнего запуска. Указывается также и контрольная сумма, по которой можно проверить безопасность файла, пробив полученный хэш по базе VirusTotal.
В этой статье мы рассмотрим, как с помощью политик аудита Windows можно узнать какие программы запускались на компьютере. Довольно часто от администратора требуют предоставить информацию о том, какие приложения запускает пользователь, когда он запускал приложение в последний раз и т.д. Эту информацию можно собрать из журнала событий Windows и преобразовать в удобный отчет с помощью PowerShell.
Сначала нужно включить политику аудита запуска/остановки процессов в Windows.
- Откройте редактор локальной групповой политики gpedit.msc ;
Если вы хотите включить политику аудита процессов на компьютерах в домене Active Directory, нужно использовать редактор доменных GPO –
gpmc.msc
. - Перейдите в раздел GPO Computer Configuration -> Windows Settings -> Security Settings -> Local Policies -> Audit Policy;
- Включите политику Audit process tracking и тип событий Success;
- Сохраните изменения и обновите локальные политики на клиенте командой:
gpupdate /force
Откройте Event Viewer (
eventvwr.msc
) и разверните раздел Windows Logs -> Security. Теперь при запуске любой программы (процесса) в этом журнале событий появляется событие Process Creation с EventID 4688.
A new process has been created.
В информации о событии указан пользователь, запустивший программу (
Creator Subject
), имя исполняемого файла процесса (
New Process Name
) и родительский процесс, из которого было запущено приложение (
Creator Process Name
).
Обратите внимание, что при включении рассмотренной выше политики Audit process tracking в журнал Security начинают сохранятся все события, связанные с процессами. Если вы хотите уменьшить число событий в Event Viewer и сохранять только информацию о событиях запуска, можно отключить данную политику и включить только расширенную политику аудита Audit Process Creation (Windows Settings -> Security Settings -> Advanced Audit Policy Configurations -> System Audit Policy -> Detailed Tracking).
Чтобы в события аудита записывалась информация о параметрах запуска процессов (аргументы, с которыми запускаются программы), включите также параметр GPO Include command line in process creation events в Computer Configuration -> Administrative Templates -> System -> Audit Process Creation.
После включения этой политики в аргументе Process Command Line видно, с каким аргументом запускался тот или иной процесс.
Не забудьте увеличить размер журнала Security со стандартных 20 Мб. Это позволит хранить история запуска приложения за более длительный период. Для этого откройте свойства журнала Security и увеличьте значение параметра Maximum log size.
Для анализа программ, запущенных пользователем можно использовать фильтры Event Viewer. Но это не очень удобно. Ниже я покажу несколько PowerShell скриптов который позволят вам получить удобные списки событий с историей запуска приложений пользователями. Для получения событий из журнала Event Viewer мы будем использовать команду Get-WinEvent:
$processhistory = @()
$today = get-date -DisplayHint date -UFormat %Y-%m-%d
$events=Get-WinEvent -FilterHashtable @{
LogName = 'Security'
starttime="$today"
ID = 4688
}
foreach ($event in $events){
$proc = New-Object PSObject -Property @{
ProcessName=$event.Properties[5].Value
Time=$event.TimeCreated
CommandLine=$event.Properties[8].Value
User=$event.Properties[1].Value
ParentProcess=$event.Properties[13].Value
}
$processhistory += $proc
}
$processhistory| Out-GridView
Данный PowerShell скрипт выберет все события запуска программ за сегодняшний день и выведет список процессов, времени запуска и пользователях в графическую таблицу Out-GridView.
Полученный массив объектов можно использовать для выполнения различных запросов.
Например,
- Найти всех пользователей, которые запускали определённое приложение:
$proc_name=”notepad++.exe”
$processhistory | where-object {$_.ProcessName –like “*$proc_name*”}|out-gridview - Вывести список программ, которые запускал сегодня определенный пользователь:
$username="aivanov"
$processhistory | where-object {$_.User –like “*$username*”}|out-gridview
Такие скрипты часто используем для анализа запуска программ пользователей на серверах RDS фермы.
Также история запуска программ в Windows ведется в файле %SystemRoot%\AppCompat\Programs\Amcache.hve. Файл заблокирован Windows и прочитать его можно только, загрузившись с LiveCD или загрузочного/установочного диска. В файле есть метки запуска, установки/удаления программы, контрольные суммы исполняемого файла (SHA1). Для преобразования этого бинарного файла в текстовый формат нужно использовать сторонние утилиты (например, regripper).
Данные из Amcache и Shimcache могут предоставить временную шкалу того, какая программа была выполнена, когда она была впервые запущена и последний раз изменена.
Кроме того, эти артефакты предоставляют информацию о программе, касающуюся пути к файлу, его размера и хэша в зависимости от версии ОС.
Amcache.hve это файл реестра, который хранит информацию о запускаемых приложениях в системе.
В Windows 8 Amcache.hve заменяет RecentFileCache.bcf и использует формат файла реестра Windows NT (REGF).
Amcache.hve расположен:
%SystemRoot%\AppCompat\Programs\Amcache.hve
Каждая запись включает в себя путь выполнения, время первого выполнения, время удаления и первую установку.
Файл Amcache.hve также является важным артефактом для поиска следов анти-криминалистических, портабельных программ, а так же внешних устройств хранения данных.
Файл может быть проанализирован с помощью плагина amcache RegRipper :
https://github.com/keydet89/RegRipper2.8
Какие данные можно получить из файла Amcache.hve?
В Amcache.hve записываются последние запущенные процессы, а так же перечисляется пути к исполняемым файлам, которые затем можно использовать для поиска необходимых данных.
Так же записывается SHA1 запущенной программы, что позволяет исследователь программу используя базы данных (например VirusTotal)
Shimcache
Shimcache, также известный как AppCompatCache, является компонентом базы данных совместимости приложений, созданной Microsoft (начиная с Windows XP ) и используемой операционной системой для выявления проблем совместимости приложений.
Кэш хранит различные метаданные файла в зависимости от операционной системы, такие как:
- Полный путь к файлу
- Размер файла
- $ Standard_Information (SI) Время последнего изменения
- Последнее обновление Shimcache
- Флаг выполнения процесса
Подобно файлу журнала, Shimcache также перезаписывает данные, что означает, что самые старые данные заменяются новыми записями.
Количество сохраняемых данных зависит от операционной системы. (1024 записей в системах Win 7/ 8/10 )
Это помогает разработчикам устранять неполадки унаследованных функций и содержит данные, относящиеся к функциям Windows: он используется для быстрого поиска, чтобы решить, нужно ли модулировать «шимминг» для совместимости или нет.
Shim — это небольшая библиотека, которая прозрачно обрабатывает взаимодействие между приложениями, чтобы обеспечить поддержку более старых API в более новой среде или наоборот.
Данные хранятся в ключе реестра CacheMainSdb, который можно найти:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatCache
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\AppCompatCache
Shimcache можно конвертировать в удобочитаемый вид при помощи ShimCacheParser.py от Mandiant:
https://github.com/mandiant/ShimCacheParser
Как можно использовать?
Shimcache отслеживает метаданные , такие как полный путь к файлу, дата последнего изменения и размер файла , но содержит только информацию до последнего запуска системы, так как текущие данные сохраняются только в памяти
События в Shimcache.hve перечислены в хронологическом порядке, начиная с самого последнего события, и их можно использовать на временных шкалах для воссоздания и определения вредоносных действий.
https://www.andreafortuna.org/2017/10/16/amcache-and-shimcache-in-forensic-analysis/
Больше на VirusNet
Подпишитесь, чтобы получать последние записи по электронной почте.
Following on from the previous [DFIR TOOLS] posts below, this time I will speak about AmcacheParser again from the Eric Zimmerman suite.
- [DFIR TOOLS] Timeline Explorer, what is it & how to use!
We will start with Erics description on its purpose:-
“Amcache.hve parser with lots of extra features. Handles locked files”
But what is the Amcache.hve?
Again, like previously I will share links to excellent resources I find but in short:-
The Amcache.hve file is a registry file that stores the metadata information of executed applications that have been executed on the system!
Amcache.hve, not to be mistaken for ‘Shimcache or Prefetch’ which I will speak about in coming blog posts is a replacement for the pre windows 8 ‘RecentFilesCache.bcf’.
Amcache.hve is a small registry hive that stores a wealth of information about recently run applications and programs, including full path, file timestamps, and file SHA1 hash value, it is commonly found at the following location:
C:\Windows\AppCompat\Programs\Amcache.hve
And is standard within Windows operating system’s since windows 8.
I am here to speak about the tools and not the files themselves so if you want to read more on that here are a few good resources I found.
- Amcache.hve in Windows 8 – Goldmine for malware hunters
- Leveraging the Windows Amcache.hve File in Forensic Investigations
- ANALYSIS OF THE AMCACHE V2
- Revealing the RecentFileCache.bcf File
As you can see from forensics stand point it really is a must that we check out these files.
How do we use AmcacheParser?
The tool comes as an exe (AmcacheParser.exe) from the page of Eric Zimmerman, here.
When downloaded we open a CMD as Admin and go to the location.
From there we can run the command AmcacheParser.exe -h to open up the help to see the options.
From there we run the tool for instance if I run:-
AmcacheParser.exe -f C:\Windows\appcompat\Programs\Amcache.hve –-csv c:\temp –dt yyyy-MM-ddTHH:mm:ss
This will:-
- Run AmcacheParser.exe
- -f tells it to use the file at that destination, i.e. C:\Windows\appcompat\Programs\Amcache.hve
- –csv tells the tool to export as this type of file and at the directory stated i.e. c:\temp
- –dt tells the tool to use a custom date/time format when displaying time stamps i.e. yyyy-MM-ddTHH:mm:ss
And then when run we get the parsed results out of SIX different .csv files for us to investigate.
From there we can load them into ‘TimeLine Explorer‘ that we spoke about HERE or even just use excel if you like.
There is lots of information we can look for like above there is ‘Found 397 unassociated file entry’.
An unassociated file entry is a program or application that is not associated with any known source like a Microsoft, Google, Adobe, HP etc so if you are looking for BAD files there is a high chance you can find them here.
Anyways, that is AmcacheParser.
Take it easy
Alex