Пример #1
0
        public static void TriageCertFile(string certFilePath, Dictionary <string, string> MasterKeys)
        {
            // triage a certificate file
            try
            {
                var certDictionary = new Dictionary <string, Tuple <string, string> >();
                var fileName       = Path.GetFileName(certFilePath);
                Console.WriteLine("  Certificate file           : {0}\r\n", fileName);

                var certificateArray = File.ReadAllBytes(certFilePath);
                try
                {
                    certDictionary.Add(fileName, Dpapi.DescribeCertificate(certificateArray, MasterKeys));
                }
                catch (Exception e)
                {
                    Console.WriteLine("[X] Error triaging {0} : {1}", fileName, e.Message);
                }
                Console.WriteLine();
            }
            catch (Exception e)
            {
                Console.WriteLine("[X] Error triaging {0} : {1}", certFilePath, e.Message);
            }

            Console.WriteLine();
        }
Пример #2
0
        public static void TriagePSCredFile(Dictionary <string, string> MasterKeys, string credFile, bool unprotect = false)
        {
            // triage a saved PSCredential .xml
            //  example - `Get-Credential | Export-Clixml -Path C:\Temp\cred.xml`

            if (!File.Exists(credFile))
            {
                throw new Exception($"PSCredential .xml); file '{credFile}' is not accessible or doesn't exist!\n");
            }

            var lastAccessed = File.GetLastAccessTime(credFile);
            var lastModified = File.GetLastWriteTime(credFile);

            var xmlDoc = new XmlDocument();

            xmlDoc.Load(credFile);

            Console.WriteLine("    CredFile         : {0}", credFile);
            Console.WriteLine("    Accessed         : {0}", lastAccessed);
            Console.WriteLine("    Modified         : {0}", lastModified);

            var props = xmlDoc.GetElementsByTagName("Props");

            if (props.Count > 0)
            {
                var userName  = props[0].ChildNodes[0].InnerText;
                var dpapiBlob = props[0].ChildNodes[1].InnerText;

                Console.WriteLine("    User Name        : {0}", userName);

                var blobBytes = Helpers.StringToByteArray(dpapiBlob);

                if (blobBytes.Length > 0)
                {
                    var decBytesRaw = Dpapi.DescribeDPAPIBlob(blobBytes, MasterKeys, "blob", unprotect);

                    if ((decBytesRaw != null) && (decBytesRaw.Length != 0))
                    {
                        var password   = "";
                        var finalIndex = Array.LastIndexOf(decBytesRaw, (byte)0);
                        if (finalIndex > 1)
                        {
                            var decBytes = new byte[finalIndex + 1];
                            Array.Copy(decBytesRaw, 0, decBytes, 0, finalIndex);
                            password = Encoding.Unicode.GetString(decBytes);
                        }
                        else
                        {
                            password = Encoding.ASCII.GetString(decBytesRaw);
                        }

                        Console.WriteLine("    Password         : {0}", password);
                    }
                }
            }

            Console.WriteLine();
        }
Пример #3
0
        public static void DisplayCredProfile(Dictionary <string, string> MasterKeys, XmlNode credProfileNode, bool unprotect = false)
        {
            // helper that displays a Credential Profile/Logon settings XML node from RDG/RDCMan.settings files

            var profileName = credProfileNode["profileName"].InnerText;

            if (credProfileNode["userName"] == null)
            {
                // have a profile name only
                Console.WriteLine("          Cred Profile : {0}", profileName);
            }
            else
            {
                var userName     = credProfileNode["userName"].InnerText.Trim();
                var domain       = credProfileNode["domain"].InnerText.Trim();
                var b64Password  = credProfileNode["password"].InnerText;
                var password     = "";
                var fullUserName = "";

                if (String.IsNullOrEmpty(domain))
                {
                    fullUserName = userName;
                }
                else
                {
                    fullUserName = $"{domain}\\{userName}";
                }

                Console.WriteLine("          Profile Name : {0}", profileName);
                Console.WriteLine("            UserName   : {0}", fullUserName);

                var passwordDPAPIbytes = Convert.FromBase64String(b64Password);

                if (passwordDPAPIbytes.Length <= 0)
                {
                    return;
                }

                var decBytesRaw = Dpapi.DescribeDPAPIBlob(passwordDPAPIbytes, MasterKeys, "rdg", unprotect);

                if (decBytesRaw.Length != 0)
                {
                    // chop off anything after the UNICODE end
                    var finalIndex = Array.LastIndexOf(decBytesRaw, (byte)0);
                    if (finalIndex > 1)
                    {
                        var decBytes = new byte[finalIndex + 1];
                        Array.Copy(decBytesRaw, 0, decBytes, 0, finalIndex);
                        password = Encoding.Unicode.GetString(decBytes);
                    }
                    else
                    {
                        password = Encoding.ASCII.GetString(decBytesRaw);
                    }
                }
                Console.WriteLine("            Password   : {0}", password);
            }
        }
