2017-11-21 4 views
0

Ich erstelle eine Wortliste mit Python, die jede Kombination von Zeichen trifft, die ein Monster einer Berechnung nach 94 ist. Bevor Sie fragen, wo ich 94 bekomme, behandelt 94 ASCII-Zeichen 32 bis 127. Verständlicherweise läuft diese Funktion super langsam, ich bin neugierig, ob es eine Möglichkeit gibt, es effizienter zu machen.Kann dies geändert werden, um schneller zu laufen?

Dies ist das Fleisch und die Kartoffeln der mein Code.

def CreateTable(name,ASCIIList,size): 
    f = open(name + '.txt','w') 
    combo = itertools.product(ASCIIList, repeat = size) 
    for x in combo: 
     passwords = ''.join(x) 
     f.write(str(passwords) + '\n') 
    f.close() 

Ich verwende diese so, dass ich Listen in einer Brute-Force nutzen machen kann, wo ich oder nicht die Länge der Passwörter kennen das Passwort, welche Zeichen enthält. Mit einer solchen Liste treffe ich jede mögliche Kombination von Wörtern, so dass ich sicher bin, dass ich irgendwann die richtige finde. Nachdem ich bereits früher gesagt habe, dass dies ein langsames Programm ist, wird dieses auch langsam eingelesen und wird nicht meine erste Wahl für eine rohe Gewalt sein, dies mehr oder weniger für eine letzte Anstrengung.

Um Ihnen eine Vorstellung davon zu geben, wie lange dieser Codeabschnitt ausgeführt wird. Ich habe alle Kombinationen der Größe 5 erstellt und lief für 3 Stunden mit etwas mehr als 50GB.

+0

Wie lange dauert es? Wie viel schneller brauchst du es? – Blorgbeard

+0

Beachten Sie, dass Sie hier eine ~ 450MB-Datei auf die Festplatte schreiben.Wenn Sie ein weiteres Zeichen hinzufügen, wird es auf ~ 50 ** GB ** gesetzt. Das ist das Problem mit Brute-Force. – Blorgbeard

+0

Um Ihnen eine Vorstellung davon zu geben, wie lange dieses Stück Code läuft. Ich habe alle Kombinationen der Größe 5 erstellt und lief für 3 Stunden mit etwas mehr als 50GB. Ich weiß, dass rohe Gewalt ein langsamer und schmerzhafter Prozess ist, aber manchmal ist es der einzige Weg. Ich brauche nur einen Weg, um 'Combo' in kleineren Brocken zu handhaben, für die @pookie mir die Bodenarbeit gab. – rocky

Antwort

1

Warnung: Ich habe diesen Code nicht getestet.

ich combo auf ein list umwandeln würde: combo_list = list(combo) würde ich es dann in Stücke brechen:

# https://stackoverflow.com/a/312464/596841 
def get_chunks(l, n): 
    """Yield successive n-sized chunks from l.""" 
    for i in range(0, len(l), n): 
     yield l[i:i + n] 

# Change 1000 to whatever works. 
chunks = get_chunks(combo_list, 1000) 

Als nächstes würde ich Multithreading verwenden, um jeden Brocken zu verarbeiten:

class myThread (threading.Thread): 
    def __init__(self, chunk_id, chunk): 
     threading.Thread.__init__(self) 
     self.chunk_id = chunk_id 
     self.chunk = chunk 

    def run(self): 
     print ("Starting " + self.chunk_id) 
     process_data(self.chunk) 
     print ("Exiting " + self.chunk_id) 

def process_data(): 
    f = open(self.chunk_id + '.txt','w') 
    for item in self.chunk: 
     passwords = ''.join(item) 
     f.write(str(passwords) + '\n') 
    f.close() 

Ich würde dann tun Sie etwas wie das:

threads = [] 
for i, chunk in enumerate(chunks): 
    thread = myThread(i, chunk) 
    thread.start() 
    threads.append(thread) 

# Wait for all threads to complete 
for t in threads: 
    t.join() 

