John the Ripper External Mode Scripting erkunden

Kali LinuxBeginner
Jetzt üben

Einleitung

John the Ripper (JtR) ist ein beliebtes und leistungsstarkes Open-Source-Tool zur Überprüfung der Passwortsicherheit und zur Wiederherstellung von Passwörtern. Es kann Passwörter mit verschiedenen Modi knacken, wie z. B. "Single Crack"-Modus, "Wordlist"-Modus und "Incremental"-Modus.

Über diese Standardmodi hinaus bietet JtR einen unglaublich flexiblen "External Mode". Dieser Modus ermöglicht die Verwendung eines externen Programms oder Skripts zur Generierung von Passwortkandidaten. Dies gibt Ihnen die vollständige Kontrolle über die Logik der Passwortgenerierung und ermöglicht es Ihnen, hochgradig angepasste und komplexe Passwortmuster zu erstellen, die mit anderen Modi nicht möglich sind.

In diesem Lab lernen Sie die Grundlagen des External Mode von JtR kennen. Sie beginnen mit dem Verständnis der Grundkonzepte, schreiben, kompilieren und verwenden dann Ihr eigenes benutzerdefiniertes C-Programm zur Generierung von Passwörtern. Sie lernen auch grundlegende Debugging-Techniken und wenden Ihr Wissen auf ein praktischeres Szenario an.

Grundlagen des External Mode verstehen

In diesem Schritt lernen Sie die grundlegenden Konzepte des External Mode von John the Ripper kennen. Dieser Modus funktioniert, indem er ein von Ihnen definiertes externes Programm ausführt. John the Ripper liest dann die Standardausgabe dieses Programms und behandelt jede Zeile als potenziellen Passwortkandidaten.

Diese externen Modi werden in der Konfigurationsdatei john.conf definiert, die sich normalerweise unter /etc/john/john.conf befindet. Jeder externe Modus wird in einem Abschnitt wie [List.External:ModeName] definiert.

Betrachten wir eine bestehende Definition eines externen Modus in der Standardkonfigurationsdatei, um zu sehen, wie sie strukturiert ist. Wir suchen nach dem Modus Keyboard, der Passwortkandidaten basierend auf Tastatur-Walk-Mustern simuliert.

Führen Sie den folgenden Befehl aus, um die Konfiguration des Keyboard-Modus anzuzeigen:

grep -A 10 "\[List.External:Keyboard\]" /etc/john/john.conf

Sie sehen einen Block mit C-ähnlichem Code. Die wichtigste Funktion ist generate(), die für die Erzeugung der Passwortkandidaten verantwortlich ist.

Um einen externen Modus in Aktion zu sehen, können Sie john mit dem Flag --stdout ausführen. Dies weist John an, die generierten Kandidaten auf dem Bildschirm auszugeben, anstatt zu versuchen, einen Hash zu knacken. Testen wir den Keyboard-Modus.

john --stdout --external=Keyboard | head -n 5

Dieser Befehl wählt den externen Modus Keyboard aus und leitet dessen Ausgabe an head weiter, das Ihnen die ersten 5 generierten Passwortkandidaten anzeigt. Die Ausgabe ist eine Zeichenfolge, die Tastaturmuster darstellt.

q
w
e
r
t

Dies demonstriert das Grundprinzip: John the Ripper führt die im externen Modus definierte Logik aus und verwendet deren Ausgabe als Quelle für Passwörter. In den nächsten Schritten erstellen wir unser eigenes Programm, das als Quelle dient.

Ein einfaches External Mode Skript schreiben

In diesem Schritt schreiben und kompilieren Sie Ihr erstes einfaches External Mode Skript mit der Programmiersprache C. Unser Ziel ist es, ein Programm zu erstellen, das eine feste Liste von Passwörtern generiert, und dann John the Ripper so zu konfigurieren, dass es dieses verwendet.

Erstellen Sie zuerst eine C-Quelldatei namens simple_gen.c mit dem nano-Editor.

nano simple_gen.c