Пример #4
0
        public static void TriageCertFolder(string folder, Dictionary <string, string> MasterKeys, bool machine = false)
        {
            // triage a specific certificate folder
            var certDictionary = new Dictionary <string, Tuple <string, string> >();

            if (!Directory.Exists(folder))
            {
                return;
            }

            var systemFiles = Directory.GetFiles(folder);

            if ((systemFiles.Length != 0))
            {
                Console.WriteLine("\r\nFolder       : {0}\r\n", folder);

                foreach (var file in systemFiles)
                {
                    if (Regex.IsMatch(file,
                                      @"[0-9A-Fa-f]{32}[_][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}")
                        )
                    {
                        var fileName = Path.GetFileName(file);
                        Console.WriteLine("\r\nCertificate file           : {0}\r\n", fileName);
                        var certificateArray = File.ReadAllBytes(file);
                        try
                        {
                            certDictionary.Add(fileName, Dpapi.DescribeCertificate(certificateArray, MasterKeys, machine));
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("[X] Error triaging {0} : {1}", fileName, e.Message);
                        }
                    }
                }
            }
            else
            {
                Console.WriteLine("\r\n[X] Folder '{0}' doesn't contain files!", folder);
            }

            Console.WriteLine();

            foreach (var key in certDictionary.Keys)
            {
                if (certDictionary[key].First != "")
                {
                    Console.WriteLine("[*] Private key file {0} was recovered\r\n", key);
                    Console.WriteLine("[*] PKCS1 Private key\r\n");
                    Console.WriteLine(certDictionary[key].First);
                    Console.WriteLine("\r\n[*] Certificate\r\n");
                    Console.WriteLine(certDictionary[key].Second);
                    Console.WriteLine();
                }
            }
        }
Пример #5
0
        public static void TriageVaultFolder(string folder, Dictionary <string, string> MasterKeys)
        {
            // takes a Vault folder, extracts the AES 128/256 keys from Policy.vpol, and uses these
            //  to decrypt any .vcrd vault credentials

            var policyFilePath = $"{folder}\\Policy.vpol";

            if (!File.Exists(policyFilePath))
            {
                return;
            }
            Console.WriteLine("\r\n[*] Triaging Vault folder: {0}", folder);

            var policyBytes = File.ReadAllBytes(policyFilePath);

            // first try to get vault keys from the Policy.vpol
            var keys = Dpapi.DescribeVaultPolicy(policyBytes, MasterKeys);

            // make sure we have keys returned
            if (keys.Count <= 0)
            {
                return;
            }

            var vaultCredFiles = Directory.GetFiles(folder);

            if ((vaultCredFiles == null) || (vaultCredFiles.Length == 0))
            {
                return;
            }

            foreach (var vaultCredFile in vaultCredFiles)
            {
                var fileName = Path.GetFileName(vaultCredFile);

                if (!fileName.EndsWith("vcrd"))
                {
                    continue;
                }

                try
                {
                    var vaultCredBytes = File.ReadAllBytes(vaultCredFile);
                    // describe the vault credential file using the Policy credentials
                    Dpapi.DescribeVaultCred(vaultCredBytes, keys);
                }
                catch (Exception e)
                {
                    Console.WriteLine("[X] Error triaging {0} : {1}", vaultCredFile, e.Message);
                }
            }
        }
