Description
After logging in, you will find multiple file parts in your home directory. These parts need to be combined and extracted to reveal the flag.
Setup
Launch the challenge instance and SSH in.
List files in the home directory to see the split archive parts.
ls -lafile *Solution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1
SSH in and list the file partsObservationI noticed the challenge description says 'multiple file parts' live in the home directory, which suggested the first step was to SSH in and run 'ls' plus 'file *' to see exactly how many parts exist and confirm their true archive format via magic bytes.Log into the challenge instance via SSH. Your home directory contains multiple numbered split-archive parts (e.g. file.zip.001, file.zip.002, ... or file.aa, file.ab, ...).bashssh ctf-player@<HOST> -p <PORT_FROM_INSTANCE>bashls -labashfile *Expected output
Archive: combined.zip inflating: flag.txt
What didn't work first
Tried: Run 'file *' and trust the filename extension instead of the magic byte output.
Extensions are cosmetic and can be stripped or renamed by the challenge author. 'file' reports the true type from magic bytes - if it says 'Zip archive data' on a file named 'data.bin', the extension is irrelevant and you should treat it as a ZIP. Trusting the name and trying the wrong extractor (e.g. 'tar xf data.bin') produces a 'not in gzip format' or similar error.
Tried: Use 'ls' without '-v' or '-la' and assume the default listing order is the correct reassembly order.
Plain 'ls' sorts alphabetically, which breaks natural numeric order when part numbers are not zero-padded (e.g. part1, part2, ..., part10 sorts as part1, part10, part2). The '-v' flag enables version/natural sort so part10 comes after part9. Concatenating in the wrong order corrupts the archive magic bytes and causes extraction to fail silently or report 'End-of-central-directory signature not found'.
Learn more
Split archives are a technique for dividing large files into smaller chunks for transfer over media with size limits, email attachments, or slow connections. The original file is split into numbered parts that must be reassembled in order before extraction. Common formats include
.zip.001/.zip.002(WinZip split),.part1.rar/.part2.rar(WinRAR split), or alphabetical suffixes from the Unixsplitcommand (file.aa,file.ab, ...).The
filecommand reads a file's magic bytes (the first few bytes of the file) to determine its true type regardless of its extension. This is essential in CTF challenges where files may have misleading names or no extension. For example, a file nameddata.binmight actually be a ZIP archive (magic bytesPK\x03\x04), a gzip stream (magic bytes\x1f\x8b), or a PNG image (\x89PNG).Understanding file magic bytes is a foundational forensics skill. Tools like
file,xxd, andbinwalkall use magic byte databases to identify file types, and this knowledge lets you choose the correct extraction tool even when extensions are wrong or missing.Step 2
Combine all partsObservationI noticed the home directory held numbered or alphabetically suffixed split-archive parts, which suggested using 'cat' with a glob ordered by 'ls -v' to concatenate them in strict sequence and produce a single valid archive file.Concatenate the parts in deterministic sort order. Always verify the glob expansion before piping into cat - a wrong order produces a corrupt archive that fails to extract.bash# Always check what the glob expands to first:bashls -v *part* *.zip.* *.a? 2>/dev/nullbash# Numbered .zip parts:bashcat *.zip.* > /tmp/combined.zipbash# Letter-suffixed (split default):bashcat *.a? > /tmp/combined.zipbash# RAR-style multi-part - tighten the glob to exclude unrelated files:bashcat *part*.rar > /tmp/combined.rarbash# When you really need natural sort (e.g. part1, part2, ..., part10):bashcat $(ls -v *part*) > /tmp/combinedbashfile /tmp/combined*What didn't work first
Tried: Use 'cat *.zip' instead of 'cat *.zip.*' to concatenate the parts.
The glob '*.zip' matches only files whose name ends exactly in '.zip', which is the final combined file if it already exists - not the numbered parts like 'file.zip.001'. The numbered parts match '*.zip.*' (with a trailing dot and suffix). Using the wrong glob either captures nothing or captures an already-combined file, producing a silently doubled or empty archive.
Tried: Use 'zip -FF combined.zip --out fixed.zip' to repair the archive instead of reassembling from parts.
zip -FF is a repair tool for a single corrupt ZIP, not a reassembly tool for split parts. It expects one file with a damaged internal structure, not multiple separate part files. Running it on just the first part produces 'fixing: combined.zip' followed by extraction errors because the central directory that zip uses to locate files lives in the last part, which was never concatenated.
Learn more
The Unix
catcommand (concatenate) is the correct tool for reassembling split binary files. Since binary archives have their own internal structure with an end-of-archive marker, simply concatenating the parts in sorted order produces a valid archive that extraction tools can parse. Shell glob expansion (*.zip.*) sorts alphabetically/numerically by default, which is the correct order for numbered parts.Sort order matters critically. If parts are concatenated out of order, the resulting file will be corrupt and unextractable. For parts with numeric suffixes, ensure the sort is numeric:
001, 002, 003, ..., 009, 010rather than001, 010, 002(lexicographic order). The glob*.zip.*sorts correctly because the numeric suffix is zero-padded.For more complex reassembly scenarios, tools like
cat $(ls -v *.part)(usingls -vfor natural sort), or explicitcat part1 part2 part3 > combined, give you full control over the concatenation order.Step 3
Extract the archive with the passwordObservationI noticed the combined file was a password-protected ZIP and the challenge instructions file contained the password 'supersecret', which suggested running 'unzip -P supersecret combined.zip' to extract its contents.The combined file is a password-protected ZIP. The instructions file says the password is 'supersecret'. Use unzip with that password.bashcat $(ls -v *) > combined.zipbashunzip -P supersecret combined.zipWhat didn't work first
Tried: Try 'unzip combined.zip' without the -P flag and enter the password interactively when prompted.
Interactive password entry works fine locally, but inside an SSH session without a TTY it can hang or fail silently. More importantly, if the wrong combined order produced a corrupt archive, the prompt never appears - unzip errors out before asking. Using '-P supersecret' explicitly in the command makes it scriptable and surfaces the real error (wrong password vs. corrupt archive) as a distinct exit code.
Tried: Try 7z x combined.zip without specifying the password, hoping 7z will auto-detect or prompt.
7z does prompt for a password on encrypted ZIPs, but it applies ZipCrypto detection differently than unzip and may report 'Wrong password' even with the correct password if the archive uses AES-256 encryption (introduced in WinZip 9). Conversely, ZipCrypto archives can be cracked with pkcrack if you know plaintext - jumping straight to cracking wastes time when the password is given in the challenge instructions file.
Learn more
Common archive formats and their extraction commands:
unzipfor ZIP files,tar xffor tar archives (which auto-detects gz/bz2/xz compression),7z xfor 7-Zip archives,unrar xfor RAR files, andgunzip/bunzip2/unxzfor single-stream compressed files.Password-protected archives are common in CTF challenges. Standard passwords to try include
picoCTF,password,flag, the challenge name, and variations. If those fail, tools likejohnwithzip2john/rar2johnorhashcatcan crack the password. ZIP encryption (ZipCrypto) is particularly weak and can be cracked even without a password if you know the contents of one file in the archive (known-plaintext attack).For layered archives (a tar inside a zip inside a gz), you may need to run multiple extraction steps.
binwalk -ecan automatically extract nested archives - it scans for file signatures within files and extracts everything it finds.Step 4
Read the flagObservationI noticed extraction produced output files in /tmp, so I used 'strings' piped through 'grep' to scan all extracted content for the picoCTF flag pattern, since the flag could be embedded as text in a file with a non-obvious name or extension.Catalogue everything that came out before grepping. The flag may be in the filename, in binary data, or in a file that doesn't have a .txt extension.bashls /tmp/bash# First triage what you got - types and any hints in filenames:bashfile /tmp/*bashls /tmp/ | grep -iE 'flag|pico'bash# Search across both text and binary:bashstrings /tmp/* 2>/dev/null | grep -E 'picoCTF\{[^}]+\}'bash# As a fallback, the bare grep across all extracted files:bashgrep -roa 'picoCTF{[^}]*}' /tmp/ 2>/dev/nullLearn more
After extraction, the flag is typically in a file named
flag.txt,flag, or a similarly obvious name, but not always. Runfile *over the extracted set first - a binary or an image among the outputs is a strong hint that the flag is embedded somewhere non-obvious.strings * | grep picoCTFhandles binary data; if even that fails, walk the files withxxdand look for fragmented or encoded flags.CTF flags sometimes appear in unexpected places: as the filename itself, embedded in an image (check with
strings), inside binary data (check withxxd | grep -a pico), or hidden behind one more decoding step (base64, hex, ROT13). For more on hex-level inspection see Hex dumps for CTF; for the general shell toolkit used here see Linux CLI for CTF.This challenge teaches a workflow that appears frequently in forensics and incident response: receiving a collection of file fragments, reassembling them, extracting the archive, and searching the contents. The same sequence is used to recover data from split disk dumps, fragmented network transfers, and distributed backups.
Flag
Reveal flag
picoCTF{z1p_4nd_sp11t_f1l3s_4r3_fun_...}
SSH into the server, read the instructions file for the password ('supersecret'), combine the split parts with cat, and unzip with -P supersecret.