带有子进程的Python多处理停止工作

2024-10-04 05:31:53 发布

您现在位置:Python中文网/ 问答频道 /正文

你能帮我吗?
-避免程序在~16000次置换后挂起,
-如果找到解决方案(参见输出),
-给我一些建议,让我的代码变得更好、更快,并学习更多关于python的知识?在

我试着用暴力破解我真正的密码容器,因为我忘了密码。我还记得单词,但我忘了组合词。所以我想到了这个剧本。在

它应该怎么做?我给它一个单词表,它应该a)建立所有的排列和b)尝试如果它找到正确的一个。因为我在Windows7上工作,所以我使用True Crypt命令行界面进行尝试,我通过python子进程访问它。在

在写了一个single threaded version之后,我想让它更快一些。我首先尝试了多个线程,然后找到了GIL并使用了多处理。对我来说,这是一次学习经验,我以前从未使用过Python,只知道Java和PHP。我以前从没做过并行编程。在

代码:

import subprocess, os, sys, time, multiprocessing, Queue, itertools

wordlist = [
"foo",
"bar",
"zoo",
"hello",
"World",
]
tcFile = r"C:\dev\tc-brute-force\test.pa"
tcProg = r"C:\Program Files\TrueCrypt\TrueCrypt.exe"
tcMountLetter = "z"
verbose = 5 # as higher as more output is shown fatal=0-5=trace
counter = 0
numberofworkers = multiprocessing.cpu_count()*2
curenttime = time.time()

def getDuration(starttime):
        return time.time() - starttime

def callTC(password, event):
    commandArgs = [
        tcProg,
        '/a',
        '/s',
        '/q',
        '/v', tcFile,
        '/l', tcMountLetter,
        '/p',  password,
    ]

    child = subprocess.Popen(commandArgs, \
        stderr=open(os.devnull, 'w'), \
        stdout=open(os.devnull, 'w'))
    result = child.communicate() # Really important to get error code!

    if verbose > 4:
        print subprocess.list2cmdline(commandArgs).rstrip() + \
            " Status out=" + str(result[0]) + \
            " err=" + str(result[1]) + \
            ", code=" + str(child.returncode)

    if child.returncode == 0:
        event.set()
        print "Successfully opened TrueCrypt file with '%s' at iteration %d, duration %.3fs" % (password, counter, getDuration(curenttime))

def callTCDaemon(queue, event):
    while True:
        if queue.empty():
            break
        else:
            password = queue.get()
            callTC(password, event)

if __name__ == '__main__':

    manager = multiprocessing.Manager()
    event = manager.Event()
    worker = manager.Queue(numberofworkers)

    # start processes
    pool = []
    for i in xrange(numberofworkers):
        process = multiprocessing.Process(target=callTCDaemon, args=(worker, event))
        process.start()
        pool.append(process)

    # generate permutations
    for x in xrange(1, (len(wordlist)+1) ):
        for permutation in itertools.permutations(wordlist, x):

            # shutdown if result is found
            if event.is_set():
                # wait till finished
                for p in pool:
                    p.join(2)

                print "Finished TrueCrypt brute-force, after %d attempts, duration %.3fs" % (counter, getDuration(curenttime))
                sys.exit(1)

            counter += 1    
            combination = ""

            # build string from permutation
            for i in range(0, len(permutation)):
                combination += permutation[i]

            # output progress
            if verbose == 4 and counter%100 == 0:
                print "%15d|%15.3fs: %s" % (counter, getDuration(curenttime), combination)

            # avoid queue overload
            while worker.qsize() > 100:
                if verbose > 3: print "Wait because queue is full, size=%d" % (worker.qsize)
                time.sleep(4)           

            worker.put(combination)

输出示例(稍作修改):

^{pr2}$

Tags: ineventforverboseiftimequeueis
1条回答
网友
1楼 · 发布于 2024-10-04 05:31:53

暴力代码有三个主要部分:

  • 生成密码
  • 检查单个密码
  • 同时检查多个密码

生成密码

产生所有可能的排列:

import itertools

def generate_passwords(wordlist):
    for password_length in range(1, len(wordlist) + 1): # no repeats
        for password in itertools.permutations(wordlist, password_length):
            yield " ".join(password)

检查密码

TRUECRYPT EXPLAINED。也许您不需要为每个密码生成一个子进程。在

^{pr2}$

同时检查多个密码

import sys
from multiprocessing.dummy import Pool # use threads

wordlist = "foo bar zoo hello World".split()
pool = Pool(20) # check 20 passwords in parallel
for i, (found, password) in enumerate(
    pool.imap_unordered(valid_password, generate_passwords(wordlist))):
    if i % 1000 == 0: # report progress
       sys.stderr.write("\rchecked %d" % i)
    if found:
       print("Found: '%s'" % password)
       break
else:
    sys.exit("failed to find")

pool.close() 
####pool.join() # uncomment if it is not the end

除了生成TrueCrypt命令行的true_crypt_command()函数外,它是完整的源代码。在

另一个代码示例:Brute force http basic auth。在

Will imap_unordered stop all the other threads/processes if one reaches rc==0?

如果您在break之后立即退出程序,那么OS会自动杀死所有剩余的线程(它们是守护进程线程,因此它们将无法生存)。在

如果您的程序在循环之后继续运行,那么最多可以继续运行20个线程(池的大小)。如果取消注释pool.join(),则可以等待它们结束。在

相关问题 更多 >