Sie könnten dann ein weiteres Skript schreiben, um alle Ausgabedateien zusammenzuführen, falls Sie dies benötigen.

+0

Das ist eigentlich keine schlechte Idee. Ich hatte darüber nachgedacht, die Ausgabe in kleinere Stücke zu teilen und ich hatte auch die Idee, es in mehrere Dateien zu drucken, war mir aber nicht sicher, wo ich anfangen sollte. Ich werde eine Weile mit diesem Code herumspielen. Vielen Dank! – rocky

+0

Großartig, froh, dass ich helfen konnte. Viel Glück und hab Spaß! – pookie

1

Ich habe etwas getestet, und ich denke, das Hauptproblem ist, dass Sie im Textmodus schreiben.

Binär-Modus ist schneller, und Sie haben nur mit ASCII, also können Sie nur Bytes statt Strings spucken.

Hier ist mein Code:

import itertools 
import time 

def CreateTable(name,ASCIIList,size): 
    f = open(name + '.txt','w') 
    combo = itertools.product(ASCIIList, repeat = size) 
    for x in combo: 
     passwords = ''.join(x) 
     f.write(str(passwords) + '\n') 
    f.close() 

def CreateTableBinary(name,ASCIIList,size): 
    f = open(name + '.txt', 'wb') 
    combo = itertools.product(ASCIIList, repeat = size) 
    for x in combo: 
     passwords = bytes(x) 
     f.write(passwords) 
     f.write(b'\n') 
    f.close() 

def CreateTableBinaryFast(name,first,last,size): 
    f = open(name + '.txt', 'wb') 
    x = bytearray(chr(first) * size, 'ASCII') 
    while True: 
     f.write(x) 
     f.write(b'\n') 

     i = size - 1 
     while (x[i] == last) and (i > 0): 
      x[i] = first 
      i -= 1 
     if i == 0 and x[i] == last: 
      break 
     x[i] += 1 
    f.close() 

def CreateTableTheoreticalMax(name,ASCIIList,size): 
    f = open(name + '.txt', 'wb') 
    combo = range(0, len(ASCIIList)**size) 
    passwords = b'A' * size 
    for x in combo: 
     f.write(passwords) 
     f.write(b'\n') 
    f.close() 

print("writing real file in text mode") 
start = time.time() 
chars = [chr(x) for x in range(32, 126)] 
CreateTable("c:/temp/output", chars, 4) 
print("that took ", time.time() - start, "seconds.") 

print("writing real file in binary mode") 
start = time.time() 
chars = bytes(range(32, 126)) 
CreateTableBinary("c:/temp/output", chars, 4) 
print("that took ", time.time() - start, "seconds.") 

print("writing real file in fast binary mode") 
start = time.time() 
CreateTableBinaryFast("c:/temp/output", 32, 125, size) 
print("that took ", time.time() - start, "seconds.") 

print("writing fake file at max speed") 
start = time.time() 
chars = [chr(x) for x in range(32, 126)] 
CreateTableTheoreticalMax("c:/temp/output", chars, 4) 
print("that took ", time.time() - start, "seconds.") 

Ausgang:

writing real file in text mode 
that took 101.5869083404541 seconds. 
writing real file in binary mode 
that took 40.960529804229736 seconds. 
writing real file in fast binary mode 
that took 35.54869604110718 seconds. 
writing fake file at max speed 
that took 26.43029284477234 seconds. 

So kann man eine ziemlich große Verbesserung sieht nur durch binären Modus umgeschaltet wird.

Auch scheint es immer noch ein wenig Spielraum zu haben, da das itertools.product weglassen und hartcodierte Bytes schreiben ist noch schneller. Vielleicht könnten Sie Ihre eigene Version von product schreiben, die Bytes-ähnliche Objekte direkt ausgibt. Nicht sicher, dass.

Bearbeiten: Ich hatte ein Handbuch itertools.product direkt auf einem Bytearray arbeiten. Es ist ein bisschen schneller - siehe "Fast Binary Mode" im Code.

Verwandte Themen