第一步
需要备份两个文件
1、账号密码信息被加密之后的文件
C:\Users\你的用户名\AppData\Local\Google\Chrome\User Data\Default\Login Data
2、解开加密文件的密钥
C:\Users\你的用户名\AppData\Local\Google\Chrome\User Data\Local State
第二步
下载我提供的代码,并把代码开头处的两个变量
login_data_path 、 local_state_path
修改到第一步中你备份的路径
夸克网盘
链接:https://pan.quark.cn/s/bfce67ff4e69
多说两句
Chrome 遵循的是Chromium的开源架构,Chromium的开源代码中,明确写出了自己的解密过程,如下:
在 os_crypt_win.cc 代码中的 bool OSCryptImpl::DecryptString 方法
所以我做的并不是破解,而仅仅是翻译
代码源码
import os
import sqlite3
import json
import base64
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
import ctypes
from ctypes import wintypes
login_data_path = "C:\Mine\Project\chromed\Login Data"
local_state_path = "C:\Mine\Project\chromed\Local State"
class AES_GCM:
@staticmethod
def encrypt(cipher, plaintext, nonce):
cipher.mode = modes.GCM(nonce)
encryptor = cipher.encryptor()
ciphertext = encryptor.update(plaintext)
return cipher, ciphertext, nonce
@staticmethod
def decrypt(cipher, ciphertext, nonce):
cipher.mode = modes.GCM(nonce)
decryptor = cipher.decryptor()
return decryptor.update(ciphertext)
@staticmethod
def get_cipher(key):
cipher = Cipher(algorithms.AES(key), None, backend=default_backend())
return cipher
def dpapi_decrypt(encrypted):
class DATA_BLOB(ctypes.Structure):
_fields_ = [('cbData', wintypes.DWORD),
('pbData', ctypes.POINTER(ctypes.c_char))]
try:
p = ctypes.create_string_buffer(encrypted, len(encrypted))
blobin = DATA_BLOB(ctypes.sizeof(p), p)
blobout = DATA_BLOB()
retval = ctypes.windll.crypt32.CryptUnprotectData(
ctypes.byref(blobin), None, None, None, None, 0, ctypes.byref(blobout))
if not retval:
raise ctypes.WinError()
result = ctypes.string_at(blobout.pbData, blobout.cbData)
return result
except Exception as e:
print(f"Error in dpapi_decrypt: {e}")
return None
def get_key_from_local_state():
with open(local_state_path, encoding='utf-8', mode="r") as f:
jsn = json.loads(str(f.readline()))
return jsn["os_crypt"]["encrypted_key"]
def aes_decrypt(encrypted_txt):
encoded_key = get_key_from_local_state()
encrypted_key = base64.b64decode(encoded_key.encode())
encrypted_key = encrypted_key[5:]
key = dpapi_decrypt(encrypted_key)
nonce = encrypted_txt[3:15]
cipher = AES_GCM.get_cipher(key)
return AES_GCM.decrypt(cipher, encrypted_txt[15:], nonce)
def chrome_decrypt(encrypted_txt):
if encrypted_txt[:4] == b'x01x00x00x00':
decrypted_txt = dpapi_decrypt(encrypted_txt)
return decrypted_txt.decode()
elif encrypted_txt[:3] == b'v10':
decrypted_txt = aes_decrypt(encrypted_txt)
return decrypted_txt[:-16].decode()
def query_logindata(url):
if url:
sql = f"select origin_url, username_value, password_value from logins where origin_url = '{url}'"
else:
sql = "select origin_url, username_value, password_value from logins"
with sqlite3.connect(login_data_path) as conn:
result = conn.execute(sql).fetchall()
return result
if __name__ == '__main__':
print("Decrypt Login Data:")
logindata = query_logindata("") # 可以传入参数筛选指定url
for data in logindata:
login = data[0], data[1], chrome_decrypt(data[2])
print(login)