Cracking encrypted archives (PKZIP: Zip ZipCrypto, Winzip: Zip AES, 7 Zip, RAR)

In this article we’ll see how to crack encrypted archive protected with a password:

  • Using Biham and Kocher plaintext attack on Zip archives (PKZIP) using encryption method ZipCrypto Store (can be extended to ZipCrypto Deflate)
  • Using classic wordlist attack on other encrypted archives: Zip archives (WinZip) using encryption method AES (128,192,256), 7-Zip and RAR.

While most of the software use only AES encrypted ZIPs (or use AES encryption by default), some software still generate ZipCrypto encrypted archives by default. This is because the Microsoft Windows operating system does not allow to generate (without installing a third party software) encrypted Zip files and can only decrypt Zip archives using ZipCrypto, which makes this old and depreciated encryption method still used today.

Note: This article is also available in french 🇫🇷.

Zip

ZipCrypto

Older encrypted ZIP archives can suffer from Biham and Kocher plaintext attack if they use the ZipCrypto Store encryption method. It is also possible if the archive use ZipCrypto Deflate but it is harder since files are compressed before encryption.

To check which encryption algorithm is used you can use 7z:

$ 7z l -slt archive.zip | grep Method
Method = ZipCrypto Store

$ 7z l -slt archive.zip | grep Method
Method = ZipCrypto Deflate

$ 7z l -slt archive.zip | grep Method
Method = AES-256 Deflate

Note: to generate a ZIP archive using ZipCrypto Store we can use the old zip utility: zip -e -0 archive.zip logo_acceis.svg or 7z: 7z a -tzip -mx0 -p -mem=ZipCrypto archive.zip logo_acceis.svg.

To conduct this attack, it requires at least 12 bytes of known plaintext and at least 8 of them must be contiguous. The larger the contiguous known plaintext, the faster the attack.

What’s nice is that the Zip format can’t protect the filenames so even is the archive is encrypted we can still list filenames, retrieve the extension to understand what kind of document is stored and target fixed file signature (aka magic bytes) if you don’t know any content from the encrypted files.

$ 7z l archive.zip

7-Zip [64] 17.04 : Copyright (c) 1999-2021 Igor Pavlov : 2017-08-28
,Utf16=on,HugeFiles=on,64 bits,8 CPUs x64)

Scanning the drive for archives:
1 file, 1694 bytes (2 KiB)

Listing archive: archive.zip

--
Path = archive.zip
Type = zip
Physical Size = 1694

   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2022-04-29 11:09:49 .....         3623         1498  logo_acceis.svg
------------------- ----- ------------ ------------  ------------------------
2022-04-29 11:09:49               3623         1498  1 files

In this archive we can see there is a SVG image, we know that any SVG image will begin with <?xml version="1.0"?> or <?xml version="1.0" encoding="utf-8"?> and maybe will be followed by <svg xmlns="http://www.w3.org/2000/svg" ..., but let’s keep only what is 100% sure: <?xml version="1.0" (19 bytes long), which should be plenty enough for our attack.

We can obtain a free additional byte from CRC, as explained in the ZIP file format specification, a 12-byte encryption header in prepended to the data in the archive. The last byte of the encryption header is the most significant byte of the file’s CRC.

6.1.3 Each encrypted file has an extra 12 bytes stored at the start
of the data area defining the encryption header for that file. The
encryption header is originally set to random values, and then
itself encrypted, using three, 32-bit keys. The key values are
initialized using the supplied encryption password. After each byte
is encrypted, the keys are then updated using pseudo-random number
generation techniques in combination with the same CRC-32 algorithm
used in PKZIP and described elsewhere in this document.

After the header is decrypted, the last 1 or 2 bytes in Buffer
SHOULD be the high-order word/byte of the CRC for the file being
decrypted, stored in Intel low-byte/high-byte order. Versions of
PKZIP prior to 2.0 used a 2 byte CRC check; a 1 byte CRC check is
used on versions after 2.0. This can be used to test if the password
supplied is correct or not.

We can get the CRC of the file using various tools:

$ 7z l -slt archive.zip  logo_acceis.svg | grep CRC
CRC = 1916B617
$ unzip -Z -v archive.zip logo_acceis.svg | grep CRC
  32-bit CRC value (hex):                         1916b617

So the byte just before the plaintext (at offset -1) is 0x19.

Then we can start the attack using bkcrack:

