Как я могу уничтожить многопроцессорный пул после того, как мой zip успешно извлечен? - PullRequest
0 голосов
/ 06 февраля 2019

Мне написали .zip brute-forcer, но я считаю, что он продолжает / пытается найти пароль, даже если он найден (пароли хранятся в .txt, который вызывается Program.py -z zipname.zip -f filename.txt

Я не уверен, как остановить программу после того, как пароль найден и остановить пул. В основном потому, что я использую multiprocessing.Pool. Мой код выглядит следующим образом:

import argparse
import multiprocessing
import zipfile

parser = argparse.ArgumentParser(description="Unzips a password protected .zip", usage="Program.py -z zip.zip -f file.txt")
# Creates -z arg
parser.add_argument("-z", "--zip", metavar="", required=True, help="Location and the name of the .zip file.")
# Creates -f arg
parser.add_argument("-f", "--file", metavar="", required=True, help="Location and the name of the file.txt.")
args = parser.parse_args()


def extract_zip(zip_filename, password):
    try:
        with zipfile.ZipFile(zip_filename, 'r') as zip_file:
            zip_file.extractall('Extracted', pwd=password)
            print(f"[+] Password for the .zip: {password.decode('utf-8')} \n")
    except:
        # If a password fails, it moves to the next password without notifying the user. If all passwords fail, it will print nothing in the command prompt.
        pass


def main(zip, file):
    if (zip == None) | (file == None):
        # If the args are not used, it displays how to use them to the user.
        print(parser.usage)
        exit(0)
    # Opens the word list/password list/dictionary in "read binary" mode.
    txt_file = open(file, "rb")
    # Allows 8 instances of Python to be ran simultaneously.
    with multiprocessing.Pool(8) as pool:
        # "starmap" expands the tuples as 2 separate arguments to fit "extract_zip"
        pool.starmap(extract_zip, [(zip, line.strip()) for line in txt_file])


if __name__ == '__main__':
    main(args.zip, args.file)

Теперь обычно file.txtимеет от сотен строк до тысяч строк (под тысячами я действительно имею в виду тысячи; например, 300 КБ или 1500 КБ). Пароль в любом месте; от первой до последней строки. Я не уверен, как внедрить / разместить этот «ручной разрыв» за один разпароль найден. Я думал об использовании break, но это казалось неправильным, так как я работал с multiprocessing.Pool, а также, если бы я поместил его после print() в try/except, это дало бы ошибку outside loop.

Я видел эту ветку , но не был уверен, сработает ли это для моего экземпляра, поскольку я не был уверен, как я могу выразить «пароль найден» и передать event/Event на def extract_zip(zip_filename, password)

Любой онЛП или руководство будет оценено!

1 Ответ

0 голосов
/ 06 февраля 2019

Один из способов сделать это - использовать Queue (или другой способ передачи сигналов между процессами).

Для нас Queue, добавить строки в main, чтобы создать Queue перед созданием Pool:

m = multiprocessing.Manager()
q = m.Queue()

Это дает вам разделяемый Queue, который можно передать процессам пула.Добавьте q к аргументам, передаваемым в ваш метод extract_zip().Затем измените ваш метод extract_zip(), чтобы использовать q:

def extract_zip(zip_filename, password, que):
    try:
        with zipfile.ZipFile(zip_filename, 'r') as zip_file:
            zip_file.extractall('Extracted', pwd=password)
            print(f"[+] Password for the .zip: {password.decode('utf-8')} \n")
            que.put('Done')    # signal success
    except:
        # If a password fails, it moves to the next password without notifying the user. If all passwords fail, it will print nothing in the command prompt.
        pass

. Вам нужно будет использовать async разновидность StarMap.Таким образом, ваш метод main выглядит следующим образом:

def main(zip, file):
    if (zip == None) | (file == None):
        # If the args are not used, it displays how to use them to the user.
        print(parser.usage)
        exit(0)
    # Opens the word list/password list/dictionary in "read binary" mode.
    txt_file = open(file, "rb")

    # create a Queue
    m = multiprocessing.Manager()
    q = m.Queue()

    # Allows 8 instances of Python to be ran simultaneously.
    with multiprocessing.Pool(8) as pool:
        # "starmap" expands the tuples as 2 separate arguments to fit "extract_zip"
        pool.starmap_async(extract_zip, [(zip, line.strip(), q) for line in txt_file])
        pool.close()
        q.get(True)    # wait for a process to signal success
        pool.terminate()    # terminate the pool
        pool.join()

Вы можете добавить timeout к q.get() для обработки случаев, когда пароль не найден.

...