TryHackMe Chrome Writeup
A concise, practical walkthrough to recover Chrome credentials from the TryHackMe “Chrome” room. This post shows the investigative flow: reconstruct files from a pcap, extract AES key material from the transfer program, decrypt the archive to retrieve Chrome profile artifacts, derive the DPAPI/masterkey secrets, and finally decrypt credentials stored in Chrome’s Login Data.
Overview
- 1 Recon & file recovery
- 1.1 Inspect pcap and rebuild transferred files
- 1.2 Identify transfer blob and pair program
- 2 Reverse & key extraction
- 3 Decrypt archive → extract AppData
- 4 DPAPI / masterkey handling and cracking
- 5 Derive Chrome AES key and decrypt Login Data
- 6 Wrap-up & references
1 Recon & file recovery
1.1 Inspect the capture
- Tools: Wireshark / tshark.
- Open the provided
chromefiles.zip
(from the TryHackMe task) and locate the.pcapng
file. - In Wireshark, look for SMB/TCP streams that contain file transfer payloads.
Tips:
- Right‑click a TCP packet → “Follow” → “TCP Stream” to view raw stream bytes.
- Export a matching TCP stream to disk if the transfer was captured in one or more streams.
Example (tshark) to extract a specific TCP stream to a raw file:
1
2
# replace X with tcp.stream id
tshark -r capture.pcapng -Y "tcp.stream==X" -T data -e tcp.payload | xxd -r -p > transfer.bin
1.2 Identify the transfer program
- The capture commonly contains both the transferred data (an encrypted blob) and a small program used to perform the transfer (e.g.,
transfer.exe
). - If the helper is a PE/.NET binary, it may contain the AES key/IV or a routine that derives them.
Use strings
, xxd
or a decompiler (dnSpy
for .NET) to inspect the binary for readable constants (base64 or hex blobs) that look like keys.
1
strings transfer.exe | grep -E "[A-Za-z0-9+/=]{24,}"
2 Reverse & key extraction
- If
transfer.exe
is .NET: open withdnSpy
and search for byte arrays,AES
,CryptoStream
orRijndaelManaged
usage. Look for constants namedkey
,iv
,salt
or for aBase64
decoded string. - If not .NET: search the file for long Base64 strings or 32/16-byte hex constants.
Record the AES key and IV when found (noting encoding — hex vs base64). Many rooms use AES-256-CBC.
3 Decrypt archive → extract AppData
- With key+IV available, decrypt the transfer blob. If the blob is raw AES-CBC you can use OpenSSL:
1
2
3
# KEYHEX and IVHEX are hex-encoded values of key/iv
openssl enc -d -aes-256-cbc -in transfer.bin -K KEYHEX -iv IVHEX -out transfer.zip
unzip transfer.zip -d recovered_appdata
- If the program embedded a base64 payload instead, decode first with
base64 -d
or CyberChef. - The decrypted archive should contain a Chrome profile tree:
Local State
,Login Data
(SQLite), and masterkey files under.../Protect
.
4 DPAPI / masterkey handling and cracking
- Chrome stores its AES key encrypted with DPAPI on Windows. The
Local State
file hasos_crypt.encrypted_key
(base64). Strip the DPAPI header and produceenc_key.bin
:
1
2
3
4
import json, base64
j = json.load(open('Local State'))
enck = base64.b64decode(j['os_crypt']['encrypted_key'])
open('enc_key.bin','wb').write(enck[5:]) # drop "DPAPI" prefix
- To decrypt DPAPI blobs you typically need the user’s logon secret. If the archive contains masterkey blobs, convert them for cracking:
1) Use DPAPImk2john.py
to make a John-compatible hash from a masterkey file.
1
2
python3 DPAPImk2john.py path/to/masterkey > dpapi_hash.txt
john --wordlist=/usr/share/wordlists/rockyou.txt dpapi_hash.txt
2) If John cracks the password, use dpapi.py
(Impacket) or mimikatz
to decrypt the masterkey and then the DPAPI-protected enc_key.bin
.
Example with Impacket helper:
1
2
python3 dpapi.py masterkey -file masterkey_blob -sid 'S-1-5-21-...' -password 'CrackedPassword'
python3 dpapi.py credential -file credential_blob -key <decrypted_masterkey_hex>
5 Derive Chrome AES key and decrypt Login Data
- After decrypting the
enc_key.bin
with DPAPI, you get the raw AES key that Chrome uses to encrypt saved passwords. - Use a small Python script or community tool (e.g.,
decrypt_chrome_password.py
) to iterate overLogin Data
(SQLite) rows and decryptpassword_value
.
A minimal pattern (conceptual):
1
2
3
4
5
6
7
8
9
# pseudocode
from Crypto.Cipher import AES
# aes_key = <decrypted bytes>
# for each row in sqlite Login Data:
# blob = row['password_value']
# if blob startswith b'v10' or b'v11':
# # AES-GCM: parse nonce/tag/ciphertext and decrypt
# else:
# # older chrome might use DPAPI directly on each entry
- Or run a community script that automates the Local State → key → Login Data → output flow.
6 Example commands & snippets
1
2
3
4
5
6
7
8
9
10
11
# Extract TCP stream (example)
tshark -r chromecapture.pcapng -Y 'tcp.stream==5' -T data -e tcp.payload | xxd -r -p > transfer.bin
# Decode Local State encrypted_key (bash/python)
python3 - <<'PY'
import json, base64
j=json.load(open('Local State'))
enc=base64.b64decode(j['os_crypt']['encrypted_key'])[5:]
open('enc_key.bin','wb').write(enc)
print('written enc_key.bin')
PY
Results & answering the room
- After following the steps above you will recover:
- The initial password(s) embedded in the extracted indexes.
- The URLs associated with the saved credentials (defang them as requested, e.g.
hxxps[:]//example[.]com
). - Any secondary passwords that appear in the decrypted Login Data.
Record the recovered values and paste them into the TryHackMe question fields.
Notes, pitfalls & tips
- Chrome versions change their encryption scheme; if you see prefixes like
v10
/v11
the entry is AES-GCM encrypted and requires the Local State AES key. - DPAPI masterkeys are user/machine specific — ensure the archive contains matching masterkey files and use the correct SID.
- If cracking DPAPI hashes with John appears slow, verify encoding (convert to UTF-8) and confirm the hash was generated correctly.
References
- CyberChef (AES/decode tools)
- dnSpy (for .NET reverse engineering)
- DPAPImk2john.py / John the Ripper
- Impacket dpapi helpers / mimikatz
- decrypt-chrome-passwords (community repo)