$ printf '<?xml version="1.0"' > plain.svg
$ bkcrack -C archive.zip -c logo_acceis.svg -p plain.svg -x -1 19
  • -C: Zip archive containing cipherfile
  • -c: File containing the ciphertext (the one we target in the archive)
  • -p: File containing the known plaintext
  • -x: Additional plaintext in hexadecimal starting at the given offset

It takes a long time (~24 min for this example) but we are able to recover the encryption keys.
A wordlist attack would be more efficient for weak passwords but this method can help recover files protected with very complex passwords.

$ bkcrack -C archive.zip -c 'logo_acceis.svg' -p plain.bin -x -1 19
bkcrack 1.3.5 - 2022-03-20
[15:07:25] Z reduction using 12 bytes of known plaintext
100.0 % (12 / 12)
[15:07:25] Attack on 573157 Z values at index 6
Keys: 18996980 070e64a5 38e61fb0
86.6 % (496251 / 573157)
[15:31:27] Keys
18996980 070e64a5 38e61fb0

Then to recover the original files we have several options.

We can create a copy archive with a chosen password.

$ bkcrack -C archive.zip -k 18996980 070e64a5 38e61fb0 -U cracked.zip noraj
bkcrack 1.3.5 - 2022-03-20
[15:57:19] Writing unlocked archive cracked.zip with password "noraj"
100.0 % (1 / 1)
Wrote unlocked archive.

Else we can also try to crack the keys to find the original password.

bkcrack can perform bruteforce on the keys but the options are limited and it doesn’t support wordlist attacks.

$ bkcrack -k 18996980 070e64a5 38e61fb0 -r 8 \?a
bkcrack 1.3.5 - 2022-03-20
[16:16:01] Recovering password
length 0-6...
length 7...
length 8...
[16:16:01] Password
as bytes: 6d 6f 72 70 68 65 75 73
as text: morpheus

Concatenating the three keys gives us the PKZIP Master Key that we can try to crack with Hashcat.

$ haiti '18996980070e64a538e61fb0'
CRC-96 (ZIP)
PKZIP Master Key [HC: 20500]
PKZIP Master Key (6 byte optimization) [HC: 20510]
Crypt16

$ hashcat -m 20500 hash-hc.txt /usr/share/wordlists/passwords/rockyou.txt

AES

First we need to extract a crackable hash from the Zip archive. To do so we can use the zip2john script shipped in john package.