Пример #6
0
        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);
        }
Пример #7
0
        public static void TriageCertFile(string certFilePath, Dictionary <string, string> MasterKeys, bool machine = false)
        {
            // triage a certificate file

            var fileName = Path.GetFileName(certFilePath);

            Console.WriteLine("\r\n  Certificate file      : {0}\r\n", fileName);
            var certificateArray = File.ReadAllBytes(certFilePath);

            try
            {
                ExportedCertificate cert = Dpapi.DescribeCertificate(certificateArray, MasterKeys, machine);

                if (cert.Thumbprint != "")
                {
                    Console.WriteLine("    Thumbprint: {0}", cert.Thumbprint);
                    Console.WriteLine("    Issuer: {0}", cert.Issuer);
                    Console.WriteLine("    Subject: {0}", cert.Subject);
                    Console.WriteLine("    Valid Date: {0}", cert.ValidDate);
                    Console.WriteLine("    Expiry Date: {0}", cert.ExpiryDate);
                }

                if (cert.EKUs.Count > 0)
                {
                    Console.WriteLine("    Enhanced Key Usages:");
                    foreach (var eku in cert.EKUs)
                    {
                        Console.WriteLine("        {0} ({1})", eku.First, eku.Second);
                        if (eku.Second == "1.3.6.1.5.5.7.3.2")
                        {
                            Console.WriteLine("         [!] Certificate is used for client auth!");
                        }
                    }
                }

                if (cert.PrivateKey != "")
                {
                    Console.WriteLine("    [*] Private key file {0} was recovered:\r\n", fileName);
                    Console.WriteLine(cert.PrivateKey);
                    Console.WriteLine(cert.PublicCertificate);
                    Console.WriteLine();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("[X] Error triaging {0} : {1}", fileName, e.Message);
            }

            Console.WriteLine();
        }
Пример #8
0
        public static void TriageVaultFolder(string folder, Dictionary <string, string> MasterKeys)
        {
            // takes a Vault folder, extracts the AES 128/256 keys from Policy.vpol, and uses these
            //  to decrypt any .vcrd vault credentials

            string policyFilePath = String.Format("{0}\\Policy.vpol", folder);

            if (File.Exists(policyFilePath))
            {
                Console.WriteLine("\r\n[*] Triaging Vault folder: {0}", folder);

                byte[] policyBytes = File.ReadAllBytes(policyFilePath);

                // first try to get vault keys from the Policy.vpol
                ArrayList keys = Dpapi.DescribePolicy(policyBytes, MasterKeys);

                if (keys.Count > 0)
                {
                    // make sure we have keys returned

                    string[] vaultCredFiles = Directory.GetFiles(folder);
                    if ((vaultCredFiles != null) && (vaultCredFiles.Length != 0))
                    {
                        foreach (string vaultCredFile in vaultCredFiles)
                        {
                            string fileName = System.IO.Path.GetFileName(vaultCredFile);
                            if (fileName.EndsWith("vcrd"))
                            {
                                byte[] vaultCredBytes = File.ReadAllBytes(vaultCredFile);

                                try
                                {
                                    // describe the vault credential file using the Policy credentials
                                    Dpapi.DescribeVaultCred(vaultCredBytes, keys);
                                }
                                catch (Exception e)
                                {
                                    Console.WriteLine("[X] Error triaging {0} : {1}", vaultCredFile, e.Message);
                                }
                            }
                        }
                    }
                }
            }
        }
Пример #9
0
        public static void TriageCredFile(string credFilePath, Dictionary <string, string> MasterKeys)
        {
            var fileName = Path.GetFileName(credFilePath);

            Console.WriteLine("  CredFile           : {0}\r\n", fileName);
            var credentialArray = File.ReadAllBytes(credFilePath);

            // describe and possibly parse the credential blob
            try
            {
                Dpapi.DescribeCredential(credentialArray, MasterKeys);
            }
            catch (Exception e)
            {
                Console.WriteLine("[X] Error triaging {0} : {1}", credFilePath, e.Message);
            }
            Console.WriteLine();
        }
Пример #10
0
        private static Dictionary <string, string> DecryptSystemMasterKeys(StringBuilder sb, List <byte[]> Dpapikeys, List <byte[]> machineMasterKeys = null, List <byte[]> userMasterKeys = null)
        {
            var mappings = new Dictionary <string, string>();

            if (machineMasterKeys != null)
            {
                foreach (byte[] masteyKeyBytes in machineMasterKeys)
                {
                    try
                    {
                        // use the "machine" DPAPI key
                        var plaintextMasterkey = Dpapi.DecryptMasterKeyWithSha(masteyKeyBytes, Dpapikeys[0]);
                        mappings.Add(plaintextMasterkey.Key, plaintextMasterkey.Value);
                    }
                    catch (Exception e)
                    {
                        sb.AppendLine(String.Format("[-] Error triaging {0} ", e.Message));
                    }
                }
            }
            if (userMasterKeys != null)
            {
                foreach (byte[] masteyKeyBytes in userMasterKeys)
                {
                    try
                    {
                        // use the "user" DPAPI key
                        var plaintextMasterKey = Dpapi.DecryptMasterKeyWithSha(masteyKeyBytes, Dpapikeys[1]);
                        mappings.Add(plaintextMasterKey.Key, plaintextMasterKey.Value);
                    }
                    catch (Exception e)
                    {
                        sb.AppendLine(String.Format("[-] Error triaging {0} ", e.Message));
                    }
                }
            }
            return(mappings);
        }
Пример #11
0
        public static void TriageKeePassKeyFile(Dictionary <string, string> MasterKeys, string keyFilePath = "", bool unprotect = false)
        {
            if (!File.Exists(keyFilePath))
            {
                return;
            }

            var lastAccessed = File.GetLastAccessTime(keyFilePath);
            var lastModified = File.GetLastWriteTime(keyFilePath);

            Console.WriteLine("    File             : {0}", keyFilePath);
            Console.WriteLine("    Accessed         : {0}", lastAccessed);
            Console.WriteLine("    Modified         : {0}", lastModified);

            byte[] keyFileBytes = File.ReadAllBytes(keyFilePath);

            // entropy from KeePass source https://fossies.org/windows/misc/KeePass-2.47-Source.zip/KeePassLib/Keys/KcpUserAccount.cs (lines 44-47)
            byte[] keyBytes = Dpapi.DescribeDPAPIBlob(keyFileBytes, MasterKeys, "keepass", unprotect, Helpers.ConvertHexStringToByteArray("DE135B5F18A34670B2572429698898E6"));
            if (keyBytes.Length > 0)
            {
                Console.WriteLine("    Key Bytes        : {0}", BitConverter.ToString(keyBytes).Replace("-", " "));
            }
        }
Пример #12
0
        public static Dictionary <string, string> TriageUserMasterKeys(byte[] backupKeyBytes, bool show = false, string computerName = "")
        {
            // triage all *user* masterkeys we can find, decrypting if the backupkey is supplied

            Dictionary <string, string> mappings = new Dictionary <string, string>();

            if (!String.IsNullOrEmpty(computerName))
            {
                bool canAccess = Helpers.TestRemote(computerName);
                if (!canAccess)
                {
                    return(new Dictionary <string, string>());
                }
            }

            if (Helpers.IsHighIntegrity() || (!String.IsNullOrEmpty(computerName) && Helpers.TestRemote(computerName)))
            {
                // 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"));
                }

                string[] userDirs = Directory.GetDirectories(userFolder);

                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);

                                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.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);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                // if not elevated, triage only the current user's masterkeys

                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);

                        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.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);
                                }
                            }
                        }
                    }
                }
            }

            return(mappings);
        }
