Структура файла мини-дампа Windows
Минидамп (minidump) — это компактный файл дампа памяти, создаваемый Windows при аварийном завершении работы системы (BSOD) или дампа процесса в момент сбоя приложения. В расследованиях инцидентов мини-дампы служат ценным источником информации: они могут содержать артефакты вредоносной активности, сетевые индикаторы, загруженные модули, открытые хендлы процесса и информацию о процессе. Очень важно понимать структуру файла и уметь извлекать информацию, которая необходима для восстановления событий и получения индикаторов компрометации.
Виды мини-дампов
1. Системные мини-дампы (Kernel-mode) - при BSOD:C:\Windows\Minidump\*.dmp малые минидампы (по умолчанию)
Содержат: stop-код и параметры ошибки, контекст процессора на момент краха, стек вызовов в режиме ядра, список загруженных драйверов, базовую информацию о системе.
2. Пользовательские мини-дампы (User-mode) - создаются при падении приложений:
%LOCALAPPDATA%\CrashDumps\ для текущего пользователя
%SystemRoot%\System32\config\systemprofile\AppData\Local\CrashDumps\ для системных служб
Пользовательские мини-дампы могут быть созданы вручную с помощью инструментов ProcDump, TaskManager, ProcessHacker/SystemInformer, либо функция MiniDumpWriteDump Windows API.
3. Полные дампы памяти:
Содержат всю физическую память системы, располагаются в C:\Windows\MEMORY.DMP. Технически это не мини-дампы, но про них важно упомянуть. Они содержат физическую память системы, из которой можно получать список процессов, сетевые соединения и т.д.
Структура файла
Рассмотрим структуру файла пользовательского файла мини-дамп (User-mode). Данные файлы встречаются на системах очень часто и многие собирают их с помощью своих Triage утилит.
Минидамп — это структурированный бинарный файл, состоящий из:
Все данные хранятся в little-endian порядке.
Заголовок мини-дамп
Каждый файл мини-дампа начинается с заголовка фиксированного размера 32 байта, который служит отправной точкой для парсинга файла.
Структура заголовка определена в официальной документации Microsoft (minidumpapiset.h):
typedef struct _MINIDUMP_HEADER {
ULONG32 Signature; // 4 байта
ULONG32 Version; // 4 байта
ULONG32 NumberOfStreams; // 4 байта
RVA StreamDirectoryRva; // 4 байта
ULONG32 CheckSum; // 4 байта
union { // 4 байта
ULONG32 Reserved;
ULONG32 TimeDateStamp;
};
ULONG64 Flags; // 8 байт
} MINIDUMP_HEADER, *PMINIDUMP_HEADER;
Signature-4 байта, всегда 0x504D444D (MDMP)Version -4 байта, версия формата. Обычно0x000A0007или0x000093A7(в little-endian:A7 93 00 00). Старшие 16 бит — версия, младшие — реализация.NumberOfStreams -4 байта, количество записей в директории потоковStreamDirectoryRVA -4 байта, смещение (в байтах от начала файла), где начинается директория потоковCheckSum -4 байта, редко используется, почти всегда 0TimeDateStamp -4 байта, время создания дампа в формате Unix timestamp (секунды с 1970-01-01 UTC)Flags -8 байт, битовая маска, указывающая, какие данные включены (например, память, хендлы, потоки и т.д.)
Содержимое дампа напрямую зависит от установленных флагов (Flags):
- MiniDumpNormal (~64КБ–2 МБ) — базовый дамп с минимальной информацией о сбое.
- MiniDumpWithDataSegs (10–100 МБ) — добавляет сегменты данных.
- MiniDumpWithHandleData (1–10 МБ) — включает информацию о дескрипторах.
- MiniDumpWithFullMemory (сотни МБ–ГБ) — полный дамп со всей виртуальной памятью процесса.
Подробный список флагов доступен в документации Microsoft.
Директория потоков
Сразу после заголовка следует директория потоков — массив структур MINIDUMP_DIRECTORY, описывающих расположение и тип каждого блока данных. Директория начинается по смещению, указанному в StreamDirectoryRVA (заголовка мини-дампа). Количество таких записей задается в NumberOfStreams (заголовка мини-дамп).
typedef struct _MINIDUMP_DIRECTORY {
ULONG32 StreamType; // Тип потока
MINIDUMP_LOCATION_DESCRIPTOR Location; // Где лежат данные
} MINIDUMP_DIRECTORY;
typedef struct _MINIDUMP_LOCATION_DESCRIPTOR {
ULONG32 DataSize; // Размер данных в байтах
RVA Rva; // Смещение от начала файла, где начинаются данные
} MINIDUMP_LOCATION_DESCRIPTOR;
04 00 00 00 48 00 00 00 30 01 00 00 │ │ └── RVA = 0x00000130 │ └── DataSize = 0x48 (72 байта) └── StreamType = 4 → ModuleListStream
Потоки данных (Streams)
Мини-дамп состоит из модульных блоков — потоков, каждый из которых содержит определенный тип информации. Расположение потока в файле мини-дамп указывается в поле RVA директории потоков.
Рассмотрим наиболее значимые для анализа потоки:
- SystemInfoStream (Тип 7) - описывает информацию о системе, в которую входит версия ОС, архитектура процессора, количество ядер.
- ModuleListStream (Тип 4) - важный поток, который содержит полный список загруженных модулей: адреса загрузки, размеры, имена DLL/EXE, временные метки, версия исполняемого файла.
Структура потока: первые 4 байта — количество модулей, далее массив структур MINIDUMP_MODULE.
Каждый MINIDUMP_MODULE содержит:
BaseOfImage— базовый адрес загрузки в память (VA)SizeOfImage— размер образаTimeDateStamp— метка времени компиляции PE-файла (в секундах с 1970)ModuleNameRva— RVA строки с путём к модулю (Unicode строка)VersionInfo— версия файла (если есть)CheckSum— контрольная сумма
Важно: из мини-дампа с полной памятью (MiniDumpWithFullMemory) можно восстановить оригинальные исполняемые файлы, зная их базовые адреса и размеры.
Пример обнаружения вредоносного модуля:
{
"name": "malware.dll",
"full_path": "c:\\Windows\\System32\\malware.dll",
"base_address": "0x00007FFC9A870000",
"size": 286720,
"size_hex": "0x46000",
"checksum": "0x00000000",
"timestamp": 1276629802,
"time_string": "2010-06-15 22:23:22",
"type": "DLL",
"is_dll": true,
"is_exe": false,
"version_info": {
"file_version": "",
"product_version": "",
"file_type": "Unknown",
"signature": 0,
"is_valid": false
}
}
При анализе данного потока обращаем внимание на необычные пути размещения модулей, модули без подписи, несоответствие времени компиляции и версий, - модули с подозрительными именами.
- ThreadListStream (Тип 3) - содержит информацию о потоках процесса: ID потоков, контекст процессора, стеки вызовов.
- ExceptionStream (Тип 6) - содержит данные об исключении: код исключения, адрес сбоя, параметры исключения.
- MemoryListStream (Тип 5) и Memory64ListStream (Тип 9) - эти потоки содержат фрагменты виртуальной памяти процесса. Структура потока MemoryListStream:
ULONG32 NumberOfMemoryRanges; MINIDUMP_MEMORY_DESCRIPTOR MemoryRanges[...];
ULONG64 StartOfMemoryRange; // виртуальный адрес
MINIDUMP_LOCATION_DESCRIPTOR Memory; // { DataSize, RVA }
Структура потока Memory64ListStream немного изменена и является более эффективной для большинства дампов. Вместо повторения RVA для каждого региона присутствует единый базовый RVA.
ULONG64 NumberOfMemoryRanges; ULONG64 BaseRva; // смещение от начала файла, где начинаются все данные памяти подряд
Затем идёт массив, содержащий:
struct {
ULONG64 StartOfMemoryRange; // виртуальный адрес
ULONG64 DataSize;
} [NumberOfMemoryRanges]
Все регионы памяти хранятся последовательно, начиная с BaseRva. В этих потоках можно искать URL-адреса, домены, IP-адреса, конфигурационные данные, текстовые строки, указывающие на активность.
- MiscInfoStream (Тип 15) - данный поток содержит информацию о процессе: время создания процесса, ID процесса.
typedef struct _MINIDUMP_MISC_INFO {
ULONG32 SizeOfInfo; // Размер структуры в байтах
ULONG32 Flags1; // Битовая маска: какие поля заполнены
ULONG32 ProcessId; // PID процесса
ULONG32 ProcessCreateTime; // Время создания процесса (Unix timestamp)
ULONG32 ProcessUserTime; // Время в пользовательском режиме (в 100-нс интервалах)
ULONG32 ProcessKernelTime; // Время в режиме ядра (в 100-нс интервалах)
} MINIDUMP_MISC_INFO;
Здесь можно вычислить время работы процесса uptime=ProceeCreateTime - DumpTime, где DumpTime берется из заголовка дампа.
- HandleDataStream (Тип 12) - этот поток содержит информацию о дескрипторах (handles), открытых процессом на момент создания дампа. Этот поток крайне полезен в цифровой криминалистике и анализе вредоносного ПО, так как позволяет увидеть, с какими объектами ядра взаимодействовал процесс: файлы, сетевые соединения, мьютексы, процессы, ключи реестра и многое другое.
Информация о хендле может быть представлена в двух форматах — в зависимости от версии операционной системы и флагов создания дампа.
typedef struct _MINIDUMP_HANDLE_DATA_STREAM {
ULONG32 SizeOfHeader; // Размер заголовка (обычно 16)
ULONG32 Reserved; // Зарезервировано (обычно 0)
ULONG32 NumberOfHandles; // Количество дескрипторов
ULONG32 Reserved2; // Зарезервировано
} MINIDUMP_HANDLE_DATA_STREAM;
typedef struct _MINIDUMP_HANDLE_DESCRIPTOR {
ULONG64 Handle; // Значение дескриптора (например, 0x5c)
RVA TypeNameRva; // RVA строки с типом объекта ("File", "Event" и т.д.)
RVA ObjectNameRva; // RVA имени объекта (например, путь к файлу)
ULONG32 Attributes; // Атрибуты (обычно 0)
ULONG32 GrantedAccess; // Права доступа (битовая маска)
ULONG32 HandleCount; // Сколько раз объект открыт в системе
ULONG32 PointerCount; // Сколько указателей на объект
} MINIDUMP_HANDLE_DESCRIPTOR;
Базовая структура MINIDUMP_HANDLE_DESCRIPTOR занимает 32 байта и содержит ключевые поля: значение дескриптора, RVA (смещение от начала файла) к строкам с типом объекта (например, File, Mutant, Key, Directory) и его именем, а также информацию о правах доступа, количестве ссылок и атрибутах.
Начиная с Windows 8 появилась расширенная версия — MINIDUMP_HANDLE_DESCRIPTOR_2 (40 байт). Она включает все поля предыдущей структуры и добавляет два новых:
ObjectInfoRva— указатель на дополнительные метаданные об объекте (например, временные метки файла или PID связанного процесса),Reserved0— зарезервированное поле для будущего использования.
На практике поле ObjectInfoRva почти всегда нулевое, так как Windows редко сохраняет расширенные данные в мини-дамп. Поэтому основное различие между версиями сводится к размеру записи: 32 байта для классической структуры и 40 байт для расширенной. При парсинге важно корректно определять размер записи, чтобы избежать смещения при чтении последующих дескрипторов.
Наиболее интересные значения TypeName: File - открытый файл, Directory - директория, Mutant - мьютекс, Key - ключ реестра.
- Имена объектов могут отсутствовать (
ObjectNameRva = 0) — особенно для анонимных объектов. - Нет сетевых сокетов — TCP/UDP-соединения не представлены как хендлы в этом формате.
- Данные статичны — вы видите состояние на момент дампа, но не историю.
- Требуется флаг — без
MiniDumpWithHandleDataпоток отсутствует.
Инструменты анализа мини-дампов
WinDbg - инструмент для анализа дампов от Microsoft, доступен через Microsoft Store. Используется, когда необходим глубокий анализ: восстановление стека вызовов, проверка контекста CPU, работа с символами Microsoft. В использовании данного инструмента есть большое ограничение в виде высокого порога входа, которое требует понимание архитектуры Windows и отладочных команд.
!analyze -v— автоматический анализ причины сбояlm— список всех загруженных модулей с базовыми адресами!handle— просмотр открытых хендлов (требуется флагMiniDumpWithHandleData)s -a 0 L?80000000 "http"— поиск ASCII-строк по всей доступной памяти
dumpchk.exe - утилита из Windows SDK, предназначенная для проверки структуры мини-дамп. Данный инструмент покажет тип дампа (user/kernel), наличие потоков, ошибки формата.
Volatility3 - инструмент для анализа дампов памяти. Volatility работает только с полными kernel-дампами (MEMORY.DMP), но не поддерживает user-mode minidumps.
# Volatility3 vol.py -f MEMORY.DMP windows.pslist # Volatility2 vol.py -f MEMORY.DMP --profile=Win10x64 pslist
Strings + Stringsifter - инструменты для анализа строк, основанный на машинном обучении, который автоматически ранжирует строки на основе их релевантности для анализа вредоносного ПО.
strings -n 6 -a crash.dmp | rank_strings
MiniDump Parser for Dfir - инструмент анали мини-дампов процессов для DFIR специалистов. Позволяет анализировать информацию о процессе, извлекать модули из мини-дампа, извлекать открытые хендлы процесса, искать артефакты в памяти процесса.
python3 main.py -f dumpfile.dmp -o report.json
Полный анализ с извлечением модулей из мини-дампа:
python3 main.py -f dumpfile.dmp -o report.json -dump true -dump-dir ./extracted_modules
Если у вас есть необходимость добавить свои собственные регулярные выражения для поиска информации в MemoryListStream, то необходимо перейти файл minidump/artifact.py и изменить значение self.patterns.
self.patterns = {
'urls': re.compile(r'https?://[a-zA-Z0-9\-\._~:/?#\[\]@!amp;\'()*+,;=%]+'),
'domains': re.compile(r'\b(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+'r'[a-zA-Z]{2,}\b')
}
Заключение
Мини-дамп Windows играет ключевую роль в расследовании инцидентов, предоставляя «моментальный снимок» состояния процесса или системы в критический момент — будь то сбой, зависание или аварийное завершение. Особенно ценными являются загруженные модули (DLL/EXE), которые позволяют выявить подозрительные библиотеки, внедрённые из нетипичных путей (например, %TEMP% или AppData), а также проверить их временные метки на несоответствие легитимным версиям. Информация о процессе — PID, время создания, потребление CPU — помогает установить длительность его работы и коррелировать с логами безопасности. Если мини-дамп создан с расширенными флагами (например, MiniDumpWithHandleData), он может содержать хендлы, указывающие на открытые файлы, мьютексы, процессы или ключи реестра — прямые индикаторы вредоносного поведения. Но особенно важна дампированная память: даже в компактном минидампе могут сохраниться фрагменты кучи или стека, где остаются следы сетевой активности — IP-адреса, доменные имена, URL-адреса C2-серверов, строки конфигураций или команд. Анализ этих артефактов позволяет не только подтвердить компрометацию, но и восстановить тактику, техники и процедуры (TTPs) злоумышленника, делая минидамп незаменимым источником данных в цифровой криминалистике.