|
import sqlite3 |
|
import sys |
|
import json |
|
from Crypto.Cipher import AES |
|
from Crypto.Protocol.KDF import PBKDF2 |
|
|
|
kSalt = "saltysalt" |
|
kDerivedKeySizeInBits = 128 |
|
kEncryptionIterations = 1003 |
|
kEncryptionVersionPrefix = "v10" |
|
|
|
|
|
def derive_key_from_password(password, salt): |
|
return PBKDF2(password, salt, dkLen=kDerivedKeySizeInBits//8, count=kEncryptionIterations) |
|
|
|
|
|
def decrypt(ciphertext, key, iv): |
|
cipher = AES.new(key, AES.MODE_CBC, iv) |
|
return cipher.decrypt(ciphertext) |
|
|
|
|
|
def unpad(data): |
|
return data[:-data[-1]] |
|
|
|
|
|
def read_all_cookies(db): |
|
cursor = db.cursor() |
|
cursor.execute("select * from cookies order by last_access_utc desc") |
|
return cursor.fetchall(), [description[0] for description in cursor.description] |
|
|
|
|
|
def decrypt_chrome_cookie(password, enc_value): |
|
if enc_value.startswith(kEncryptionVersionPrefix.encode()): |
|
raw_enc_value = enc_value[len(kEncryptionVersionPrefix.encode()):] |
|
else: |
|
print("invalid encrypted data") |
|
return None |
|
|
|
iv = b' ' * AES.block_size |
|
aes_key = derive_key_from_password(password, kSalt) |
|
decrypted_text = decrypt(raw_enc_value, aes_key, iv) |
|
decrypted_text = unpad(decrypted_text) |
|
return decrypted_text |
|
|
|
|
|
def main(): |
|
password = sys.argv[2] |
|
db = sqlite3.connect(sys.argv[1]) |
|
cookies, column_names = read_all_cookies(db) |
|
|
|
for cookie in cookies: |
|
cookie_data = dict(zip(column_names, cookie)) |
|
encrypted_value = cookie_data["encrypted_value"] |
|
decrypted_value = decrypt_chrome_cookie(password, encrypted_value) |
|
if decrypted_value: |
|
cookie_data["value"] = decrypted_value.decode('utf-8', 'ignore') |
|
|
|
# del the encrypted_value so we can serialize |
|
del cookie_data["encrypted_value"] |
|
print(json.dumps(cookie_data, indent=4)) |
|
|
|
if __name__ == "__main__": |
|
main() |