TryHackMe - Management Wants a Word CFT

 




CTF Writeup: Management Wants a Word (Forensics)

📌 Executive Summary

  • Target System: Windows 10/11 Forensic Artifacts (KAPE Triage Package)

  • Goal: Recover encrypted credentials from Google Chrome to unlock a hidden VeraCrypt container and retrieve the target financial flag.

  • Environment: Kali Linux (100% Command Line)

  • Key Artifacts Exploited:

    • Windows Registry Hives (SAM, SYSTEM, SECURITY)

    • Windows DPAPI Master Keys & LSA Secrets

    • Google Chrome Local State & Login Data (SQLite)

    • VeraCrypt Encrypted Volume (backup)

🛠️ Phase 1: Windows Registry Forensics & LSA Secret Extraction

Windows stores local user hashes in the SAM hive, boot key material in the SYSTEM hive, and domain/LSA secrets in the SECURITY hive.

Instead of dumping only SAM hashes and attempting a dictionary attack, we extract LSA secrets directly using Impacket's secretsdump.

Command:

Bash
impacket-secretsdump -sam KAPE/C/Windows/System32/config/SAM \
                     -system KAPE/C/Windows/System32/config/SYSTEM \
                     -security KAPE/C/Windows/System32/config/SECURITY LOCAL

Explanation of Arguments:

  • -sam: Extracts local account password hashes (e.g., NTLM hash for user vera).

  • -system: Provides the BootKey / SysKey required to decrypt secrets inside SAM and SECURITY.

  • -security: Extracts LSA Secrets, including service passwords and AutoLogon credentials.

  • LOCAL: Informs Impacket to parse offline hive files rather than targeting a live system.

Key Artifact Recovered:

Under [*] Dumping LSA Secrets -> [*] DefaultPassword, the Windows AutoLogon secret revealed the user's plaintext password:

  • Target Username: vera

  • User SID: S-1-5-21-2529683458-431225740-1723070931-1000

  • Plaintext Password: minivera

🔑 Phase 2: Decrypting the DPAPI Master Key

Windows DPAPI (Data Protection API) protects sensitive user data (like Chrome keys) using Master Key files stored under %APPDATA%\Roaming\Microsoft\Protect\<SID>\. To decrypt these files offline, we need the user's SID, password, and the GUID of the target Master Key file.

1. Locate the Master Key GUID File:

Bash
ls -la KAPE/C/Users/vera/AppData/Roaming/Microsoft/Protect/S-1-5-21-2529683458-431225740-1723070931-1000/

Identified Master Key GUID file: c90719ef-5b98-474e-b934-136d606a702a

2. Decrypt the DPAPI Master Key:

Bash
impacket-dpapi masterkey -file "KAPE/C/Users/vera/AppData/Roaming/Microsoft/Protect/S-1-5-21-2529683458-431225740-1723070931-1000/c90719ef-5b98-474e-b934-136d606a702a" \
                         -sid "S-1-5-21-2529683458-431225740-1723070931-1000" \
                         -password "minivera"

Explanation:

Impacket derives the user's Key Derivation Function (KDF) using the SID and plaintext password (minivera) to unprotect the Master Key file.

Key Artifact Recovered:

Plaintext
[+] Decrypted key: 0x5e5715ec9b6df5a86e97902692a66d28e691f05d5bc1e04d0159cfe960e94c978c07e5004a0179d3a96df2468885a28175b0b02cc064445f116a752d2b3e9d40

🌐 Phase 3: Unprotecting Google Chrome's Master AES Key

Modern Google Chrome versions do not use DPAPI to encrypt every password directly. Instead, Chrome generates a random 32-byte AES key, encrypts that key using DPAPI, and stores it inside the JSON file Local State under os_crypt.encrypted_key.

1. Extract and Strip the DPAPI Prefix from Local State:

The base64-decoded string starts with a 5-byte header (DPAPI). We must slice off those first 5 bytes to leave only the raw DPAPI blob.

Bash
python3 -c "import json, base64; data = json.load(open('KAPE/C/Users/vera/AppData/Local/Google/Chrome for Testing/User Data/Local State')); open('/tmp/chrome_blob.bin', 'wb').write(base64.b64decode(data['os_crypt']['encrypted_key'])[5:])"

2. Unprotect the Chrome AES Key:

Pass the binary blob and the MasterKey (with the required 0x hex prefix) to impacket-dpapi unprotect:

Bash
impacket-dpapi unprotect -file /tmp/chrome_blob.bin -key 0x5e5715ec9b6df5a86e97902692a66d28e691f05d5bc1e04d0159cfe960e94c978c07e5004a0179d3a96df2468885a28175b0b02cc064445f116a752d2b3e9d40

