Skip to content

Commit b3f441c

Browse files
committed
Have --catch-up=SESSION add the new hash files to SESSION
After the --catch-up=SESSION run caught up, its input files are now added to SESSION's recovery file so that it can simply be resumed for continuing with its old files as well as the new ones. This can be disabled with a new --no-catch-up-add option.
1 parent d8f5b01 commit b3f441c

File tree

7 files changed

+106
-14
lines changed

7 files changed

+106
-14
lines changed

doc/NEWS

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,9 @@ Major changes from 1.9.0-jumbo-1 (May 2019) in this bleeding-edge version:
210210

211211
- Add new option --catch-up=NAME, for running a new session only until it
212212
reaches the candidates tried count of a different, existing and paused
213-
session, then exit. [magnum; 2021]
213+
session, then exit. Unless the --no-catch-up-add option is also given,
214+
the new input hashes (file names) used for the new session will be added
215+
to the old session file once caught up. [magnum; 2021, 2026]
214216

215217
- Add BestCrypt Volume Encryption V4 format. [Jean-Christophe Delaunay; 2021]
216218

doc/OPTIONS

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,9 +229,11 @@ numbers printed on the status line mean?"
229229
Limit the session to running only until it reaches the candidates tried
230230
count of a different, existing and paused session NAME. This can be
231231
used for adding more hashes to an existing job: After the new session
232-
finishes, just concatenate the new hashes to the older session's hash
233-
file and resume the old session. This will end up more or less as if
234-
both sets of hashes were in the original session to start with.
232+
finishes, the new hashes (file names) will be added to the older session
233+
file so you can just resume that session. This will end up just as if both
234+
sets of hashes were in the original session to start with, with no wasted
235+
resources or time (assuming salted hashes). If you do not wish the original
236+
session file to be touched, also add the --no-catch-up-add option.
235237

236238
--make-charset=FILE make a charset, overwriting FILE
237239

