1

I've written this code:

import sqlite3
import win32crypt

c = sqlite3.connect("Login Data")

cursor = c.cursor()

cursor.execute("SELECT origin_url, username_value, password_value FROM logins")

data = cursor.fetchall()

credentials = {}

for url, user, pwd in data:
    password = win32crypt.CryptUnprotectData(pwd, None, None, None, 0)[1]
    credential[url] = (user, password)

for item in credentials:
    login = credentials[item]
    print(login[0] + " " + login[1])

and it states that: password = win32crypt.CryptUnprotectData(pwd, None, None, None, 0)[1] pywintypes.error: (87, 'CryptProtectData', 'The parameter is incorrect.')

As I've searched it, Chrome v80 has changed encryption type. What should I do?

Florin Cristi
  • 41
  • 1
  • 1
  • 7

2 Answers2

5
import os
import json
import base64
import sqlite3
import win32crypt
from Crypto.Cipher import AES
import shutil


def get_master_key():
    with open(os.environ['USERPROFILE'] + os.sep + r'AppData\Local\Google\Chrome\User Data\Local State', "r", encoding='utf-8') 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]
    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 as e:
        # print("Probably saved password from Chrome version older than v80\n")
        # print(str(e))
        return "Chrome < 80"



if __name__ == '__main__':

    master_key = get_master_key()
    login_db = os.environ['USERPROFILE'] + os.sep + r'AppData\Local\Google\Chrome\User Data\default\Login Data'
    shutil.copy2(login_db, "Loginvault.db") #making a temp copy since Login Data DB is locked while Chrome is running
    conn = sqlite3.connect("Loginvault.db")
    cursor = conn.cursor()

    try:
        cursor.execute("SELECT action_url, username_value, password_value FROM logins")
        for r in cursor.fetchall():
            url = r[0]
            username = r[1]
            encrypted_password = r[2]
            decrypted_password = decrypt_password(encrypted_password, master_key)
            print("URL: " + url + "\nUser Name: " + username + "\nPassword: " + decrypted_password + "\n" + "*" * 50 + "\n")
    except Exception as e:
        pass

    cursor.close()
    conn.close()
    try:
        os.remove("Loginvault.db")
    except Exception as e:
        pass
LimerBoy
  • 66
  • 2
  • 2
    Your answer will be more useful if you can explain what you've done/ doing.. – Ahmad A.A Apr 21 '20 at 01:34
  • I'm getting the error `module 'Crypto.Cipher.AES' has no attribute 'MODE_GCM'`. Am I missing any library? – Gaurav S Jul 09 '20 at 07:23
  • 1
    pip install pycryptodome – LimerBoy Jan 06 '21 at 18:24
  • Works like a charm, can confirm being more effective than LaZange, and yes chrome version is greater the 80.1 :) `pip install pycryptodome` might solve your problem @GauravS – Muneeb Ahmad Khurram Feb 19 '21 at 07:58
  • @LimerBoy: One bug with this code is that you get `"Chrome < 80"` for empty saved passwords. Any idea how to detect empty passwords properly? – BullyWiiPlaza Jun 18 '21 at 14:48
  • If you see the error: module 'Crypto.Cipher.AES' has no attribute 'MODE_GCM' you can install pycryptodome but make sure to update the imports in the Python file: "from Crypto.Cipher import AES" to "from Cryptodome.Cipher import AES" – ezzadeen Mar 03 '23 at 13:43
0

I'm getting the error module 'Crypto.Cipher.AES' has no attribute 'MODE_GCM'. Am I missing any library? – Gaurav S Jul 9 at 7:23

No you have everything. The crypto\Cipher\__init__.py file imports from Crypto.Cipher._mode_ecb import _create_ecb_cipher. However the directory's real name is crypto and not Crypto. You need to rename the directory to Crypto and then it works perfectly.

Wrench56
  • 290
  • 2
  • 14