ZipCracker puts pseudo-encryption repair, dictionary, mask, CRC32 and KPA recovery into one Python script
ZipCracker是Hx0战队出品的一款功能强大的Zip密码破解工具。它集成了字典攻击、掩码攻击、短明文 CRC32 枚举恢复、已知明文攻击、套娃ZIP解压等多种破解模式,并能自动修复伪加密文件。凭借其高性能与多功能的特点,ZipCracker已成为CTF比赛中的一把利器。(ZipCracker by Hx0 team is a tool for cracking passwords on Zip files, great for CTF competitions.)
At a glance
- What is it?
- ZipCracker is a Python tool from the Hx0 team that attacks ZIP archives through several routes at once: dictionary and mask guessing, CRC32 short-plaintext solving, known-plaintext attacks, and recursive recovery of nested archives. It suits CTF solvers and authorised recovery work, but several of its strongest paths depend on unverified candidates or on optional external engines.
- Who is it for?
- Adopt ZipCracker for CTF ZIP challenges and for recovering archives you are authorised to open, particularly when the entries are short or a known-plaintext pair exists. Skip it for AES-protected archives you cannot decrypt, for bulk password spraying against systems you do not own, and for any workflow where an unverified CRC32 candidate could be mistaken for a success.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 13 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One script aimed at CTF ZIP challenges and authorised recovery
ZipCracker is a Python tool for the specific problem of getting back into a ZIP archive whose password you do not have. The project describes itself as a ZIP cracking and recovery tool from the Hx0 team, aimed first at the common ZIP challenge types found in CTF competitions, and second at authorised security testing and recovering your own encrypted backups. Those are the cases worth caring about: a challenge machine, an archive a colleague locked and forgot, a backup you own and cannot open.
What makes it worth a look is consolidation. The techniques that normally sit in separate utilities, such as identifying a fake-encrypted archive, running a wordlist, applying a character mask, solving short plaintexts from CRC32 metadata, executing a known-plaintext attack, and descending into nested archives, are reachable from the same script. One invocation can also detect header entries that look like known plaintext, such as png, zip, exe or pcapng templates, and offer to switch into template mode when the confidence is high enough.
The repository ships test01.zip through test07.zip as worked samples, plus a bundled password list and English and Chinese entry points named ZipCracker.py and ZipCracker_en.py. The last push was on 2026-10-09, and the two most recent releases are v2.2.0 on 2026-10-07 and v2.2.1 on 2026-10-09.
Getting the script running: Python 3.10+ and two optional accelerators
The tool is distributed as a source ZIP package rather than a packaged application, and it runs directly from the extracted directory. Only the Python standard library is required. The script needs at least Python 3.7, with 3.10 or newer recommended. If you see this error on the first run, the documented cause is an outdated interpreter rather than a broken archive:
TypeError: 'type' object is not subscriptableCheck the interpreter version like this:
python --versionTwo optional dependencies change what the tool can do. pyzipper enables AES ZIP handling, and it is installed with:
python3 -m pip install pyzipper -i https://pypi.tuna.tsinghua.edu.cn/simpleIf pyzipper is absent the script asks whether to install it, and answering n skips the offer and continues. bkcrack is the second optional piece, used for faster known-plaintext recovery when the target is not covered by a dictionary or mask. Unlike pyzipper, passing the --bkcrack switch without the engine installed is fatal: the program exits rather than falling back.
A first run needs no arguments beyond a target file. Running the script with just a path tries pseudo-encryption detection and repair first:
python3 ZipCracker.py test01.zipThe samples ship inside the package, so replace the sample names with your own paths.
Default dictionary order and the huge-dictionary escape hatch
The default run does not fire a single method. With a plain path and no options, the tool attempts, in order, the file password_list.txt if it sits in the current working directory, and then every numeric password from one to six digits. The bundled list that ships next to the script is used when no local password_list.txt exists, so the script still finds its wordlist when launched from an unrelated directory. An explicit dictionary file or dictionary directory overrides that behaviour and is used exactly as given.
The default numeric sweep is what makes a bare invocation feel slow on a real archive, and the documentation addresses that directly for very large wordlists:
ZIPCRACKER_SKIP_DICT_COUNT=1 python3 ZipCracker.py target.zip huge_dict.txtSetting that environment variable skips the count stage and hands the run straight to the supplied dictionary. A single custom dictionary file is passed positionally after the archive, and a directory of dictionaries works the same way, with the script treating every file inside it as a source of candidates:
python3 ZipCracker.py test02.zip YourDict.txtpython3 ZipCracker.py test02.zip YourDictDirectoryA mask narrows the search space when the shape of the password is known but the characters are not. Placeholders cover digits, lowercase, uppercase, special characters, and a literal question mark:
python3 ZipCracker.py test04.zip -m '?uali?s?d?d?d'The mask path is worth understanding before you reach for it, because the space it covers is still exponential in the number of unknown positions.
The CRC32 short-plaintext path and its candidate budget
The most interesting mechanism in the script is not brute force at all. For traditional ZIP encryption and entries of one to four bytes, the CRC32 value stored in the archive is enough to solve the plaintext directly, provided the length and the CRC32 metadata are correct, in which case the preimage is unique for that range. Instead of enumerating character combinations, the implementation uses a cached CRC32 linear inverse transform, with at most 32 elimination steps per entry, and it handles binary bytes such as 00 and FF rather than printable characters only.
Budgets are explicit and shared. Each package gets a default allowance of one million candidate or solve attempts and five seconds of computation, and each short-entry solve counts against those limits, so hitting either cap moves the run on to the next attack rather than stalling it. Unencrypted short entries are read directly, and AES entries are skipped by this path entirely. When you supply a dictionary or a mask, the named method is tried first and CRC32 only comes into play after it fails.
Lengths of five to six bytes are the hard case, because CRC32 collisions become possible, so they are skipped by default. The escape hatch is the --crc-candidates switch, which enumerates one or two byte printable prefixes, solves the remaining four bytes, and checks that the whole candidate is printable, inspecting at most 100 or 10000 prefixes depending on budget. Candidates are written to a directory suffixed _crc_candidates beside the output, they never overwrite normal extraction results, and they are explicitly not treated as a success and not allowed to delete the source archive. Password verification continues after a candidate is found, and an unrecovered archive still exits with code 1.
python3 ZipCracker.py target.zip --batch --crc-candidates --crc-max-candidates 10000000 --crc-timeout 10The flag name is the warning label: these are unverified candidates, and the accelerated prefix enumeration does not change that.
Known-plaintext attacks and the compressed-data trap
Known-plaintext mode takes the -kpa switch and either a plaintext file or a password-free ZIP to compare against the target:
python3 ZipCracker.py test05.zip -kpa test05_plain.txtpython3 ZipCracker.py C.zip -kpa M.zipThe matching logic is forgiving. If the argument is a ZIP, the tool looks for an entry with the same name as in the target. If it is a plain file, it still tries to match a same-named entry inside the archive, and if the plaintext ZIP holds only one regular file it uses that. A specific entry can be targeted with -c, and partial knowledge is expressed with an offset plus extra known bytes in hex:
python3 ZipCracker.py secret.zip -kpa part.bin --kpa-offset 78 -x 0 4d5aThe important subtlety is what counts as plaintext. In a known-plaintext attack on a ZIP, the plaintext is the data stream before ZipCrypto encryption, which is not necessarily the file you see after extraction. For a ZIP_STORED entry the original file can be handed over directly. For ZIP_DEFLATED, ZIP_BZIP2 or ZIP_LZMA entries, what gets encrypted is usually the compressed stream, so passing an uncompressed original can produce the error ciphertext is smaller than plaintext. The --kpa-offset switch only expresses the start of known bytes within the pre-encryption stream, and it cannot map an uncompressed file onto the compressed data. The repository keeps a bilingual note on this in docs/KPA_KNOWN_PLAINTEXT_NOTE.md, and the script prefers bkcrack for this mode when it is installed.
Nested archives and unattended recovery with --batch
Nested archives are handled with -r, which recurses into archives found inside archives. The sample designated for this is test06.zip:
python3 ZipCracker.py outer.zip -rBatch mode, added in v2.2.1 alongside the test07 CTF sample, removes the interactive prompts so the tool can run unattended. It answers questions on its own, applies the CRC32 limit and the automatic template calculation without stopping for confirmation, and can write recovered content to a chosen output directory:
python3 ZipCracker.py test07.zip -r --batch -o test07_outThat combination is the closest the tool comes to a pipeline mode, and it is the configuration to reach for when a challenge has several layers. The same release also added faster CRC32 and known-plaintext password checking, support for binary short content, isolation of CRC32 collision candidates, and fixes for password verification on duplicate entry names and for threads hanging on exceptions. Existing commands from earlier versions continue to work, which is a reasonable migration story given that the v2.2.0 release two days earlier was itself about stabilising nested recovery and compatibility.
Budgets still apply in recursive mode. Candidate writing counts toward the cumulative extraction budget for nested work, so a large recursive sweep can hit the shared caps and stop partway through.
Where the approach fails and where it beats plain guessing
The limitations are specific rather than general. AES archives are the clearest boundary. AES encryption is inherently slower than traditional ZipCrypto, and if pyzipper is skipped, genuinely AES protected archives are kept intact and the pointless attempts stop. The CRC32 solver also skips AES entries, and the CRC32 and known-plaintext routes both assume the older ZipCrypto scheme. If the archive is AES protected, the tool keeps the original package and tells you to install pyzipper and rerun.
The comparison worth drawing is against brute force over character combinations. A dictionary or mask run scales with the size of the candidate set, and a six-digit numeric sweep is small while a masked alphabet is not. The CRC32 route sidesteps that entirely for one to four byte entries because it solves rather than searches. For known-plaintext work, the division of labour with bkcrack is that bkcrack does the faster recovery when present and the script falls back to dictionary or mask search when it is not, and asking for bkcrack explicitly without installing it ends the run immediately. For masks, the placeholders cover digits, lowercase, uppercase, special characters and the literal question mark, so a pattern containing anything outside those classes is not expressible.
Two smaller edges are worth knowing. Duplicate entry names caused password verification problems that v2.2.1 fixed, so older copies of the script can behave incorrectly on archives with repeated names. And the licence identifier is not published, which matters more for a tool you might fold into a workflow than the version numbers do.
Maintenance state and what a release cycle actually costs
The project is not archived, and the last push was on 2026-10-09, with v2.2.1 published the same day and v2.2.0 on 2026-10-07. Recent release notes name specific engineering concerns rather than feature lists: stable nested recovery and compatibility fixes in v2.2.0, then batch recovery, CRC32 acceleration, and correctness fixes in v2.2.1. That pattern suggests a tool being tightened rather than expanded, and it means the cost of upgrading is low in effort but non-zero in verification, because behaviour around collisions, duplicate names, and threading changed between the two versions.
Two upgrade checks are worth naming. First, the default numeric sweep is still part of a bare invocation, so the environment variable that skips the count stage matters for large dictionaries. Second, the --bkcrack switch has no fallback path, and an install that silently omits bkcrack turns that switch from an optimisation into an exit. Neither is a configuration file to edit, both are command line arguments and an environment variable, and both are the sort of detail that surfaces on the second run of a script rather than the first.
The licence is listed as unknown, so no permission statement can be read off the repository, and redistribution or inclusion in a commercial workflow cannot be confirmed from what is published here.
Editorial conclusion
Adopt ZipCracker for CTF ZIP challenges and for recovering archives you are authorised to open, particularly when the entries are short or a known-plaintext pair exists. Skip it for AES-protected archives you cannot decrypt, for bulk password spraying against systems you do not own, and for any workflow where an unverified CRC32 candidate could be mistaken for a success. Before trusting it, check the Python version, confirm whether pyzipper and bkcrack are present, and read the exit codes, since a non-zero exit after a candidate hit still means nothing was recovered.
Frequently asked questions
How do I install ZipCracker and run it for the first time?
Download the full ZIP package for the release, extract it, and run the script from inside the ZipCracker-v2.2.1 directory using Python 3.7 or newer, with 3.10 or newer recommended. The first useful run is python3 ZipCracker.py test01.zip, which identifies and repairs pseudo-encrypted archives, and only the Python standard library is required for that.
Can ZipCracker crack an AES encrypted ZIP file?
Not on its own. AES support depends on the optional pyzipper dependency, and without it the tool keeps the original AES package and stops invalid attempts, telling you to install pyzipper and run again. AES is also skipped by the CRC32 short-plaintext solver.
What is the difference between a mask attack and a dictionary attack in ZipCracker?
A dictionary attack tries candidates from a wordlist file or directory, while a mask attack generates candidates from a pattern with placeholders such as ?d for a digit, ?l for a lowercase letter, ?u for an uppercase letter, ?s for a special character and ?? for a literal question mark. The mask path still scales with the number of unknown positions in the pattern.
Why does my known-plaintext run report ciphertext is smaller than plaintext?
Because the known plaintext must be the data stream before ZipCrypto encryption, which for a deflated entry is the compressed stream rather than the extracted file. For ZIP_STORED entries the original file works directly, and --kpa-offset cannot map an uncompressed file onto compressed data.
Does ZipCracker need bkcrack installed?
No, it is optional. If bkcrack is detected the script prefers the faster known-plaintext recovery, and if it is missing the flow continues with dictionary or mask attempts. Passing the --bkcrack switch without the engine installed causes an immediate exit rather than a fallback.
How does the --batch mode change behaviour?
Batch mode answers prompts automatically, applies the CRC32 limit and the automatic template calculation without asking, and can write results to a directory you name with -o. It was added in v2.2.1 together with the test07 CTF sample, and it pairs with -r for unattended nested recovery.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/asaotomo-zipcracker)