Rorschachs Tagebuch

dm-crypt mit LUKS bruteforcen Januar 24, 2009

Filed under: Linux,OpenSource,Sicherheit — Rorschach @ 11:07
Tags: , , ,

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.

 

12 Responses to “dm-crypt mit LUKS bruteforcen”

  1. Hanna_ Says:

    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.

  2. eeeeeeeeeeeee Says:

    Das klingt nach ziemlichem Unsinn. Wieso rufst du jedes mal LUKS auf? Du solltest eher den Passwort-Hash extrahieren und das selber machen.

  3. Rorschach Says:

    @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.

  4. eeeeeeeeeeeee Says:

    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.

  5. Rorschach Says:

    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.

  6. Void Says:

    Der Dativ ist dem Genitiv sein Tod

  7. eeeeeeeeeeeee Says:

    Punkt 2.4.1 in dem von dir verlinktem Dokument:

    > The underlaying hash function is SHA1, we use it solely in LUKS.

  8. Stefan Says:

    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.

  9. Michael Says:

    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!

  10. Michael Says:

    Ach ja außerdem musste ich das Script anpassen wo es im Quelltext heißt:

    Command failed: No key available with this passphrase.

    Mein cryptsetup wirft es nämlich halb Deutsch halb Englisch aus:

    Aufruf fehlgeschlagen: No key available with this passphrase.

    Da wirft’s einem natürlich einen „unknown error“ hin ;).

  11. xxx Says:

    for i in $(cut -d: -f1 /root/passwdfile.txt); do cryptsetup luksOpen home /dev/sda3 $i;cryptsetup remove home; done

  12. jonnyfoo Says:

    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


Hinterlasse einen Kommentar