Navigating the world of browser cookies is key to safeguarding your online privacy and security. Think of cookies as small digital helpers that websites place on your computer to track your browsing habits, store your login details, and remember your preferences. They’re designed to make your online experience smoother and more personalized. However, these tiny data packets can also pose privacy risks if they’re not managed carefully. For anyone interested in keeping their digital life secure, especially those dabbling in ethical hacking, getting a handle on cookie management is essential.
In today’s tutorial, you’ll learn how to manage Chrome cookies with Python. We’ll walk you through extracting, decrypting, and deleting cookies using tkinter for a user-friendly graphical interface. By leveraging the pycryptodome library, you’ll ensure that your cookie management process is secure and efficient. So, let’s get started!
Table of Contents
- Disclaimer
- Necessary Libraries
- Imports
- Functions for Extracting, Decrypting and Deleting Chrome Cookies
- Setting Up the Tkinter GUI
- Example
- Full Code
Disclaimer
Please note: This tutorial is for educational purposes only. Managing browser cookies can involve privacy and security risks. Ensure you have proper permissions and comply with legal guidelines when handling browser data. This guide is not for unauthorized access or circumventing security measures.
Necessary Libraries
For the code to function properly, make sure to install the tkinter
, pypiwin32 and pycryptodome libraries via the terminal or your command prompt by running these commands:
$ pip install tk
$ pip install pypiwin32
$ pip install pycryptodome
Imports
import os
import json
import base64
import sqlite3
import shutil
from datetime import datetime, timedelta
import win32crypt # pip install pypiwin32
from Cryptodome.Cipher import AES # pip install pycryptodome
import tkinter as tk
from tkinter import messagebox, ttk
Our first objective here is to extract cookies from Chrome—essentially, it’s like trying to open a lock without the key. That’s why we need a specific toolbox, which we’ll import:
- os: Think of this as our navigator, helping us traverse the complex file paths of the operating system.
- json: Our decoder for JSON data, the language in which Chrome’s secrets (encryption keys) are written.
- base64: Essential for deciphering the encoded messages (encryption keys) that Chrome uses.
- sqlite3: Our tool to query the database where Chrome stores its cookies—like accessing a hidden compartment.
- shutil: Assists in safely moving and copying files, ensuring that our cookie data is transferred without a hitch.
- datetime and timedelta: These function as our time machines, transforming Chrome’s cryptic timestamps into readable dates.
- win32crypt: A specialist tool for unlocking data that Windows has secured.
- Cryptodome.Cipher: Our cipher to decrypt the cookie values, revealing their true content.
- Tkinter: The architect of our user interface, making our tools accessible through a friendly graphical layout.
- messagebox and ttk: The finishing touches for our GUI, providing sleek, themed widgets and dialog boxes to interact with the user.
Functions for Extracting, Decrypting and Deleting Chrome Cookies
Converting Chrome Time Format
Chrome stores timestamps in a unique format—microseconds since January 1, 1601. This format isn’t directly usable for most applications, so we need to convert it into a more familiar one.
That’s where the chrome_time_to_datetime()
function comes into play. How does it work? Let’s break it down:
- This function first checks if the
chrome_time
value is valid and not set to a special marker (86400000000). If valid, it adds the number of microseconds to January 1, 1601, converting it into a standard timestamp format we’re familiar with. However, ifchrome_time
is invalid or marked by the special value, the function returnsNone
.
def chrome_time_to_datetime(chrome_time):
"""Convert Chrome time format to a datetime object."""
if chrome_time and chrome_time != 86400000000:
return datetime(1601, 1, 1) + timedelta(microseconds=chrome_time)
return None
Fetching the Encryption Key
Next, this is where we obtain the key that unlocks the vault where Chrome stores its cookies:
First, we need to locate this key. We use the os
module to act as our GPS, constructing a path to the “Local State” file that contains the encrypted key. Once we reach this file, we open and read it as JSON to extract the key. We then decode it using base64
and decrypt it using win32crypt
. If successful, we can unlock all the encrypted cookies; otherwise, we encounter the “failed to get encryption key” error message.
def fetch_encryption_key():
"""Retrieve the encryption key used by Chrome."""
state_path = os.path.join(os.environ["USERPROFILE"], "AppData", "Local", "Google", "Chrome", "User Data", "Local State")
try:
with open(state_path, "r", encoding="utf-8") as file:
state_data = json.load(file)
encrypted_key = base64.b64decode(state_data["os_crypt"]["encrypted_key"])[5:]
return win32crypt.CryptUnprotectData(encrypted_key, None, None, None, 0)[1]
except Exception as e:
print(f"Failed to get encryption key: {e}")
return None
Decrypting Cookie Values
Now that we have the key, it’s time to unlock the vault and unveil Chrome’s encrypted cookie values.
How do we do that? With the help of the decrypt_cookie_value()
function. This function begins by extracting the initialization vector (IV) from positions 3 to 15 of the encrypted cookie value, leaving the remainder as the encrypted data. It then uses AES, configured with the decryption key and the extracted IV, to decrypt the data. If this endeavor is successful, we proceed to retrieve the decrypted cookies from Chrome. However, if it fails, we will be met with a printed decryption error message.
def decrypt_cookie_value(encrypted_value, key):
"""Unveil the encrypted cookie content with the given encryption key."""
try:
iv, encrypted_value = encrypted_value[3:15], encrypted_value[15:]
cipher = AES.new(key, AES.MODE_GCM, iv)
return cipher.decrypt(encrypted_value)[:-16].decode()
except Exception as e:
print(f"Decryption error: {e}")
return ""
Retrieving Cookies from Chrome’s Database
Having located the cookies, it’s time to retrieve them in a manner that avoids disrupting Chrome’s functionality. This is precisely why we designed the retrieve_cookies()
function. It starts by utilizing the os
and shutil
modules to create a temporary Chrome Cookies database file. It first identifies the path to the actual Chrome cookies database and then copies this database to a temporary file to prevent any interference with Chrome’s ongoing processes.
Next, the function connects to this SQLite database to extract the cookies. The function then decrypts the cookie values using the decrypt_cookie_value()
function, converts their timestamp formats with the chrome_time_to_datetime()
function, and organizes them into a list for later display.
def retrieve_cookies():
"""Extract cookies from Chrome's database."""
db_path = os.path.join(os.environ["USERPROFILE"], "AppData", "Local", "Google", "Chrome", "User Data", "Default", "Network", "Cookies")
temp_db_path = "Temp_Cookies.db"
if not os.path.isfile(temp_db_path):
try:
shutil.copyfile(db_path, temp_db_path)
except PermissionError as e:
messagebox.showerror("Permission Error", f"Failed to copy cookies database: {e}")
return []
conn = sqlite3.connect(temp_db_path)
conn.text_factory = lambda b: b.decode(errors="ignore")
cursor = conn.cursor()
cursor.execute("SELECT host_key, name, value, creation_utc, last_access_utc, expires_utc, encrypted_value FROM cookies")
key = fetch_encryption_key()
if key is None:
messagebox.showerror("Error", "Failed to retrieve encryption key.")
return []
cookies_data = []
for host, name, value, creation_time, last_access, expiry, encrypted_value in cursor.fetchall():
decrypted_value = decrypt_cookie_value(encrypted_value, key) if not value else value
cookies_data.append((host, name, decrypted_value, chrome_time_to_datetime(creation_time), chrome_time_to_datetime(last_access), chrome_time_to_datetime(expiry)))
cursor.execute("UPDATE cookies SET value = ?, has_expires = 1, expires_utc = 99999999999999999, is_persistent = 1, is_secure = 0 WHERE host_key = ? AND name = ?", (decrypted_value, host, name))
conn.commit()
conn.close()
return cookies_data
Deleting Selected Cookies
With the cookies now fully displayed, there may be some that we want to delete. This is the objective of the delete_selected_cookies()
function, which operates in a somewhat similar manner to the retrieve_cookies()
function. Like its counterpart, this function copies the Chrome Cookies database to a temporary file and connects to it. However, it then differentiates itself by deleting the selected cookies from the temporary file.
Finally, it copies the updated database back to its original path, while a message box informs the user of the success or failure of the operation.
def delete_selected_cookies(selected_cookies):
"""Delete selected cookies from Chrome's database."""
db_path = os.path.join(os.environ["USERPROFILE"], "AppData", "Local", "Google", "Chrome", "User Data", "Default", "Network", "Cookies")
temp_db_path = "Temp_Cookies.db"
try:
shutil.copyfile(db_path, temp_db_path)
except PermissionError as e:
messagebox.showerror("Permission Error", f"Failed to copy cookies database: {e}")
return
conn = sqlite3.connect(temp_db_path)
cursor = conn.cursor()
for cookie in selected_cookies:
cursor.execute("DELETE FROM cookies WHERE host_key = ? AND name = ?", (cookie[0], cookie[1]))
conn.commit()
conn.close()
try:
shutil.copyfile(temp_db_path, db_path)
except PermissionError as e:
messagebox.showerror("Permission Error", f"Failed to update cookies database: {e}")
return
messagebox.showinfo("Info", "Selected cookies have been deleted.")
Deleting All Cookies
Here, we aim to delete all cookies, and we’ll accomplish this with the help of the delete_all_cookies()
function. This function operates similarly to the delete_selected_cookies()
function, but with a crucial difference: it deletes all cookies from the database before copying the updated database back to its original location. Additionally, a message box informs the user of the success or failure of the operation.
def delete_all_cookies():
"""Delete all cookies from Chrome's database."""
db_path = os.path.join(os.environ["USERPROFILE"], "AppData", "Local", "Google", "Chrome", "User Data", "Default", "Network", "Cookies")
temp_db_path = "Temp_Cookies.db"
try:
shutil.copyfile(db_path, temp_db_path)
except PermissionError as e:
messagebox.showerror("Permission Error", f"Failed to copy cookies database: {e}")
return
conn = sqlite3.connect(temp_db_path)
cursor = conn.cursor()
cursor.execute("DELETE FROM cookies")
conn.commit()
conn.close()
try:
shutil.copyfile(temp_db_path, db_path)
except PermissionError as e:
messagebox.showerror("Permission Error", f"Failed to update cookies database: {e}")
return
messagebox.showinfo("Info", "All cookies have been deleted.")
GUI Handlers for Extracting and Deleting Cookies
These functions are responsible for extracting and deleting cookies. How do they work? It’s quite straightforward:
- The
on_extract_click()
function utilizes theretrieve_cookies()
function to display the retrieved cookies on a Treeview widget. Additionally, theon_delete_click()
function uses thedelete_selected_cookies()
function to remove selected cookies and then updates the displayed list of cookies.
def on_extract_click():
"""Handle the extract cookies button click event."""
cookies_data = retrieve_cookies()
for i, cookie in enumerate(cookies_data):
tree.insert("", "end", values=cookie, iid=i)
def on_delete_click():
"""Handle the delete selected cookies button click event."""
selected_items = tree.selection()
selected_cookies = [tree.item(item)['values'][:2] for item in selected_items]
delete_selected_cookies(selected_cookies)
for item in selected_items:
tree.delete(item)
Setting Up the Tkinter GUI
Just as the name suggests, this is where we create the graphical user interface and its elements. We start by initiating the main window, or the GUI, and give it a title. Next, we create a frame to hold the interface elements. Once the frame is set up, we add an “Extract Cookies” button that triggers the on_extract_click()
function.
Following that, we introduce a Treeview widget, which will display the extracted cookies, and attach a scrollbar to it to facilitate easier navigation. We then create two additional buttons:
- “Delete Selected Cookies“, which activates the
on_delete_click()
function. - “Delete All Cookies“, which engages the
delete_all_cookies()
function.
Finally, we initiate the main event loop to keep the main window running and responsive to user interactions.
# Set up the Tkinter GUI
root = tk.Tk()
root.title("Chrome Cookies Manager - The Pycodes")
frame = tk.Frame(root)
frame.pack(padx=10, pady=10)
tk.Button(frame, text="Extract Cookies", command=on_extract_click).pack(pady=5)
columns = ("Domain", "Name", "Value", "Created On", "Accessed On", "Expires On")
tree = ttk.Treeview(frame, columns=columns, show='headings')
# Adding scrollbar
scrollbar = ttk.Scrollbar(frame, orient="vertical", command=tree.yview)
tree.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side="right", fill="y")
tree.pack(pady=5)
for col in columns:
tree.heading(col, text=col)
tree.column(col, width=150)
tk.Button(frame, text="Delete Selected Cookies", command=on_delete_click).pack(pady=5)
tk.Button(frame, text="Delete All Cookies", command=delete_all_cookies).pack(pady=5)
root.mainloop()
Example
This is the result when you run the code:
And here I extracted my cookies by clicking on “Extract Cookies” Button:
Lastly, I selected a cookie and then I deleted it by clicking on “Delete Selected Cookies” Button:
Full Code
import os
import json
import base64
import sqlite3
import shutil
from datetime import datetime, timedelta
import win32crypt # pip install pypiwin32
from Cryptodome.Cipher import AES # pip install pycryptodome
import tkinter as tk
from tkinter import messagebox, ttk
def chrome_time_to_datetime(chrome_time):
"""Convert Chrome time format to a datetime object."""
if chrome_time and chrome_time != 86400000000:
return datetime(1601, 1, 1) + timedelta(microseconds=chrome_time)
return None
def fetch_encryption_key():
"""Retrieve the encryption key used by Chrome."""
state_path = os.path.join(os.environ["USERPROFILE"], "AppData", "Local", "Google", "Chrome", "User Data", "Local State")
try:
with open(state_path, "r", encoding="utf-8") as file:
state_data = json.load(file)
encrypted_key = base64.b64decode(state_data["os_crypt"]["encrypted_key"])[5:]
return win32crypt.CryptUnprotectData(encrypted_key, None, None, None, 0)[1]
except Exception as e:
print(f"Failed to get encryption key: {e}")
return None
def decrypt_cookie_value(encrypted_value, key):
"""Unveil the encrypted cookie content with the given encryption key."""
try:
iv, encrypted_value = encrypted_value[3:15], encrypted_value[15:]
cipher = AES.new(key, AES.MODE_GCM, iv)
return cipher.decrypt(encrypted_value)[:-16].decode()
except Exception as e:
print(f"Decryption error: {e}")
return ""
def retrieve_cookies():
"""Extract cookies from Chrome's database."""
db_path = os.path.join(os.environ["USERPROFILE"], "AppData", "Local", "Google", "Chrome", "User Data", "Default", "Network", "Cookies")
temp_db_path = "Temp_Cookies.db"
if not os.path.isfile(temp_db_path):
try:
shutil.copyfile(db_path, temp_db_path)
except PermissionError as e:
messagebox.showerror("Permission Error", f"Failed to copy cookies database: {e}")
return []
conn = sqlite3.connect(temp_db_path)
conn.text_factory = lambda b: b.decode(errors="ignore")
cursor = conn.cursor()
cursor.execute("SELECT host_key, name, value, creation_utc, last_access_utc, expires_utc, encrypted_value FROM cookies")
key = fetch_encryption_key()
if key is None:
messagebox.showerror("Error", "Failed to retrieve encryption key.")
return []
cookies_data = []
for host, name, value, creation_time, last_access, expiry, encrypted_value in cursor.fetchall():
decrypted_value = decrypt_cookie_value(encrypted_value, key) if not value else value
cookies_data.append((host, name, decrypted_value, chrome_time_to_datetime(creation_time), chrome_time_to_datetime(last_access), chrome_time_to_datetime(expiry)))
cursor.execute("UPDATE cookies SET value = ?, has_expires = 1, expires_utc = 99999999999999999, is_persistent = 1, is_secure = 0 WHERE host_key = ? AND name = ?", (decrypted_value, host, name))
conn.commit()
conn.close()
return cookies_data
def delete_selected_cookies(selected_cookies):
"""Delete selected cookies from Chrome's database."""
db_path = os.path.join(os.environ["USERPROFILE"], "AppData", "Local", "Google", "Chrome", "User Data", "Default", "Network", "Cookies")
temp_db_path = "Temp_Cookies.db"
try:
shutil.copyfile(db_path, temp_db_path)
except PermissionError as e:
messagebox.showerror("Permission Error", f"Failed to copy cookies database: {e}")
return
conn = sqlite3.connect(temp_db_path)
cursor = conn.cursor()
for cookie in selected_cookies:
cursor.execute("DELETE FROM cookies WHERE host_key = ? AND name = ?", (cookie[0], cookie[1]))
conn.commit()
conn.close()
try:
shutil.copyfile(temp_db_path, db_path)
except PermissionError as e:
messagebox.showerror("Permission Error", f"Failed to update cookies database: {e}")
return
messagebox.showinfo("Info", "Selected cookies have been deleted.")
def delete_all_cookies():
"""Delete all cookies from Chrome's database."""
db_path = os.path.join(os.environ["USERPROFILE"], "AppData", "Local", "Google", "Chrome", "User Data", "Default", "Network", "Cookies")
temp_db_path = "Temp_Cookies.db"
try:
shutil.copyfile(db_path, temp_db_path)
except PermissionError as e:
messagebox.showerror("Permission Error", f"Failed to copy cookies database: {e}")
return
conn = sqlite3.connect(temp_db_path)
cursor = conn.cursor()
cursor.execute("DELETE FROM cookies")
conn.commit()
conn.close()
try:
shutil.copyfile(temp_db_path, db_path)
except PermissionError as e:
messagebox.showerror("Permission Error", f"Failed to update cookies database: {e}")
return
messagebox.showinfo("Info", "All cookies have been deleted.")
def on_extract_click():
"""Handle the extract cookies button click event."""
cookies_data = retrieve_cookies()
for i, cookie in enumerate(cookies_data):
tree.insert("", "end", values=cookie, iid=i)
def on_delete_click():
"""Handle the delete selected cookies button click event."""
selected_items = tree.selection()
selected_cookies = [tree.item(item)['values'][:2] for item in selected_items]
delete_selected_cookies(selected_cookies)
for item in selected_items:
tree.delete(item)
# Set up the Tkinter GUI
root = tk.Tk()
root.title("Chrome Cookies Manager - The Pycodes")
frame = tk.Frame(root)
frame.pack(padx=10, pady=10)
tk.Button(frame, text="Extract Cookies", command=on_extract_click).pack(pady=5)
columns = ("Domain", "Name", "Value", "Created On", "Accessed On", "Expires On")
tree = ttk.Treeview(frame, columns=columns, show='headings')
# Adding scrollbar
scrollbar = ttk.Scrollbar(frame, orient="vertical", command=tree.yview)
tree.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side="right", fill="y")
tree.pack(pady=5)
for col in columns:
tree.heading(col, text=col)
tree.column(col, width=150)
tk.Button(frame, text="Delete Selected Cookies", command=on_delete_click).pack(pady=5)
tk.Button(frame, text="Delete All Cookies", command=delete_all_cookies).pack(pady=5)
root.mainloop()
Happy Coding!