
Volcar lsass usando solo funciones NTAPI creando manualmente archivos Minidump (¡sin MiniDumpWriteDump!!!)
NativeDump permite volcar el proceso lsass usando solo NTAPIs generando un archivo Minidump con solo los streams necesarios para ser analizados por herramientas como Mimikatz o Pypykatz (SystemInfo, ModuleList y Memory64List Streams).

El programa tiene un argumento opcional para el archivo de salida, el nombre de archivo por defecto es "proc_<PID>.dmp":
NativeDump.exe [DUMP_FILE]

La herramienta ha sido probada en las últimas versiones de Windows con las soluciones de seguridad más comunes (Microsoft Defender for Endpoints, CrowdStrike...) y funciona bien, pero el sigilo dependerá de la "versión" que elijas: ¡usa lenguajes poco comunes y personaliza los binarios para obtener los mejores resultados! Sin embargo, no funciona si PPL está habilitado o la estructura PEB no es legible. Actualización: Ahora es posible ejecutar los programas sin leer el PEB, consulta la rama peb-unreadable :)
Algunos beneficios de esta técnica son:
Puedes encontrar el proyecto en diferentes "versiones" (o lenguajes):
main - Implementación básica en .NET (esta rama)
python-flavour - Implementación en Python con 3 métodos de sobrescritura de ntdll.dll + Exfiltración a máquina remota
golang-flavour - Implementación en Golang con 3 métodos de sobrescritura de ntdll.dll + Exfiltración a máquina remota
c-flavour - Implementación en C/C++ con 3 métodos de sobrescritura de ntdll.dll
bof-flavour - Archivo BOF con 3 métodos de sobrescritura de ntdll.dll
rust-flavour - Implementación en Rust por @safedv
crystal-flavour - Implementación en Crystal con capacidades de sobrescritura de ntdll.dll
nim-flavour - Implementación en Nim con capacidades de sobrescritura de ntdll.dll
Otras ramas interesantes usando .NET:
remote - Exfiltración a máquina remota + 3 métodos de sobrescritura de ntdll.dll + Resolución dinámica de funciones + Cifrado AES de cadenas + Codificación XOR del contenido del Minidump
all-modules - Obtener la información de todos los módulos (no solo lsasrv.dll)
peb-unreadable - Implementación sin leer la estructura PEB de lsass + 3 métodos de sobrescritura de ntdll.dll
Después de leer las estructuras no documentadas de Minidump, su estructura se puede resumir en:

Creé una herramienta de análisis que puede ser útil: MinidumpParser. Nos centraremos en crear un archivo válido con solo los valores necesarios para el encabezado, el directorio de streams y los únicos 3 streams necesarios para que un archivo Minidump sea analizado por Mimikatz/Pypykatz: SystemInfo, ModuleList y Memory64List Streams.
El encabezado es una estructura de 32 bytes que se puede definir en C# como:
public struct MinidumpHeader
{
public uint Signature;
public ushort Version;
public ushort ImplementationVersion;
public ushort NumberOfStreams;
public uint StreamDirectoryRva;
public uint CheckSum;
public IntPtr TimeDateStamp;
}
Los valores requeridos son:
Cada entrada en el Directorio de Streams es una estructura de 12 bytes, por lo que al tener 3 entradas el tamaño es de 36 bytes. La definición de struct en C# para una entrada es:
public struct MinidumpStreamDirectoryEntry
{
public uint StreamType;
public uint Size;
public uint Location;
}
El campo "StreamType" representa el tipo de stream como un entero o ID, algunos de los más relevantes son:
El primer stream es un Stream SystemInformation, con ID 7. El tamaño es de 56 bytes y se ubicará en el offset 68 (0x44), después del Directorio de Streams. Su definición en C# es:
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;
}
Los valores requeridos son:
El segundo stream es un Stream ModuleList, con ID 4. Se ubica en el offset 124 (0x7C) después del stream SystemInformation y también tendrá un tamaño fijo de 112 bytes, ya que contendrá la entrada de un solo módulo, el único necesario para que el análisis sea correcto: "lsasrv.dll".
La estructura típica para este stream es un valor de 4 bytes que contiene el número de entradas seguido de entradas de 108 bytes para cada módulo:
public struct ModuleListStream
{
public uint NumberOfModules;
public ModuleInfo[] Modules;
}
Como solo hay una, se simplifica a:
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;
}
Los valores requeridos son:
El tercer stream es un Stream Memory64List, con ID 9. Se ubica en el offset 298 (0x12A), después del stream ModuleList y la cadena Unicode, y su tamaño depende del número de módulos.
public struct Memory64ListStream
{
public ulong NumberOfEntries;
public uint MemoryRegionsBaseAddress;
public Memory64Info[] MemoryInfoEntries;
}
Cada entrada de módulo es una estructura de 16 bytes:
public struct Memory64Info
{
public IntPtr Address;
public IntPtr Size;
}
Los valores requeridos son:
Hay requisitos previos para recorrer las regiones de memoria del proceso lsass.exe que se pueden resolver usando solo NTAPIs:
Con esto es posible recorrer la memoria del proceso llamando a:
Después de los pasos anteriores tenemos todo lo necesario para crear el archivo Minidump. Podemos crear un archivo localmente o enviar los bytes a una máquina remota, con la posibilidad de codificar o cifrar los bytes antes. Algunas de estas posibilidades están codificadas en la rama delegates, donde el archivo creado localmente se puede codificar con XOR, y en la rama remote, donde el archivo se puede codificar con XOR antes de enviarlo a una máquina remota.
Para un enfoque alternativo que evita crear un archivo Minidump, consulta TrickDump: genera tres archivos JSON y un archivo ZIP, y el Minidump se reconstruye en la máquina del atacante. Esto puede ayudar a evadir soluciones de seguridad que monitorean la creación o exfiltración de Minidump.
| ID | Tipo de Stream |
|---|
| 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 |