$ zip2john archive.zip
archive.zip/logo_acceis.svg:$zip2$*0*3*0*d56b93462995433968b5f3f76eccbaea*5d55*5aa*27b48e12e3164b4dedd49a676c53392544c2c73eb472aab93ab61ce8968c8bfe7780b5de771f5ec32172c99687cf38ec469c35ffb71b2b1b6d2679fcf173970b59e1b9207adf8c9190e394c3346ced7372e149dc91b84ca8b19321cadffa9f5b75514a2f58e9e840778aa70900507ec8dda645bb8c8e066edf98f8f87feb7a2d10aa084fdb39c696f3c92592ba81c543cc11e2dd969de477321abd7639435495e4f1b26f6badb31bd88792b96757936b47b26ed267685bd9240ee11777c42a10e6a5829e64b2dd1a4ae77d8bf80854450385f6e4fd98ac07ed8e0ed852a682133d81ef903b43d534e6f785172b9f078dad64351efdad6e0348983c0407fef4d87c0090989f158bdfbe97e30710869370c70d95aef04ce815cacf8405baa921e0441dd8d69d7e17aed4b8adbc9651732fc1d5d7a2c7ec99af45e25a4047805ee6a88649eda6e170a682c19b20c5bbfe4f5720f425d4afe71d1954c87b3b910213a3f059db5eedeb696d34773482e43f8067248054b520642648b002534acb732dd0bbec6fa4eeee508b25688b0fa70c64a09bb50dc9ead6aa8410f432b982c529b67161db42c00aeba567682856d610c8768c695b562522dd57456062e947b5fc0f4316b7a2a818274e166508e0211125bafc37cbe590de9b44925149a421d3b8c15b05aa82acbc41a6c20c933d6f0ad605506db122d588e1656c540c1c69d58c5f7532933f479f5db305c7d2575275a666c8ee3b7a37ec7f0fcf53fcbe0176df72e188667de4c503956dea8fcc6ec88c868fc3505c4aea03a46e4c395a673ad7981f943dd9457a847eac7fe6758fe98336ef33ce613ddaede21848be50b062984f42d53abb84b7bad59c8d8e39ab55415700a3a416249d8d35098e59a7152ce304e91c541a46418b986b31580820cd19796a739c485c2445b21c5736e1239198a9faf05fe642e26385f90dc082a74fe560fb269bf90529af46b6986cf1ada22e95cf3dc276dd46fdbd501da78991f251556773543e8e6519c4ed4db2d954dd7e9b82e7694f17be9c75a3d5813347f0f5f7bdc8086a06bbc7510bc30b81e9fb31aec599ce018558e06214b42063386ddde083efe25889f262d25640cba5c2c3088d3cfd08263a89922ab6cf7fb3e5887acb20c851e130391a0034029a4400f4b9118f1fa740868da097b7c4529c55dc02c568c6dee5304ffd461e945c2be22d6d2fe5efe94937834035851d584bf7da08d9db49916bb055fb12983e1bce1be997f9e9b3e2f0650eccb250592f3720ba8ed1ee210b795c022b01326047d5fe23ee10058b43950fdd7520dda0cf3ec5c026d767c5cb40599a24da7c49fb4609b69900ad922680e1f3da25afd0d8581c6ff0dad8897a72f4e9a0540b1ba7d8a4d316714adb0543ef3377feeab47e2b6739db092cbe254afb9f9fbe485b971aca0a4fea5f669bf6f71492508e6bc1ace46aec90533e4fdf3c93fc6a1e0897cfcc965f7457d53045ec2a2d5da2b04249894cf920c91f20a03128adbf7d2a4072b287481d4c7714ad8785fae5713666d1308ea90f07d99951a36f687be95d35f7ec1322f7b92e3a0d6615485461cad911472faae76a6b548fa5226c1cca1187245c3ca7978fb19ccb5911d34a158888d3b6a758def7546a21cc0f4120687edc25f798a0583b768f99d5021d35bfefc4f22e0e909e720dc02f9a2350dc8f41c2e092726dcca4cdc45eb0e0d969312d4ee7a79b6856fb8792868ed3e4b97aecb62c61779658b9b55c5fe4606c086bdf88d88dc24a5ff822ae035093a104839acf0566367e13d4b658249db0d947f37e26dbe67d6fe92313d4c5546576000891e3e46c749848d5dd3cb9110709f75f35fd826650a2787a300303583cbeb06f88fe0209482b403fd8fe0cbc88159d420acb0c2f680e96a43087c170a9f07b93748b36359f5a522d0f2354f4d540e0fc45e9f7de99aced9d9ee0ba64dc9b61bc4d9111f439c6d9d79f50b1e3143e259a5a09094dd4a8d946b24564919e5350ed83562df37e2419620c29b0d72f7639d6*d4a4e58a92cbb2a72f38*$/zip2$:logo_acceis.svg:archive.zip:archive.zip
$ rar2john archive.rar > hash.txt

We can use haiti to determine the hash type (we already know) and the corresponding reference for Hashcat (HC) and John the Ripper (JtR):

$ haiti $(cut -d ':' -f 2 hash.txt)
WinZip [HC: 13600] [JtR: zip]

Now we can try a wordlist bruteforce attack on the hash with JtR.

# ~56k tries per second on my machine (Intel i5-1145G7 @ 2.6 GHz), instant crack for the password morpheus
john hash.txt -w=/usr/share/wordlists/passwords/rockyou.txt --format=zip

If we want to try with HC we need to strip the filename from the hash:

$ cut -d ':' -f 2 hash.txt > hash-hc.txt

The cracking with Hashcat has 3 times more tries per second but takes strangely more time:

# ~163k tries per second on my machine (Intel TigerLake-LP GT2 [Iris Xe Graphics]), 20 secs crack for the password morpheus
hashcat -m 13600 hash-hc.txt /usr/share/wordlists/passwords/rockyou.txt

Note: this method can also work for ZipCrypto protected archives. As discusses before wordlist or bruteforce attacks are more efficient for weak passwords but Biham and Kocher plaintext attack could be the only option for complex passwords.

7-zip

First we need to extract a crackable hash from the 7z archive. To do so we can use the 7z2john script shipped in john package but it requires Compress::Raw::Lzma Perl module to work. We can install it with CPAN: cpan install Compress::Raw::Lzma.