Пример #13
0
        public static Dictionary <string, string> TriageSystemMasterKeys(bool show = false)
        {
            // retrieve the DPAPI_SYSTEM key and use it to decrypt any SYSTEM DPAPI masterkeys

            Dictionary <string, string> mappings = new Dictionary <string, string>();

            if (Helpers.IsHighIntegrity())
            {
                // get the system and user DPAPI backup keys, showing the machine DPAPI keys
                //  { machine , user }

                List <byte[]> keys = LSADump.GetDPAPIKeys(true);

                string systemFolder = String.Format("{0}\\Windows\\System32\\Microsoft\\Protect\\", Environment.GetEnvironmentVariable("SystemDrive"));

                string[] systemDirs = Directory.GetDirectories(systemFolder);

                foreach (string directory in systemDirs)
                {
                    string[] machineFiles = Directory.GetFiles(directory);
                    string[] userFiles    = new string[0];

                    if (Directory.Exists(String.Format("{0}\\User\\", directory)))
                    {
                        userFiles = Directory.GetFiles(String.Format("{0}\\User\\", directory));
                    }

                    foreach (string file in machineFiles)
                    {
                        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 SYSTEM system MasterKey : {0}", file);
                            }

                            byte[] masteyKeyBytes = File.ReadAllBytes(file);
                            try
                            {
                                // use the "machine" DPAPI key
                                Dictionary <string, string> mapping = Dpapi.DecryptMasterKeyWithSha(masteyKeyBytes, keys[0]);
                                mapping.ToList().ForEach(x => mappings.Add(x.Key, x.Value));
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine("[X] Error triaging {0} : {1}", file, e.Message);
                            }
                        }
                    }

                    foreach (string file in userFiles)
                    {
                        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 SYSTEM user MasterKey : {0}", file);
                            }

                            byte[] masteyKeyBytes = File.ReadAllBytes(file);
                            try
                            {
                                // use the "user" DPAPI key
                                Dictionary <string, string> mapping = Dpapi.DecryptMasterKeyWithSha(masteyKeyBytes, keys[1]);
                                mapping.ToList().ForEach(x => mappings.Add(x.Key, x.Value));
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine("[X] Error triaging {0} : {1}", file, e.Message);
                            }
                        }
                    }
                }
            }
            else
            {
                Console.WriteLine("\r\n[X] Must be elevated to triage SYSTEM masterkeys!\r\n");
            }

            return(mappings);
        }