Kopieren Sie nun den folgenden C-Code und fügen Sie ihn in den nano-Editor ein. Dieses Programm gibt einfach drei verschiedene Passwörter auf der Standardausgabe aus, jedes in einer neuen Zeile.

#include <stdio.h>

int main() {
    printf("pass1\n");
    printf("pass2\n");
    printf("pass3\n");
    return 0;
}

Drücken Sie Strg+X, dann Y und Enter, um die Datei zu speichern und nano zu beenden.

Kompilieren Sie als Nächstes diesen C-Code mit dem gcc-Compiler in eine ausführbare Datei namens simple_gen.

gcc -o simple_gen simple_gen.c

Nachdem wir nun unsere ausführbare Datei haben, müssen wir John the Ripper mitteilen, wie er sie verwenden soll. Dies tun wir, indem wir eine lokale Kopie der Konfigurationsdatei in unserem Projektverzeichnis erstellen und eine neue Definition für den externen Modus hinzufügen.

cp /etc/john/john.conf ./my_john.conf

Öffnen Sie die neue Datei my_john.conf mit nano.

nano my_john.conf

Scrollen Sie zum Ende der Datei und fügen Sie den folgenden Konfigurationsblock hinzu. Dies definiert einen neuen externen Modus namens MySimple, der unser Programm simple_gen ausführt.

[List.External:MySimple]
void generate()
{
  exec("./simple_gen");
}

Speichern und beenden Sie nano (Strg+X, Y, Enter).

Testen wir schließlich unseren neuen externen Modus. Wir verwenden erneut das Flag --stdout, um die Ausgabe anzuzeigen, und das Flag --config, um John auf unsere benutzerdefinierte Konfigurationsdatei zu verweisen.

john --stdout --external=MySimple --config=./my_john.conf

Sie sollten die exakte Ausgabe unseres C-Programms sehen, was bestätigt, dass John the Ripper erfolgreich unser benutzerdefiniertes Skript ausführt.

pass1
pass2
pass3

Implementierung benutzerdefinierter Passwortgenerierungslogik

In diesem Schritt erweitern Sie Ihr Skript, um eine dynamischere Passwortgenerierungslogik zu implementieren. Anstelle einer festen Liste generieren wir Passwörter basierend auf einem Muster: ein Basiswort gefolgt von einer Zahlenfolge. Dies ist ein gängiges Muster für schwache Passwörter.

Ändern wir unser C-Programm, um Passwörter wie labex0, labex1, labex2 usw. zu generieren.

Öffnen Sie die Datei simple_gen.c erneut mit nano.

nano simple_gen.c

Ersetzen Sie den vorhandenen Code durch den folgenden. Diese neue Version verwendet eine for-Schleife, um die Zahlen von 0 bis 199 an das Basiswort "labex" anzuhängen.

#include <stdio.h>

int main() {
    char *base_word = "labex";
    for (int i = 0; i < 200; i++) {
        printf("%s%d\n", base_word, i);
    }
    return 0;
}

Speichern und beenden Sie nano. Kompilieren Sie das Programm nun mit gcc neu, um die Änderungen zu übernehmen.

gcc -o simple_gen simple_gen.c

Testen wir den aktualisierten Generator mit dem Flag --stdout, um eine Stichprobe der neuen Ausgabe zu sehen.

john --stdout --external=MySimple --config=./my_john.conf | head -n 5

Die Ausgabe sollte nun das neue Muster anzeigen.

labex0
labex1
labex2
labex3
labex4

Nun zum eigentlichen Test. Wir werden unseren benutzerdefinierten externen Modus verwenden, um den Passwort-Hash zu knacken, den wir während der Einrichtung vorbereitet haben. Das Passwort für den testuser ist labex123. Unser Skript generiert diesen Kandidaten, daher sollte es eine Übereinstimmung finden.

Führen Sie den folgenden Befehl aus, um den Knackvorgang zu starten. Beachten Sie, dass wir --stdout entfernt und den Pfad zu unserer Hash-Datei, hashes.txt, hinzugefügt haben.

john --external=MySimple --config=./my_john.conf ./hashes.txt