Key Artifact Recovered:

Plaintext
Successfully decrypted data
0000   20 6A 39 A0 97 13 27 EA  94 87 E4 AE A9 84 4F 5D
0010   36 70 16 24 56 98 22 76  93 9A 71 26 46 DA 0B 02
  • Decrypted Chrome Master AES-256 Key: 206a39a0971327ea9487e4aea9844f5d3670162456982276939a712646da0b02

🔓 Phase 4: Programmatic Extraction of Chrome Passwords

Chrome stores saved passwords in an SQLite database located at User Data/Default/Login Data. Passwords encrypted with Chrome v80+ use AES-256-GCM:

  • Bytes 0–2: Version prefix (v10 or v11)

  • Bytes 3–14: 12-byte Nonce / Initialization Vector (IV)

  • Bytes 15 to N-16: Encrypted Ciphertext

  • Last 16 Bytes: GCM Authentication Tag

Rather than interacting with sqlite3 manually, we run a Python script using pycryptodome to query the SQLite DB and decrypt the stored credentials non-interactively.

Python Decryption Script:

Bash
python3 -c "
import sqlite3, glob
from Crypto.Cipher import AES

key = bytes.fromhex('206a39a0971327ea9487e4aea9844f5d3670162456982276939a712646da0b02')
db = glob.glob('**/Login Data', recursive=True)[0]

conn = sqlite3.connect(db)
cursor = conn.cursor()
cursor.execute('SELECT origin_url, username_value, password_value FROM logins')

for url, user, enc_pwd in cursor.fetchall():
    if enc_pwd.startswith(b'v10') or enc_pwd.startswith(b'v11'):
        nonce = enc_pwd[3:15]
        ciphertext = enc_pwd[15:-16]
        tag = enc_pwd[-16:]
        cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
        decrypted = cipher.decrypt_and_verify(ciphertext, tag).decode('utf-8', errors='ignore')
        print(f'[+] URL: {url}')
        print(f'[+] Username: {user}')
        print(f'[+] Decrypted Password: {decrypted}\n')
"

Key Artifact Recovered:

Plaintext
[+] Username: VeraSecretVault
[+] Decrypted Password: Wh4t1sV3raD0inG0nTh1sh0st

📦 Phase 5: Mounting the VeraCrypt Container on Linux

In Windows forensics, VeraCrypt volumes are usually mounted via the VeraCrypt GUI. On Kali Linux, native kernel/cryptsetup modules allow mounting VeraCrypt volumes directly via terminal without installing extra GUI applications.

The target encrypted container was located at: KAPE/C/Users/vera/Documents/backup.

1. Unlock the Container using cryptsetup:

Bash
sudo cryptsetup tcryptOpen --veracrypt KAPE/C/Users/vera/Documents/backup vera_backup

Prompts for passphrase: Enter Wh4t1sV3raD0inG0nTh1sh0st

2. Mount the Virtual Device Read-Only:

Bash
sudo mkdir -p /mnt/vera
sudo mount -o ro /dev/mapper/vera_backup /mnt/vera

🏆 Phase 6: Flag Retrieval & Environment Cleanup

1. Read PDF Contents Directly in Terminal:

Bash
pdftotext /mnt/vera/secret_financial_documents/important_invoice_byte_lotus.pdf -

Output:

The command converted the PDF structure on the fly and printed invoice details containing the total amount ($100) and the room's final flag:

  • Invoice #: 7926

  • Flag: Included in the text output.

2. Forensic Clean-up:

Unmount the filesystem and close the device mapper mapper loop:

Bash
sudo umount /mnt/vera
sudo cryptsetup close vera_backup


VIDEO : https://youtu.be/YRzcYe_DAZ0

🎯 Summary Checklist

StageCommand / Tool UsedResult / Artifact Obtained
1. Registry Dumpingimpacket-secretsdumpPassword: minivera
2. MasterKey Recoveryimpacket-dpapi masterkeyMasterKey 0x5e5715...
3. Chrome Key Extractionimpacket-dpapi unprotectAES Key 206a39a0...
4. DB Password DecryptionPython (AES.MODE_GCM)VeraCrypt Pass: Wh4t1sV3raD0inG0nTh1sh0st
5. Container Mountingcryptsetup tcryptOpenDecrypted VeraCrypt filesystem
6. Flag ExtractionpdftotextInvoice PDF Flag

Comments

Popular posts from this blog

TryHackMe - Typo Snare Threat Hunter Simulator (medium level)

TryHackMe - Matryoshka CFT

TryHackMe - Threat Hunting Simulator - Health Hazard