Пример #14
0
        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);
        }
Пример #15
0
        public static void TriageUserCerts(Dictionary <string, string> MasterKeys, string computerName = "")
        {
            string[] userDirs;
            if (!String.IsNullOrEmpty(computerName))
            {
                // if we're triaging a remote computer, check connectivity first
                var canAccess = Helpers.TestRemote(computerName);
                if (!canAccess)
                {
                    return;
                }
            }

            //TODO have not verified with multiple users
            if (Helpers.IsHighIntegrity() || (!String.IsNullOrEmpty(computerName) && Helpers.TestRemote(computerName)))
            {
                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)
            {
                var parts    = dir.Split('\\');
                var userName = parts[parts.Length - 1];
                if (dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users"))
                {
                    continue;
                }

                var userCertkeysBasePath = $"{dir}\\AppData\\Roaming\\Microsoft\\Crypto\\RSA\\";

                if (!Directory.Exists(userCertkeysBasePath))
                {
                    continue;
                }

                var certDictionary = new Dictionary <string, Tuple <string, string> >();
                var directories    = Directory.GetDirectories(userCertkeysBasePath);

                foreach (var directory in directories)
                {
                    var files = Directory.GetFiles(directory);

                    foreach (var file in files)
                    {
                        if (!Regex.IsMatch(file, @"[0-9A-Fa-f]{32}[_][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;
                        }

                        var fileName = Path.GetFileName(file);
                        Console.WriteLine("\r\nCertificate file           : {0}\r\n", fileName);
                        var certificateArray = File.ReadAllBytes(file);
                        try
                        {
                            certDictionary.Add(fileName, Dpapi.DescribeCertificate(certificateArray, MasterKeys));
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("[X] Error triaging {0} : {1}", fileName, e.Message);
                        }
                    }
                }
                Console.WriteLine();

                foreach (var key in certDictionary.Keys)
                {
                    if (string.IsNullOrEmpty(certDictionary[key].First))
                    {
                        continue;
                    }

                    Console.WriteLine("[*] Private key file {0} was recovered\r\n", key);
                    Console.WriteLine("[*] PKCS1 Private key\r\n");
                    Console.WriteLine(certDictionary[key].First);
                    Console.WriteLine("\r\n[*] Certificate\r\n");
                    Console.WriteLine(certDictionary[key].Second);
                    Console.WriteLine();
                }
                Console.WriteLine("[*] Hint: openssl pkcs12 -export -inkey key.pem -in cert.cer -out cert.p12");
            }
        }
Пример #16
0
        public static Dictionary <string, string> TriageMasterKeys(byte[] backupKeyBytes, bool show = false)
        {
            Dictionary <string, string> mappings = new Dictionary <string, string>();

            if (Helpers.IsHighIntegrity())
            {
                string   userFolder = String.Format("{0}\\Users\\", Environment.GetEnvironmentVariable("SystemDrive"));
                string[] dirs       = Directory.GetDirectories(userFolder);
                foreach (string dir in dirs)
                {
                    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);

                                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.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);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                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);

                        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.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);
                                }
                            }
                        }
                    }
                }
            }

            return(mappings);
        }
