mirror of
https://github.com/SpecterOps/Nemesis
synced 2026-06-08 12:36:42 +00:00
fixup old local state parsing
This commit is contained in:
@@ -8,8 +8,7 @@ import psycopg
|
||||
import structlog
|
||||
from Crypto.Cipher import AES, ChaCha20_Poly1305
|
||||
from dapr.clients import DaprClient
|
||||
from impacket.dpapi import DPAPI_BLOB
|
||||
from impacket.uuid import bin_to_string
|
||||
from nemesis_dpapi import Blob
|
||||
|
||||
logger = structlog.get_logger(module=__name__)
|
||||
|
||||
@@ -101,15 +100,10 @@ def detect_encryption_type(encrypted_value: bytes) -> tuple[str, str | None]:
|
||||
# Check for DPAPI (first 4 bytes are \x01\x00\x00\x00)
|
||||
if encrypted_value[:4] == b"\x01\x00\x00\x00":
|
||||
try:
|
||||
blob = DPAPI_BLOB(encrypted_value)
|
||||
if blob.rawData is not None:
|
||||
blob.rawData = blob.rawData[: len(blob.getData())]
|
||||
masterkey_guid = bin_to_string(blob["GuidMasterKey"]).lower()
|
||||
return "dpapi", masterkey_guid
|
||||
blob = Blob.parse(encrypted_value)
|
||||
return "dpapi", str(blob.masterkey_guid)
|
||||
except Exception as e:
|
||||
logger.warning("Failed to parse DPAPI blob", error=str(e))
|
||||
return "dpapi", None
|
||||
return "dpapi", None
|
||||
raise Exception(f"Found DPAPI app bound key, but couldn't parse blob: {str(e)}") from e
|
||||
|
||||
# Check for key-based encryption (v10, v11)
|
||||
if len(encrypted_value) >= 3:
|
||||
|
||||
@@ -57,7 +57,7 @@ async def process_chromium_local_state(
|
||||
with psycopg.connect(conn_str) as pg_conn:
|
||||
state_key_data = await _insert_state_keys(file_enriched, username, browser, content, pg_conn, dpapi_manager)
|
||||
|
||||
logger.warning("Completed processing Chromium Local State", object_id=object_id)
|
||||
logger.debug("Completed processing Chromium Local State", object_id=object_id)
|
||||
return state_key_data
|
||||
|
||||
|
||||
@@ -155,6 +155,7 @@ async def _insert_state_keys(
|
||||
app_bound_key_b64 = os_crypt.get("app_bound_encrypted_key")
|
||||
app_bound_key_enc = b""
|
||||
app_bound_key_system_masterkey_guid = None
|
||||
app_bound_key_user_masterkey_guid = None
|
||||
|
||||
if app_bound_key_b64:
|
||||
logger.debug("Found v2 app bound key encrypted_key in Local State")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Chromium Login Data file parsing and database operations."""
|
||||
|
||||
import sqlite3
|
||||
import asyncio
|
||||
import sqlite3
|
||||
|
||||
import psycopg
|
||||
import structlog
|
||||
@@ -109,7 +109,7 @@ def _insert_logins(
|
||||
try:
|
||||
password_dec_bytes = asyncio.run(dpapi_manager.decrypt_blob(Blob.parse(password_value)))
|
||||
if password_dec_bytes:
|
||||
password_value_dec = password_dec_bytes.decode('utf-8', errors='replace')
|
||||
password_value_dec = password_dec_bytes.decode("utf-8", errors="replace")
|
||||
is_decrypted = True
|
||||
except:
|
||||
pass
|
||||
@@ -134,13 +134,15 @@ def _insert_logins(
|
||||
password_dec_bytes = password_dec_bytes[:-16]
|
||||
# v20 passwords typically don't have offset like cookies
|
||||
|
||||
password_value_dec = password_dec_bytes.decode('utf-8', errors='replace')
|
||||
password_value_dec = password_dec_bytes.decode("utf-8", errors="replace")
|
||||
is_decrypted = True
|
||||
except Exception as e:
|
||||
logger.debug("Failed to decrypt password with state key",
|
||||
state_key_id=state_key_id,
|
||||
encryption_type=encryption_type,
|
||||
error=str(e))
|
||||
logger.debug(
|
||||
"Failed to decrypt password with state key",
|
||||
state_key_id=state_key_id,
|
||||
encryption_type=encryption_type,
|
||||
error=str(e),
|
||||
)
|
||||
|
||||
login_data = {
|
||||
"originating_object_id": file_enriched.object_id,
|
||||
|
||||
Reference in New Issue
Block a user