PKZIP streaming

Description

Applies to master. Hash-mode 17240 arrived after 8.0.0. It reads a ZIP archive itself, where the older PKZIP modes take a hash somebody extracted from one:

$ hashcat -m 17240 -a 0 archive.zip passwords.txt
$ hashcat -m 17240 -a 3 archive.zip ?d?d?d?d?d?d

The point of it is size. The native modes 17200 to 17230 hold the encrypted data in fixed device buffers, so a member larger than those buffers cannot be attacked with them at all. 17240 reads from the file as it goes and its memory use does not depend on the member's size.

It covers traditional ZipCrypto with stored members (method 0) and DEFLATE members (method 8), in single-volume ZIP and ZIP64 archives, data descriptors included. AES and the other strong encryption schemes are not supported, and no streaming makes them supportable: those are different ciphers, not a different container.

Which member it attacks

An archive usually holds several files, and hashcat picks one. By default it takes the smallest supported encrypted member that carries enough data to verify a candidate against, which means at least 4 bytes for a stored member and any content at all for a DEFLATE one.

To choose for yourself, count entries in the central directory from zero and name the index:

$ hashcat -m 17240 --pkzip-member-index 2 -a 0 archive.zip passwords.txt

The count includes directories and members hashcat cannot use, so the index is a position in the archive rather than a position among the attackable files. Naming an empty member, a stored member that is too short, or an unsupported one is an error rather than a silent fall back to another.

What it needs while it runs

  • The archive has to stay where it is and stay unchanged. hashcat opens the path you gave on the command line, never a path stored inside the archive. If the file disappears, moves, changes size or timestamp, or fails a read, the session stops with a task error. That is deliberately distinguished from exhaustion, so a stopped run is never mistaken for a finished one.
  • DEFLATE verification needs zlib at runtime. Stored members are verified without it. This is the same loading scheme compressed wordlists use, so the library is wanted only when it is used.
  • --hook-threads is worth setting. The GPU derives the ZipCrypto keys, checks the encryption header and throws out candidates whose DEFLATE header cannot be right. What survives goes to a host hook that decrypts in 32 KiB chunks, inflates where needed, and checks the full length and CRC32. Each worker keeps its own file handles and buffers per device, and on a stored member the GPU filter is weaker, so a run can end up bound by the CPU or by the disk rather than by the card.

Several passwords can be correct

ZipCrypto is weak enough that more than one candidate can pass every check. Give --keep-guessing if you want hashcat to carry on after the first match rather than treating it as the answer.

Output, and what is switched off

As with the other container modes, the potfile, --show and outfile checking are switched off, and --remove is refused outright because rewriting the hash list would mean rewriting your ZIP file. Use --outfile to keep what you recover.

In that output the hash field is the archive path, so a line can be fed back in as input with the same member selection. An inline hash keeps its inline form.

The inline format

There is a $pkzip-stream$ line as well, which exists for the self-tests and for small oracle vectors rather than for ordinary use:

$pkzip-stream$*METHOD*0*PACKED*UNPACKED*CRC*CHECK*SAMPLE*-

The numeric fields are hexadecimal, CRC has eight digits and CHECK two. SAMPLE is the whole encrypted member including its 12 byte encryption header, and it is capped at 256 bytes, which is why this form is no substitute for pointing hashcat at the file. The experimental earlier format that referenced an external path is rejected, and the path in it is not opened.

Full documentation

  • docs/pkzip-streaming.md, which adds the test invocations and what the direct-input tests cover. It is a master document: there is no release carrying this mode yet
Except where otherwise noted, content on this wiki is licensed under the following license: Public Domain