๐ฃNested ZIP Password Chain - CTF Writeup
In may 2025, right before the main Microsoft ADC CTF, there was a teaser challenge. In this challenge, we were given a ZIP archive named ExtractMe.zip. At first glance, it seemed like a simple password-protected archive โ but it turned out to be a recursive ZIP chain, where every ZIP file contains another ZIP file, and the password for each ZIP is the name of the next ZIP file inside, without the .zip extension.
๐ต๏ธ Manual Inspection
We began by running unzip on the initial file:
1
unzip ExtractMe.zip
We were prompted for a password. Upon inspecting the contents of the archive (using tools like zipinfo), we found that it contains a single file, for example 44008.zip. When we tried entering 44008 as the password โ it worked! This became the key insight for solving the challenge.
Each ZIP file in the chain followed this pattern:
ExtractMe.zipโ contains44008.zip, password is4400844008.zipโ contains91521.zip, password is9152191521.zipโ contains88711.zip, password is88711- โฆ and so on.
๐ธ The initial unzip prompt.
๐ The Problem
The nesting goes on and on โ with each layer revealing another ZIP. Doing this manually is not only boring, but very time-consuming. So we decided to automate it using Python.
๐ Python Script for Recursive Extraction
Here is the complete Python script we wrote to automate the recursive unzipping process:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import os
import zipfile
def recursive_unzip(start_zip):
current_zip_path = os.path.abspath(start_zip)
base_dir = os.path.dirname(current_zip_path)
count = 0
while True:
with zipfile.ZipFile(current_zip_path) as zf:
# Assume only one file inside
names = zf.namelist()
if len(names) != 1:
print(f"[!] Unexpected contents in {current_zip_path}: {names}")
break
inner_file = names[0]
inner_name = os.path.splitext(os.path.basename(inner_file))[0]
# Prepare output directory
next_dir = os.path.join(base_dir, f"extracted_{count}")
os.makedirs(next_dir, exist_ok=True)
try:
print(f"[+] Extracting {current_zip_path} using password: {inner_name}")
zf.extract(inner_file, path=next_dir, pwd=inner_name.encode())
except RuntimeError as e:
print(f"[!] Failed to extract {current_zip_path} with password '{inner_name}': {e}")
break
# Move to next ZIP
current_zip_path = os.path.join(next_dir, inner_file)
if not zipfile.is_zipfile(current_zip_path):
print(f"[โ] Extraction complete. Final file: {current_zip_path}")
break
count += 1
# Replace with your actual starting ZIP file
if __name__ == "__main__":
recursive_unzip("ExtractMe.zip")
๐ธ Running the script.
๐ป How to Use the Script
- Save the script above as
recursive_unzip.py. - Place it in the same directory as
ExtractMe.zip. - Run it:
1
python3 recursive_unzip.py
- The script will:
- Automatically extract each ZIP file using the next filename as the password
- Store each layerโs extracted content in folders like
extracted_0,extracted_1, etc. - Stop when the final (non-ZIP) file is extracted
๐ Folder Structure During Execution
As the script runs, the directory will look something like this:
1
2
3
4
5
6
7
8
9
10
.
โโโ ExtractMe.zip
โโโ recursive_unzip.py
โโโ extracted_0
โ โโโ 44008.zip
โโโ extracted_1
โ โโโ 91521.zip
โโโ extracted_2
โ โโโ 88711.zip
...
๐ธ folder structure.
โ Final Result
Once the final file is extracted, the script will output a message like:
1
[โ] Extraction complete. Final file: /path/to/extracted_N/flag.txt
Now you can open that file and retrieve your flag or next challenge step.
๐ธ The Final extracted File.
๐ง Lessons Learned
- Automating repetitive tasks is essential in CTFs.
- Always look for patterns โ here, the password logic was very systematic.
- Pythonโs
zipfilemodule is great for handling encrypted ZIPs.
๐ Resources
recursive_unzip.pyโ Download the full script here.- Python zipfile docs
- CTF Writeups on this site
๐ฌ Got Questions?
Feel free to reach out or drop a comment below if you got stuck in a similar challenge or want help building custom automation tools!