Пример #17
0
        public static Dictionary <string, string> TriageSystemMasterKeys(bool show = false)
        {
            // retrieve the DPAPI_SYSTEM key and use it to decrypt any SYSTEM DPAPI masterkeys

            var mappings = new Dictionary <string, string>();

            if (Helpers.IsHighIntegrity())
            {
                // get the system and user DPAPI backup keys, showing the machine DPAPI keys
                //  { machine , user }

                var keys = LSADump.GetDPAPIKeys(true);
                Helpers.GetSystem();
                var systemFolder =
                    $"{Environment.GetEnvironmentVariable("SystemDrive")}\\Windows\\System32\\Microsoft\\Protect\\";

                var systemDirs = Directory.GetDirectories(systemFolder);

                foreach (var directory in systemDirs)
                {
                    var machineFiles = Directory.GetFiles(directory);
                    var userFiles    = new string[0];

                    if (Directory.Exists($"{directory}\\User\\"))
                    {
                        userFiles = Directory.GetFiles($"{directory}\\User\\");
                    }

                    foreach (var file in machineFiles)
                    {
                        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;
                        }

                        var fileName = Path.GetFileName(file);
                        if (show)
                        {
                            Console.WriteLine("[*] Found SYSTEM system MasterKey : {0}", file);
                        }

                        var masteyKeyBytes = File.ReadAllBytes(file);
                        try
                        {
                            // use the "machine" DPAPI key
                            var plaintextMasterkey = Dpapi.DecryptMasterKeyWithSha(masteyKeyBytes, keys[0]);
                            mappings.Add(plaintextMasterkey.Key, plaintextMasterkey.Value);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("[X] Error triaging {0} : {1}", file, e.Message);
                        }
                    }

                    foreach (var file in userFiles)
                    {
                        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;
                        }

                        var fileName = Path.GetFileName(file);
                        if (show)
                        {
                            Console.WriteLine("[*] Found SYSTEM user MasterKey : {0}", file);
                        }

                        var masteyKeyBytes = File.ReadAllBytes(file);
                        try
                        {
                            // use the "user" DPAPI key
                            var plaintextMasterKey = Dpapi.DecryptMasterKeyWithSha(masteyKeyBytes, keys[1]);
                            mappings.Add(plaintextMasterKey.Key, plaintextMasterKey.Value);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("[X] Error triaging {0} : {1}", file, e.Message);
                        }
                    }
                }
            }
            else
            {
                Console.WriteLine("\r\n[X] Must be elevated to triage SYSTEM masterkeys!\r\n");
            }

            return(mappings);
        }
Пример #18
0
        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);
        }