src/john.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* This file is part of John the Ripper password cracker,
33
* Copyright (c) 1996-2024 by Solar Designer
4-
* Copyright (c) 2009-2025, magnum
4+
* Copyright (c) 2009-2026, magnum
55
* Copyright (c) 2021, Claudio
66
* Copyright (c) 2009-2018, JimF
77
*
@@ -1954,10 +1954,15 @@ static void john_done(void)
19541954
mask_iter_warn);
19551955
}
19561956
if (event_abort && options.catchup && john_max_cands && status.cands >= john_max_cands) {
1957+
if (options.catchup_add)
1958+
rec_add_files(options.catchup);
19571959
event_abort = 0;
1958-
log_event("Done catching up with '%s'", options.catchup);
1959-
if (john_main_process)
1960-
fprintf(stderr, "Done catching up with '%s'\n", options.catchup);
1960+
log_event("Done catching up with '%s'%s", options.catchup,
1961+
options.catchup_add ? ", and added this session's password file(s) to it" : "");
1962+
if (john_main_process) {
1963+
fprintf(stderr, "Done catching up with '%s'%s\n", options.catchup,
1964+
options.catchup_add ? ", and added this session's password file(s) to it" : "");
1965+
}
19611966
}
19621967
if (event_abort) {
19631968
char *abort_msg = (aborted_by_timer) ?

src/options.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/*
22
* This file is part of John the Ripper password cracker,
33
* Copyright (c) 1996-2025 by Solar Designer
4-
*
5-
* ...with changes in the jumbo patch, by JimF and magnum (and various others?)
4+
* Copyright (c) 2009-2026, magnum
5+
* Copyright (c) 2009-2018, JimF
66
*
77
* Redistribution and use in source and binary forms, with or without
88
* modification, are permitted.
@@ -139,6 +139,7 @@ static struct opt_entry opt_list[] = {
139139
{"restore", FLG_RESTORE_SET, FLG_RESTORE_CHK, 0, ~FLG_RESTORE_SET & ~GETOPT_FLAGS, OPT_FMT_STR_ALLOC, &options.session},
140140
{"session", FLG_SESSION, FLG_SESSION, FLG_CRACKING_SUP, OPT_REQ_PARAM, OPT_FMT_STR_ALLOC, &options.session},
141141
{"catch-up", FLG_ONCE, 0, 0, OPT_REQ_PARAM, OPT_FMT_STR_ALLOC, &options.catchup},
142+
{"catch-up-add", FLG_ONCE, 0, 0, USUAL_REQ_CLR | OPT_TRISTATE, NULL, &options.catchup_add},
142143
{"status", FLG_STATUS_SET, FLG_STATUS_CHK, 0, ~FLG_STATUS_SET & ~GETOPT_FLAGS, OPT_FMT_STR_ALLOC, &options.session},
143144
{"make-charset", FLG_MAKECHR_SET, FLG_MAKECHR_CHK, 0, FLG_CRACKING_CHK | FLG_SESSION | OPT_REQ_PARAM, OPT_FMT_STR_ALLOC, &options.charset},
144145
{"show", FLG_SHOW_SET, FLG_SHOW_CHK, 0, FLG_CRACKING_SUP | FLG_MAKECHR_CHK, OPT_FMT_STR_ALLOC, &show_uncracked_str},
@@ -332,6 +333,8 @@ JOHN_USAGE_FORK \
332333
"--no-log Disables creation and writing to john.log file\n" \
333334
"--bare-always-valid=Y Treat bare hashes as valid (Y/N)\n" \
334335
"--catch-up=NAME Catch up with existing (paused) session NAME\n" \
336+
"--no-catch-up-add Do not add the new hashes (files) to NAME after\n" \
337+
" --catch-up=NAME caught up\n" \
335338
"--config=FILE Use FILE instead of john.conf or john.ini\n" \
336339
"--encoding=NAME Input encoding (eg. UTF-8, ISO-8859-1). See also\n" \
337340
" doc/ENCODINGS.\n" \
@@ -623,6 +626,9 @@ void opt_init(char *name, int argc, char **argv)
623626
if (options.catchup && options.max_cands)
624627
error_msg("Can't combine --max-candidates and --catch-up options\n");
625628

629+
if ((options.catchup_add != -1) && !options.catchup)
630+
error_msg("The --no-catch-up-add option can only be used with --catch-up\n");
631+
626632
if (options.flags & FLG_STATUS_CHK) {
627633
#if OS_FORK
628634
char *rec_name_orig = rec_name;

src/options.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/*
22
* This file is part of John the Ripper password cracker,
33
* Copyright (c) 1996-98,2003,2006,2013 by Solar Designer
4-
*
5-
* ...with changes in the jumbo patch, by JimF and magnum (and various others?)
4+
* Copyright (c) 2009-2026, magnum
5+
* Copyright (c) 2009-2015, JimF
66
*
77
* Redistribution and use in source and binary forms, with or without
88
* modification, are permitted.
@@ -457,6 +457,8 @@ struct options_main {
457457
int crack_status;
458458
/* --catch-up=oldsession */
459459
char *catchup;
460+
/* --catch-up-add (tri-state) */
461+
int catchup_add;
460462
#if defined(HAVE_OPENCL) || defined(HAVE_ZTEX)
461463
/* --mask-internal-target=N */
462464
int req_int_cand_target;

src/recovery.c

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/*
22
* This file is part of John the Ripper password cracker,
33
* Copyright (c) 1996-2003,2005,2006,2009,2010,2013,2017 by Solar Designer
4-
*
5-
* ...with changes in the jumbo patch, by JimF and magnum.
4+
* Copyright (c) 2009-2026, magnum
5+
* Copyright (c) 2009-2018, JimF
66
*
77
* Redistribution and use in source and binary forms, with or without
88
* modification, are permitted.
@@ -763,3 +763,72 @@ uint64_t rec_read_cands(char *session)
763763

764764
return ret;
765765
}
766+
767+
void rec_add_files(char *session)
768+
{
769+
char *other_name;
770+
FILE *other_file = NULL;
771+
int64_t other_size = 0;
772+
773+
if (!john_main_process && options.node_min) {
774+
char suffix[1 + 20 + sizeof(RECOVERY_SUFFIX)];
775+
776+
sprintf(suffix, ".%u%s", options.node_min, RECOVERY_SUFFIX);
777+
other_name = path_session(session, suffix);
778+
} else {
779+
other_name = path_session(session, RECOVERY_SUFFIX);
780+
}
781+
782+
if (!(other_file = fopen(other_name, "r+")))
783+
pexit("fopen catch-up file: '%s'", other_name);
784+
785+
#if !(__MINGW32__ || _MSC_VER)
786+
if (jtr_lock(fileno(other_file), F_SETLK, F_WRLCK, other_name))
787+
error_msg("Catch-Up session file '%s' is locked\n", other_name);
788+
#endif
789+
790+
jtr_fseek64(other_file, 0, SEEK_END);
791+
if ((other_size = jtr_ftell64(other_file)) == -1)
792+
pexit("ftell");
793+
jtr_fseek64(other_file, 0, SEEK_SET);
794+
if (other_size == 0) {
795+
error_msg("Error, %s is empty\n", other_name);
796+
}
797+
798+
char *other_data = mem_alloc_tiny(other_size + 1, MEM_ALIGN_NONE);
799+
memset(other_data, 0, other_size + 1);
800+
801+
if (fread(other_data, 1, (size_t)other_size, other_file) != other_size) {
802+
if (ferror(other_file))
803+
pexit("fread");
804+
error_msg("fread: Unexpected EOF\n");
805+
}
806+
807+
char magic[16];
808+
int argc;
809+
unsigned offset;
810+
sscanf(other_data, "%15s\n%d\n%nu", magic, &argc, &offset);
811+
812+
jtr_fseek64(other_file, 0, SEEK_SET);
813+
814+
fprintf(other_file, "%s\n%d\n", magic, argc + (int)options.passwd->count);
815+
816+
struct list_entry *current;
817+
if ((current = options.passwd->head)) {
818+
do {
819+
fprintf(other_file, "%s\n", current->data);
820+
} while ((current = current->next));
821+
}
822+
823+
fprintf(other_file, "%s", other_data + offset);
824+
fclose(other_file);
825+
826+
if (unlink(path_expand(rec_name)))
827+
pexit("unlink: %s", path_expand(rec_name));
828+
829+
if (rec_file) {
830+
if (fclose(rec_file))
831+
pexit("fclose");
832+
rec_file = NULL;
833+
}
834+
}

src/recovery.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,10 @@ extern void rec_restore_mode(int (*restore_mode)(FILE *file));
118118
*/
119119
extern uint64_t rec_read_cands(char *session);
120120

121+
/*
122+
* Add the current session's password files to the file we caught up with.
123+
* --catch-up=SESSION does this after successfully catching up.
124+
*/
125+
extern void rec_add_files(char *session);
126+
121127
#endif

0 commit comments

Comments
 (0)