Skip to content

Instantly share code, notes, and snippets.

@borgle
Created April 20, 2022 11:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save borgle/b348aa0e0de48fc7fcf3324f735db568 to your computer and use it in GitHub Desktop.
Save borgle/b348aa0e0de48fc7fcf3324f735db568 to your computer and use it in GitHub Desktop.
读取 chrome 记录在 sqlite 里面的 cookie 记录
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
""" ReadChromeCookies.py: chrome cookie读取工具
__email__ = "wu@borgle.io"
__date__ = "2022-04-20"
__version__ = "1.0.0"
"""
import base64
import json
import os
import sqlite3
''' python 依赖库
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pywin32
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple cryptography
'''
from win32crypt import CryptUnprotectData
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
''' Chrome Cookie 存放说明
1、chrome80以前的版本的加解密机制
chrome80以前的版本的加解密是直接通过DPAPI来进行加解密的:
DPAPI是Windows系统级对数据进行加解密的一种接口,用户无需自实现加解密代码,DPAPI提供了经过验证的高质量加解密算法,提供了用户接口对密钥存储数据加解密,实现透明并提供较高的安全保证
DPAPI提供了两个用户态接口:CryptProtectData加密数据、CryptUnprotectData解密数据。
因此chrome80以前的版本可以直接调用CryptUnprotectData对加密数据进行解密。
2、chrome80以后版本的加解密机制
chrome80以后版本的加解密机制与上面的大不同,其具体步骤为:
从环境变量HOMEPATH对应目录的/Google/Chrome/User Data/子目录下的Local State文件中读取读取一个值为os_crypt下的encrypted_key;
注:Local State文件为chrome用于存储本地状态(包括浏览器的不少状态信息,插件的详细信息等)的json文件。
将encrypted_key用base64进行解密,然后去除前5个字符,再通过dpapi解密剩余字符的值保存为key;
将加密数据截取3-14位保存为Nonce,15位开始后的其他数据保存为cipherbytes加密数据,然后使用key作为密钥通过asegcm进行解密。
'''
def decrypt_string(key, data):
nonce, cipherbytes = data[3:15], data[15:]
aesgcm = AESGCM(key)
plainbytes = aesgcm.decrypt(nonce, cipherbytes, None)
plaintext = plainbytes.decode('utf-8')
return plaintext
def get_key():
local_state = os.environ['LOCALAPPDATA'] + r'\Google\Chrome\User Data\Local State'
with open(local_state, 'r', encoding='utf-8') as f:
base64_encrypted_key = json.load(f)['os_crypt']['encrypted_key']
encrypted_key_with_header = base64.b64decode(base64_encrypted_key)
encrypted_key = encrypted_key_with_header[5:]
key = CryptUnprotectData(encrypted_key, None, None, None, 0)[1]
return key
def get_cookies(host):
cookie_path = os.environ['LOCALAPPDATA'] + r"\Google\Chrome\User Data\Default\Network\Cookies"
if not os.path.exists(cookie_path):
raise Exception('Cookies file not exist!')
sql = f"select name,encrypted_value from cookies where host_key = '.{host}'"
conn = sqlite3.connect(cookie_path)
conn.text_factory = bytes
res = conn.execute(sql).fetchall()
conn.close()
key = get_key()
result = []
for row in res:
result.append(f'{str(row[0], encoding="utf-8")}={decrypt_string(key, row[1])}')
# return result
return ';'.join(result)
domain = input('Please input domain:')
cookies = get_cookies(domain)
if cookies:
print(cookies)
else:
print('not found cookies')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment