Post

๐Ÿ’ฃNested ZIP Password Chain - CTF Writeup

๐Ÿ’ฃ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

image

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 โ†’ contains 44008.zip, password is 44008
  • 44008.zip โ†’ contains 91521.zip, password is 91521
  • 91521.zip โ†’ contains 88711.zip, password is 88711
  • โ€ฆ and so on.

๐Ÿ“ธ The initial unzip prompt.

ZIP asking for password


๐Ÿ” 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.

Recursive extraction in progress


๐Ÿ’ป How to Use the Script

  1. Save the script above as recursive_unzip.py.
  2. Place it in the same directory as ExtractMe.zip.
  3. Run it:
1
python3 recursive_unzip.py
  1. 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.

image


โœ… 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

image

Now you can open that file and retrieve your flag or next challenge step.

๐Ÿ“ธ The Final extracted File.

Final file extracted


๐Ÿง  Lessons Learned

  • Automating repetitive tasks is essential in CTFs.
  • Always look for patterns โ€” here, the password logic was very systematic.
  • Pythonโ€™s zipfile module is great for handling encrypted ZIPs.

๐Ÿ“Ž Resources


๐Ÿ’ฌ 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!

This post is licensed under CC BY 4.0 by the author.