Cookies:无法在 python 中使用 AES 解密提取 chrome/edge v20 cookie

问题描述 投票:0回答:1

问题:读取 chrome/edge cookie 以提取从桌面应用程序启动的浏览器中用户的 XSRF-Token 和 .AspNet.Cookies 值并将其保存在注册表项中

我使用了下面的代码,过去两个月工作正常,突然有一天,秘密密钥能够像平常一样提取,但初始化向量和加密密码似乎与之前不同,两个密钥似乎都正在提取,但面临问题:

'utf-8' codec can't decode byte 0xf0 in position 0: invalid continuation byte

由于取值不正确,请参考代码后的值。

import os
import win32crypt
from Crypto.Cipher import AES
import base64
import sqlite3
import json
import winreg as reg

#Extracting the secret key
def get_aes_key():
local_state_path = 'C:/Users/<username>/AppData/Local/Google/Chrome/User Data/Local state' # Update with your path
with open(local_state_path, 'r', encoding='utf-8') as f:
    local_state_data = json.load(f)
    encrypted_key = local_state_data['os_crypt']['encrypted_key']
    print(encrypted_key)
    encrypted_key_base64_dpapi = base64.b64decode(encrypted_key)
    print(encrypted_key_base64_dpapi)
    encrypted_key_base64 = encrypted_key_base64_dpapi[5:]  # Strip 'DPAPI' prefix
    encrypted_key_base64 = win32crypt.CryptUnprotectData(encrypted_key_base64, None, None, None, 0)[1]
    aes_key = encrypted_key_base64  # Strip DPAPI prefix
    return aes_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)

# Function to decrypt cookie value using AES
def decrypt_aes(dec_aes_key, encrypted_data):
try:
    # (3-a) Initialisation vector for AES decryption
    initialisation_vector = encrypted_data[3:15]
    # (3-b) Get encrypted password by removing suffix bytes (last 16 bits)
    # Encrypted password is 192 bits
    encrypted_password = encrypted_data[15:-16]
    # (4) Build the cipher to decrypt the ciphertext
    cipher = generate_cipher(dec_aes_key, initialisation_vector)
    decrypted_pass = decrypt_payload(cipher, encrypted_password)
    decrypted_pass = decrypted_pass.decode()
    return decrypted_pass
except Exception as e:
    print("%s" % str(e))
    print("[ERR] Unable to decrypt, Chrome version <80 not supported. Please check.")
    return ""

# Path to Chrome's Cookies database
logged_in_user = os.getlogin()
cookies_db = 'C:/Users/' + logged_in_user + '/AppData/Local/Google/Chrome/User 
Data/Default/Network/Cookies'

# Connect to the Cookies database
conn = sqlite3.connect(cookies_db)
cursor = conn.cursor()

aes_key = get_aes_key()
print(aes_key)

# Example query to fetch cookies
cursor.execute('SELECT host_key, name, encrypted_value FROM cookies')


def set_environment_variable(name, value):
try:
    # Open the registry key for environment variables
    with reg.OpenKey(reg.HKEY_LOCAL_MACHINE, r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 0, reg.KEY_SET_VALUE) as key:
        # Set the environment variable
        reg.SetValueEx(key, name, 0, reg.REG_SZ, value)
    print(f'Successfully set {name} to {value}')
except PermissionError:
    print("Permission denied. You need to run this script with administrative privileges.")
except Exception as e:
    print(f'Failed to set environment variable: {e}')


for row in cursor.fetchall():
host_key, name, encrypted_value = row
if host_key == "adregression02":
    #print(f'Name: {name}, encrypted value: {encrypted_value}')
    decrypted_value = decrypt_aes(aes_key, encrypted_value)
    #print(f'Name: {name}, Decrypted Value: {decrypted_value.decode("utf-8")}')
    print("Name: %s\ncookie: %s\n" % (name, decrypted_value))
    set_environment_variable(name, decrypted_value)

conn.close()

我认为问题在于以下几行:

def decrypt_aes(dec_aes_key, encrypted_data):
try:
    # (3-a) Initialisation vector for AES decryption
    initialisation_vector = encrypted_data[3:15]
    # Encrypted password is 192 bits
    encrypted_password = encrypted_data[15:-16]
    # (4) Build the cipher to decrypt the ciphertext
    cipher = generate_cipher(dec_aes_key, initialisation_vector)
    decrypted_pass = decrypt_payload(cipher, encrypted_password)
    decrypted_pass = decrypted_pass.decode()
    return decrypted_pass

