diff options
Diffstat (limited to 'misc/dict_search')
-rw-r--r-- | misc/dict_search/Makefile | 17 | ||||
-rw-r--r-- | misc/dict_search/README | 22 | ||||
-rw-r--r-- | misc/dict_search/crypt_dict.c | 158 |
3 files changed, 197 insertions, 0 deletions
diff --git a/misc/dict_search/Makefile b/misc/dict_search/Makefile new file mode 100644 index 0000000..0226c98 --- /dev/null +++ b/misc/dict_search/Makefile @@ -0,0 +1,17 @@ +TARGET=crypt_dict +CFLAGS=-O2 -g -Wall -D_GNU_SOURCE +LDLIBS=-lcryptsetup +CC=gcc + +SOURCES=$(wildcard *.c) +OBJECTS=$(SOURCES:.c=.o) + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) -o $@ $^ $(LDLIBS) + +clean: + rm -f *.o *~ core $(TARGET) + +.PHONY: clean diff --git a/misc/dict_search/README b/misc/dict_search/README new file mode 100644 index 0000000..fc6aa44 --- /dev/null +++ b/misc/dict_search/README @@ -0,0 +1,22 @@ +Simple example how to use libcryptsetup +for password search. + +Run: crypt_dict luks|tcrypt <device|image> <dictionary> [cpus] + +luks|tcrypt specified device type (LUKS or TrueCrypt) + +<device|image> is LUKS or TrueCrypt device or image + +<dictionary> is list of passphrases to try +(note trailing EOL is stripped) + +cpus - number of processes to start in parallel + +Format of dictionary file is simple one password per line, +if first char on line is # it is skipped as comment. + +For LUKS, you have it run as root (device-mapper cannot +create dmcrypt devices as nrmal user. Code need +to map keyslots as temporary dmcrypt device.) + +For TrueCrypt devices root privilege is not required. diff --git a/misc/dict_search/crypt_dict.c b/misc/dict_search/crypt_dict.c new file mode 100644 index 0000000..c80d502 --- /dev/null +++ b/misc/dict_search/crypt_dict.c @@ -0,0 +1,158 @@ +/* + * Example of LUKS/TrueCrypt password dictionary search + * + * Copyright (C) 2012 Milan Broz <gmazyland@gmail.com> + * + * Run this (for LUKS as root), + * e.g. ./crypt_dict test.img /usr/share/john/password.lst 4 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/prctl.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <libcryptsetup.h> + +#define MAX_LEN 512 + +static enum { LUKS, TCRYPT } device_type; + +static void check(struct crypt_device *cd, const char *pwd_file, unsigned my_id, unsigned max_id) +{ + FILE *f; + int len, r = -1; + unsigned long line = 0; + char pwd[MAX_LEN]; + + if (fork()) + return; + + /* open password file, now in separate process */ + f = fopen(pwd_file, "r"); + if (!f) { + printf("Cannot open %s.\n", pwd_file); + exit(EXIT_FAILURE); + } + + while (fgets(pwd, MAX_LEN, f)) { + + /* every process tries N-th line, skip others */ + if (line++ % max_id != my_id) + continue; + + len = strlen(pwd); + + /* strip EOL - this is like a input from tty */ + if (len && pwd[len - 1] == '\n') { + pwd[len - 1] = '\0'; + len--; + } + + /* lines starting "#!comment" are comments */ + if (len >= 9 && !strncmp(pwd, "#!comment", 9)) { + /* printf("skipping %s\n", pwd); */ + continue; + } + + /* printf("%d: checking %s\n", my_id, pwd); */ + if (device_type == LUKS) + r = crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, pwd, len, 0); + else if (device_type == TCRYPT) { + struct crypt_params_tcrypt params = { + .flags = CRYPT_TCRYPT_LEGACY_MODES, + .passphrase = pwd, + .passphrase_size = len, + }; + r = crypt_load(cd, CRYPT_TCRYPT, ¶ms); + } + if (r >= 0) { + printf("Found passphrase for slot %d: \"%s\"\n", r, pwd); + break; + } + } + + fclose(f); + crypt_free(cd); + exit(r >= 0 ? 2 : EXIT_SUCCESS); +} + +int main(int argc, char *argv[]) +{ + int i, status, procs = 4; + struct crypt_device *cd; + + if (argc < 4 || argc > 5) { + printf("Use: %s luks|tcrypt <device|file> <password file> [#processes] %d\n", argv[0], argc); + exit(EXIT_FAILURE); + } + + if (argc == 5 && (sscanf(argv[4], "%i", &procs) != 1 || procs < 1)) { + printf("Wrong number of processes.\n"); + exit(EXIT_FAILURE); + } + + if (!strcmp(argv[1], "luks")) + device_type = LUKS; + else if (!strcmp(argv[1], "tcrypt")) + device_type = TCRYPT; + else { + printf("Wrong device type %s.\n", argv[1]); + exit(EXIT_FAILURE); + } + + /* crypt_set_debug_level(CRYPT_DEBUG_ALL); */ + + /* + * Need to create temporary keyslot device-mapper devices and allocate loop if needed, + * so root is required here. + */ + if (getuid() != 0) { + printf("You must be root to run this program.\n"); + exit(EXIT_FAILURE); + } + + /* signal all children if anything happens */ + prctl(PR_SET_PDEATHSIG, SIGHUP); + setpriority(PRIO_PROCESS, 0, -5); + + /* we are not going to modify anything, so common init is ok */ + if (crypt_init(&cd, argv[2]) || + (device_type == LUKS && crypt_load(cd, CRYPT_LUKS1, NULL))) { + printf("Cannot open %s.\n", argv[2]); + exit(EXIT_FAILURE); + } + + /* run scan in separate processes, it is up to scheduler to assign CPUs inteligently */ + for (i = 0; i < procs; i++) + check(cd, argv[3], i, procs); + + /* wait until at least one finishes with error or status 2 (key found) */ + while (wait(&status) != -1 && WIFEXITED(status)) { + if (WEXITSTATUS(status) == EXIT_SUCCESS) + continue; + /* kill rest of processes */ + kill(0, SIGHUP); + /* not reached */ + break; + } + exit(0); +} |