Now we can obtain the hash:

$ 7z2john archive.7z
archive.7z:$7z$0$19$0$$16$fece1a2adfc036675b63b8d17fd3f23f$1908987488$128$122$525a8b050266d616bc88c39ef6184bfe642ed3b2efa7a97c1661fe46ffab4fada7501a39702397a38fae8b61289a22a3cdefd85812e637da96e723ded8b41f6def71aab1c5722413eaafba07fc6945cfe495650ef9f36ef5cb98f6f060994359717a3e4e5e3c1ee31139c0ab51140a79804064ad7fa870c5a1d0b97d98ce6934
$ 7z2john archive.7z > hash.txt

Note: the test 7z archive was generated with LZMA2 compression, AES256 encryption and no multi-volume.

We can use haiti to determine the has type (we already know) and the corresponding reference for Hashcat (HC) and John the Ripper (JtR):

$ haiti $(cut -d ':' -f 2 hash.txt)
7-zip [HC: 11600] [JtR: 7z]

Now we can try a wordlist bruteforce attack on the hash with JtR, it’s slow.

# 43 tries per second on my machine (Intel i5-1145G7 @ 2.6 GHz), 5 mins crack for the password morpheus
john hash.txt -w=/usr/share/wordlists/passwords/rockyou.txt --format=7z

If we want to try with HC we need to strip the filename from the hash:

$ cut -d ':' -f 2 hash.txt > hash-hc.txt

The cracking with Hashcat has 3 times more tries per second but is strangely 2 times longer:

# 130 tries per second on my machine (Intel TigerLake-LP GT2 [Iris Xe Graphics]), 10 mins, 44 secs crack for the password morpheus
hashcat -m 11600 hash-hc.txt /usr/share/wordlists/passwords/rockyou.txt

Note: 7z encrypted archives also protect filenames.

RAR

First we need to extract a crackable hash from the RAR archive. To do so we can use the rar2john script shipped in john package.

$ rar2john archive.rar
archive.rar:$rar5$16$0ee908df02e8f7e7697d862388d329eb$15$52eafa34fd7337161521ca986dcc9e8b$8$a887866220451ac5
$ rar2john archive.rar > hash.txt

Note: the test archive was generated in RAR 5.0 format which seems to use AES-256.

We can use haiti to determine the hash type (we already know) and the corresponding reference for Hashcat (HC) and John the Ripper (JtR):

$ haiti $(cut -d ':' -f 2 hash.txt)
SAP CODVN B (BCODE) [HC: 7700] [JtR: sapb]
RAR5 [HC: 13000] [JtR: rar5]

Now we can try a wordlist bruteforce attack on the hash with JtR.

# ~350 tries per second on my machine (Intel i5-1145G7 @ 2.6 GHz), 35 secs crack for the password morpheus
john hash.txt -w=/usr/share/wordlists/passwords/rockyou.txt --format=rar5

If we want to try with HC we need to strip the filename from the hash:

$ cut -d ':' -f 2 hash.txt > hash-hc.txt

The cracking with Hashcat has 5 times more tries per second but takes strangely the same time:

# ~2000 tries per second on my machine (Intel TigerLake-LP GT2 [Iris Xe Graphics]), 40 secs crack for the password morpheus
hashcat -m 13000 hash-hc.txt /usr/share/wordlists/passwords/rockyou.txt

Note: the same method works for RAR3 archives, only HC and JtR references will be different.

Conclusion

Regardless of the archive format, it is recommended to check the encryption method used and choose the most robust one in the options of the software used to generate an encrypted archive.

For the ZIP format in particular, it is recommended to use AES as the encryption method. Indeed, even with a strong password, ZipCrypto is vulnerable by design, so there is a high chance that it is possible to read the documents that the archive contains without knowing the password.

Finally, even if a strong encryption method is used, the use of a weak password can compromise the security of the archive. It is therefore recommended to use a strong password to protect the archive.

Example of the choice of the encryption method in 7-zip:

7-zip

Example of the choice of the encryption method in Ark:

ark

Example of the choice of the encryption method in WinRAR (Checking the box "ZIP legacy encryption" will use ZipCrypto, WinRAR will use AES if not checked):

WinRAR

About the author

Article written by Alexandre ZANNI aka noraj, Penetration Testing Engineer at ACCEIS.

Besoin d’être accompagné en cybersécurité ?