
Дамп lsass с использованием только функций NTAPI путем ручного создания файлов Minidump (без MiniDumpWriteDump!!!)
NativeDump позволяет дампить процесс lsass, используя только NTAPI, создавая файл Minidump только с теми потоками, которые необходимы для анализа такими инструментами, как Mimikatz или Pypykatz (потоки SystemInfo, ModuleList и Memory64List).

Программа имеет один необязательный аргумент для выходного файла, имя файла по умолчанию — "proc_<PID>.dmp":
NativeDump.exe [DUMP_FILE]

Инструмент протестирован на последних версиях Windows с наиболее распространенными решениями безопасности (Microsoft Defender for Endpoints, CrowdStrike...) и работает нормально, но скрытность будет зависеть от выбранной "разновидности": используйте нестандартные языки и настраивайте бинарники для наилучших результатов! Однако он не работает, если включен PPL или структура PEB нечитаема. Обновление: теперь можно выполнять программы без чтения PEB, см. ветку peb-unreadable branch :)
Некоторые преимущества этой техники:
Вы можете найти проект в различных "разновидностях" (или на разных языках):
main — .NET базовая реализация (эта ветка)
python-flavour — Реализация на Python с 3 методами перезаписи ntdll.dll + Экфильтрация на удаленную машину
golang-flavour — Реализация на Golang с 3 методами перезаписи ntdll.dll + Экфильтрация на удаленную машину
c-flavour — Реализация на C/C++ с 3 методами перезаписи ntdll.dll
bof-flavour — BOF файл с 3 методами перезаписи ntdll.dll
rust-flavour — Реализация на Rust от @safedv
crystal-flavour — Реализация на Crystal с возможностями перезаписи ntdll.dll
nim-flavour — Реализация на Nim с возможностями перезаписи ntdll.dll
Другие интересные ветки с использованием .NET:
remote — Экфильтрация на удаленную машину + 3 метода перезаписи ntdll.dll + Динамическое разрешение функций + AES-шифрование строк + XOR-кодирование содержимого Minidump
all-modules — Получение информации для всех модулей (не только lsasrv.dll)
peb-unreadable — Реализация без чтения структуры PEB процесса lsass + 3 метода перезаписи ntdll.dll
После изучения недокументированных структур Minidump его структуру можно свести к следующему:

Я создал инструмент парсинга, который может быть полезен: MinidumpParser. Мы сосредоточимся на создании валидного файла только с необходимыми значениями для заголовка, каталога потоков и только 3 потоков, необходимых для того, чтобы файл Minidump был распарсен Mimikatz/Pypykatz: SystemInfo, ModuleList и Memory64List.
Заголовок представляет собой структуру размером 32 байта, которую можно определить в C# как:
public struct MinidumpHeader
{
public uint Signature;
public ushort Version;
public ushort ImplementationVersion;
public ushort NumberOfStreams;
public uint StreamDirectoryRva;
public uint CheckSum;
public IntPtr TimeDateStamp;
}
Необходимые значения:
Каждая запись в каталоге потоков представляет собой структуру размером 12 байт, поэтому при 3 записях размер составляет 36 байт. Определение структуры C# для записи:
public struct MinidumpStreamDirectoryEntry
{
public uint StreamType;
public uint Size;
public uint Location;
}
Поле "StreamType" представляет тип потока в виде целого числа или ID, некоторые из наиболее важных:
Первый поток — это поток SystemInformation, с ID 7. Его размер составляет 56 байт, и он будет расположен по смещению 68 (0x44), после каталога потоков. Его определение в C#:
public struct SystemInformationStream
{
public ushort ProcessorArchitecture;
public ushort ProcessorLevel;
public ushort ProcessorRevision;
public byte NumberOfProcessors;
public byte ProductType;
public uint MajorVersion;
public uint MinorVersion;
public uint BuildNumber;
public uint PlatformId;
public uint UnknownField1;
public uint UnknownField2;
public IntPtr ProcessorFeatures;
public IntPtr ProcessorFeatures2;
public uint UnknownField3;
public ushort UnknownField14;
public byte UnknownField15;
}
Необходимые значения:
Второй поток — это поток ModuleList, с ID 4. Он расположен по смещению 124 (0x7C) после потока SystemInformation и также будет иметь фиксированный размер 112 байт, так как будет содержать запись только одного модуля, единственного, необходимого для корректного парсинга: "lsasrv.dll".
Типичная структура этого потока представляет собой 4-байтовое значение, содержащее количество записей, за которым следуют 108-байтовые записи для каждого модуля:
public struct ModuleListStream
{
public uint NumberOfModules;
public ModuleInfo[] Modules;
}
Поскольку запись только одна, это упрощается до:
public struct ModuleListStream
{
public uint NumberOfModules;
public IntPtr BaseAddress;
public uint Size;
public uint UnknownField1;
public uint Timestamp;
public uint PointerName;
public IntPtr UnknownField2;
public IntPtr UnknownField3;
public IntPtr UnknownField4;
public IntPtr UnknownField5;
public IntPtr UnknownField6;
public IntPtr UnknownField7;
public IntPtr UnknownField8;
public IntPtr UnknownField9;
public IntPtr UnknownField10;
public IntPtr UnknownField11;
}
Необходимые значения:
Третий поток — это поток Memory64List, с ID 9. Он расположен по смещению 298 (0x12A), после потока ModuleList и строки Unicode, и его размер зависит от количества модулей.
public struct Memory64ListStream
{
public ulong NumberOfEntries;
public uint MemoryRegionsBaseAddress;
public Memory64Info[] MemoryInfoEntries;
}
Каждая запись модуля представляет собой структуру размером 16 байт:
public struct Memory64Info
{
public IntPtr Address;
public IntPtr Size;
}
Необходимые значения:
Для перебора областей памяти процесса lsass.exe существуют предварительные требования, которые могут быть решены с использованием только NTAPI:
С этим можно пройти по памяти процесса, вызывая:
После предыдущих шагов у нас есть все необходимое для создания файла Minidump. Мы можем создать файл локально или отправить байты на удаленную машину с возможностью предварительного кодирования или шифрования байтов. Некоторые из этих возможностей реализованы в ветке delegates branch, где файл, созданный локально, может быть закодирован с помощью XOR, и в ветке remote branch, где файл может быть закодирован с помощью XOR перед отправкой на удаленную машину.
Для альтернативного подхода, который позволяет избежать создания файла Minidump, посмотрите TrickDump: он генерирует три JSON-файла и ZIP-архив, а Minidump восстанавливается на машине атакующего. Это может помочь обойти решения безопасности, которые отслеживают создание или эксфильтрацию Minidump.
| ID | Тип потока |
|---|
| 0x00 | UnusedStream |
| 0x01 | ReservedStream0 |
| 0x02 | ReservedStream1 |
| 0x03 | ThreadListStream |
| 0x04 | ModuleListStream |
| 0x05 | MemoryListStream |
| 0x06 | ExceptionStream |
| 0x07 | SystemInfoStream |
| 0x08 | ThreadExListStream |
| 0x09 | Memory64ListStream |
| 0x0A | CommentStreamA |
| 0x0B | CommentStreamW |
| 0x0C | HandleDataStream |
| 0x0D | FunctionTableStream |
| 0x0E | UnloadedModuleListStream |
| 0x0F | MiscInfoStream |
| 0x10 | MemoryInfoListStream |
| 0x11 | ThreadInfoListStream |
| 0x12 | HandleOperationListStream |
| 0x13 | TokenStream |
| 0x16 | HandleOperationListStream |