void do_regex_crack(struct db_main *db, const char *regex) { c_simplestring_ptr buffer = c_simplestring_new(); c_iterator_ptr iter = NULL; charset encoding = CHARSET_UTF8; int ignore_case = 0; char word[WORDSIZE]; if (john_main_process) fprintf(stderr, "Warning: regex mode currently can't be " "resumed if aborted\n"); rexgen_setlocale(); status_init(&get_progress, 0); rec_restore_mode(restore_state); rec_init(db, save_state); crk_init(db, fix_state, NULL); iter = c_regex_iterator_cb(regex, ignore_case, encoding, callback); if (!iter) { fprintf(stderr, "Error, invalid regex expression. John exiting now\n"); exit(1); } while (c_iterator_next(iter)) { c_iterator_value(iter, buffer); c_simplestring_to_binary_string(buffer, &word[0], sizeof(word)); c_simplestring_clear(buffer); if (ext_filter((char*)word)) { if (crk_process_key((char*)word)) break; } } c_simplestring_delete(buffer); c_iterator_delete(iter); crk_done(); rec_done(event_abort); }
static void single_init(void) { struct db_salt *salt; log_event("Proceeding with \"single crack\" mode"); progress = 0; length = single_db->format->params.plaintext_length; key_count = single_db->format->params.min_keys_per_crypt; if (key_count < SINGLE_HASH_MIN) key_count = SINGLE_HASH_MIN; if (rpp_init(rule_ctx, SUBSECTION_SINGLE)) { log_event("! No \"single crack\" mode rules found"); fprintf(stderr, "No \"single crack\" mode rules found in %s\n", cfg_name); error(); } rules_init(length); rec_rule = rule_number = 0; rule_count = rules_count(rule_ctx, 0); log_event("- %d preprocessed word mangling rules", rule_count); status_init(get_progress, 0); rec_restore_mode(restore_state); rec_init(single_db, save_state); salt = single_db->salts; do { single_alloc_keys(&salt->keys); } while ((salt = salt->next)); if (key_count > 1) log_event("- Allocated %d buffer%s of %d candidate passwords%s", single_db->salt_count, single_db->salt_count != 1 ? "s" : "", key_count, single_db->salt_count != 1 ? " each" : ""); guessed_keys = NULL; single_alloc_keys(&guessed_keys); crk_init(single_db, NULL, guessed_keys); }
void do_external_crack(struct db_main *db) { unsigned char *internal; c_int *external; log_event("Proceeding with external mode: %.100s", ext_mode); if (!f_generate) { log_event("! No generate() function defined"); fprintf(stderr, "No generate() for external mode: %s\n", ext_mode); error(); } internal = (unsigned char *)int_word; external = ext_word; while (*external) *internal++ = *external++; *internal = 0; status_init(NULL, 0); rec_restore_mode(restore_state); rec_init(db, save_state); crk_init(db, fix_state, NULL); do { c_execute(f_generate); if (!ext_word[0]) break; c_execute(f_filter); if (!ext_word[0]) continue; internal = (unsigned char *)int_word; external = ext_word; while (*external) *internal++ = *external++; *internal = 0; if (crk_process_key(int_word)) break; } while (1); crk_done(); rec_done(event_abort); }
void do_external_crack(struct db_main *db) { unsigned char *internal; c_int *external; log_event("Proceeding with external mode: %.100s", ext_mode); #ifdef HAVE_MPI if (mpi_p > 1) log_event("MPI: each node will process 1/%u of candidates", mpi_p); #endif internal = (unsigned char *)int_word; external = ext_word; while (*external) *internal++ = *external++; *internal = 0; status_init(&get_progress, 0); rec_restore_mode(restore_state); rec_init(db, save_state); crk_init(db, fix_state, NULL); do { c_execute_fast(f_generate); if (!ext_word[0]) break; if (f_filter) { c_execute_fast(f_filter); if (!ext_word[0]) continue; } #ifdef HAVE_MPI // MPI distribution if (mpi_line++ % mpi_p != mpi_id) continue; #endif int_word[0] = ext_word[0]; if ((int_word[1] = ext_word[1])) { internal = (unsigned char *)&int_word[2]; external = &ext_word[2]; do { if (!(internal[0] = external[0])) break; if (!(internal[1] = external[1])) break; if (!(internal[2] = external[2])) break; if (!(internal[3] = external[3])) break; internal += 4; external += 4; } while (1); } int_word[maxlen] = 0; if (crk_process_key(int_word)) break; } while (1); if (!event_abort) progress = 100; // For reporting DONE after a no-ETA run crk_done(); rec_done(event_abort); }
void do_wordlist_crack(struct db_main *db, char *name, int rules) { union { char buffer[2][LINE_BUFFER_SIZE + CACHE_BANK_SHIFT]; ARCH_WORD dummy; } aligned; char *line = aligned.buffer[0], *last = aligned.buffer[1]; struct rpp_context ctx; char *prerule, *rule, *word; char *(*apply)(char *word, char *rule, int split, char *last); int dist_rules, dist_switch; unsigned long my_words, their_words, my_words_left; log_event("Proceeding with wordlist mode"); if (name) { if (!(word_file = fopen(path_expand(name), "r"))) pexit("fopen: %s", path_expand(name)); log_event("- Wordlist file: %.100s", path_expand(name)); } else { word_file = stdin; log_event("- Reading candidate passwords from stdin"); } length = db->format->params.plaintext_length; if (rules) { if (rpp_init(rule_ctx = &ctx, SUBSECTION_WORDLIST)) { log_event("! No wordlist mode rules found"); if (john_main_process) fprintf(stderr, "No wordlist mode rules found in %s\n", cfg_name); error(); } rules_init(length); rule_count = rules_count(&ctx, -1); log_event("- %d preprocessed word mangling rules", rule_count); apply = rules_apply; } else { rule_ctx = NULL; rule_count = 1; log_event("- No word mangling rules"); apply = dummy_rules_apply; } rule_number = 0; line_number = 0; status_init(get_progress, 0); rec_restore_mode(restore_state); rec_init(db, save_state); crk_init(db, fix_state, NULL); prerule = rule = ""; if (rules) prerule = rpp_next(&ctx); /* A string that can't be produced by fgetl(). */ last[0] = '\n'; last[1] = 0; dist_rules = 0; dist_switch = rule_count; /* never */ my_words = ~0UL; /* all */ their_words = 0; if (options.node_count) { int rule_rem = rule_count % options.node_count; const char *now, *later = ""; dist_switch = rule_count - rule_rem; if (!rule_rem || rule_number < dist_switch) { dist_rules = 1; now = "rules"; if (rule_rem) later = ", then switch to distributing words"; } else { dist_switch = rule_count; /* never */ my_words = options.node_max - options.node_min + 1; their_words = options.node_count - my_words; now = "words"; } log_event("- Will distribute %s across nodes%s", now, later); } my_words_left = my_words; if (their_words) { if (line_number) { /* Restored session. line_number is right after a word we've actually used. */ int for_node = line_number % options.node_count + 1; if (for_node < options.node_min || for_node > options.node_max) { /* We assume that line_number is at the beginning of other nodes' block */ if (skip_lines(their_words, line) && /* Check for error since a mere EOF means next rule (the loop below should see * the EOF again, and it will skip to next rule if applicable) */ ferror(word_file)) prerule = NULL; } else { my_words_left = options.node_max - for_node + 1; } } else { /* New session. Skip lower-numbered nodes' lines. */ if (skip_lines(options.node_min - 1, line)) prerule = NULL; } } if (prerule) do { if (rules) { if (dist_rules) { int for_node = rule_number % options.node_count + 1; if (for_node < options.node_min || for_node > options.node_max) goto next_rule; } if ((rule = rules_reject(prerule, -1, last, db))) { if (strcmp(prerule, rule)) log_event("- Rule #%d: '%.100s'" " accepted as '%.100s'", rule_number + 1, prerule, rule); else log_event("- Rule #%d: '%.100s'" " accepted", rule_number + 1, prerule); } else { log_event("- Rule #%d: '%.100s' rejected", rule_number + 1, prerule); goto next_rule; } } while (fgetl(line, LINE_BUFFER_SIZE, word_file)) { line_number++; if (line[0] != '#') { process_word: if ((word = apply(line, rule, -1, last))) { last = word; if (ext_filter(word)) if (crk_process_key(word)) { rules = 0; break; } } next_word: if (--my_words_left) continue; if (skip_lines(their_words, line)) break; my_words_left = my_words; continue; } if (strncmp(line, "#!comment", 9)) goto process_word; goto next_word; } if (ferror(word_file)) break; if (rules) { next_rule: if (!(rule = rpp_next(&ctx))) break; rule_number++; if (rule_number >= dist_switch) { log_event("- Switching to distributing words"); dist_rules = 0; dist_switch = rule_count; /* not anymore */ my_words = options.node_max - options.node_min + 1; their_words = options.node_count - my_words; } line_number = 0; if (fseek(word_file, 0, SEEK_SET)) pexit("fseek"); if (their_words && skip_lines(options.node_min - 1, line)) break; } my_words_left = my_words; } while (rules); crk_done(); rec_done(event_abort || (status.pass && db->salts)); if (ferror(word_file)) pexit("fgets"); if (name) { if (event_abort) progress = get_progress(); else progress = 100; if (fclose(word_file)) pexit("fclose"); word_file = NULL; } }
static void single_init(void) { struct db_salt *salt; log_event("Proceeding with \"single crack\" mode"); if ((words_pair_max = cfg_get_int(SECTION_OPTIONS, NULL, "SingleWordsPairMax")) < 0) words_pair_max = SINGLE_WORDS_PAIR_MAX; progress = 0; length = single_db->format->params.plaintext_length; if (options.force_maxlength && options.force_maxlength < length) length = options.force_maxlength; key_count = single_db->format->params.min_keys_per_crypt; if (key_count < SINGLE_HASH_MIN) key_count = SINGLE_HASH_MIN; /* * We use "short" for buffered key indices and "unsigned short" for buffered * key offsets - make sure these don't overflow. */ if (key_count > 0x8000) key_count = 0x8000; while (key_count > 0xffff / length + 1) key_count >>= 1; if (rpp_init(rule_ctx, pers_opts.activesinglerules)) { log_event("! No \"%s\" mode rules found", pers_opts.activesinglerules); if (john_main_process) fprintf(stderr, "No \"%s\" mode rules found in %s\n", pers_opts.activesinglerules, cfg_name); error(); } rules_init(length); rec_rule = rule_number = 0; rule_count = rules_count(rule_ctx, 0); log_event("- %d preprocessed word mangling rules", rule_count); status_init(get_progress, 0); rec_restore_mode(restore_state); rec_init(single_db, save_state); salt = single_db->salts; do { single_alloc_keys(&salt->keys); } while ((salt = salt->next)); if (key_count > 1) log_event("- Allocated %d buffer%s of %d candidate passwords%s", single_db->salt_count, single_db->salt_count != 1 ? "s" : "", key_count, single_db->salt_count != 1 ? " each" : ""); guessed_keys = NULL; single_alloc_keys(&guessed_keys); crk_init(single_db, NULL, guessed_keys); }
void do_incremental_crack(struct db_main *db, char *mode) { char *charset; int min_length, max_length, max_count; char *extra; FILE *file; struct charset_header *header; unsigned int check; char allchars[CHARSET_SIZE + 1]; char char1[CHARSET_SIZE + 1]; char2_table char2; chars_table chars[CHARSET_LENGTH - 2]; unsigned char *ptr; unsigned int length, fixed, count; unsigned int real_count; int last_length, last_count; int pos; if (!mode) { if (db->format == &fmt_LM) mode = "LanMan"; else if (db->format == &fmt_NETLM) mode = "LanMan"; else if (db->format == &fmt_NETHALFLM) mode = "LanMan"; else mode = "All"; } log_event("Proceeding with \"incremental\" mode: %.100s", mode); if (!(charset = cfg_get_param(SECTION_INC, mode, "File"))) { log_event("! No charset defined"); fprintf(stderr, "No charset defined for mode: %s\n", mode); error(); } extra = cfg_get_param(SECTION_INC, mode, "Extra"); if ((min_length = cfg_get_int(SECTION_INC, mode, "MinLen")) < 0) min_length = 0; if ((max_length = cfg_get_int(SECTION_INC, mode, "MaxLen")) < 0) max_length = CHARSET_LENGTH; max_count = cfg_get_int(SECTION_INC, mode, "CharCount"); if (min_length > max_length) { log_event("! MinLen = %d exceeds MaxLen = %d", min_length, max_length); fprintf(stderr, "MinLen = %d exceeds MaxLen = %d\n", min_length, max_length); error(); } if (min_length > db->format->params.plaintext_length) { log_event("! MinLen = %d is too large for this hash type", min_length); fprintf(stderr, "MinLen = %d exceeds the maximum possible " "length for the current hash type (%d)\n", min_length, db->format->params.plaintext_length); error(); } if (max_length > db->format->params.plaintext_length) { log_event("! MaxLen = %d is too large for this hash type", max_length); fprintf(stderr, "Warning: " "MaxLen = %d is too large for the current hash type, " "reduced to %d\n", max_length, db->format->params.plaintext_length); max_length = db->format->params.plaintext_length; } if (max_length > CHARSET_LENGTH) { log_event("! MaxLen = %d exceeds the compile-time limit of %d", max_length, CHARSET_LENGTH); fprintf(stderr, "\n" "MaxLen = %d exceeds the compile-time limit of %d\n\n" "There are several good reasons why you probably don't " "need to raise it:\n" "- many hash types don't support passwords " "(or password halves) longer than\n" "7 or 8 characters;\n" "- you probably don't have sufficient statistical " "information to generate a\n" "charset file for lengths beyond 8;\n" "- the limitation applies to incremental mode only.\n", max_length, CHARSET_LENGTH); error(); } if (!(file = fopen(path_expand(charset), "rb"))) pexit("fopen: %s", path_expand(charset)); header = (struct charset_header *)mem_alloc(sizeof(*header)); charset_read_header(file, header); if (ferror(file)) pexit("fread"); if (feof(file) || (memcmp(header->version, CHARSET_V1, sizeof(header->version)) && memcmp(header->version, CHARSET_V2, sizeof(header->version))) || !header->count) inc_format_error(charset); if (header->min != CHARSET_MIN || header->max != CHARSET_MAX || header->length != CHARSET_LENGTH) { log_event("! Incompatible charset file: %.100s", charset); fprintf(stderr, "Incompatible charset file: %s\n", charset); error(); } if (header->count > CHARSET_SIZE) inc_format_error(charset); check = (unsigned int)header->check[0] | ((unsigned int)header->check[1] << 8) | ((unsigned int)header->check[2] << 16) | ((unsigned int)header->check[3] << 24); if (!rec_restoring_now) rec_check = check; if (rec_check != check) { log_event("! Charset file has changed: %.100s", charset); fprintf(stderr, "Charset file has changed: %s\n", charset); error(); } fread(allchars, header->count, 1, file); if (ferror(file)) pexit("fread"); if (feof(file)) inc_format_error(charset); allchars[header->count] = 0; if (expand(allchars, extra ? extra : "", sizeof(allchars))) inc_format_error(charset); real_count = strlen(allchars); if (max_count < 0) max_count = CHARSET_SIZE; if (min_length != max_length) log_event("- Lengths %d to %d, up to %d different characters", min_length, max_length, max_count); else log_event("- Length %d, up to %d different characters", min_length, max_count); if ((unsigned int)max_count > real_count) { log_event("! Only %u characters available", real_count); fprintf(stderr, "Warning: only %u characters available\n", real_count); } if (!(db->format->params.flags & FMT_CASE)) switch (is_mixedcase(allchars)) { case -1: inc_format_error(charset); case 1: log_event("! Mixed-case charset, " "but the hash type is case-insensitive"); fprintf(stderr, "Warning: mixed-case charset, " "but the current hash type is case-insensitive;\n" "some candidate passwords may be unnecessarily " "tried more than once.\n"); } if (header->length >= 2) char2 = (char2_table)mem_alloc(sizeof(*char2)); else char2 = NULL; for (pos = 0; pos < (int)header->length - 2; pos++) chars[pos] = (chars_table)mem_alloc(sizeof(*chars[0])); rec_compat = 0; rec_entry = 0; memset(rec_numbers, 0, sizeof(rec_numbers)); status_init(NULL, 0); rec_restore_mode(restore_state); #ifdef WEBAPI if(packet_id) { int ret; // This is a new packet inc_rec_state.initialized = 0; inc_rec_state.words_requested = packet_rounds; inc_rec_state.words_generated = 0; inc_rec_state.cc_0 = -1; inc_rec_state.cc_1 = -1; inc_rec_state.cc_2 = -1; ret = sscanf(packet_state, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%127[^\n]", &rec_entry, &rec_numbers[0], &rec_numbers[1], &rec_numbers[2], &rec_numbers[3], &rec_numbers[4], &rec_numbers[5], &rec_numbers[6], &rec_numbers[7], &inc_rec_state.pos, &inc_rec_state.numbers_cache, &inc_rec_state.cc_0, &inc_rec_state.cc_1, &inc_rec_state.cc_2, inc_rec_state.key_i); if(ret < 14 || ret > 15) { log_event("Invalid packet state, found %d fields in %s", ret, packet_state); // XXX - Handle more gracefully.. error(); } status_init(webapi_inc_get_progress, 0); } #endif rec_init(db, save_state); ptr = header->order + (entry = rec_entry) * 3; memcpy(numbers, rec_numbers, sizeof(numbers)); crk_init(db, fix_state, NULL); last_count = last_length = -1; entry--; while (ptr < &header->order[sizeof(header->order) - 1]) { entry++; length = *ptr++; fixed = *ptr++; count = *ptr++; if (length >= CHARSET_LENGTH || fixed > length || count >= CHARSET_SIZE) inc_format_error(charset); if (entry != rec_entry) memset(numbers, 0, sizeof(numbers)); if (count >= real_count || (fixed && !count)) continue; if ((int)length + 1 < min_length || (int)length >= max_length || (int)count >= max_count) continue; if ((int)length != last_length) { inc_new_length(last_length = length, header, file, charset, char1, char2, chars); last_count = -1; } if ((int)count > last_count) inc_new_count(length, last_count = count, charset, allchars, char1, char2, chars); if (!length && !min_length) { min_length = 1; if (crk_process_key("")) break; } #if 0 log_event("- Trying length %d, fixed @%d, character count %d", length + 1, fixed + 1, count + 1); #endif if (inc_key_loop(length, fixed, count, char1, char2, chars)) break; } crk_done(); rec_done(event_abort); for (pos = 0; pos < (int)header->length - 2; pos++) MEM_FREE(chars[pos]); MEM_FREE(char2); MEM_FREE(header); fclose(file); }
void do_external_crack(struct db_main *db) { unsigned char *internal; c_int *external; int my_words, their_words; log_event("Proceeding with external mode: %.100s", ext_mode); internal = (unsigned char *)int_word; external = ext_word; while (*external) *internal++ = *external++; *internal = 0; seq = 0; status_init(&get_progress, 0); rec_restore_mode(restore_state); rec_init(db, save_state); crk_init(db, fix_state, NULL); my_words = options.node_max - options.node_min + 1; their_words = options.node_min - 1; if (seq) { /* Restored session. seq is right after a word we've actually used. */ int for_node = seq % options.node_count + 1; if (for_node < options.node_min || for_node > options.node_max) { /* We assume that seq is at the beginning of other nodes' block */ their_words = options.node_count - my_words; } else { my_words = options.node_max - for_node + 1; their_words = 0; } } do { c_execute_fast(f_generate); if (!ext_word[0]) break; if (options.node_count) { seq++; if (their_words) { their_words--; continue; } if (--my_words == 0) { my_words = options.node_max - options.node_min + 1; their_words = options.node_count - my_words; } } if (f_filter) { c_execute_fast(f_filter); if (!ext_word[0]) continue; } int_word[0] = ext_word[0]; if ((int_word[1] = ext_word[1])) { internal = (unsigned char *)&int_word[2]; external = &ext_word[2]; do { if (!(internal[0] = external[0])) break; if (!(internal[1] = external[1])) break; if (!(internal[2] = external[2])) break; if (!(internal[3] = external[3])) break; internal += 4; external += 4; } while (1); } int_word[maxlen] = 0; if (options.mask) { if (do_mask_crack(int_word)) break; } else if (crk_process_key(int_word)) break; } while (1); if (!event_abort) progress = 100; // For reporting DONE after a no-ETA run crk_done(); rec_done(event_abort); }