Contents

Password Recovery for ZIP Archive Using Hashcat

Goal: recover the archive password.
We will use the hashcat utility to search for the password using a dictionary and mask attack.

Let’s create a test archive containing the secret file flag.txt and set a password on the archive:

# zip -e secret.zip flag.txt

Enter password:
Verify password:
  adding: flag.txt (stored 0%)

The archive is created. We can list the files inside:

# unzip -l secret.zip

Archive:  secret.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
       76  2025-06-17 13:51   flag.txt
---------                     -------
       76                     1 file

Extracting flag.txt without the password fails:

# unzip -p secret.zip flag.txt

[secret.zip] flag.txt password:
password incorrect--reenter:
password incorrect--reenter:

Extract the password hash:

# zip2john secret.zip | cut -d':' -f2 > hashes.txt

ver 1.0 efh 5455 efh 7875 secret.zip/flag.txt PKZIP Encr: 2b chk, TS_chk, cmplen=88, decmplen=76, crc=7AF43AA6 ts=6E7D cs=6e7d type=0

Check the contents of the hashes.txt file:

# cat hashes.txt

$pkzip$1*2*2*0*58*4c*7af43aa6*0*42*0*58*6e7d*c6a72dece19b5ba535806c44639f46c2ef9a67e612ae82cb5e48d29832e5675a9494f5686c16f42749234bbe2f0c346e5e8782c115e824893d96ac30ce5edd2c7aa7e06a764e3fae4932fd56f0dc31ea9419943f4d330913*$/pkzip$

Determine which hashing algorithm to use:

# hashcat --identify hashes.txt
The following 2 hash-modes match the structure of your input hash:

      # | Name                                 | Category
  ======+======================================+==============
  17225 | PKZIP (Mixed Multi-File)             | Archive
  17210 | PKZIP (Uncompressed)                 | Archive

Start the password recovery process using a dictionary:

# hashcat -m 17225 -a 0 hashes.txt ./rockyou.txt

hashcat (v6.2.6) starting

OpenCL API (OpenCL 3.0 PoCL 6.0+debian  Linux, None+Asserts, RELOC, SPIR-V, LLVM 18.1.8, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
====================================================================================================================================================
* Device #1: cpu, 6959/13983 MB (2048 MB allocatable), 10MCU

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256

Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1

Optimizers applied:
* Not-Iterated
* Single-Hash
* Single-Salt

Watchdog: Hardware monitoring interface not found on your system.
Watchdog: Temperature abort trigger disabled.

Host memory required for this attack: 2 MB

Dictionary cache hit:
* Filename..: ./rockyou.txt
* Passwords.: 14344384
* Bytes.....: 139921497
* Keyspace..: 14344384

$pkzip$1*2*2*0*58*4c*7af43aa6*0*42*0*58*6e7d*c6a72dece19b5ba535806c44639f46c2ef9a67e612ae82cb5e48d29832e5675a9494f5686c16f42749234bbe2f0c346e5e8782c115e824893d96ac30ce5edd2c7aa7e06a764e3fae4932fd56f0dc31ea9419943f4d330913*$/pkzip$:pacman25

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 17225 (PKZIP (Mixed Multi-File))
Hash.Target......: $pkzip$1*2*2*0*58*4c*7af43aa6*0*42*0*58*6e7d*c6a72d...pkzip$
Time.Started.....: Tue Jun 17 16:53:50 2025 (1 sec)
Time.Estimated...: Tue Jun 17 16:53:51 2025 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (./rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:  5240.8 kH/s (0.97ms) @ Accel:1024 Loops:1 Thr:1 Vec:4
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 4843520/14344384 (33.77%)
Rejected.........: 0/4843520 (0.00%)
Restore.Point....: 4833280/14344384 (33.69%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Device Generator
Candidates.#1....: paiboon2502 -> paafdo

Started: Tue Jun 17 16:53:49 2025
Stopped: Tue Jun 17 16:53:52 2025

The password pacman25 was found in 3 seconds.

If the password is not in the dictionary but some information about the password format is known, you can use a mask.

For example, suppose we know the password consists of 6 lowercase letters followed by 2 digits.
The mask would be ?l?l?l?l?l?l?d?d, where ?l stands for a lowercase letter and ?d for a digit.
Let’s apply the mask to search for the password:

# hashcat -m 17225 -a 3 hashes.txt "?l?l?l?l?l?l?d?d"

hashcat (v6.2.6) starting

OpenCL API (OpenCL 3.0 PoCL 6.0+debian  Linux, None+Asserts, RELOC, SPIR-V, LLVM 18.1.8, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
====================================================================================================================================================
* Device #1: cpu, 6959/13983 MB (2048 MB allocatable), 10MCU

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256

Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates

Optimizers applied:
* Not-Iterated
* Single-Hash
* Single-Salt
* Brute-Force

Watchdog: Hardware monitoring interface not found on your system.
Watchdog: Temperature abort trigger disabled.

Host memory required for this attack: 2 MB

$pkzip$1*2*2*0*58*4c*7af43aa6*0*42*0*58*6e7d*c6a72dece19b5ba535806c44639f46c2ef9a67e612ae82cb5e48d29832e5675a9494f5686c16f42749234bbe2f0c346e5e8782c115e824893d96ac30ce5edd2c7aa7e06a764e3fae4932fd56f0dc31ea9419943f4d330913*$/pkzip$:pacman25

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 17225 (PKZIP (Mixed Multi-File))
Hash.Target......: $pkzip$1*2*2*0*58*4c*7af43aa6*0*42*0*58*6e7d*c6a72d...pkzip$
Time.Started.....: Tue Jun 17 16:57:35 2025 (4 mins, 31 secs)
Time.Estimated...: Tue Jun 17 17:02:06 2025 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Mask.......: ?l?l?l?l?l?l?d?d [8]
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 58531.9 kH/s (10.98ms) @ Accel:128 Loops:512 Thr:1 Vec:4
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 15755960320/30891577600 (51.00%)
Rejected.........: 0/15755960320 (0.00%)
Restore.Point....: 896000/1757600 (50.98%)
Restore.Sub.#1...: Salt:0 Amplifier:5632-6144 Iteration:0-512
Candidate.Engine.: Device Generator
Candidates.#1....: itshnq14 -> jebume25

Started: Tue Jun 17 16:57:33 2025
Stopped: Tue Jun 17 17:02:07 2025

The password pacman25 was found in 5 minutes.

The main challenge here is speed. The fewer possible combinations in the mask, the faster the search.
For overly broad masks, there is a high chance you won’t get a result in a reasonable time.

Let’s try to read the contents of the flag.txt file using the recovered password:

# unzip -p secret.zip flag.txt

[secret.zip] flag.txt password:
RED_BLUE_STRATEGY{SUPER_SECRET_FLAG} - 7c6ed1ff-de8b-4a6d-b145-6f85cfbbb6fa