diff options
Diffstat (limited to 'misc/dict_search/crypt_dict.c')
-rw-r--r-- | misc/dict_search/crypt_dict.c | 158 |
1 files changed, 158 insertions, 0 deletions
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); +} |