John wird Ihr Skript ausführen, Kandidaten generieren und diese gegen den Hash testen. Es sollte das Passwort schnell finden. Die Ausgabe wird ungefähr so aussehen:

Using default input encoding: UTF-8
Loaded 1 password hash (sha512crypt, $6$ [SHA512 256/256 AVX2 4x])
Cost 1 (iteration count) is 5000 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
labex123         (testuser)
1g 0:00:00:00 DONE (2024-05-20 08:30) 100.0g/s 12300p/s 12300c/s 12300C/s labex123..labex130
Use the "--show" option to display all of the cracked passwords reliably
Session completed

Um das geknackte Passwort zu bestätigen, verwenden Sie die Option --show.

john --show ./hashes.txt

Dies zeigt das geknackte Passwort neben dem Benutzernamen an.

testuser:labex123:1001:1001::/home/testuser:/bin/sh

1 password hash cracked, 0 left

Debugging von External Mode Skripten

In diesem Schritt lernen Sie einige grundlegende Techniken zum Debuggen Ihrer External Mode Skripte. Wenn ein Skript nicht wie erwartet funktioniert, kann es schwierig sein, die Ursache zu ermitteln, da es von einem anderen Programm (John the Ripper) ausgeführt wird.

Eine gängige und effektive Debugging-Methode ist das Schreiben von Log-Nachrichten aus Ihrem Skript in eine separate Datei. Dies ermöglicht es Ihnen, den Ausführungsfluss zu verfolgen und Variablenwerte zu überprüfen.

Ändern wir unser C-Programm, um in eine Log-Datei namens debug.log zu schreiben. Öffnen Sie simple_gen.c mit nano.

nano simple_gen.c

Ersetzen Sie den Code durch die folgende Version. Dieser Code öffnet debug.log zum Schreiben und verwendet dann fprintf, um während der Ausführung Statusmeldungen dorthin zu schreiben.

#include <stdio.h>
#include <stdlib.h>

int main() {
    FILE *log_file = fopen("debug.log", "w");
    if (log_file == NULL) {
        // Cannot open log file, exit
        return 1;
    }

    fprintf(log_file, "Debug: Script started.\n");

    char *base_word = "labex";
    for (int i = 0; i < 200; i++) {
        printf("%s%d\n", base_word, i);
        fprintf(log_file, "Debug: Generated candidate %s%d\n", base_word, i);
    }

    fprintf(log_file, "Debug: Script finished.\n");
    fclose(log_file);
    return 0;
}

Speichern und beenden Sie nano und kompilieren Sie das Programm dann neu.

gcc -o simple_gen simple_gen.c

Führen Sie nun John the Ripper erneut aus. Wir müssen die Passwortkandidaten nicht sehen, daher können wir die Standardausgabe nach /dev/null umleiten. Wichtig ist, dass unser Skript ausgeführt wird und die Log-Datei erstellt.

john --stdout --external=MySimple --config=./my_john.conf > /dev/null

Der Befehl wird einen Moment lang ausgeführt und dann beendet. Nun sollte eine Datei debug.log in Ihrem Projektverzeichnis vorhanden sein. Sehen wir uns ihren Inhalt an.

cat debug.log | head -n 5

Sie sollten die Debug-Nachrichten sehen, die wir unserem Programm hinzugefügt haben.

Debug: Script started.
Debug: Generated candidate labex0
Debug: Generated candidate labex1
Debug: Generated candidate labex2
Debug: Generated candidate labex3

Diese Technik ist von unschätzbarem Wert, um Probleme in Ihrer Logik zu finden, wie z. B. falsche Schleifen, falsche Variablenwerte oder Fehler beim Dateizugriff, ohne die Störung durch die eigene Ausgabe von John the Ripper.

Anwenden des External Mode auf spezifische Szenarien

In diesem Schritt wenden Sie Ihr Wissen auf ein praxisnäheres Szenario an. Anstatt eines fest codierten Basisworts liest Ihr Skript eine Liste von Basiswörtern aus einer Datei und generiert für jedes davon Variationen. Dies ist ein wesentlich leistungsfähigerer und realistischerer Ansatz.

