public static Dictionary <string, string> TriageUserMasterKeysWithPass(string password, bool show = false) { Dictionary <string, string> mappings = new Dictionary <string, string>(); string userName = Environment.GetEnvironmentVariable("USERNAME"); string userDPAPIBasePath = String.Format("{0}\\AppData\\Roaming\\Microsoft\\Protect\\", System.Environment.GetEnvironmentVariable("USERPROFILE")); if (System.IO.Directory.Exists(userDPAPIBasePath)) { string[] directories = Directory.GetDirectories(userDPAPIBasePath); foreach (string directory in directories) { string[] files = Directory.GetFiles(directory); string domain = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName; Dpapi.CalculateKeys(password, directory, false); byte[] hmacbytes; if (domain == "") { hmacbytes = Dpapi.CalculateKeys(password, directory, false); //convert user password to SHA1 } else { hmacbytes = Dpapi.CalculateKeys(password, directory, true); } foreach (string file in files) { if (Regex.IsMatch(file, @"[0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12}")) { string fileName = System.IO.Path.GetFileName(file); if (show) { Console.WriteLine("[*] Found MasterKey : {0}", file); } byte[] masteyKeyBytes = File.ReadAllBytes(file); try { Dictionary <string, string> mapping = Dpapi.DecryptMasterKeyWithSha(masteyKeyBytes, hmacbytes); mapping.ToList().ForEach(x => mappings.Add(x.Key, x.Value)); } catch (Exception e) { Console.WriteLine("[X] Error triaging {0} : {1}", file, e.Message); } } } } } return(mappings); }
public static Dictionary <string, string> TriageUserMasterKeys(byte[] backupKeyBytes, bool show = false, string computerName = "", string password = "", string target = "") { // triage all *user* masterkeys we can find, decrypting if the backupkey is supplied var mappings = new Dictionary <string, string>(); var canAccess = false; if (!String.IsNullOrEmpty(target)) { // if we're targeting specific masterkey files if (backupKeyBytes.Length == 0) { // currently only backupkey is supported Console.WriteLine("[X] The masterkey '/target:X' option currently requires '/pvk:BASE64...'"); return(mappings); } if (!File.Exists(target) && !Directory.Exists(target)) { Console.WriteLine($"[X] The target '{target}' doesn't exist!"); return(mappings); } KeyValuePair <string, string> plaintextMasterKey; if ((File.GetAttributes(target) & FileAttributes.Directory) == FileAttributes.Directory) { // if we're triaging a folder of masterkeys var files = Directory.GetFiles(target); foreach (var file in files) { try { FileInfo f = new FileInfo(file); if (Helpers.IsGuid(f.Name)) { var masterKeyBytes = File.ReadAllBytes(file); plaintextMasterKey = Dpapi.DecryptMasterKey(masterKeyBytes, backupKeyBytes); mappings.Add(plaintextMasterKey.Key, plaintextMasterKey.Value); } } catch (Exception e) { Console.WriteLine("[X] Error triaging masterkey target '{0}' : {1}", target, e.Message); } } } else { // otherwise we're triaging one file try { var masterKeyBytes = File.ReadAllBytes(target); plaintextMasterKey = Dpapi.DecryptMasterKey(masterKeyBytes, backupKeyBytes); mappings.Add(plaintextMasterKey.Key, plaintextMasterKey.Value); } catch (Exception e) { Console.WriteLine("[X] Error triaging masterkey target '{0}' : {1}", target, e.Message); } } } else { if (!String.IsNullOrEmpty(computerName)) { canAccess = Helpers.TestRemote(computerName); if (!canAccess) { return(new Dictionary <string, string>()); } } string[] userDirs; if (Helpers.IsHighIntegrity() || (!String.IsNullOrEmpty(computerName) && canAccess)) { // if elevated, triage ALL reachable masterkeys var userFolder = !String.IsNullOrEmpty(computerName) ? $"\\\\{computerName}\\C$\\Users\\" : $"{Environment.GetEnvironmentVariable("SystemDrive")}\\Users\\"; userDirs = Directory.GetDirectories(userFolder); } else { // otherwise we're only triaging the current user's path userDirs = new string[] { Environment.GetEnvironmentVariable("USERPROFILE") }; } foreach (var dir in userDirs) { if (dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users")) { continue; } var userDPAPIBasePath = $"{dir}\\AppData\\Roaming\\Microsoft\\Protect\\"; if (!Directory.Exists(userDPAPIBasePath)) { continue; } var directories = Directory.GetDirectories(userDPAPIBasePath); foreach (var directory in directories) { var files = Directory.GetFiles(directory); var isDomain = false; byte[] hmacBytes = null; foreach (var file in files) { // if the BK-<NETBIOSDOMAINNAME> file exists, assume this is a domain user. if (Regex.IsMatch(file, @".*\\BK-[0-9A-Za-z]+")) { isDomain = true; // means use the NTLM of the user password instead of the SHA1 } } if (!String.IsNullOrEmpty(password)) { hmacBytes = Dpapi.CalculateKeys(password, directory, isDomain); } foreach (var file in files) { if (!Regex.IsMatch(file, @"[0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12}")) { continue; } if (show) { Console.WriteLine("[*] Found MasterKey : {0}", file); } var masterKeyBytes = File.ReadAllBytes(file); try { KeyValuePair <string, string> plaintextMasterKey; if (!String.IsNullOrEmpty(password)) { plaintextMasterKey = Dpapi.DecryptMasterKeyWithSha(masterKeyBytes, hmacBytes); } else { plaintextMasterKey = Dpapi.DecryptMasterKey(masterKeyBytes, backupKeyBytes); } mappings.Add(plaintextMasterKey.Key, plaintextMasterKey.Value); } catch (Exception e) { // Console.WriteLine("[X] Error triaging {0} : {1}", file, e.Message); } } } } } if (!String.IsNullOrEmpty(password)) { if (mappings.Count == 0) { Console.WriteLine("\n[!] No master keys decrypted!\r\n"); } else { Console.WriteLine("\n[*] User master key cache:\r\n"); foreach (var kvp in mappings) { Console.WriteLine("{0}:{1}", kvp.Key, kvp.Value); } Console.WriteLine(); } } Console.WriteLine(); return(mappings); }
public static Dictionary <string, string> TriageUserMasterKeys(byte[] backupKeyBytes, bool show = false, string computerName = "", string password = "") { // triage all *user* masterkeys we can find, decrypting if the backupkey is supplied Dictionary <string, string> mappings = new Dictionary <string, string>(); bool canAccess = false; if (!String.IsNullOrEmpty(computerName)) { canAccess = Helpers.TestRemote(computerName); if (!canAccess) { return(new Dictionary <string, string>()); } } string[] userDirs; if (Helpers.IsHighIntegrity() || (!String.IsNullOrEmpty(computerName) && canAccess)) { // if elevated, triage ALL reachable masterkeys string userFolder = ""; if (!String.IsNullOrEmpty(computerName)) { userFolder = String.Format("\\\\{0}\\C$\\Users\\", computerName); } else { userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive")); } userDirs = Directory.GetDirectories(userFolder); } else { // otherwise we're only triaging the current user's path userDirs = new string[] { System.Environment.GetEnvironmentVariable("USERPROFILE") }; } foreach (string dir in userDirs) { string[] parts = dir.Split('\\'); string userName = parts[parts.Length - 1]; if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))) { string userDPAPIBasePath = String.Format("{0}\\AppData\\Roaming\\Microsoft\\Protect\\", dir); if (System.IO.Directory.Exists(userDPAPIBasePath)) { string[] directories = Directory.GetDirectories(userDPAPIBasePath); foreach (string directory in directories) { string[] files = Directory.GetFiles(directory); bool isDomain = false; byte[] hmacbytes = null; foreach (string file in files) { // if the BK-<NETBIOSDOMAINNAME> file exists, assume this is a domain user. if (Regex.IsMatch(file, @".*\\BK-[0-9A-Za-z]+")) { isDomain = true; // means use the NTLM of the user password instead of the SHA1 } } if (!String.IsNullOrEmpty(password)) { hmacbytes = Dpapi.CalculateKeys(password, directory, isDomain); } foreach (string file in files) { if (Regex.IsMatch(file, @"[0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12}")) { string fileName = System.IO.Path.GetFileName(file); if (show) { Console.WriteLine("[*] Found MasterKey : {0}", file); } byte[] masteyKeyBytes = File.ReadAllBytes(file); try { if (!String.IsNullOrEmpty(password)) { Dictionary <string, string> mapping = Dpapi.DecryptMasterKeyWithSha(masteyKeyBytes, hmacbytes); mapping.ToList().ForEach(x => mappings.Add(x.Key, x.Value)); } else { Dictionary <string, string> mapping = Dpapi.DecryptMasterKey(masteyKeyBytes, backupKeyBytes); mapping.ToList().ForEach(x => mappings.Add(x.Key, x.Value)); } } catch (Exception e) { Console.WriteLine("[X] Error triaging {0} : {1}", file, e.Message); } } } } } } } if (!String.IsNullOrEmpty(password)) { if (mappings.Count == 0) { Console.WriteLine("\n[!] No master keys decrypted!\r\n"); } else { Console.WriteLine("\n[*] User master key cache:\r\n"); foreach (KeyValuePair <string, string> kvp in mappings) { Console.WriteLine("{0}:{1}", kvp.Key, kvp.Value); } Console.WriteLine(); } } Console.WriteLine(); return(mappings); }