dictionary file. After instantiating a ZipFile class, we open a dictionary file and iterate through and test each word in the dictionary. If the method extractall() executes without error, we print a message indicating the working password. However, if extractall() throws a bad password exception, we ignore the exception and continue trying passwords in the dictionary.
import zipfile
zFile = zipfile.ZipFile(‘evil.zip’)
passFile = open(‘dictionary.txt’)
for line in passFile.readlines():
password = line.strip(‘\n’)
try:
zFile.extractall(pwd=password)
print ‘[+] Password = ‘ + password + ‘\n’
exit(0)
except Exception, e:
pass
Executing our script, we see that it correctly identifies the password for the password-protected zip file.
programmer$ python unzip.py
[+] Password = secret
Let’s clean up our code a little bit at this point. Instead of having a linear program, we will modularize our script with functions.
import zipfile
def extractFile(zFile, password):
try:
zFile.extractall(pwd=password)
return password
except:
return
def main():
zFile = zipfile.ZipFile(‘evil.zip’)
passFile = open(‘dictionary.txt’)
for line in passFile.readlines():
password = line.strip(‘\n’)
guess = extractFile(zFile, password)
if guess:
print ‘[+] Password = ‘ + password + ‘\n’
exit(0)
if __name__ == ‘__main__’:
main()
With our program modularized into separate functions, we can now increase our performance. Instead of trying each word in the dictionary one at a time, we will utilize threads of execution to allow simultaneous testing of multiple passwords. For each word in the dictionary, we will spawn a new thread of execution.
import zipfile
from threading import Thread
def extractFile(zFile, password):
try:
zFile.extractall(pwd=password)
print ‘[+] Found password ‘ + password + ‘\n’
except:
pass
def main():
zFile = zipfile.ZipFile(‘evil.zip’)
passFile = open(‘dictionary.txt’)
for line in passFile.readlines():
password = line.strip(‘\n’)
t = Thread(target=extractFile, args=(zFile, password))
t.start()
if __name__ == ‘__main__’:
main()
Now let’s modify our script to allow the user to specify the name of the zip file to crack and the name of the dictionary file. To do this, we will import the optparse library. We will describe this library better in the next chapter. For the purposes of our script here, we only need to know that it parses flags and optional parameters following our script. For our zip-file-cracker script, we will add two mandatory flags—zip file name and dictionary name.
import zipfile
import optparse
from threading import Thread
def extractFile(zFile, password):
try:
zFile.extractall(pwd=password)
print ‘[+] Found password ‘ + password + ‘\n’
except:
pass
def main():
parser = optparse.OptionParser(“usage%prog “+\
“-f -d ”)
parser.add_option(‘-f’, dest=’zname’, type=’string’,\
help=’specify zip file’)
parser.add_option(‘-d’, dest=’dname’, type=’string’,\
help=’specify dictionary file’)
(options, args) = parser.parse_args()
if (options.zname == None) | (options.dname == None):
print parser.usage
exit(0)
else:
zname = options.zname
dname = options.dname
zFile = zipfile.ZipFile(zname)
passFile = open(dname)
for line in passFile.readlines():
password = line.strip(‘\n’)
t = Thread(target=extractFile, args=(zFile, password))
t.start()
if __name__ == ‘__main__’:
main()
Finally, we test our completed password-protected zip-file-cracker script to ensure it works. Success with a