1

Я создал многопроцессорный взломщик паролей (используя список слов) для определенной функции, он сократил вдвое время, необходимое по сравнению с использованием одного процесса.Pipon Multiprocessing - Too Slow

Первоначальная проблема в том, что она покажет вам взломанный пароль и прекратит работу, но оставшиеся работники будут продолжать, пока у них не закончится хэш! не идеально.

Мой новый шаг вперед - использовать Manager.Event(), чтобы прервать оставшихся рабочих, это работает так, как я надеялся (после некоторых проб и ошибок), но приложение теперь занимает гораздо больше времени, чем это займет один процесс, Я уверен, что это должно быть связано с функцией if внутри pwd_find(), но я думал, что буду искать совета.

#!/usr/bin/env python 

import hashlib, os, time, math 
from hashlib import md5 
from multiprocessing import Pool, cpu_count, Manager 

def screen_clear(): # Small function for clearing the screen on Unix or Windows 
    if os.name == 'nt': 
     return os.system('cls') 
    else: 
     return os.system('clear') 

cores = cpu_count() # Var containing number of cores (Threads) 

screen_clear() 

print "" 
print "Welcome to the Technicolor md5 cracker" 
print "" 

user = raw_input("Username: ") 
print "" 
nonce = raw_input("Nonce: ") 
print "" 
hash = raw_input("Hash: ") 
print "" 
file = raw_input("Wordlist: ") 
screen_clear() 
print "Cracking the password for \"" + user + "\" using " 
time1 = time.time() # Begins the 'Clock' for timing 

realm = "Technicolor Gateway" # These 3 variables dont appear to change 
qop = "auth" 
uri = "/login.lp" 

HA2 = md5("GET" + ":" + uri).hexdigest() # This hash doesn't contain any changing variables so doesn't need to be recalculated 

file = open(file, 'r') # Opens the wordlist file 
wordlist = file.readlines() # This enables us to use len() 
length = len(wordlist) 

screen_clear() 
print "Cracking the password for \"" + user + "\" using " + str(length) + " words" 

break_points = [] # List that will have start and stopping points 
for i in range(cores): # Creates start and stopping points based on length of word list 
    break_points.append({"start":int(math.ceil((length+0.0)/cores * i)), "stop":int(math.ceil((length+0.0)/cores * (i + 1)))}) 

def pwd_find(start, stop, event): 
    for number in range(start, stop): 
     if not event.is_set(): 
      word = (wordlist[number]) 
      pwd = word.replace("\n","") # Removes newline character 
      HA1 = md5(user + ":" + realm + ":" + pwd).hexdigest() 
      hidepw = md5(HA1 + ":" + nonce +":" + "00000001" + ":" + "xyz" + ":" + qop + ":" + HA2).hexdigest() 
      if hidepw == hash: 
       screen_clear() 
       time2 = time.time() # stops the 'Clock' 
       timetotal = math.ceil(time2 - time1) # Calculates the time taken 
       print "\"" + pwd + "\"" + " = " + hidepw + " (in " + str(timetotal) + " seconds)" 
       print "" 
       event.set() 
       p.terminate 
       p.join 
     else: 
      p.terminate 
      p.join 

if __name__ == '__main__': # Added this because the multiprocessor module sometimes acts funny without it. 

    p = Pool(cores) # Number of processes to create. 
    m = Manager() 
    event = m.Event() 
    for i in break_points: # Cycles though the breakpoints list created above. 
     i['event'] = event 
     a = p.apply_async(pwd_find, kwds=i, args=tuple()) # This will start the separate processes. 
    p.close() # Prevents any more processes being started 
    p.join() # Waits for worker process to end 

if event.is_set(): 
    end = raw_input("hit enter to exit") 
    file.close() # Closes the wordlist file 
    screen_clear() 
    exit() 
else: 
    screen_clear() 
    time2 = time.time() # Stops the 'Clock' 
    totaltime = math.ceil(time2 - time1) # Calculates the time taken 
    print "Sorry your password was not found (in " + str(totaltime) + " seconds) out of " + str(length) + " words" 
    print "" 
    end = raw_input("hit enter to exit") 
    file.close() # Closes the wordlist file 
    screen_clear() 
    exit() 

Edit (для @noxdafox):