以下是提取的值:

名称:XSRF-TOKEN,加密值

b"v20>QT\xc3.A^E\x85\xc6c+\xac\x0eT\xa3z\xe4\x94\xaa!\x83\x99?\x1e\x04\xdd\x1ad\xbc\x15\r\xf7\x18\x86-\x0bVi\xae\xe8\x0b\x12\x16\xf9+\xb5\xcb\xf8I\x8d\xa9\x1ez\x13\x1fwt\xa5\xb2\x8e\x1dW\xfd\xa1\x99;\xe1\xdc\x8cw[\x05\xd72z\xbfHNm\x05\xcb\x02\xc1\xf5\r\xdd\x9d\xfe\x80\r\x9a:\x81\xcc\x88\xd7-uj\xfe\x9c\xe1\x19\xeb\xbb?@ \x17\xa2\xd1\x87\xc6\xba\x8b\r'\xf1n\r\x1e\x0bK\xad-\xa3r\x1c4d\x93\x14\x9ae\xbca\xfc\xce%\xedc\xf6\x0b/R\xe1\xa1\xe8\xb9\x02
_Y\x01\xcd\xe4\xd1\x90@"`

**initialisation_vector--** b'>QT\xc3.A^E\x85\xc6c+'

**encrypted_password--** b"\xac\x0eT\xa3z\xe4\x94\xaa!\x83\x99?\x1e\x04\xdd\x1ad\xbc\x15\r\xf7\x18\x86-\x0bVi\xae\xe8\x0b\x12\x16\xf9+\xb5\xcb\xf8I\x8d\xa9\x1ez\x13\x1fwt\xa5\xb2\x8e\x1dW\xfd\xa1\x99;\xe1\xdc\x8cw[\x05\xd72z\xbfHNm\x05\xcb\x02\xc1\xf5\r\xdd\x9d\xfe\x80\r\x9a:\x81\xcc\x88\xd7-uj\xfe\x9c\xe1\x19\xeb\xbb?@ \x17\xa2\xd1\x87\xc6\xba\x8b\r'\xf1n\r\x1e\x0bK\xad-\xa3r\x1c4d\x93\x14\x9ae\xbca\xfc\xce%\xedc\xf6\x0b/R\xe1\xa1\xe8\xb9\x02
_Y\x01\xcd\xe4\xd1\x90@"`

预期的 xsrf 令牌:

v3eMK3iMPhdF8tumLxbjEHmSVqwT__4MFAhhFZH6-lP4ffXhfPvACW8oQYuxpQ8OZnI0y8-sVjwc4TobVGDjNTXFlrFI287t5B_SNah9yQSHVkppuRsT510cJXGT05IU9rlJibfMnu-iU4CRk--XyrZ7iOJSugxlKFukH8hDyJ--Gv_F6AUqIo6bFJ1i-10cu7bkZ4hLEvfhdk2q08tKyTn7e6oDfQ6nLicSoKIWjuPvEutpZIZQyK4li32GPirk_ysUKolUbLrl2AjwPVFrCZbgil8yHKyNrmAveY1b0lNNzsDljzsfF_TMLZazpYbbIvEarQuPe6wkL8sQuT-L9YpitNpeW8Wvfgyj96EWCbQ

有人可以指出缺少什么吗?或者edge/chrome更新了他们的加密?

目前加密更新似乎是从V20开始的,其中cookie加密标准自chrome版本127以来已从V10更新到V20。

我提到了链接:https://ohyicong.medium.com/how-to-hack-chrome-password-with-python-1bedc167be3d

python google-chrome aes microsoft-edge aes-gcm
1个回答
0
投票

TL;DR:runassu这个 Github 存储库 中,您可以找到有关如何解密 Chrome v20 cookie 的说明,包括 Python 脚本


铬:

与 v10 cookie 解密的主要区别在于用于解密 cookie 的 AES 密钥的确定。对于 v10 cookie,加密密钥(在

Local State
JSON 文件中称为 encrypted_key)只需使用 DPAPI 进行解密。对于 v20,需要对加密密钥(在
Local State
JSON 文件中称为 app_bound_encrypted_key)进行三阶段解密:首先,必须使用系统帐户执行 DPAPI 解密,然后使用用户帐户,最后是 AES-GCM 解密。
前两个解密步骤,即使用系统帐户解密,然后使用用户帐户解密,可以按如下方式实现(这本质上是上面脚本中的解决方案,需要依赖项 pywin32 和 pypsexec;pywin 允许访问 Win32 API,pypsexec 允许使用不同的帐户通过 PAExec/PSExec 执行命令(参见例如 here),根据此处的要求):

