We found on one of our backup CDs an old password protected zip archive, containing several important documents. Since the password for this file were long forgotten, we used elcomSoft's (http://www.elcomsoft.com/) excellent recovery tool (azpr) to brute force the password for up to 7 characters. After seeing we were facing 50 days of brute forcing, we decided to give known-plaintext attack a shot. Here's what happened.
To decrypt a password protected .zip file, you will need the following:
1) A PKZip password protected file.
2) pkcrack toolkit, which can be downloaded from: http://www.unix-ag.uni-kl.de/~conrad/krypto/pkcrack.html
2) Zip compressing software, same that was used to encrypt the original file (see note that follows).
3) Some known plaintext from the encrypted file.
"Why would we want to decrypt a password protected file if we already have its contents in plaintext?"
You don't have to have the entire archive contents in plaintext - you only need a part of it.
PKZip allows us to list the file's contents (even if it is password protected) so we can look at this example file:
Plain text we can use:
My_logo.gif - You will be surprised how easy it is to find images that match the original (of course you need to know more details besides the image name).
Document.doc - We can use known MS-Word header as plaintext, we do not require the entire file. You will need to know the MS-Word version number, but you can guess that as well from the date of the document or simply try all the possibilities.
Setup.exe - executables are (relatively) easy to find on the net.
Let's say we have the original My_logo.gif.
Note on PKZip version:
You don't need to have the exact same version as the one used to encrypt the file. Our original file was from 2001 and the WinZip version we used was the latest (8.1 SR-1).
Now on to Work:
Use extract.exe to get the (encrypted) file from its archive:
extract -p Documents.zip My_logo.gif
If all went ok, a new My_logo.gif will be created.
The -p option tells extract to ignore file path, and simply look for the name. If you have more than one file with the same name, use full path.
Note: when you use 'extract' make sure that in the working dir you don't have another file named My_logo.gif (e.g the plaintext file ) extract will overwrite the file (not good ).
Rename My_logo.gif to My_logoC.gif.
Now let's prep the plaintext:
Create a new zip archive: DocumentsP.zip containing only the plaintext file you have.
Before compressing, choose compression method (in WinZip fast, normal, Maximum etc.)
How to choose? Well, very simple, open your password protected file with WinZip and press File-> Properties. Press "Details" button. WinZip will prompt you for password, give it a dummy or an empty one, and look at the window opened, near each file listed you should be able too see (for WinZip created archive only) the compression method used.
Now run extract for the plaintext:
extract DocumentsP.zip My_logo.gif
And rename My_logo.gif to My_logoP.gif.
Now we have both encrypted file and "stripped" plaintext file.
Verify: If you used an entire file for plaintext and everything went according to plans, the stripped encrypted file (My_logoC.gif) should be exactly 12 bytes longer than the stripped plaintext file (My_logoP.gif).
Baking the Cake:
We'll start the crack with the command:
pkcrack -c My_logoC.gif -p My_logoP.gif
And the resulting output should be something like this:
Files read. Starting stage 1 on Thu Apr 10 11:23:09 2003
Generating 1st generation of possible key2_121049 values...done.
Found 4194304 possible key2-values.
Now we're trying to reduce these...
Lowest number: 991 values at offset 108676
Lowest number: 951 values at offset 108661
Lowest number: 927 values at offset 108649
Lowest number: 907 values at offset 108641
Lowest number: 902 values at offset 108636
Lowest number: 851 values at offset 108635
Lowest number: 803 values at offset 108634
Lowest number: 757 values at offset 108630
Lowest number: 700 values at offset 108208
Lowest number: 676 values at offset 108207
Lowest number: 667 values at offset 108206
Lowest number: 615 values at offset 108200
Lowest number: 597 values at offset 108183
Lowest number: 595 values at offset 108182
Lowest number: 588 values at offset 108180
Lowest number: 563 values at offset 108179
Lowest number: 528 values at offset 108178
Lowest number: 502 values at offset 108177
Lowest number: 497 values at offset 108176
Lowest number: 492 values at offset 108175
Lowest number: 487 values at offset 108159
Lowest number: 484 values at offset 108158
Lowest number: 467 values at offset 108154
Lowest number: 460 values at offset 108152
Lowest number: 447 values at offset 94308
Lowest number: 417 values at offset 94306
Lowest number: 406 values at offset 94304
Lowest number: 381 values at offset 94291
Lowest number: 370 values at offset 94290
Lowest number: 349 values at offset 94284
Lowest number: 344 values at offset 94267
Lowest number: 328 values at offset 64108
Lowest number: 318 values at offset 64107
Lowest number: 313 values at offset 64097
Lowest number: 303 values at offset 64095
Lowest number: 282 values at offset 64094
Lowest number: 271 values at offset 64093
Lowest number: 269 values at offset 64091
Lowest number: 260 values at offset 64090
Lowest number: 257 values at offset 64087
Lowest number: 247 values at offset 64086
Lowest number: 244 values at offset 64085
Lowest number: 233 values at offset 64083
Lowest number: 225 values at offset 64046
Lowest number: 218 values at offset 64045
Lowest number: 193 values at offset 64043
Lowest number: 169 values at offset 64042
Lowest number: 167 values at offset 64023
Lowest number: 152 values at offset 64022
Lowest number: 143 values at offset 64021
Lowest number: 138 values at offset 64019
Lowest number: 129 values at offset 64016
Lowest number: 114 values at offset 18707
Lowest number: 107 values at offset 18706
Lowest number: 98 values at offset 18705
Done. Left with 98 possible Values. bestOffset is 18705.
Stage 1 completed. Starting stage 2 on Thu Apr 10 11:26:58 2003
Ta-daaaaa! key0= f8e40eb, key1= c0c39ec, key2=7e37e79c
Probabilistic test succeeded for 102349 bytes.
Stage 2 completed. Starting password search on Thu Apr 10 11:27:16 2003
Key: 64 6f 63 75 6d 65 6e 74 73 32 Or as a string: 'documents2' (without the enclosing single quotes)
Key: 64 6f 63 75 6d 65 6e 74 73 32
Or as a string: 'documents2' (without the enclosing single quotes)
Finished on Thu Apr 10 11:31:33 2003
Ta-daaaa indeed, 8 minutes later and a couple of CPU years, we cracked a 10 characters length password!
The test ran on P4 1.8 GHZ.
Keep in mind that the smaller the plaintext, the slower the run.
Also remember that before attempting to crack the password, pkcrack outputs the 3 key set used by PKZip. These keys can be used to decrypt the file without having the actual password. The tool 'decrypt' in the pkcrack toolkit does just that.
In comparison to other techniques - with ElcomSoft's azpr we were able to go as fast as 18,000,000 p/s. That's fast! Still, cracking 10 characters password, with only [a-z],[A-Z], and [space] , will take around 2 days on a P4 1.8! Do the math.
Finally, about pkcrack. Pkcrack is an excellent tool, with far more options than shown here. For more details, RTFM.