def finisher(answer): 
    if answer: 
     p.terminate() 
     p.join() 
     end = raw_input("hit enter to exit") 
     file.close() # Closes the wordlist file 
     screen_clear() 
     exit() 

def pwd_find(start, stop): 
    for number in range(start, stop): 
     word = (wordlist[number]) 
     pwd = word.replace("\n","") # Removes newline character 
     HA1 = md5(user + ":" + realm + ":" + pwd).hexdigest() 
     hidepw = md5(HA1 + ":" + nonce +":" + "00000001" + ":" + "xyz" + ":" + qop + ":" + HA2).hexdigest() 
     if hidepw == hash: 
      screen_clear() 
      time2 = time.time() # stops the 'Clock' 
      timetotal = math.ceil(time2 - time1) # Calculates the time taken 
      print "\"" + pwd + "\"" + " = " + hidepw + " (in " + str(timetotal) + " seconds)" 
      print "" 
      return True 
     elif hidepw != hash: 
      return False 

if __name__ == '__main__': # Added this because the multiprocessor module sometimes acts funny without it. 

    p = Pool(cores) # Number of processes to create. 
    for i in break_points: # Cycles though the breakpoints list created above. 
     a = p.apply_async(pwd_find, kwds=i, args=tuple(), callback=finisher) # This will start the separate processes. 
    p.close() # Prevents any more processes being started 
    p.join() # Waits for worker process to end 
+0

[Это] (http://stackoverflow.com/questions/14579474/multiprocessing-pool-spawning-new-childern-after-terminate-on-linux-python2-7) может быть полезно – sgrg

ответ

1

Вы можете использовать примитивы Pool, чтобы решить вашу проблему. Вам не нужно обмениваться объектами Event, доступ к которым синхронизирован и медленный.

Here Я приводил пример о том, как прекратить пул, учитывая желаемый результат от работника.

Вы можете просто сигнализировать пулу, возвращая определенное значение и завершая пул в обратном вызове.

+0

Спасибо @noxdafox, я пробовал этот метод ранее, но не мог заставить его работать, я думал, что еще один раз буду использовать ваш пост в качестве примера, чтобы следовать, я снова столкнулся с той же проблемой - с помощью 'pdb' я могу посмотрите, что он выполняет функцию обратного вызова один или два раза, а затем завершает работу, даже если 'answer' никогда не будет вызван как« True ». его функция, которая вызывается через обратный вызов: определения функции финишер (ответ): \t если ответ: \t \t p.terminate \t \t p.join \t \t конца = raw_input ("хит вход для выхода") \t \t файл.закрыть() \t \t screen_clear() \t \t выхода() ' – Andy

+0

Я извиняюсь за то, как неаккуратно мой комментарий выглядит, я не знаю этикета для размещения обновленного кода! – Andy

+0

Не уверен, что вы можете публиковать код в комментариях, просто добавьте его в исходное сообщение. Пожалуйста, отправьте код, который вы попробовали. – noxdafox

1

Я думаю, что ваша догадка верна. Вы проверяете примитив синхронизации внутри быстрого цикла. Возможно, я только проверю, установлено ли событие так часто. Вы можете экспериментировать, чтобы найти сладкое место, где вы проверяете его достаточно, чтобы не делать слишком много работы, но не так часто, что вы замедляете программу.

+0

Если бы я должен был двигаться 'if not event.is_set():' за пределами 'для числа в диапазоне (start, stop):' и увеличивать переменную 'cores' (увеличивая количество потоков), все нити будут пытаться и начинаться с того же или они будут ждать, пока пространство не будет бесплатным (я не совсем понимаю, как работает эта многопроцессорная работа), если они ждут тогда, что должно предотвратить их запуск после того, как будет найден ответ - я прав? Я пойду, как только я вернусь домой. – Andy

+0

Все рабочие потоки будут запускаться в одно и то же время, но каждый работник будет работать над функцией и не будет поднимать новую, пока она не завершится, или функция не выпустит GIL. Увидев, что ваш код только планирует одну задачу на одного работника, этот момент является спорным. Если вы планируете свою машину таким образом, чтобы вы делали гораздо больше работников, чем разумно, им придется время делиться своим распределением центрального процессора и может в конечном итоге идти медленно. Но количество рабочих потоков - это то, с чем вы можете играть, чтобы посмотреть, как сделать это как можно быстрее. –