from pypsexec.client import Client
import os
import sys
import json
import base64

local_state_path = r'%LocalAppData%\Google\Chrome\User Data\Local State'
local_state_path = os.path.expandvars(local_state_path)
with open(local_state_path, "r") as f:
    local_state = json.load(f)

app_bound_encrypted_key_b64 = local_state["os_crypt"]["app_bound_encrypted_key"]
app_bound_encrypted_key = base64.b64decode(app_bound_encrypted_key_b64)[4:] # Base64 decode and remove APPB prefix

arguments = "-c \"" + """from win32 import win32crypt
import base64
encrypted_key = win32crypt.CryptUnprotectData(base64.b64decode('{}'), None, None, None, 0)
print(base64.b64encode(encrypted_key[1]).decode())
""".replace("\n", ";") + "\""

c = Client("localhost")
c.connect()
try:
    c.create_service()
    # DPAPI decryption with SYSTEM account
    decryption_sys_b64, stderr, rc = c.run_executable(
        sys.executable,
        arguments=arguments.format(base64.b64encode(app_bound_encrypted_key).decode().strip()),
        use_system_account=True
    )
    # DPAPI decryption with User account
    decryption_usr_b64, stderr, rc = c.run_executable(
        sys.executable,
        arguments=arguments.format(decryption_sys_b64.decode().strip()),
        use_system_account=False
    )
finally:
    c.remove_service()
    c.disconnect()

encrypted_content_key = base64.b64decode(decryption_usr_b64)[-60:] # Base64 decode; the last 60 bytes are the encrypted content key

encrypted_content_key
包含使用 AES-GCM 加密的内容密钥。它由解密数据的最后 60 个字节给出(前面的数据本质上包含了 Chrome 的安装路径)。在下一步中,必须使用 AES-GCM 解密该密钥。

encrypted_content_key
的格式为nonce|ciphertext|tag,其中nonce大小为12字节,密文大小为32字节,标签大小为16字节,即总共60字节。此加密所需的 AES 密钥是硬编码在elevation_service.exe中(下文称为
elevation_key
)。 PyCryptodome 的可能实现是:

from Crypto.Cipher import AES

def decrypt_aes_gcm(encrypted_data, key):
    nonce = encrypted_data[0:12]
    ciphertext = encrypted_data[12:-16]
    tag = encrypted_data[-16:]
    cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
    return cipher.decrypt_and_verify(ciphertext, tag)

elevation_key = base64.b64decode("sxxuJBrIRnKNqcH6xJNmUc/7lE0UOrgWJ2vMbaAoR4c=") # hard-coded key from elevation_service.exe
content_key = decrypt_aes_gcm(encrypted_content_key, elevation_key)

content_key
现在是内容密钥,可以使用 AES-GCM 对 cookie 进行解密。从这里开始,解密类似于 v10 cookie 的解密。 Cookie 数据从索引位置 32 开始(前 32 个字节是
host_key
字段的 SHA256 哈希值,请参阅此处):

encrypted_cookie = bytes.fromhex('763230...')
encrypted_cookie_prefix_removed = encrypted_cookie[3:]
cookie =  decrypt_aes_gcm(encrypted_cookie_prefix_removed, content_key)
cookie_content = cookie[32:] # decrypted cookie

边缘:

与 Chrome 相比,Edge 中加密密钥的解密只有两阶段,并且由双 DPAPI 解密组成。没有 AES-GCM 解密:

content_key = base64.b64decode(decryption_usr_b64)[-32:] # Base64 decode; the last 32 bytes are the content key

即双 DPAPI 解密数据的最后 32 个字节直接是内容密钥(同样,前面的数据本质上包含安装路径,现在是 Edge)。

此外,Local State文件和Cookies数据库的路径不同,即

%LocalAppData%\Microsoft\Edge\User Data\...
而不是
%LocalAppData%\Google\Chrome\User Data\...

© www.soinside.com 2019 - 2024. All rights reserved.