How to Extract All Stored Chrome Passwords with Python?

Posted in /  

How to Extract All Stored Chrome Passwords with Python?
vinaykhatri

Vinay Khatri
Last updated on April 24, 2024

    This Python tutorial explains how to extract all stored Chrome passwords with Python. Chrome is a very powerful web browser. It provides a default password manager to generate and store passwords. The password manager store all the passwords in the cloud as well as in the user's local system in an SQLite database.

    We can use the sqlite3 database and Chrome decrypt libraries to extract and decrypt the stored passwords. Manually decrypting all the Chrome passwords can be a tedious task, but luckily with Python and a few lines of code, we can extract all the saved passwords from Chrome as well as all the other popular web browsers.

    For this Python tutorial, we will be writing a Python script that can extract all the passwords stored in your Chrome browser.

    This Python tutorial is for those users who are using Chrome on the Windows operating system. If you are a macOS or Linux user, then you might have to make some changes in the specified path, but the rest of the Python program will stay the same.

    How to Extract All Stored Chrome Password with Python?

    To make this tutorial more legible, we have followed the modular approach in which we have divided the entire Python code into multiple functions.

    Before diving into the main code, we need to first install the dependencies or libraries we require for building the Python program that can extract all stored passwords in Chrome.

    Install libraries

    We need to install pycryptodome and pywin32 libraries to make the code work. Following are the pip commands to install them:

    pip install pycryptodome
    pip install pypiwin32

    Now open your favorite Python IDE or text editor and start coding. We will start with importing all the necessary modules at the top of our Python script.

    #python standard modules
    import os
    import json
    import base64
    import sqlite3
    import shutil
    from datetime import timezone, datetime, timedelta
    
    #3rd party modules
    import win32crypt
    from Crypto.Cipher import AES

    As we have already mentioned, we will be wrapping our code around the functions. So, let's define our first function, my_chrome_datetime() , which will convert Chrome time to a human-readable format.

    #function 1 my_chrome_datetime(time_in_mseconds)

    def my_chrome_datetime(time_in_mseconds):
        return datetime(1601, 1, 1) + timedelta(microseconds=time_in_mseconds)

    The my_chrome_datetime(time_in_mseconds) function accepts the time in microseconds because Chrome stores the time in timestamps format as base 1 Jan 1601 . Next, let's define the encryption_key() function. It will extract and decode the Chrome ASE key that was used to encrypt the passwords. The ASE key is located in the " Local State " file in the C:\Users\USER_Name\AppData\Local\Google\Chrome\User Data directory.

    #function 2 encryption_key()

    def encryption_key():
    
        #C:\Users\USER_Name\AppData\Local\Google\Chrome\Local State
        localState_path = os.path.join(os.environ["USERPROFILE"],
                                        "AppData", "Local", "Google", "Chrome",
                                        "User Data", "Local State")
    
        #read local state file
        with open(localState_path, "r", encoding="utf-8") as file:
            local_state_file = file.read()
            local_state_file = json.loads(local_state_file)
    
        # decode the key and remove first 5 DPAPI str characters
        ASE_key = base64.b64decode(local_state_file["os_crypt"]["encrypted_key"])[5:]
    
        return win32crypt.CryptUnprotectData(ASE_key, None, None, None, 0)[1]  # decryted key

    Now we have the function for the encrypted key. Next, let's define a function decrypt_password(enc_password, key) that will take the encrypted password and encrypted key as arguments and decode or decrypt the password in a human-readable format.

    # function 3 decrypt_password(enc_password, key)

    def decrypt_password(enc_password, key):
        try:
    
            init_vector = enc_password[3:15]
            enc_password = enc_password[15:]
    
            # initialize cipher object
            cipher = AES.new(key, AES.MODE_GCM, init_vector)
            # decrypt password
            return cipher.decrypt(enc_password)[:-16].decode()
        except:
            try:
                return str(win32crypt.CryptUnprotectData(password, None, None, None, 0)[1])
            except:
                return "No Passwords(logged in with Social Account)"

    Now let's create the main() function that will open the Passwords database to read the encrypted passwords, call the encryption_key() function to get the encryption key, and pass the password and encryption key to the decrypt_password() function to decode the password.

    #function 4 main()
    def main():
    
        # local passwords path
        password_db_path = os.path.join(os.environ["USERPROFILE"], "AppData", "Local",
                                "Google", "Chrome", "User Data", "Default", "Login Data")
    
        #copy the login data file to current directory as "my_chrome_data.db
        shutil.copyfile(password_db_path,"my_chrome_data.db")
    
        # connect to the database
        db = sqlite3.connect("my_chrome_data.db")
        cursor = db.cursor()
    
        # run the query
        cursor.execute("SELECT origin_url, username_value, password_value, date_created FROM logins")
    
        #get the encryption key
        encp_key = encryption_key()
    
        # iterate over all rows
        for row in cursor.fetchall():
            site_url = row[0]
            username = row[1]
            password = decrypt_password(row[2], encp_key)
            date_created = row[3]
    
            if username or password:
                print("Site Login URL:", site_url)
                print("Username/Email:", username)
                print(f"Password:",password)
            else:
                continue
            if date_created:
                print("Date date_created:", str(my_chrome_datetime(date_created)))
            print("\n|","-"*50, "|\n")
    
        cursor.close()
        db.close()
    
        #remove the copied database after reading passwords
        os.remove("my_chrome_data.db")

    After defining the main() function, let's call it with the if __name__=="__main__" statement. Although we can also call the main function directly, using the aforementioned statement is a better option. #call the main() function

    if __name__ == "__main__":
        main()

    How to Extract All Stored Chrome Password with Python? [The Code]

    Finally, put all the code together and execute it.

    #Python program to extract all the stored Chrome passwords
    #python standard modules
    import os
    import json
    import base64
    import sqlite3
    import shutil
    from datetime import timezone, datetime, timedelta
    
    #3rd party modules
    import win32crypt
    from Crypto.Cipher import AES
    
    def my_chrome_datetime(time_in_mseconds):
        """Return a `datetime.datetime` object from a chrome format datetime
        Since `chromedate` is formatted as the number of microseconds since January, 1601"""
        return datetime(1601, 1, 1) + timedelta(microseconds=time_in_mseconds)
    
    def encryption_key():
    
        #C:\Users\USER_Name\AppData\Local\Google\Chrome\Local State
        localState_path = os.path.join(os.environ["USERPROFILE"],
                                        "AppData", "Local", "Google", "Chrome",
                                        "User Data", "Local State")
        #read local state file
        with open(localState_path, "r", encoding="utf-8") as file:
            local_state_file = file.read()
            local_state_file = json.loads(local_state_file)
    
        # decode the key and remove first 5 DPAPI str characters
        ASE_key = base64.b64decode(local_state_file["os_crypt"]["encrypted_key"])[5:]
    
        return win32crypt.CryptUnprotectData(ASE_key, None, None, None, 0)[1]  # decryted key
    
    def decrypt_password(enc_password, key):
        try:
    
            init_vector = enc_password[3:15]
            enc_password = enc_password[15:]
    
            # initialize cipher object
            cipher = AES.new(key, AES.MODE_GCM, init_vector)
            # decrypt password
            return cipher.decrypt(enc_password)[:-16].decode()
        except:
            try:
                return str(win32crypt.CryptUnprotectData(password, None, None, None, 0)[1])
            except:
                return "No Passwords(logged in with Social Account)"
    
    def main():
    
        # local passwords path
        password_db_path = os.path.join(os.environ["USERPROFILE"], "AppData", "Local",
                                "Google", "Chrome", "User Data", "Default", "Login Data")
    
        #copy the login data file to current directory as "my_chrome_data.db
        shutil.copyfile(password_db_path,"my_chrome_data.db")
    
        # connect to the database
        db = sqlite3.connect("my_chrome_data.db")
        cursor = db.cursor()
    
        # run the query
        cursor.execute("SELECT origin_url, username_value, password_value, date_created FROM logins")
    
        #get the encryption key
        encp_key = encryption_key()
        print("\n|","-"*50, "|\n")
        # iterate over all rows
        for row in cursor.fetchall():
            site_url = row[0]
            username = row[1]
            password = decrypt_password(row[2], encp_key)
            date_created = row[3]
    
            if username or password:
                print("Site Login URL:", site_url)
                print("Username/Email:", username)
                print(f"Password:",password)
            else:
                continue
            if date_created:
                print("Date date_created:", str(my_chrome_datetime(date_created)))
            print("\n|","-"*50, "|\n")
    
        cursor.close()
        db.close()
    
        #remove the copied database after reading passwords
        os.remove("my_chrome_data.db")
    
    if __name__ == "__main__":
        main()

    Output We cannot show the output because of obvious security concerns, and we also recommend you not to share your passwords and credential script output with others.

    How to Delete all the stored Chrome Passwords?

    Now that you know how to access the Chrome " Login Data" file that stores all the login details, including passwords, you can also perform the SQL delete query on the database with Python SQLite and delete all the stored passwords.

    The below Python command will delete all the stored passwords, so please execute the code with caution.

    #import standared libraies
    import sqlite3
    import os
    
    my_chrome_db_path = os.path.join(os.environ["USERPROFILE"], "AppData", "Local",
    "Google", "Chrome", "User Data", "Default", "Login Data")
    
    #connect to database
    db = sqlite3.connect(my_chrome_db_path)
    cursor = db.cursor()
    
    # query for data
    cursor.execute("SELECT origin_url, username_value, password_value FROM logins")
    
    total_passwords = len(cursor.fetchall())
    print("Total Passwords to delete:", total_passwords)
    
    #execute delete query
    cursor.execute("DELETE FROM logins")
    cursor.connection.commit()
    print("All passwords have been deleted")

    Conclusion

    In this Python tutorial, you learned how to extract all stored Chrome password with Python. You also learned how to delete them. The above program for deleting the passwords will delete not only the passwords but also other data within the login table.

    Thus, we recommend you execute the delete command with caution.

    People are also reading:

    Leave a Comment on this Post

    0 Comments