mirror of
https://github.com/SpecterOps/Nemesis
synced 2026-06-08 12:36:42 +00:00
First pass at v3 ABE dec
- First pass at v3 ABE dec
This commit is contained in:
@@ -367,7 +367,10 @@ def try_decrypt_with_all_keys(
|
||||
return None, None
|
||||
|
||||
|
||||
def parse_abe_blob(abe_data: bytes) -> dict | None:
|
||||
def byte_xor(ba1, ba2):
|
||||
return bytes([_a ^ _b for _a, _b in zip(ba1, ba2)])
|
||||
|
||||
def parse_abe_blob(abe_data: bytes, chromekey: bytes | None = None) -> dict | None:
|
||||
"""Parse ABE (App-Bound Encryption) blob data.
|
||||
|
||||
Args:
|
||||
@@ -392,10 +395,17 @@ def parse_abe_blob(abe_data: bytes) -> dict | None:
|
||||
abe_parsed["tag"] = content[12 + 32 : 12 + 32 + 16]
|
||||
else: # Version 3
|
||||
# Version|encAES|IV|ciphertext|tag, 1|32|12|32|16 bytes
|
||||
# adapted from:
|
||||
# https://github.com/KingOfTheNOPs/cookie-monster/blob/4ec4b3555682ac1e71a6428a4b0f45b2cf1fd8f7/decrypt.py
|
||||
# https://github.com/tijldeneut/diana/blob/b9473b5004ecf1d7bdd5852232b5cd06a5378e5e/diana-browserdec.py
|
||||
abe_parsed["encrAES"] = content[:32]
|
||||
abe_parsed["iv"] = content[32 : 32 + 12]
|
||||
abe_parsed["cipherdata"] = content[32 + 12 : 32 + 12 + 32]
|
||||
abe_parsed["tag"] = content[32 + 12 + 32 : 32 + 12 + 32 + 16]
|
||||
|
||||
if chromekey:
|
||||
xor_key = bytes.fromhex("CCF8A1CEC56605B8517552BA1A2D061C03A29E90274FB2FCF59BA4B75C392390")
|
||||
abe_parsed["xored_aes_key"] = byte_xor(chromekey, xor_key)
|
||||
return abe_parsed
|
||||
except Exception as e:
|
||||
logger.warning("Failed to parse ABE blob", error=str(e))
|
||||
@@ -424,8 +434,11 @@ def derive_abe_key(abe_data: dict) -> bytes | None:
|
||||
nonce=abe_data["iv"],
|
||||
)
|
||||
elif abe_data["version"] == 3:
|
||||
# TODO: Version 3 requires CNG decryption of encrypted AES key
|
||||
logger.warning("ABE version 3 not yet supported - requires CNG decryption")
|
||||
if abe_data["xored_aes_key"]:
|
||||
cipher = AES.new(abe_data["xored_aes_key"], AES.MODE_GCM, nonce=abe_data["iv"])
|
||||
else:
|
||||
# Version 3 requires CNG decryption of encrypted AES key
|
||||
logger.warning("xored_aes_key not present, ABE version 3 requires CNG decrypted (or memory-extracted) 'Google Chromekey1'")
|
||||
return None
|
||||
else:
|
||||
logger.warning("Unknown ABE version", version=abe_data["version"])
|
||||
|
||||
@@ -119,6 +119,29 @@ def _add_user_masterkey_link(file_enriched, username: str | None, masterkey_guid
|
||||
add_file_linking(file_enriched.source, file_enriched.path, masterkey_path, "windows:user_masterkey")
|
||||
|
||||
|
||||
def _get_chromekey_from_source(source: str, pg_conn) -> bytes | None:
|
||||
"""Get decrypted Chrome key from chrome_keys table by source.
|
||||
|
||||
Args:
|
||||
source: Source value to match
|
||||
pg_conn: PostgreSQL connection
|
||||
|
||||
Returns:
|
||||
Decrypted key bytes if found and decrypted, None otherwise
|
||||
"""
|
||||
try:
|
||||
with pg_conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"SELECT key_bytes_dec FROM chromium.chrome_keys WHERE source = %s AND key_is_decrypted = TRUE",
|
||||
(source,),
|
||||
)
|
||||
result = cur.fetchone()
|
||||
return result[0] if result else None
|
||||
except Exception as e:
|
||||
logger.warning("Failed to lookup chrome key from source", error=str(e))
|
||||
return None
|
||||
|
||||
|
||||
async def _insert_state_keys(
|
||||
file_enriched,
|
||||
username: str | None,
|
||||
@@ -135,6 +158,9 @@ async def _insert_state_keys(
|
||||
# Extract os_crypt section
|
||||
os_crypt = data.get("os_crypt", {})
|
||||
|
||||
# Get Chrome key from chrome_keys table if available
|
||||
chromekey = _get_chromekey_from_source(file_enriched.source, pg_conn)
|
||||
|
||||
key_bytes_dec = b""
|
||||
key_is_decrypted = False
|
||||
app_bound_key_dec_inter = b""
|
||||
@@ -220,7 +246,7 @@ async def _insert_state_keys(
|
||||
abe_blob_bytes = await dpapi_manager.decrypt_blob(user_blob)
|
||||
if abe_blob_bytes:
|
||||
# Parse and derive the final ABE key
|
||||
abe_parsed = parse_abe_blob(abe_blob_bytes)
|
||||
abe_parsed = parse_abe_blob(abe_blob_bytes, chromekey)
|
||||
if abe_parsed:
|
||||
app_bound_key_dec = derive_abe_key(abe_parsed)
|
||||
if app_bound_key_dec:
|
||||
|
||||
Reference in New Issue
Block a user