Erstellen wir zunächst eine einfache Wortlisten-Datei namens words.txt, die einige potenzielle Basiswörter enthält.

echo "admin" > words.txt
echo "user" >> words.txt
echo "guest" >> words.txt

Als Nächstes ändern wir unser C-Programm, um diese Datei zu lesen. Das Programm muss den Namen der Wortlisten-Datei als Kommandozeilenargument akzeptieren. Öffnen Sie simple_gen.c mit nano.

nano simple_gen.c

Ersetzen Sie den Code durch den folgenden. Diese Version liest einen Dateinamen von der Kommandozeile, öffnet diese Datei und generiert für jedes gelesene Wort drei Passwortkandidaten: das Wort selbst, das Wort gefolgt von "123" und das Wort gefolgt von "2024".

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <wordlist_file>\n", argv[0]);
        return 1;
    }

    FILE *file = fopen(argv[1], "r");
    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    char line[256];
    while (fgets(line, sizeof(line), file)) {
        // Remove newline character from the end of the line
        line[strcspn(line, "\n")] = 0;

        // Generate variations for the word
        printf("%s\n", line);
        printf("%s123\n", line);
        printf("%s2024\n", line);
    }

    fclose(file);
    return 0;
}

Speichern, beenden und kompilieren Sie das Programm neu.

gcc -o simple_gen simple_gen.c

Nun müssen wir unsere Datei my_john.conf aktualisieren, um den Dateinamen words.txt als Argument an unser Skript zu übergeben. Erstellen wir dafür einen neuen External Mode namens MyAdvanced. Öffnen Sie my_john.conf mit nano.

nano my_john.conf

Scrollen Sie zum Ende der Datei und fügen Sie diesen neuen Abschnitt hinzu. Beachten Sie, wie "words.txt" als zweiter Parameter an die exec-Funktion übergeben wird.

[List.External:MyAdvanced]
void generate()
{
  exec("./simple_gen", "words.txt");
}

Speichern und beenden Sie nano. Testen Sie abschließend Ihren neuen erweiterten External Mode.

john --stdout --external=MyAdvanced --config=./my_john.conf

Die Ausgabe sollte nun eine Liste von Passwortkandidaten sein, die aus den Wörtern in Ihrer Datei words.txt generiert wurden, wobei die angegebenen Variationen auf jedes angewendet wurden.

admin
admin123
admin2024
user
user123
user2024
guest
guest123
guest2024

Sie haben erfolgreich einen flexiblen, dateigesteuerten Passwortgenerator für John the Ripper erstellt.

Zusammenfassung

Herzlichen Glückwunsch zum Abschluss dieses Labs! Sie haben den leistungsstarken External Mode von John the Ripper erfolgreich erkundet.

In diesem Lab haben Sie gelernt:

  • Das Grundkonzept des External Mode von John the Ripper und wie externe Programme zur Generierung von Passwortkandidaten verwendet werden.
  • Wie man ein einfaches C-Programm schreibt, kompiliert und als Passwortgenerator verwendet.
  • Wie man einen benutzerdefinierten External Mode in der Datei john.conf konfiguriert.
  • Wie man eine dynamische Passwortgenerierungslogik basierend auf Mustern implementiert.
  • Wie man Ihren benutzerdefinierten Modus verwendet, um erfolgreich einen Passwort-Hash zu knacken.
  • Eine grundlegende, aber effektive Technik zum Debuggen Ihrer externen Skripte durch Protokollierung in eine Datei.
  • Wie man ein fortgeschritteneres und praxisnäheres Skript erstellt, das Basiswörter aus einer Datei liest.

Die erworbenen Fähigkeiten bilden die Grundlage für die Erstellung hochspezialisierter Passwort-Cracking-Regeln, die auf spezifische Ziele und Szenarien zugeschnitten sind. Sie können dieses Thema weiter erforschen, indem Sie andere Skriptsprachen wie Python oder Perl verwenden oder noch komplexere Passwortmutations- und Generierungslogiken implementieren.