简体   繁体   中英

Python zipfile library fix

I've got a problem. I've made a simple zip file with password 12345. Now, when I try to extract the password using brute-force, zipfile chooses wrong password. It says it found password aaln0, but the extracted file is completly empty. Is there a way to 'fix' the library? Or is there a replacement for it? Thanks

Program code:

#!/usr/bin/env python
import itertools
import threading
import argparse
import time
import zipfile
import string
global found
found = False

def extract_zip(zFile, password):
    """
    Extract archive with password
    """
    try:
        zFile.extractall(pwd=password)
        write("[+] Password found:", password, "\n")
        global found
        found = True
    except Exception, e:
        pass

def write(*args):
    print "[%s] %s" % (time.ctime(), " ".join(args))

def main_loop(zFile, length):
    """
    Main loop
    """
    write("[*] Python Brute-Force zip cracker")
    write("[*] Zipfile: %s; password length: %s" % (zFile, length))
    try:
        zfile = zipfile.ZipFile(zFile)
    except:
        write("Cannot open zip file")
        exit(1)
    for combo in itertools.imap(''.join, itertools.product(string.letters + string.digits,
                                                            repeat=length)):
        if found:
            break
        thread = threading.Thread(target=extract_zip, args=(zfile, combo))
        thread.start()
    if not found:
        write("[-] Password not found")

def main():
    """
    Main function
    """
    parser = argparse.ArgumentParser(usage="brute-force-zipcracker.py -f <zipfile> -l <password length>")
    parser.add_argument("-f", "--zipfile", help="specify zip file", type=str)
    parser.add_argument("-l", "--length", type=int, help="password length", default=5)
    args = parser.parse_args()
    if (args.zipfile == None):
        print parser.usage
        exit(0)

    main_loop(args.zipfile, args.length)

if __name__ == '__main__':
    main()

First of all, you're doing:

for combo in itertools.imap(...):
    if found:
        break
    thread = ...
    thread.start()
if not found:
    ...

Just look at it for a second.
found is defined in a thread, but you're starting multiple threads and you globally hope that it will be set in one of the threads. How can you ensure that the correct thread has done the proper job? What if there's a false positive in one of the threads and you don't bother to retrieve the value from each individual thread. Careful with your threads!

Secondly, if the threads don't finish in time for your combo loop you'll end up in if not found because the threads haven't finished running yet to find what you're looking for, especially if you have a larger zip-file that takes a few seconds to complete (a successful password would start unzipping the file and it could take minutes, and found will not be set until that process is done).

And finally it would be neat to get the parameters used to protect this zip-file.

Edit:

You could also give us more information in the format of:

zFile.debug(3)
zFile.testzip()
zFile.extractall(pwd=password)

And other useful things from zipfile.ZipInfo(filename)

To the solution then

#!/usr/bin/env python
import itertools
import argparse
import zipfile
import string

def extract_zip(filename, password):
    try:
        zFile = zipefile.ZipFile(filename)
        zFile.extractall(pwd=password)
        return True
    except zipfile.BadZipFile:
        return False

def main_loop(filename, length):
    print("[*] Python Brute-Force zip cracker")
    print("[*] Zipfile: %s; password length: %s" % (zFile, length))
    cracked = False
    for combo in itertools.imap(''.join, itertools.product(string.letters + string.digits, repeat=length)):
        cracked = extract_zip(filename, combo)
        if cracked:
            print('Yaay your password is:',combo)
            break
    if not cracked:
        print('Sorry, no luck..')
def main():
    parser = argparse.ArgumentParser(usage="brute-force-zipcracker.py -f <zipfile> -l <password length>")
    parser.add_argument("-f", "--zipfile", help="specify zip file", type=str)
    parser.add_argument("-l", "--length", type=int, help="password length", default=5)
    args = parser.parse_args()
    if (args.zipfile == None):
        print parser.usage
        exit(0)

    main_loop(args.zipfile, args.length)

if __name__ == '__main__':
    main()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM