Passwortcracker für Zip-Archiv funktioniert nicht

Code-Stücke können hier veröffentlicht werden.
Antworten
Carola1
User
Beiträge: 3
Registriert: Freitag 18. November 2016, 12:33

Hallo werte Community,
folgendes Program zum cracken von Zip-Archiven liegt vor:

Code: Alles auswählen

# -*- coding: utf-8 -*-

import zipfile
import itertools
import string
import sys
from threading import Thread

boolean = False
zipFile = zipfile.ZipFile("C:/Users/T510a/Desktop/Python.zip")

def crack(zip, pwd):
    print(pwd)
    try:
        zip.extractall(pwd=str.encode(pwd))
        print('Sucess: Password is ' + pwd)
        global boolean 
        boolean = True

    except Exception:
        pass
    
if __name__ == "__main__":
    
    myLetters = string.ascii_letters + string.digits + string.punctuation
    
    for i in range(1,6):
        for j in map(''.join, itertools.product(myLetters,repeat=i)):
            if boolean==True:
                sys.exit()                      
            t = Thread(target=crack, args=(zipFile, j))
            t.start()
Dem Code nach erwarte ich das der try-Block vollständig ausgeführt wird sobald 'zip.extractall(pwd=str.encode(pwd))' ein passendes Passwort ermittelt. Somit also print('Sucess: Password is ' + pwd) ausgeführt wird, die Variable boolean auf globaler Ebene True gesetzt wird und in der main durch die Bedingung if boolean==True: sys.exit() das gesamte Programm beendet wird. Dies geschieht jedoch nicht, es werden ganz stumpf alle Buchstabenkombinationen durchprobiert. Wo liegt mein Denkfehler? Würde mich sehr freuen, wenn mir hier jemand weiterhelfen kann.
Zuletzt geändert von Anonymous am Freitag 18. November 2016, 13:55, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
sebastian0202
User
Beiträge: 168
Registriert: Montag 9. Mai 2016, 09:14
Wohnort: Berlin

Hallo,

Habe mir schnell ein Zip Archiv mit '123' als Passwort erstellt.
Wenn ich deine Variable myLetters nur mit string.digits setze,
findet er ohne Probleme das Passwort.

Bist du sicher, dass dein Passwort gefunden werden kann?

Global ist böse.
Übrigens erzeugst du für jede Passwortprüfung einen Thread.
Dann kannst du auch gleich crack(zipFile, j) aufrufen.
So sollte man Threads nicht nutzen.
Carola1
User
Beiträge: 3
Registriert: Freitag 18. November 2016, 12:33

Danke für die schnelle Antwort sebastian0202!!!
Warum ist global böse?
Mein Passwort ist 'aa' das müsste doch eigentlich gefunden werden können.
Carola1
User
Beiträge: 3
Registriert: Freitag 18. November 2016, 12:33

Uuuiii nun bin ich selbst ein kleinen Schritt weiter gekommen.
Anscheinend darf das Zip-Archiv eine bestimmte Dateigröße nicht überschreiten. :shock:
sebastian0202
User
Beiträge: 168
Registriert: Montag 9. Mai 2016, 09:14
Wohnort: Berlin

Hallo,


mit Global holt man sich viele Probleme ins Boot.

Dein 'aa' Passwort sollte eigentlich gefunden werden.
Habe jetzt mal mein Passwort auf 'aaa' gesetzt.
Wenn ich dein Programm jetzt laufen lassen, findet er 15 Passwörter die stimmen..
Scheint so, als würde das zipfile Modul nicht richtig funktionieren?

Die Größe deines Zipfiles sollte keine Rolle spielen.


Edit:
Das Problem liegt bei der Verschlüsselung.
Man sollte natürlich fürs Packen und Entpacken die Gleiche nehmen :mrgreen:
Zuletzt geändert von sebastian0202 am Freitag 18. November 2016, 14:23, insgesamt 1-mal geändert.
BlackJack

@Carola1: ``global`` ist böse weil globaler Zustand böse ist, weil das eine Menge Probleme und Einschränkungen mit sich bringt. Das betrifft auch `zipFile`, `i`, und `j`, und `t`, die ebenfalls global auf Modulebene verfügbar sind und dort nichts zu suchen haben. Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Reines importieren sollte zudem ohne Seiteneffekte funktionieren, also ohne dass das Hauptprogramm läuft. Das ist zum Beispiel wichtig wenn man in CPython das Ganze tatsächlich parallel ausführen möchte, denn dazu eignen sich Threads hier nicht, da muss man Prozesse verwenden. Über `multiprocessing` oder `concurrent.futures`.

Selbst wenn man es mit Threads macht, sollte eines der beiden Module verwenden weil die einen Pool zur Verfügung stellen, also die Anzahl der gleichzeitig laufenden Threads beschränken. Dein Ansatz ist da fehlerhaft weil die meisten Betriebssysteme die Anzahl von Threads pro Prozesse einschränken und Dein Programm dann mit einer Ausnahme abbricht wenn zu viele Threads gestartet werden.

Wo wird garantiert das `zipfile.ZipFile` threadsicher ist? Das mag zufällig funktionieren, oder aber auch nicht. Solange das nicht explizit garantiert ist, sollte man da pro Thread ein Objekt von erstellen. Würde ich sonst als Fehler im Programm ansehen. Und das ist vielleicht sogar genau das Problem hier. Viele Threads die auf dem inneren Zustand des gleichen Objektes operieren.

Die Namenschreibweise hält sich nicht an den Style Guide for Python Code. Zudem ist `boolean` ein schlechter Name. Den Leser interessiert mehr was der Wert bedeutet und weniger von welchem Grunddatentyp der ist. Das sieht man an der Verwendung im Code.

`crack()` stimmt als Name auch nicht so wirklich und das `my` bei `myLetters` macht keinen Sinn. Einbuchstabige Namen sind selten wirklich beschreibend, und `j` als Laufvariable in einer Schleife an etwas anderes als ganze Zahlen zu binden ist sehr verwirrend.

Expliziter Vergleich mit `True` und `False` ist überflüssig. Da kommt sowieso nur wieder `True` oder `False` bei heraus, also in diesem Fall genau der Wert den `boolean` sowieso schon hatte.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@Carola1: global ist böse, weil globale veränderliche Zustände eine Programm untestbar machen, es kompliziert ist, es zu verstehen und zu Fehlern führt, die schwer zu entdecken sind. Genauso sollte man nicht generell alle Exceptions stillschweigend ignorieren. Bei Deinem Fall ist es höchstwahrscheinlich so, dass irgendein anderer Fehler, der nichts mit "falsches Passwort" zu tun hat, auftritt. Dann sollte man nicht Millionen an Threads gleichzeitig erzeugen, weil das das Betriebssystem überlastet. Hier böte es sich an multiprocessing.Pool.imap_unordered zu benutzen.
Antworten