January 16

Структура файла мини-дампа 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 утилит.

Минидамп — это структурированный бинарный файл, состоящий из:

  1. Заголовка (Header)
  2. Директории потоков (Stream Directory)
  3. Самих потоков данных (Streams)

Все данные хранятся в 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 байта, редко используется, почти всегда 0
  • TimeDateStamp -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), наличие потоков, ошибки формата.

dumpchk crash.dmp

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) злоумышленника, делая минидамп незаменимым источником данных в цифровой криминалистике.