Ich habe mal ein kleines Programm geschrieben um den Schlüssel von Partitionen zu bruteforcen welche mit dm-crypt und LUKS verschlüsselt wurden.
LUKS ist recht langsam bei der Verifizierung des Passwortes, so schaffe ich mit dem Programm auf einem Intel Core Duo mit 1.6 GHz ca. 90.000 Passwörter pro Tag auszuprobieren. Für eine Wörterbuchattacke ist das immernoch gut, wenn man aber alle möglichen Passwörter der Reihe nach ausprobieren möchte dann sollte man die verschlüsselte Partition mehrmals kopieren und dann parallel an den Kopien der Partition arbeiten. Denn mit mehreren Threads an einer Partition zu arbeiten geht leider nicht da dm-crypt die Partition locked während dem Versuch sie aufzusperren.
Das ganze funktioniert nur mit Partition die mit einem Passwort verschlüsselt wurden. Eine mit einer Keyfile verschlüsselte Partition so zu knacken dürfte nahezu unmöglich sein, da die Grösse der Keyfile soviele Möglichkeiten besitzt, dass man schon mehrere tausend Rechner mehrere Jahre rechnen lassen müsste.
Die Benutzung ist recht einfach. Man setzt die richtige Partition im Skript als Variable und startet das Programm dann mit der Passwort-/Wörterbuchdatei als Argument. Da man meist Root-Rechte benötigt um auf die Partition zugreifen zu können sollte man es mit sudo starten.
#!/usr/bin/env ruby # # dm-crypt LUKS bruteforcing script # # Copyright 2009 by Rorschach (r0rschach@lavabit.com) # Licence: GPL3 $VERBOSE=true require 'open3' $partition='/dev/sdXY' $mapper='brute' def error(msg) puts " Error: #{msg}" puts " Aborting now!" exit 1 end def check_if_correct(stderr,stdout) return false if stderr.chomp.chomp == "Command failed: No key available with this passphrase." return true if stdout =~ /^key\sslot\s\d\sunlocked\.$/ case stderr.chomp when "Command failed: Device already exists" error("#{$partition} is already unencrypted and mapped to #{$mapper}.") when "Command failed: Can not access device" error("Wheter #{$partition} does not exist or is already mapped to another device.") else error("An unknown error has occured:\n #{stderr.chomp}") end end if ARGV[0]==nil error("Not enough arguments!\n Usage: #{$0} dictionaryfile") end if not FileTest::exist?(ARGV[0]) error("#{ARGV[0]} doesn't exist.") end File.open(ARGV[0], "r").each_line do |password| puts "Testing: #{password}" Open3.popen3("sudo cryptsetup luksOpen #{$partition} #{$mapper}") do |stdin,stdout,stderr| stdin.puts password.chomp if check_if_correct(stderr.read,stdout.read) puts "\n Correct password found: #{password.chomp}" system("sudo cryptsetup remove #{$mapper}") exit 0 end end end puts "\n Haven't found the correct password." exit 1
Falls auf Grund der Auflösung das Skript oben nicht vollständig dargestellt werden sollte habe ich es hier nochmal hinterlegt.
aber selbst mit 90000 pro tag bräuchtest du eine ganze weile. selbst wenn du 100 gleichzeitig berechnen lässt. jedenfalls wenn man nicht nur 6 zeichen als passwort benutzt.
Das klingt nach ziemlichem Unsinn. Wieso rufst du jedes mal LUKS auf? Du solltest eher den Passwort-Hash extrahieren und das selber machen.
@eeeeeeeeeeeee: Also ich finde nicht, dass es nach Unsinn klingt. Natürlich hast du recht, dass es nicht die schnellste Methode ist sondern wie du richtig sagst, wenn man die einzelnen Keys aus den Slots des Headers extrahiert und dann versucht diese zu knacken. Aber erstens war obiges Skript in 5 Minuten geschrieben und mehr eine kleine Spielerei von mir, welche aber durchaus funktioniert und benutzt werden kann und zweitens wäre der Aufwand zum Brechen der Keys mit einem eigenen Programm relativ gross, da LUKS in seinen Spezifikationen (http://cryptsetup.googlecode.com/svn-history/r42/wiki/LUKS-standard/on-disk-format.pdf) keinen Hash-Alogirthmus festschreibt sondern einen beliebigen erlaubt. Man müsste in das Tool also alle interessanten Hash-Algorithmen integrieren. Wenn eine fehlt die benutzt wurde um den Key zu hashen kann man mit dem Tool das Passwort nicht bruteforcen. Mit dem kleinen Skript von oben kann man es jedoch immer wenn man es auf dem Rechner benutzt welcher die Partition erstellt hat. Aber wie gesagt du hast natürlich recht, dass es nicht die schnellste Methode ist und wenn ich mal Zeit habe werde ich mich mal an der schnelleren Variante versuchen. Der Aufbau des LUKS-Headers ist jedenfalls ziemlich simpel, sollte also kein Problem sein die Daten daraus zu extrahieren.
@Hanna_: Ja aber für eine Wörterbuchattacke, wie gesagt, kann es immernoch ziemlich effektiv sein.
Falsch: LUKS schreibt SHA1 vor (der übrigens auch noch als geknackt gilt).
Und selbst wenn es den nicht vorschreiben müsste, müsste dabei stehen, welcher Hash benutzt wird, sonst kann LUKS selbst auch nichts machen.
Sorry aber das ist einfach nicht richtig. LUKS schreibt keinen Hash-Algirithmus explizit vor, siehe Punkt 2.3 der Specs. Der verwendete Hash-Algorithmus steht aber in der Tat im LUKS-Header drin.
SHA-1 ist aber meistens der Standardalgorithmus.
Der Dativ ist dem Genitiv sein Tod
Punkt 2.4.1 in dem von dir verlinktem Dokument:
> The underlaying hash function is SHA1, we use it solely in LUKS.
Statt die Partitionen zu kopieren reicht es, nur den Header/Anfang zu nehmen. Das kann man dann mit losetup auf loop0 etc. packen. Der Anfang reicht aus, dass cryptsetup das Passwort checken kann. Aber mit cryptsetup ist es echt scheiss lahm.
Also mir hat das Script sehr geholfen, nachdem ich ein Passwort für eine Platte nach einem Jahr im Ausland vergessen hatte und einfach viele Permutationen verschiedener Passphrasen ausprobieren musste, da ich mich zwar genau erinnerte welche Komponenten im Passwort vorkamen, aber nicht in welcher Reihenfolge (so baue ich Passwörter z.B. aus Rechnernamen, Einrichtungsdatum und Ort an dem die Rechner stehen zusammen).
Danke vielmals also – ich stimme voll und ganz zu, das Script hat seinen Platz in der Welt, auch wenn es nicht das schnellste ist!
Ach ja außerdem musste ich das Script anpassen wo es im Quelltext heißt:
Mein cryptsetup wirft es nämlich halb Deutsch halb Englisch aus:
Da wirft’s einem natürlich einen „unknown error“ hin ;).
for i in $(cut -d: -f1 /root/passwdfile.txt); do cryptsetup luksOpen home /dev/sda3 $i;cryptsetup remove home; done
Hey guys.
nice ruby script. I had the problem myself forgotten the correct password. I think it*s pretty useful if you know the pattern and have to try let*s say a few hundred or whatever permutations. But if you’re using bash… why I shouldn*t just use this one line…? I think it does the same job… probably a little slower…
while read line; do echo -n „Testing: $line „; echo -n „$line“ | cryptsetup luksOpen /dev/loop0 king; done < dictfoo.txt
kind regards