Unfinished File
Unfinished File
Platform: Tjctf | Category: Forensics | Type: Challenge | Difficulty: Easy | OS: NA | Author: D3v0o0Nu11 | Date: 2026-05-16 | Status: Solved Techniques: crdl_file_format_analysis, embedded_zip_extraction, single_byte_xor_known_plaintext
Summary
Task: analyze a Chrome .crdownload incomplete download file containing embedded data. Solution: extract embedded ZIP archive, recover XOR-encrypted flag using known-plaintext attack with flag prefix.
Recon
Port scan
bash read-only • copy allowednmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
| Port | Service | Version | Notes |
|---|---|---|---|
| <PORT> | <SVC> | <VER> | <notes> |
Enumeration highlights
- Event:
tjctf| ID:20260516_tjctf_unfinished_file - Tags: zip, known_plaintext, xor, file_format, crdownload, single_byte_xor, chrome_download
- Indicators: crdownload file extension (Chrome incomplete download), CRDL magic bytes at file start, embedded PK (ZIP) signature inside binary blob, XOR-encrypted data with known flag prefix enabling key recovery, small file size suggesting manual analysis over automated tools
- Source:
20260516_tjctf_unfinished_file.md
Foothold
Vulnerability / Misconfiguration
- crdl_file_format_analysis
- embedded_zip_extraction
- single_byte_xor_known_plaintext
bash read-only • copy allowed<command>
Exploitation
- See original writeup content for detailed exploitation.
Privilege Escalation
Enumeration
bash read-only • copy allowedsudo -l find / -perm -4000 2>/dev/null getcap -r / 2>/dev/null cat /etc/crontab ps aux
Exploitation
- N/A for challenge-type writeup; see exploitation above.
- Flag obtained via challenge solve.
bash read-only • copy allowed<command>
Flags
| Flag | Location | Value |
|---|---|---|
| flag | REDACTED |
Key Takeaways / Lessons
- crdl_file_format_analysis
- embedded_zip_extraction
- single_byte_xor_known_plaintext
- Tags: zip, known_plaintext, xor, file_format, crdownload, single_byte_xor, chrome_download
Original Writeup
<details><summary>Click to expand original content</summary>Description
"my stupid friend tried downloading this file before i shut my laptop down, what was he trying to do?"
Attachment: secret_archive.zip.crdownload (463 bytes) — a Chrome incomplete download file.
Analysis
The .crdownload extension is Chrome's format for incomplete downloads. At only 463 bytes, this file is small enough for manual binary analysis.
Examining the file structure revealed three distinct regions:
- CRDL header (offset
0x00): Magic bytesCRDL, version info, and the source URLhttps://example.com/secret_archive.zip - XOR-encrypted blob (offset
0x47): Encoded data with preceding control characters - Embedded ZIP archive (offset
0x100): StandardPKsignature (ZIP magic bytes)
The embedded ZIP contained two files:
readme.txt— decoy text: "This file is incomplete. Keep looking..."hidden/.flagdata— 47 bytes of XOR-encrypted data
The .flagdata hex content:
36 28 21 36 24 39 2c 71 34 71 30 1d 2e 71 36 1d
72 36 2a 27 30 1d 32 71 72 32 2e 27 1d 36 72 37
21 2a 1d 37 30 1d 21 72 2f 32 37 36 27 30 3f
Solution
Known-plaintext attack on single-byte XOR
The flag format tjctf{ provides 6 known plaintext bytes. XORing the first encrypted byte with the expected plaintext reveals the key:
0x36 ^ 0x74 ('t') = 0x42 ('B')
Verifying against all 6 prefix bytes:
| Encrypted | Expected | XOR result |
|---|---|---|
0x36 | t (0x74) | 0x42 ✓ |
0x28 | j (0x6A) | 0x42 ✓ |
0x21 | c (0x63) | 0x42 ✓ |
0x36 | t (0x74) | 0x42 ✓ |
0x24 | f (0x66) | 0x42 ✓ |
0x39 | { (0x7B) | 0x42 ✓ |
All 6 bytes produce the same key 0x42 — confirmed single-byte XOR with key B.
Decryption
</details>python read-only • copy allowed#!/usr/bin/env python3 data = bytes.fromhex( '3628213624392c71347130' '1d2e71361d72362a2730' '1d3271723227' '1d36723721' '2a1d37301d2172' '2f323736273' '03f' ) # Cleaner version with exact bytes data = bytes([ 0x36, 0x28, 0x21, 0x36, 0x24, 0x39, 0x2c, 0x71, 0x34, 0x71, 0x30, 0x1d, 0x2e, 0x71, 0x36, 0x1d, 0x72, 0x36, 0x2a, 0x27, 0x30, 0x1d, 0x32, 0x71, 0x72, 0x32, 0x2e, 0x27, 0x1d, 0x36, 0x72, 0x37, 0x21, 0x2a, 0x1d, 0x37, 0x30, 0x1d, 0x21, 0x72, 0x2f, 0x32, 0x37, 0x36, 0x27, 0x30, 0x3f ]) key = 0x42 flag = ''.join(chr(b ^ key) for b in data) print(flag) # tjctf{REDACTED}
signed by XESXOR