
Despejar lsass usando apenas funções NTAPI criando manualmente arquivos Minidump (sem MiniDumpWriteDump!!!)
NativeDump permite despejar o processo lsass usando apenas NTAPIs, gerando um arquivo Minidump com apenas os streams necessários para serem analisados por ferramentas como Mimikatz ou Pypykatz (SystemInfo, ModuleList e Memory64List Streams).

O programa tem um argumento opcional para o arquivo de saída, o nome padrão é "proc_<PID>.dmp":
NativeDump.exe [DUMP_FILE]

A ferramenta foi testada nas versões mais recentes do Windows com as soluções de segurança mais comuns (Microsoft Defender for Endpoints, CrowdStrike...) e funciona bem, mas a furtividade dependerá da "variante" que você escolher: use linguagens incomuns e personalize os binários para obter os melhores resultados! No entanto, não funciona se o PPL estiver ativado ou a estrutura PEB não for legível. Atualização: Agora é possível executar os programas sem ler o PEB, confira o branch peb-unreadable :)
Alguns benefícios desta técnica são:
Você pode encontrar o projeto em diferentes "variantes" (ou linguagens):
main - .NET implementação básica (este branch)
python-flavour - Python implementação com 3 métodos de sobrescrita da ntdll.dll + Exfiltração para máquina remota
golang-flavour - Golang implementação com 3 métodos de sobrescrita da ntdll.dll + Exfiltração para máquina remota
c-flavour - C/C++ implementação com 3 métodos de sobrescrita da ntdll.dll
bof-flavour - Arquivo BOF com 3 métodos de sobrescrita da ntdll.dll
rust-flavour - Rust implementação por @safedv
crystal-flavour - Crystal implementação com capacidades de sobrescrita da ntdll.dll
nim-flavour - Nim implementação com capacidades de sobrescrita da ntdll.dll
Outros branches interessantes usando .NET:
remote - Exfiltração para máquina remota + 3 métodos de sobrescrita da ntdll.dll + Resolução dinâmica de funções + Criptografia AES de strings + Codificação XOR do conteúdo Minidump
all-modules - Obtém as informações para todos os módulos (não apenas lsasrv.dll)
peb-unreadable - Implementação sem ler a estrutura PEB do lsass + 3 métodos de sobrescrita da ntdll.dll
Após ler as estruturas não documentadas do Minidump, sua estrutura pode ser resumida em:

Criei uma ferramenta de análise que pode ser útil: MinidumpParser. Vamos nos concentrar em criar um arquivo válido com apenas os valores necessários para o cabeçalho, diretório de streams e os únicos 3 streams necessários para que um arquivo Minidump seja analisado por Mimikatz/Pypykatz: SystemInfo, ModuleList e Memory64List Streams.
O cabeçalho é uma estrutura de 32 bytes que pode ser definida em 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;
}
Os valores necessários são:
Cada entrada no Diretório de Streams é uma estrutura de 12 bytes, portanto com 3 entradas o tamanho é 36 bytes. A definição da struct em C# para uma entrada é:
public struct MinidumpStreamDirectoryEntry
{
public uint StreamType;
public uint Size;
public uint Location;
}
O campo "StreamType" representa o tipo de stream como um inteiro ou ID, alguns dos mais relevantes são:
O primeiro stream é um SystemInformation Stream, com ID 7. O tamanho é 56 bytes e estará localizado no offset 68 (0x44), após o Diretório de Streams. Sua definição em 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;
}
Os valores necessários são:
O segundo stream é um ModuleList stream, com ID 4. Ele está localizado no offset 124 (0x7C) após o SystemInformation stream e também terá um tamanho fixo de 112 bytes, pois conterá a entrada de um único módulo, o único necessário para a análise correta: "lsasrv.dll".
A estrutura típica para este stream é um valor de 4 bytes contendo o número de entradas seguido por entradas de 108 bytes para cada módulo:
public struct ModuleListStream
{
public uint NumberOfModules;
public ModuleInfo[] Modules;
}
Como há apenas um, fica simplificado para:
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;
}
Os valores necessários são:
O terceiro stream é um Memory64List stream, com ID 9. Ele está localizado no offset 298 (0x12A), após o ModuleList stream e a string Unicode, e seu tamanho depende do número de módulos.
public struct Memory64ListStream
{
public ulong NumberOfEntries;
public uint MemoryRegionsBaseAddress;
public Memory64Info[] MemoryInfoEntries;
}
Cada entrada de módulo é uma estrutura de 16 bytes:
public struct Memory64Info
{
public IntPtr Address;
public IntPtr Size;
}
Os valores necessários são:
Existem pré-requisitos para percorrer as regiões de memória do processo lsass.exe que podem ser resolvidos usando apenas NTAPIs:
Com isso é possível percorrer a memória do processo chamando:
Após as etapas anteriores, temos tudo o que é necessário para criar o arquivo Minidump. Podemos criar um arquivo localmente ou enviar os bytes para uma máquina remota, com a possibilidade de codificar ou criptografar os bytes antes. Algumas dessas possibilidades estão codificadas no branch delegates, onde o arquivo criado localmente pode ser codificado com XOR, e no branch remote, onde o arquivo pode ser codificado com XOR antes de ser enviado para uma máquina remota.
Para uma abordagem alternativa que evita criar um arquivo Minidump, confira TrickDump: ele gera três arquivos JSON e um arquivo ZIP, e o Minidump é reconstruído na máquina do atacante. Isso pode ajudar a evadir soluções de segurança que monitoram a criação ou exfiltração de Minidumps.
| 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 |