Overview
The challenge provides a partial Windows filesystem from a compromised host. The important trail is:
- a downloaded payload cached by Windows Cryptnet URL cache,
- an obfuscated batch loader,
- a custom ransomware binary named
Fusion Software Group, - encrypted files under
C:\Users\Public, and - an
$MFTresident ADS that reveals where one encrypted PDF originally came from.
The solve is a known-plaintext attack against a reused ransomware keystream. Once the keystream is recovered from VESTIGE.enc.pdf, it decrypts Flag.enc.pdf, which contains a QR code with the final flag.
Initial Triage
A deeper examination of the forensic artifacts revealed that a file had been downloaded using certutil, as both its metadata and content were recorded in:
Users\admin\AppData\LocalLow\Microsoft\CryptnetUrlCache\MetaData\9D6F390AF749577790ACA34686A5E68C and Users\admin\AppData\LocalLow\Microsoft\CryptnetUrlCache\Content\9D6F390AF749577790ACA34686A5E68C
The metadata points to:
http://skill.windows-update.bit:8484/windows-update.bat
The cached content is a heavily obfuscated batch script.

After deobfuscating the batch loader, it drops and executes a second-stage executable.

Reverse engineering the second stage shows that it is a custom ransomware sample branded as Fusion Software Group.
Ransomware Behavior
The ransomware only runs on the intended victim host. It checks:
MD5(Environment.MachineName) == 037e39a5c57380ea9357167684ca4dd7
Its file encryption behavior is:
- target directory:
C:\Users\Public - random 9-character secret generated with
RandomNumberGenerator - 32-byte AES key derived through chained hashes and PBKDF2-HMAC-SHA512 with 100,000 iterations
- one random 12-byte nonce generated per ransomware run
- a 4 MiB keystream generated by AES-ECB over
nonce || counter - file bytes XORed with that keystream
- the nonce written at the beginning of each encrypted file
- 16 random bytes appended after each encrypted chunk
The critical weakness is that the same AES key, nonce, and 4 MiB keystream are reused for all files encrypted in the same run. For full 4 MiB chunks, the keystream starts at offset 0, so one known plaintext file can recover enough keystream to decrypt other small encrypted files from the same run.
Finding Known Plaintext
Among the encrypted files, VESTIGE.enc.pdf is larger than 4 MiB. The $MFT also preserves a resident Zone.Identifier alternate data stream for the original VESTIGE.pdf.

The ADS contains:
[ZoneTransfer]
ZoneId=3
HostUrl=https://arxiv.org/pdf/2606.20006#pdfjs.action=download
That URL identifies the original PDF, so we can recover the plaintext VESTIGE.pdf and XOR it with VESTIGE.enc.pdf to recover the first 4 MiB of keystream.
Decryption Script
#!/usr/bin/env python3
import hashlib
import os
import sys
BLOCK_SIZE = 0x400000
LABEL = b"Fusion Software Group"
def plain_name_from_enc(path):
return os.path.basename(path).replace(".enc.", ".")
def select_window(machine_name, file_name, length, nonce):
if length >= BLOCK_SIZE:
return 0
material = (
machine_name.encode("utf-8")
+ file_name.encode("utf-8")
+ length.to_bytes(4, "little")
+ nonce
+ LABEL
)
value = int.from_bytes(hashlib.sha256(material).digest()[:4], "little")
return value % (BLOCK_SIZE - length + 1)
def recover_keystream(known_enc_path, known_plain_path, machine_name):
plain_name = os.path.basename(known_plain_path)
with open(known_plain_path, "rb") as f:
known = f.read(BLOCK_SIZE)
with open(known_enc_path, "rb") as f:
nonce = f.read(12)
first_ct = f.read(len(known))
offset = select_window(machine_name, plain_name, len(known), nonce)
keystream = bytearray(BLOCK_SIZE)
known_mask = bytearray(BLOCK_SIZE)
recovered = bytes(a ^ b for a, b in zip(first_ct, known))
keystream[offset : offset + len(recovered)] = recovered
known_mask[offset : offset + len(recovered)] = b"\x01" * len(recovered)
print(f"[*] MachineName : {machine_name}")
print(f"[*] Nonce : {nonce.hex()}")
print(f"[*] Plain file : {plain_name}")
print(f"[*] Offset : {offset}")
print(f"[*] Keystream : {len(recovered)} bytes recovered")
return bytes(keystream), bytes(known_mask)
def decrypt_file(enc_path, keystream, known_mask, machine_name):
dst_path = enc_path.replace(".enc.", ".")
plain_name = plain_name_from_enc(enc_path)
chunks = []
with open(enc_path, "rb") as f:
nonce = f.read(12)
while True:
ct_with_tag = f.read(BLOCK_SIZE + 16)
if not ct_with_tag:
break
if len(ct_with_tag) < 16:
raise ValueError("truncated block: missing 16-byte tag")
ct = ct_with_tag[:-16]
offset = select_window(machine_name, plain_name, len(ct), nonce)
if 0 in known_mask[offset : offset + len(ct)]:
raise ValueError(
f"missing keystream coverage for {plain_name}: "
f"need offset={offset} len={len(ct)}"
)
chunks.append(bytes(a ^ b for a, b in zip(ct, keystream[offset : offset + len(ct)])))
with open(dst_path, "wb") as f:
for chunk in chunks:
f.write(chunk)
print(f"[+] Decrypted: {os.path.basename(enc_path)} -> {os.path.basename(dst_path)}")
if __name__ == "__main__":
if len(sys.argv) != 5:
print("Usage: python dec.py <known.enc> <known.plain> <target.enc> <machine_name>")
sys.exit(1)
print(f"[*] Recovering keystream from: {os.path.basename(sys.argv[1])}")
keystream, known_mask = recover_keystream(sys.argv[1], sys.argv[2], sys.argv[4])
decrypt_file(sys.argv[3], keystream, known_mask, sys.argv[4])
print("[*] Done.")
Run it from the solve directory:
python .\dec.py .\VESTIGE.enc.pdf .\VESTIGE.pdf .\Flag.enc.pdf WIN10
Expected output:
[*] Recovering keystream from: VESTIGE.enc.pdf
[*] MachineName : WIN10
[*] Nonce : c08d0e0058fe9a76d6471d68
[*] Plain file : VESTIGE.pdf
[*] Offset : 0
[*] Keystream : 4194304 bytes recovered
[+] Decrypted: Flag.enc.pdf -> Flag.pdf
[*] Done.
Flag.pdf contains a QR code. Decoding it gives the flag.