New Attack-Mode: Association Attack
#1
With commit 04d5e5a119ba4c44bedb5bcccd5a42f82463cca3 I have added a new attack-mode called "Association Attack" (a different name could be "Context Attack"), but let's stick to "Association Attack" for reference. This attack is not yet ready to be used in a production environment, it's a very early first version, but I wanted you to play with it.

If you ever used JtR before, the "Association Attack" is somehow of what the "single mode" is in JtR. The attack-mode is strong if you have large -salted- hashlist and at the same time you have some "hint" or "information" for each of the hashes inside the hashlist. Typically the username. The username itself could be seen as a "hint", because some humans tend to use the username as a part of the password. Or the username contains parts of the password because the username is changed for the site the username is used. Then we can extract this information using rules.

The main idea of this attack is to not try all the different (unique) salts with all password candidates from a wordlist, but to only attack each of the hashes in the hashlist with the associated "hint". From a development perspect, we remove the loop in hashcat which iterates through the different salts. To make this attack more efficient, we typically use the "hint" in combination with rules (but that's not a requirement). Using a GPU for this task is not so easy because of the many cores that we have and that we have to give work to. That brings us to an important requirement. Your hashlist needs a large number of unique salts to make this attack efficient (to utilize the GPU fully). Ideally the number of GPU Processors * 64 (or more). You can find out about the GPU Processors of your GPU using hashcat -I. My GTX980 has 16, so I need a hashlist of at least 1024 entries to fully utilize the GPU.

Unrelated Pro-Tip: If you want to attack a slow single hash with a single word but with some rules added to it, then the capitalized -S is what you want.

When I first created this patch I was thinking of how the user could specify what is the "hint" for each of the hashes. In JtR's single mode it simply uses the username from the hashlist. This is very easy to handle, but it's not exactly what I was looking for. In hashcat we specify a hashlist as regular (with or without username) but we also provide a wordlist as regular. However, this wordlist has to have exactly the number of lines as the hashlist. This has both advantages and disadvantages, but I liked the idea to use this even with a folder with many wordlists. This is kind of the opposite of what creates the efficiency of this attack, but I think there are some situations where multiple wordlists make sense. For instance, if you have large portions of substrings which were added to a passwords afterwards, by yubikeys on keypress, by site specific pepper strings or by user using the company name. I can also try to make it 1:1 as in JtR where the username is building some sort of virtual wordlist in memory, but only if I see that you people are really interested in this attack-mode.

One of the problems I was thinking of is if it is possible to have a mixed version of this attack-mode and a regular rule-based straight attack-mode in combination with -S. That could be useful if you have let's say only 10 hashes, because this is not enough to keep the GPU busy and then combine it with rules. This is a more complicated code change and again if I see you people being interested in it.

So here's how you use it. In a first step we will build a demonstration dataset (hashlist) in username:hashlist format as you probably have it and then I show you how to split it so you can use it with the new attack-modes.

1. Build the test dataset, creating a bcrypt hashlist

Code:
$ head -10000 example.dict > wordlist.txt
$ shuf wordlist.txt | sponge wordlist.txt
$ tools/test.pl passthrough 3200 < wordlist.txt > hashlist.txt
$ perl -e 'open (IN, "wordlist.txt"); my @a = <IN>; close (IN); open (IN, "hashlist.txt"); my @b = <IN>; close (IN); for (my $i = 0; $i < scalar @a; $i++) { chomp $a[$i]; chomp ($b[$i]); printf ("%s:%s\n", $a[$i], $b[$i]); } print scalar @b' > final.txt
$ rm wordlist.txt hashlist.txt

The resulting "final.txt" looks like this:

Code:
$ more final.txt
001071:$2a$05$KReyKhSyKRi0LBSwLBWyLOj88ZjDCPMD83re/SBNJ9TXJrrPLDbwW
02011511:$2a$05$LBCyKhC1MRGvLxeuLxOxMOilYzVzEnWVFr79uLTj6vTPAPO2y2tbS
01papirus:$2a$05$MB.3MBazLhW0MRKzMBSzKOsHZE77Ou9mGW88yOG2Q5TxF5yvLe48C
010108dh:$2a$05$LBGyLBeuKxavLh.3MRWyLOhOiQVGYyUBYE.rOUiRomCQFGIZfutEK
000123258:$2a$05$LxiwMR.wKhGvKBiyKxeuM.rHYpUIrIOLksCsvo//8YT5J5z28rzBW
...

2. This is the point where you typically start. You have a hashlist in username:hash format. We need to split them in order to use them with the new attack-mode.

Code:
$ cut -d: -f1 < final.txt > wordlist.txt
$ cut -d: -f2 < final.txt > hashlist.txt 

3. Here's a traditional -a 0 attack. This will work fine, but take a look at the time it takes.

Code:
$ ./hashcat -m 3200 hashlist.txt wordlist.txt -o result.txt

Code:
...
Time.Started.....: Tue Sep 29 15:38:06 2020 (2 secs)
Time.Estimated...: Tue Sep 29 18:25:37 2020 (2 hours, 47 mins)
...
Recovered........: 6/10000 (0.06%) Digests, 6/10000 (0.06%) Salts
...

In 2+ hours all the 10000 hashes will be cracked. If you know hashcat you know it will finish sooner because as soon as one unique salt has been fully cracked, it does not need to retry that salt, etc. But it will take some time, but you can't beat the -a 9 as you will see next.

4. New attack mode, the syntax is the same just add the -a 9:

Code:
$ ./hashcat -m 3200 hashlist.txt wordlist.txt -o result.txt -a 9

Code:
...
Time.Started.....: Tue Sep 29 15:40:46 2020 (2 secs)
Time.Estimated...: Tue Sep 29 15:40:48 2020 (0 secs)
...
Recovered........: 10000/10000 (100.00%) Digests, 10000/10000 (100.00%) Salts
...

So it cracked all 10000 bcrypt in just 2 seconds. This is really not black magic and only worked because we had the right password.

In reality the idea is if you have a large salted hashlist, for instance bcrypt, and you have the usernames for it. Run the -a 9 first with rules. This will crack some of the hashes in a very short time. If you then start your regular -a 0 attack you have already removed a good portion of the unique salts, so it will be a faster.

--
atom
Reply
#2
Kernel Developer:

There's two changes you typically need to apply to your kernel.

1. Replace "salt_pos" with "SALT_POS"
2. Replace "digests_offset" with "DIGESTS_OFFSET"

That's it.
Reply
#3
Wow, this is going to be a game-changer!

If feasible, one UX request: Please do what JtR does here and warn the user about any "calculatable" efficiency thresholds into this new mode. For example, a warning could say "700 total salts found - at least 1024 salts needed for full attack efficiency", etc. (Of course, this can only be implemented for thresholds that can actually be calculated at runtime)
~
Reply
#4
This is awesome. Is there any interest in a variation of this attack that, instead of using rules on each individual hash's associated hint, you can provide a short list of hints to try for that hash only? Like for password reuse wordlist attacks.

Example:
password1!:<bcrypt hash>
mypass,funnybunny,pass1:<another bcrypt hash>

That way, you can attack each hash with more than just one base word that is likely to crack it.
Reply
#5
(09-29-2020, 05:20 PM)Peanutbutter1 Wrote: This is awesome. Is there any interest in a variation of this attack that, instead of using rules on each individual hash's associated hint, you can provide a short list of hints to try for that hash only? Like for password reuse wordlist attacks.

Example:
password1!:<bcrypt hash>
mypass,funnybunny,pass1:<another bcrypt hash>

That way, you can attack each hash with more than just one base word that is likely to crack it.

You can do it like this:
Code:
hash.txt:
hash1
hash1
hash1

wordlist.txt:
mypass
funnybunny
pass1


Which I believe is better solution because this way some parsing issues are easily avoided (comma in the hint word etc.)

Although I agree that, probably JTR like format would be better.
Code:
pass1:hash1
pass2:hash1
pass3:hash1

Regarding the new attack mode, it's truly amazing. Thank you very much for your hard work. I understand it's very early version but if I may suggest few things at this moment (if you're not looking for user suggestions yet then please just ignore it):
- I believe that JtR like format hint:hash would be great
- Making it work properly with potfile would also be huge improvement
- Enabling debug mode for this attack
Reply
#6
as far as I understood it, you would need to specify more files or a folder instead.

Code:
hashcat -m 3200 -a 9 hash.txt dict_*.txt

or
Code:
hashcat -m 3200 -a 9 hash.txt dicts/

all the files of course need to have the correct amount of lines/passwords that match the number of hashes.

so the input that is used per hash does depend on the line number, as explained in the first post of this thread
Reply
#7
If this is not a correct place to report some issues/make suggestions then please let me know and I'll shut up Big Grin

I noticed that this mode doesn't really work with optimized kernels (-O).

Errors like CL_UNKNOWN_ERROR and L_OUT_OF_RESOURCES appeared even when I've tried running some small amount hashes without any rules. Pure kernel works perfectly though.
Reply
#8
I think this new attack method is awesome and I would also like to be able to use something like
Code:
mypass,passtest,passguess:<hash>

Of course using something like
Code:
pass1:hash1
pass2:hash1
pass3:hash1
works I suppose, also generates more work
Reply
#9
(09-29-2020, 05:03 PM)royce Wrote: Wow, this is going to be a game-changer!

If feasible, one UX request: Please do what JtR does here and warn the user about any "calculatable" efficiency thresholds into this new mode. For example, a warning could say "700 total salts found - at least 1024 salts needed for full attack efficiency", etc. (Of course, this can only be implemented for thresholds that can actually be calculated at runtime)

We have. It's this:

Code:
The wordlist or mask that you are using is too small.
This means that hashcat cannot use the full parallel power of your device(s).
Unless you supply more work, your cracking speed will drop.
For tips on supplying more work, see: https://hashcat.net/faq/morework
Reply
#10
(09-29-2020, 05:20 PM)Peanutbutter1 Wrote: This is awesome. Is there any interest in a variation of this attack that, instead of using rules on each individual hash's associated hint, you can provide a short list of hints to try for that hash only? Like for password reuse wordlist attacks.

Example:
password1!:<bcrypt hash>
mypass,funnybunny,pass1:<another bcrypt hash>

That way, you can attack each hash with more than just one base word that is likely to crack it.

Yeah I already tried to explain, you can do that already. I just don't like the format:

Code:
mypass,funnybunny,pass1

Instead you would create 3 wordlists, each containing one of the passwords at the same line number. That's much easier to maintain (especially automatically).
Reply