Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use restore_tester_fmt.c to find and correct restore issues #2082

Open
4 of 8 tasks
jfoug opened this issue Mar 8, 2016 · 71 comments
Open
4 of 8 tasks

Use restore_tester_fmt.c to find and correct restore issues #2082

jfoug opened this issue Mar 8, 2016 · 71 comments
Labels
core branch Bug or issue coming from John the Ripper core non-trivial testing A testing task or issue (e.g., with CI)

Comments

@jfoug
Copy link
Collaborator

jfoug commented Mar 8, 2016

Things I know about. Add more as they are seen/fixed, since some of these should get done in core also.

  • rules. When restarting, the words are restarted for whatever rules were being worked on. (Fixed 2 bugs 2110a37 and 62310e8)
  • rexgen does not resume Add session save/restore for --regex mode #570 (fixed but can not use until v1.4.0 of rexgen is released).
  • rexgen-hybrid only resumes the base-word Add session save/restore for --regex mode #570.
  • Multi-salt mode restarts all salt work over again (Multisalt resume #2087)
  • single mode
  • markov mode
  • mask mode Restore is almost right. Just the very last word which was properly done is started with. (fix found, pending verify)
  • wordlist mask hybrid was also 'off by one', i.e. replaying last tested word. (fixed, pending verify)

Some of these could be handled as 'hybrid' type blocks added to the end of a .rec file (I think). Things like the rules and multi-salts redoing work, could be addressed in that manner. The 'normal' V4 processing of the rec file gets us back to the right words, and then the hybrid extra block appended provides additional information on how far to skip ahead inside the subwork done on the word or set of words, so that prior completed work is not replicated.

The restore_tester_fmt is great for determining exactly what was processed, written to .pot files, etc. So that we know 100% that we restart at proper location, not before, and CERTAINLY not later in the word stream.

@jfoug jfoug added core branch Bug or issue coming from John the Ripper core bug non-trivial labels Mar 8, 2016
@jfoug
Copy link
Collaborator Author

jfoug commented Mar 11, 2016

Here is what rules does (currently)

27e_01           (?)
27f_01           (?)
5904g 0:00:01:49 1.19% (ETA: 11:45:04) 54.16g/s 54.16p/s 54.16c/s 54.16C/s 280_01..2ff_01
Session aborted

$ ../run/john -res=tst-x
Loaded 1 password hash (restore_tester [None])
5904g 0:00:01:50 1.00% (ETA: 12:14:52) 53.67g/s 53.67p/s 53.67c/s 53.67C/s 000_01
000_01           (?)
001_01           (?)
002_01           (?)
003_01           (?)

here is the rec file:

Jim.Fougeron@1PQHGQ1 /c/projects/phpbb/johnripper/john-1.7.9/bleed64/test
$ cat *.rec
REC4
9
--rules=appendnumnum
--wordlist=tst-x.dic
tst-xx.in
--session=tst-x
--pot=tst-x.pot
--format=restore_tester
--input-encoding=ASCII
--target-encoding=ASCII
112
5936
1730
0
0
1730
0
1730
0
0
0
1
0
1
0
32

So it appears that under rules, only the rule# gets restored, and the run starts at the first input word on that rule.

So we need to save not only the rule# but also the word# for restore to work 'correctly'.

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 11, 2016

Rules bug (listed above), found and fixed. Still more testing to do, but that one WAS a bug, and is corrected.

NOTE, the restore_tester format kicks ass for finding these issues, and then knowing that it is correctly fixed!!!!

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 11, 2016

Found another bug in wordlist resume. If the .rec file was made with a version that has mem_map enabled and restored on a build that does not have mem_map, then the offset was set to 0, so the new run does not restore properly. I think I can fix this, but not sure it is worth it. NOTE, if the .rec was made on a non-mem_map build, then it restores properly on a non-mem_map build (or on a mem_map build for that matter).

Fixed it here. 62310e8

Now it does not matter if the build was mem_map or not. Either can resume the other's .rec files properly.

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 11, 2016

I believe wordlist is fixed. If others wanted to see if there are other restore things that could be 'fixed', then by all means try (-stdin, -pipe ??)

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 11, 2016

I will have to enhance restore_tester format for testing salted hashes. I think I will make a 2nd format for this, so that any issues between pure-raw and salted running 1 salt does not get in the way

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 11, 2016

Here is multi-salt restore issues (wordlist and rules, but I do not think it will matter on the mode).

Note, switched MAX/MIN candidates to 3

$ OMP_NUM_THREADS=1 ../run/john -rules=appendnumnum -mem=5 -w=tst-x.dic tst-x.in -ses=tst-x -pot=tst-x.pot
Loaded 9 password hashes with 9 different salts (restore_tester_salted [None])
000_00$SLT1      (?)
001_00$SLT1      (?)
002_00$SLT1      (?)
000_00$SLT8      (?)
001_00$SLT8      (?)
002_00$SLT8      (?)
000_00$SLT7      (?)
001_00$SLT7      (?)
002_00$SLT7      (?)
000_00$SLT6      (?)
001_00$SLT6      (?)
002_00$SLT6      (?)
000_00$SLT5      (?)
001_00$SLT5      (?)
002_00$SLT5      (?)
000_00$SLT4      (?)
001_00$SLT4      (?)
002_00$SLT4      (?)
000_00$SLT3      (?)
001_00$SLT3      (?)
002_00$SLT3      (?)
000_00$SLT2      (?)
001_00$SLT2      (?)
002_00$SLT2      (?)
000_00$SLT9      (?)
001_00$SLT9      (?)
002_00$SLT9      (?)
003_00$SLT1      (?)
004_00$SLT1      (?)
005_00$SLT1      (?)
003_00$SLT8      (?)
004_00$SLT8      (?)
005_00$SLT8      (?)
003_00$SLT7      (?)
004_00$SLT7      (?)
005_00$SLT7      (?)
003_00$SLT6      (?)
004_00$SLT6      (?)
005_00$SLT6      (?)
39g 0:00:00:02 0.00% (ETA: 2016-03-13 01:16) 16.09g/s 1.238p/s 16.09c/s 16.09C/s 003_00$SLT5..005_00$SLT5
Session aborted

$ OMP_NUM_THREADS=1 ../run/john -res=tst-x
Loaded 9 password hashes with 9 different salts (restore_tester_salted [None])
39g 0:00:00:03 0.00% (ETA: 2016-03-13 21:14) 13.00g/s 1.000p/s 13.00c/s 13.00C/s 003_00$SLT1
003_00$SLT1      (?)
004_00$SLT1      (?)
005_00$SLT1      (?)
003_00$SLT8      (?)
004_00$SLT8      (?)
005_00$SLT8      (?)
003_00$SLT7      (?)
004_00$SLT7      (?)
005_00$SLT7      (?)
003_00$SLT6      (?)
004_00$SLT6      (?)
005_00$SLT6      (?)
003_00$SLT5      (?)
004_00$SLT5      (?)
005_00$SLT5      (?)
003_00$SLT4      (?)
004_00$SLT4      (?)
005_00$SLT4      (?)

Note, the correct resume location is

000_00$SLT5      (?)
001_00$SLT5      (?)
002_00$SLT5      (?)
000_00$SLT4      (?)
001_00$SLT4      (?)

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 11, 2016

I have multi-salt restore working, but it will (may) require a new REC-VERSION (v5). This 'could' be handled in the same manner as I have done on the other 'extra' blocks. So I could keep this at REC_VERSION=4 and add a block like this to the end of the file

slt-v1
%x

%x is a salt idx.

Currently, I have added the salt idx to the bottom of the 'normal' block of restore stuff, and read it from there. But it would not have to be done in this manner. The way I did it for the other 'hybrid' modes would work just fine.

I am asking (@magnumripper and @frank-dittrich mostly), which way they would like to see this done? I could easily add this as a slt-v1 block, and then later if solar adds this data into a REC5 model, we could switch our logic to use that (but keep the slt-v1 processing, so any .rec files created could still be read).

But I really want this to be put into code. When working with a LARGE number of salts of some pretty slow formats, means that there is a lot of replicated work any time you have to shut down.

@magnumripper
Copy link
Member

When testing wordlist mode, be sure to also try adding --mem=1 to the command line, disabling buffering. The logic is different for that.

EDIT it looks like you already did so.

@magnumripper
Copy link
Member

I am asking (@magnumripper and @frank-dittrich mostly), which way they would like to see this done?

This really should be discussed on john-dev before doing anything. I presume the problem exists in john proper? Solar may want to fix this and in that case we should do nothing (except possibly testing ideas for him).

@frank-dittrich
Copy link
Collaborator

I don't think storing salt idx in .rec file is the way to go,
What if you have multiple sessions running, and when you restore, some salts got removed due to all passwords being cracked?
Or, if that still works, provided you don't change the input files: What if you drop all cracked hashes before restoring, to reduce load time.

Also, I don't think it i a good idea to create .rec files that are incompatible with master branch.

@magnumripper
Copy link
Member

What if you have multiple sessions running, and when you restore, some salts got removed due to all passwords being cracked?

This is an important caveat. The current behavior fully supports stopping a job and then resume it when there's much fewer salts left (from cracking in other sessions).

@magnumripper
Copy link
Member

I think I will make a 2nd format for this, so that any issues between pure-raw and salted running 1 salt does not get in the way

Not needed. As far as I know there is absolutely no difference between an unsalted format, and a salted one that has only one unique salt loaded.

@frank-dittrich
Copy link
Collaborator

But I really want this to be put into code. When working with a LARGE number of salts of some pretty slow formats, means that there is a lot of replicated work any time you have to shut down.

Don't we have an option to completely test one block of password candidates before stopping a session?

Appatently AbortGraceTime only works with --max-run-time, may be we need a config option to complete testing all salts before terminating the session.
(But woulodn't that make AbortGraceTime obsolete?

@magnumripper
Copy link
Member

Don't we have an option to completely test one block of password candidates before stopping a session?

It's not even an option, this is just how it works off the top of my head. Unless you brutally kill john with eg. kill -9, it will complete the block for all salts.

@frank-dittrich
Copy link
Collaborator

@magnumripper

See issue #1638 and your commit:

commit 31834168ba59311387944ad1c33972f7f5984e82
Author: magnum <john.magnum@hushmail.com>
Date:   Wed Nov 4 23:12:11 2015 +0100

    Add a john.conf option AbortGraceTime for tweaking behavior
    of --max-run-time=N option. Closes #1638.

@magnumripper
Copy link
Member

Sure, the --max-run-time option is special. Is that what we're testing here? We shouldn't use it, or it should be used with AbortGraceTime = -1 here.

@frank-dittrich
Copy link
Collaborator

@magnumripper If you mean the behavior for sessions interrupted by pressing q or ctrl-c, then why is there a need to store the salt index in the .rec file at all?

@magnumripper
Copy link
Member

As far as I know there is no need but I'm not sure I understand how @jfoug tested it.

@magnumripper
Copy link
Member

magnumripper commented Mar 11, 2016

Likewise, if you press 'q' or 'ctrl-c' twice, all bets are off. We shouldn't fix "too early restore" caused by that. We should just ensure that the restore doesn't miss anything, EVER.

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 11, 2016

This really should be discussed on john-dev before doing anything. I presume the problem exists in john proper? Solar may want to fix this and in that case we should do nothing (except possibly testing ideas for him).

Solar has mentioned this, and made a statement about 'IF I ever chose to fix it'.

I have done so keeping REC4 format. I simply append a slt-v1 block if there is a salt index (i.e. it is not at 0). It would be very trivial to switch this back to a REC5 structure if we later have that. All the other logic would need no adjustments. Only adjustment is where to grab the 'salt_idx' value.

@magnumripper
Copy link
Member

You should revert this and use a topic branch instead. And you should not merge that topic branch ever. Leave that to me.

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 11, 2016

Agreed:

What if you have multiple sessions running, and when you restore, some salts got removed due to all passwords being cracked?

This is an important caveat. The current behavior fully supports stopping a job and then resume it when there's much fewer salts left (from cracking in other sessions).

jfoug added a commit that referenced this issue Mar 11, 2016
@magnumripper
Copy link
Member

Don't get me wrong, you might be on to something. Or perhaps not. But you are too trigger happy for sure, with major core changes like this. Using topic branches, you are totally free to commit just anything for testing and reviewing. Even better you are free to git push --force to those topic branches, and/or rebase them, squash commits and so on until you end up with a nice clean fully tested PR for merging.

@magnumripper
Copy link
Member

So, I am re-thinking the logic. What I think I need is:

  1. the salt sort has to be EXACTLY the same, every time, without regard to the input value order.
  2. hashing information must be stored about the EXACT salt that is currently being worked on (at time of .rec save).
  3. this logic likely should be made optional, default off, which would be current behavior.

We have a default AlwaysSortSalts = Y that sort salts most used first. This will screw things up. Given we drop that default, I guess you could just

  1. Always store a hash (or some other id) of current salt, ie. the salt a resumed session should start with.
  2. At resume, look for that salt. If it exists, we continue there - if not, we start the loop from scratch.

However, we don't want to perform a SHA-1 every time we switch salt. Yet we can't wait until "needed" because a hard kill should ideally resume perfectly too (the AM will nearly always be a hard kill).

I'm not sure we need any fix at all, except possibly add an option to actually process all salts before soft abort. Given that, you'd simply run a sane number of salts at a time and there'll be no problem.
We don't need a fix for the case "months to compute all salts against 3 passwords" because that case is hopeless regardless.

@magnumripper
Copy link
Member

Perhaps simply using the existing "salt hash" is good enough? It will home in to the right neighborhood even if that bucket contains several salts. And the salt hash is readily available.

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 12, 2016

This type salt_compare function is a no go (from 7z)

static int salt_compare(const void *x, const void *y)
{
    const struct custom_salt *s1 = x;
    const struct custom_salt *s2 = y;

    return (s1->NumCyclesPower - s2->NumCyclesPower);
}

This is due to undefined order if NumCyclesPower is same in a group.

So the above needs to be something like:

static int salt_compare(const void *x, const void *y)
{
    const struct custom_salt *s1 = x;
    const struct custom_salt *s2 = y;
    if (s1->NumCyclesPower != s2->NumCyclesPower)
       return (s1->NumCyclesPower - s2->NumCyclesPower);
     return (some comparison that is repeatable)
}

Dynamic format will also need adjustment. It sorts solely based upon salt length (that is a REQUIREMENT for dynamic due to implementation issues). But there will need to be a strcmp/memcmp added if the lengths are equal, so that the end result is 100% repeatable.

Again, we have to store some indication of the salt being worked on (that may be salt-hash AND some other exact hash of the salt). Then upon restart, we scan for the salt-hash, and if found not found, we start over. Then we scan the salts for the right value, and if not found, start at the first one of that salt hash. If an exact match is found, then we know that we need to start there.

That should be universal working, even if it has to fall back and redo salts (because the salt it no longer there, and was cracked somewhere else). It is likely that the 'matching id' could be done at salt load time, and stored, so no run-time recompute is needed.

@frank-dittrich
Copy link
Collaborator

This type salt_compare function is a no go (from 7z)

It wasn't a problem until you started to use the salt_compare() function for something new.
formats.h doesn't mention the need to never return 0.
So far, the "unreliable" sequence didn't hurt. The format only cared about sorting salts based on NumCyclesPower.
So may be if you have additional requirements, you should implement your own comparison function.
Wouldn't you need a stable sequence even if the format doesn't have a salt_compare() function?
(Not sure how ugly it gets if you want to make use of the format's salt_compare(), and only take care of never returning 0...)

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 12, 2016

f7659bd

This should have ALL salts in deterministic order (BUT does this not happen if that AlwaysSortSalts = N ???

Now, I should also comment the salt_sort. Basically, it needs to provide an fully useful comparison function ready for qsort. The ONLY way to have qsort be deterministic (if there are NO dupes), is to never return 0, UNLESS the values match. Thus if there are no matching salts, then a properly written qsort should never see a 0 return from the int(cmp_)(void_,void*) function NOTE, there are busted implementations of qsort (they still work, just not optimally), where the qsort function will compare a value against itself. So it is not 100% out of realm to return a 0, BUT it should only be done if the salts is actually 100% identical. Also, I think salt_cmp is called during loader, to see if salt is the same, or does loader simply do a memcmp() call ?

The salt_cmp() should really behave like memcmp. It can be 'smart' about it, but if the salt is not 100% equal to the other salt, then 0 should not be returned.

The salt_cmp_num was easy to fix. I just passed in the salts, pre-called dyna_salt_init, and then use the dyna_salt_cmp function.

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 12, 2016

We may have to change this in loader, to simply always sort, OR if not sorted, then there will be no salt-resume logic added for the current session (unless it has a fmt.salt_compare function).

    int always;

    always = cfg_get_bool(SECTION_OPTIONS, NULL, "AlwaysSortSalts", 1);

    if (db->salt_count < 2 || (!fmt_salt_compare && !always))
        return;
// sorting happens later in the ldr function

@magnumripper what do you think?

NOTE, if the order of the input file is not changed, and there is no sorting, then I believe the salt order would still be deterministic. This may not be 100% correct, since I think the salt_hash buckets are created, and if there are some buckets removed, it would change the order of the buckets. NOTE, I still do not have my mind fully around all the intricacies of how salts are stored, with or without salt_hash functions.

@magnumripper
Copy link
Member

I think your focus is completely off. Only a handful formats have their own salt sort, and we can ignore this new resume enhancement for them.

You should focus on the 400+ other formats.

@magnumripper
Copy link
Member

No, wait... we NEED a default salt sort that is deterministic, that is what you say right? The ones that currently (optionally) is salted by "most used first" should instead default to some deterministic order.

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 12, 2016

No, wait... we NEED a default salt sort that is deterministic, that is what you say right?

Absolutely. That is what I have right now, in the 2nd commit to this branch. I have also 'fixed' the other formats to properly sort (dynamic and the 2 7z's which should get unified code).

I have also looked at the salt_hash, and it appears to play no part at all, when we get to the cracker loop (which is where we have to 'skip' salts to resume. I made a 3rd test format, that also added a salt_hash, and the salt hash was simply the 4th byte (minus '0'). Note, that the salts are in deterministic salt order. They do not give a crap about the salt hash. I am pretty sure that was only used during the loader code reading salts, and striking them off from the .pot file.

000_ salt->SAT0 salthash->0 (?)
001_ salt->SAT0 salthash->0 (?)
002_ salt->SAT0 salthash->0 (?)
000_ salt->SAT1 salthash->1 (?)
001_ salt->SAT1 salthash->1 (?)
002_ salt->SAT1 salthash->1 (?)
000_ salt->SAT2 salthash->2 (?)
001_ salt->SAT2 salthash->2 (?)
002_ salt->SAT2 salthash->2 (?)
000_ salt->SAT3 salthash->3 (?)
001_ salt->SAT3 salthash->3 (?)
002_ salt->SAT3 salthash->3 (?)
000_ salt->SAT4 salthash->4 (?)
001_ salt->SAT4 salthash->4 (?)
002_ salt->SAT4 salthash->4 (?)
000_ salt->SAT5 salthash->5 (?)
001_ salt->SAT5 salthash->5 (?)
002_ salt->SAT5 salthash->5 (?)
000_ salt->SAT6 salthash->6 (?)
001_ salt->SAT6 salthash->6 (?)
002_ salt->SAT6 salthash->6 (?)
000_ salt->SAT7 salthash->7 (?)
001_ salt->SAT7 salthash->7 (?)
002_ salt->SAT7 salthash->7 (?)
000_ salt->SAT8 salthash->8 (?)
001_ salt->SAT8 salthash->8 (?)
002_ salt->SAT8 salthash->8 (?)
000_ salt->SAT9 salthash->9 (?)
001_ salt->SAT9 salthash->9 (?)
002_ salt->SAT9 salthash->9 (?)
000_ salt->SLT0 salthash->0 (?)
001_ salt->SLT0 salthash->0 (?)
002_ salt->SLT0 salthash->0 (?)
000_ salt->SLT1 salthash->1 (?)
001_ salt->SLT1 salthash->1 (?)
002_ salt->SLT1 salthash->1 (?)
000_ salt->SLT2 salthash->2 (?)

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 12, 2016

This really should be a very easy solution, now that I am fully seeing the nuances of the salt running and am able to get salts into deterministic order all the time (note, I am 'assuming' that AlwaysSortSalts = Y behavior will simply have to be done always, or if it is NOT done, then salt resume simply starts over.

I now only need to build a universal salt hash, and then on restore search for it. I will likely make this something computed at load time, and then simply used to store the .rec file, and later used to search for the thing. Very easy and should have no overhead during runtime (other than writing a few extra bytes into the .rec file).

If I was not going out on a date for who knows how long (doing a cycle ride with no destination, lol), I would probably get this done today. But I will almost certainly have this branch working correctly by the start of next week.

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 12, 2016

I believe this covers everything.

5015bc6

There is a MD5 hash done at final salt load time (after stripped/sorted salts are loaded back into final usable array).

Before starting a salt, there is a pointer in the status record that is pointed to this md5. NOTE during runtime, setting this pointer is the only CPU hit.

At .rec file writing, the pointer from status is read, a 32 byte buffer ascii buffer built and written to file. No hashing needed.

At recover time, a static buffer is built based upon the prior .rec file saved hash. Also a flag is set in the status object listing that we should resume the salt, if we can find it.

in cracker loop, if that flag is set, we enter a loop that clears the flag, and then searches for the salt (based upon the MD5). If we find it, we skip our salt ahead to that salt record. If not, we simply revert to normal start at first salt logic.

Boom, I think this is it! I see no holes in this logic. It all is based upon getting those salts into the same deterministic sorted order, so that when we find our MD5, we are 'golden'. Unfortunately a linear search is needed, but it is not 'too' bad. I put the MD5 buffers into code as uint32_t [4] array, so most of the walk is simply assigning our salt ptr to s->next and then checking if s->md5[0] == recover->md5[0] so it is all just pointer walking and 32 bit int dereference.

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 12, 2016

Fuk! CI failed :( I gotta see why, grr! Well, that's not good. But should be easy to fix, lol

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 14, 2016

Crap, I can't use this format for core. Core does not know about FMT_NOT_EXACT. Somewhat easy (partial) fix, so it is in there.

Well, it is obvious that core does not restore prior salt work. I was pretty sure Solar had stated this fact prior.

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 14, 2016

How do we test single mode ? Any ideas? I would think we may have to build a version which does a printf of every candidate (or use restore_tester format), and then have a list of words, in order. Then re-run the single mode, breaking out and restarting several times, and make sure that the exact same words were tested, and only tested one time.

Can someone think of an easier way to do this?

@frank-dittrich
Copy link
Collaborator

For single mode, you can have multiple "users" with the same hash. John will try candidates based on all the "user names".
The list of candidates will differ for restarted sessions, because with default single mode settings john will retry successful guesses on all the other hashes. In restored sessions, that will only be done for successful guesses of the restarted session...

@magnumripper
Copy link
Member

I've had the idea to allow -single -stdout hashfile for debug purposes (perhaps with -DDEBUG) and make it print candidates instead of (or along with) actually using them. But I'm not sure how to do it with a KISS non-intrusive patch.

@frank-dittrich
Copy link
Collaborator

But just printing the candidates will not work, because single mode generates individual candidates per hash, based on user name etc., so you would have to print the hashes as well.
I don't think --stdout should be misused for that.

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 14, 2016

I have not started on this one yet, but I think the restore_tester will be ideal. It will list candidates and the hash they are being tested on at same time. Ideal I just have to use the salted variety, and make sure each hash has a unique salt.

One thing single will not resume properly, is the try found words against other candidates. But we have ability to replay the .pot file to handle that.

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 23, 2016

Then how come ctrl-c with thousands of slow salts take ages?

I think this slow shutdown has to do with rules. What takes long, is if there are a LOT of rules. john will NOT exit, until the current loaded salt/words block has been run against ALL rules.

It must have been seen early on, that rules needed to be either forced to finish, or some form is sub-block restore code added. It looks like solar (or possibly even early with cracker jack) chose to take the easy route, and let the rules complete. However, this is probably not as bad as the resume of salts. For really slow (especially salted formats), you can not use rules much anyway. When it takes days (or weeks), to burn through all the salts on a load of data for a hash, I assure you, that rules are the last thing anyone worries about, lol.

So it may be ok, to have rules 'complete', and not have to worry about sub-resume logic at all. Yes, there will be times where you hit 'q' and it takes a while to exit. How long, depends upon how slow the format is, and how willing you are to have an excruciatingly slow search.

@frank-dittrich
Copy link
Collaborator

Does that (ctrl-c taking ages) really happen with CPU formats, or is it just with GPU formats with huge max_keys_per_crypt?

@magnumripper
Copy link
Member

I'm pretty sure it happens with CPU formats. @jfoug is probably right.

@jfoug
Copy link
Collaborator Author

jfoug commented Mar 23, 2016

Its within the cracker loop. Cracker is not going to exit until the rules are exhausted.

However, that logic (which I am GLAD about), was not done for the multi-salts.

So, what this implies, is that there is NO additional logic needed to get -rules[=anything] from restoring properly. It always should be good. But multi-salts, yes, there is need for resume there.

NOTE, I have not tested this (in the multi-salt pull request) so I need to test. Multi-salted hash using -rules. That may have failures, because john may toss us to the next block of words. That will not be a logic error in the multi-salt logic, but will simply be something that may have to change. The restore_tester_fmt will help to easily shine the light on exactly what the functionality is. It may be that the current logic is working fine, and that the save/resume does not go to the next words until the salt is done, and 'only' pauses until all rules have spun through. But that is still to be seen, in the actual running of the executable.

@jfoug
Copy link
Collaborator Author

jfoug commented Apr 4, 2016

This fixes the bug in non-hybrid mask mode (was restarting with the candidate completed just before the save)

$ git diff mask.c
diff --git a/src/mask.c b/src/mask.c
index b78a04c..f9e86f5 100644
--- a/src/mask.c
+++ b/src/mask.c
@@ -1769,7 +1769,8 @@ void mask_save_state(FILE *file)
 int mask_restore_state(FILE *file)
 {
        int i, d;
-       unsigned char uc;
+       unsigned cu;
+       int fixed = 0;
        unsigned long long ull;
        int fail = !(options.flags & FLG_MASK_STACKED);

@@ -1799,9 +1800,24 @@ int mask_restore_state(FILE *file)
                        return fail;
        }

+       /* vc and mingw can not handle %hhu and blow the stack
+          and fail to restart properly */
        for (i = 0; i < cpu_mask_ctx.count; i++)
-       if (fscanf(file, "%hhu\n", &uc) == 1)
-               cpu_mask_ctx.ranges[i].iter = uc;
+       if (fscanf(file, "%u\n", &cu) == 1) {
+               cpu_mask_ctx.ranges[i].iter = cu;
+               /*
+                * Code was starting off with the last value. So increment
+                * things by 1 so we start at the next mask value.
+                */
+               if (!fixed) {
+                       if (++cpu_mask_ctx.ranges[i].iter <
+                           cpu_mask_ctx.ranges[i].count) {
+                               fixed = 1;
+                       } else {
+                               cpu_mask_ctx.ranges[i].iter = 0;
+                       }
+               }
+       }
        else
                return fail;
        restored = 1;

This increments to the next value. I have tested with many 'q' and ^c vs single runs, and the end result with the above change is correct. I am not 100% sure this is the best way to fix this, BUT it does fix it. I am waiting to check this in, to let @magnumripper or @solardiz have a look and see if there is a better way.

@jfoug
Copy link
Collaborator Author

jfoug commented Aug 8, 2016

Rexgen 1.4.0 with proper resume is now checked into bleeding

@magnumripper
Copy link
Member

magnumripper commented Aug 18, 2016

Just throwing this up here: Hashcat now has an alternate quit option 'c' (checkpoint) that is same as 'q' (quit) except the former waits until eg. all keys and salts are processed. It might take ages but it can also be very rewarding when resuming. I had a look at implementing it but it will be very tricky with OMP signaling and stuff.

@magnumripper magnumripper added testing A testing task or issue (e.g., with CI) and removed bug labels Jan 26, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core branch Bug or issue coming from John the Ripper core non-trivial testing A testing task or issue (e.g., with CI)
Projects
None yet
Development

No branches or pull requests

3 participants