Recovering Hashes without Dozens of GPUs
Cryptographic hash functions are the most used method for saving user passwords. A hash function is a one-way function that gets a string as input and translates it into another string that looks nothing like the original. Even though transforming a password into hash is easy, there is no way of turning a hashed string back to a password. That is the main reason almost all of the user passwords stored as hashes.
Let us imagine a public web service that allows users to store their valuable files. The system currently holds 10TB of data. A hacker finds a small problem with input sanitation and utilizes this to run a piece of malicious code and escalate privileges. Now the attacker can access all the information, but downloading 10TB from the backdoor can raise quite a few alarms. At this point, using a proper hashing algorithm can change everything. If passwords not hashed, the attacker can log in web service with credentials and pull all the information. Given how many people still use the same passwords for different sites, attackers could easily steal more data. If the passwords stored with a modern cryptographic hash function, the attacker needs to invest a lot more time in cracking this hash.
Linux and Windows store passwords as hashes, just like every system that has multi-user functionality. Slow hashing algorithms are better for credential storage; fast and old hash algorithms are still in use for verify file integrity.
1. Hash Cracking Theory
When creating a hash, most of the systems use CPU. Calculating a hash is not a small task. When we write down our credentials to any system and press enter, we have to wait a few seconds, even if the password is wrong. This is because the system can not validate a password without hashing it first, and hashing on a CPU can take a few seconds. hashcat uses GPU instead of CPU and uses it very efficiently. This provides us a much-needed performance advantage.
Since it is not possible to reverse hash functions, we need to try hashing different strings until we found a match for the given hash. It is effortless to try every combination for a four-digit PIN code. There are 100(10x10x10x10) combinations. What if these characters can also be letters as well as numbers? We can choose between 10 digits, 26 uppercase letters, and 26 lowercase letters. Now we have to try out 14,776,336(62x62x62x62) combinations. As the numbers show, trying out every combination in such ranges would take years, even with a weak hashing algorithm.
There are also specialized ways of recovering hashing like rainbow tables. Such methods are effective in only certain types of hashes.
Luckily, human beings are not very random when creating passwords. We can exploit this to make more educated password guesses instead of trying out every combination.
2. Preparation
Before making any attempt to recover the passwords, it is best to start by learning about the system that produced the hashes. First, we need to learn which hashing algorithm is used. Hash type can be MD5, SHA1, bcrypt, WPA. The full candidate list can be found on hashcat website. Hash mode needs to be set for hashcat to work. -m
flag can be used for this.
If possible, it would be very useful to learn about the password policy. What is the minimum number of characters allowed, what kind of passwords are prohibited by the system for being weak. Such information saves precious processing time. It is impossible for the hashcat to know the password policy of the hash, so it can easily waste time with impossible candidates.
3. Maximize the Cracking Speed
There are few things to consider to reach max speed with your hardware. Most important thing is using correct drivers. Without a proper GPU driver, hashcat might function slower than it should be.
3.1 Create Enough Candidates for Fast Hashes
hashcat needs a steady supply of candidates to work on max performance. This problem usually happens with fast hashes. Brute force methods with large enough keyspace, max out resources instantly, but adding rules can speed up hash cracking if you are working with a wordlist.
3.2 Cooling
hashcat has a GPU temperature limit; when it reaches this limit, speed gets reduced to not damage the GPU. Most GPU don't max out fans unless it gets scalding. Disable automatic fan control and max out the fans manually. This can increase your hash cracking speed, and it will improve the life expectancy of the GPU. If you don't have many case fans, consider leaving the case door open while cracking hashes.
3.3 Track your attempts
There are many methods of cracking hashes, understand your attacks, and don't waste time on overlapping spaces. Merge wordlists and remove duplicates before scanning. Keep notes about your past scans and avoid the same spaces.
Test Hashes and Hardware
For this guide, we will use the infamous LinkedIn leak from 2012, which later resurfaced in 2016. The leak has 17,264,398 SHA1 hashes. To keep playfield even, we used a GTX 970 for our guide, a GPU from 2014.
Hashes get removed from the list when found. The goal is to show the effectiveness of methods as some methods use hashes cracked as older steps to improve attacks. While reading the steps, keep in mind, every step deals with hashes that survived at earlier stages.
4. Hashcat
hashcat is the world's fastest password recovery utility. It supports five unique modes of attack.
For limiting hashcat to use only the second GPU -d 2
parameter was given to all examples.
4.1 Install Hashcat
Install process for hashcat is pretty simple. You can also use package managers, but pulling directly from the official site guarantees the latest version. The package is pretty good, and you don't have to deal with dependencies.
wget https://hashcat.net/files/hashcat-6.0.0.7z
7z x hashcat-6.0.0.7z
cat linkedin.txt | cut -d: -f2 | sort | uniq
5 Modes of Hashcat
hashcat offers different modes of attacks.
5.1 Straight Mode | 0
The straight attack is the most basic option we have. We need to provide the hashcat with a wordlist, and hashcat would try every line in this list on the given list of hashes.
When it comes to wordlists, there are many of them out there. Most of the wordlists include cracked from passwords from older hash leaks. Since we are working on a leaked hash list, using a wordlist like RockYou would be cheating. So we start with a simple English dictionary we found from google.
./hashcat-6.0.0/hashcat.bin -m 100 hashlist --remove -d 2 ~/corncob_lowercase.txt
Session..........: hashcat
Status...........: Exhausted
Hash.Name........: SHA1
Hash.Target......: hashlist
Time.Started.....: Mon Jul 6 12:04:45 2020 (3 secs)
Time.Estimated...: Mon Jul 6 12:04:48 2020 (0 secs)
Guess.Base.......: File (/speed/corncob_lowercase.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.2..........: 13366.2 kH/s (1.06ms) @ Accel:1024 Loops:1 Thr:64 Vec:1
Recovered........: 25570/17264398 (0.15%) Digests
Remaining........: 17238828 (99.85%) Digests
Recovered/Time...: CUR:N/A,N/A,N/A AVG:623132,37387971,897311312 (Min,Hour,Day)
Progress.........: 58110/58110 (100.00%)
Rejected.........: 0/58110 (0.00%)
Restore.Point....: 58110/58110 (100.00%)
Restore.Sub..2...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidates..2....: aardvark -> zulus
Hardware.Mon..2..: Temp: 38c Fan: 99% Util: 8% Core:1328MHz Mem:3004MHz Bus:4
GPU Time = 3s
Cracked = 25.570
Hash Cracked per Second = 8.523,33
Total Cracked So Far = 25.570
Remaining Hashes = %99,85
Twenty-five thousand five hundred seventy people used lowercase dictionary words for their passwords.
5.1.1 Wordlist with Rules
But what about people who used capitalization in the first letter(Fire)? What about the people who added a calendar year at the end of the word(fire2000)? Some people might do both(Fire2000).
To scan for such passwords, we can modify the wordlist. The thing about wordlists are, they are not just data; they are big data. Changing only the first letter in a large wordlist could take hours and a lot of free disk space. Luckily, hashcat has an option to make such modifications on the fly. It is called rule based attack.
To capitalize on the first letter, we need to use the operator "c". To add constants to the end of the candidate, we can use "$" operator. There are much more rules can do for us.
First, we need a file to store our rules. Our first rule is just "c"
cat myrules.rule
c
To use hashcat with rules, -r
parameter is used.
./hashcat-6.0.0/hashcat.bin -m 100 --remove -d 2 hashlist -r myrules.rule /speed/corncob_lowercase.txt
Time.Started.....: Mon Jul 6 12:16:26 2020 (1 sec)
Time.Estimated...: Mon Jul 6 12:16:27 2020 (0 secs)
Guess.Base.......: File (/speed/corncob_lowercase.txt)
Guess.Mod........: Rules (myrules.rule)
Guess.Queue......: 1/1 (100.00%)
Speed2...........: 12304.0 kH/s (0.85ms) @ Accel:1024 Loops:1 Thr:64 Vec:1
Recovered........: 9009/17238828 (0.05%) Digests
GPU Time = 1s
Cracked = 9.009
Hash Cracked per Second = 9.009
Total Cracked So Far = 34.579
Remaining Hashes = %99,80
Now, let's add "2000" to the end of every candidate and capitalize first letters. Notice there are now two rules in the file.
cat myrules.rule
c
c$2$0$0$0
./hashcat-6.0.0/hashcat.bin -m 100 --remove -d 2 hashlist -r myrules.rule /speed/corncob_lowercase.txt
Time.Started.....: Mon Jul 6 12:18:32 2020 (0 secs)
Guess.Base.......: File (/speed/corncob_lowercase.txt)
Guess.Mod........: Rules (myrules.rule)
Guess.Queue......: 1/1 (100.00%)
Speed2...........: 14466.4 kH/s (0.72ms) @ Accel:1024 Loops:1 Thr:64 Vec:1
Recovered........: 624/17229819 (0.00%) Digests
Candidates..2....: Aardvark2000 -> Zulus2000
GPU Time = 1s
Cracked = 624
Hash Cracked per Second = 624
Total Cracked So Far = 35.203
Remaining Hashes = %99,80
Six hundred twenty-four people used a dictionary word, but they made the first character uppercase and added the year 2000 to the end.
There are infinite rule combinations, but some of the best rule lists come with the latest hashcat.
ls hashcat-6.0.0/rules/
best64.rule Incisive-leetspeak.rule T0XlC-insert_00-99_1950-2050_toprules_0_F.rule toggles3.rule
combinator.rule InsidePro-HashManager.rule T0XlC-insert_space_and_special_0_F.rule toggles4.rule
d3ad0ne.rule InsidePro-PasswordsPro.rule T0XlC-insert_top_100_passwords_1_G.rule toggles5.rule
dive.rule leetspeak.rule T0XlC.rule unix-ninja-leetspeak.rule
generated2.rule oscommerce.rule T0XlCv1.rule
generated.rule rockyou-30000.rule toggles1.rule
hybrid specific.rule toggles2.rule
Let's try best64 rule set with our wordlist.
./hashcat-6.0.0/hashcat.bin -m 100 hashlist -r hashcat-6.0.0/rules/best64.rule /speed/corncob_lowercase.txt --remove
Time.Started.....: Mon Jul 6 12:21:11 2020 (23 secs)
Guess.Base.......: File (/speed/corncob_lowercase.txt)
Guess.Mod........: Rules (hashcat-6.0.0/rules/best64.rule)
Guess.Queue......: 1/1 (100.00%)
Speed2...........: 84501.0 kH/s (17.70ms) @ Accel:32 Loops:77 Thr:64 Vec:1
Recovered........: 215845/17229195 (1.25%) Digests
Candidates..2....: foundation -> resres
GPU Time = 23s.
Cracked = 215.845
Hash Cracked Per Second = 9.384,57
Total Cracked So Far = 251.048
Remaining Hashes = %99,55
Rule lists are very good at increasing the number of candidates. Another thing to note here is the speed of operation. The very same GPU working on the same hash type started working faster:
Pure wordlist
Speed2...........: 13366.2 kH/s (1.06ms) @ Accel:1024 Loops:1 Thr:64 Vec:1
Wordlist with rule list
Speed2...........: 84501.0 kH/s (17.70ms) @ Accel:32 Loops:77 Thr:64 Vec:1
But what made GPU go six times faster? As mentioned in the speed section, this is a fast hash. It is not easy to provide enough candidates for such fast hashes. Ruleset simply provides more candidates for the process, and the process gets faster. We are yet to achieve the max hash cracking speed for our GPU.
We can specify multiple rule files to hashcat, but it runs them one by one, stopping and restarting sessions for every rule file. This is not very efficient. To create a single rule file that has all the rules in it:
find hashcat-6.0.0/rules/ -type f -exec cat "{}" \; | sort | uniq > allrules
As we can see, these rules are very optimized. Our wordlist found out 25570 passwords, but the same wordlist with rules:
./hashcat-6.0.0/hashcat.bin -m 100 hashlist -r allrules ~/corncob_lowercase.txt --remove
Time.Started.....: Mon Jul 6 12:25:23 2020 (6 mins, 54 secs)
Guess.Base.......: File (/speed/corncob_lowercase.txt)
Guess.Mod........: Rules (allrules)
Guess.Queue......: 1/1 (100.00%)
Speed2...........: 61623.4 kH/s (18.91ms) @ Accel:192 Loops:32 Thr:64 Vec:1
Recovered........: 2416561/17013350 (14.20%) Digests
Candidates..2....: zzaardvarkark -> Zzzuluslus
GPU Time = 414 sec
Cracked = 2.416.561
Hash Cracked Per Second = 5.837,10
Total Cracked So Far = 2.667.609
Remaining Hashes = %84,55
We cracked more than %15 of the remaining passwords in this attack. In the earlier example, testing the same wordlist took 3 seconds. Now it took 6 minutes 54 seconds to recover two and a half million hashes.
Since we exhausted the most basic attack, now we need to move on to more advanced methods.
5.2 Combination | 1
A combination attack is pretty similar to the straight attack. Instead of one dictionary, this attack uses two dictionaries and adds the words side by side. Let's check for users who just added two lowercase dictionary words together.
./hashcat-6.0.0/hashcat.bin -m 100 hashlist --remove -d 2 -a 1 /speed/corncob_lowercase.txt /speed/corncob_lowercase.txt
Time.Started.....: Mon Jul 6 12:35:22 2020 (31 secs)
Guess.Base.......: File (/speed/corncob_lowercase.txt), Left Side
Guess.Mod........: File (/speed/corncob_lowercase.txt), Right Side
Speed2...........: 110.8 MH/s (3.73ms) @ Accel:2 Loops:128 Thr:1024 Vec:1
Recovered........: 63299/14596789 (0.43%) Digests
Candidates..2....: trussesyoke -> zuluszulus
GPU Time = 31 secs
Cracked = 63.299
Hash Cracked Per Second = 2.041,90
Total Cracked So Far = 2.730.908
Remaining Hashes = %84,18
What about the users who added two dictionary words with capitalizing only the first letter?
In this mode, -j applies rules to the left wordlist, -k applies rules to the right wordlist. We need to specify individual rules instead of rule lists.
Time.Started.....: Mon Jul 6 12:43:54 2020 (23 secs)
Guess.Base.......: File (/speed/corncob_lowercase.txt), Left Side
Guess.Mod........: File (/speed/corncob_lowercase.txt), Right Side
Speed2...........: 147.1 MH/s (3.70ms) @ Accel:2 Loops:128 Thr:1024 Vec:1
Recovered........: 14890/14533490 (0.10%) Digests
Candidates..2....: Trussesyoke -> Zuluszulus
GPU Time = 23secs
Cracked = 14.890
Hash Cracked Per Second = 647,39
Total Cracked So Far = 2.745.798
Remaining Hashes = %84,10
Notice the speed. Two wordlists have exponentially more candidates that one.
Pure wordlist
Speed2...........: 13366.2 kH/s (1.06ms) @ Accel:1024 Loops:1 Thr:64 Vec:1
Wordlist with rule list
Speed2...........: 84501.0 kH/s (17.70ms) @ Accel:32 Loops:77 Thr:64 Vec:1
Combinator with single rule
Speed2...........: 147.1 MH/s (3.70ms) @ Accel:2 Loops:128 Thr:1024 Vec:1
5.3 Brute-force | 3
As the most popular form of password cracking, we try out every possible combination on the list without a guiding wordlist. This attack is often very time-consuming, even for GPUs. Official guide explains the details, We need to write masks to attack certain keyspaces. -i
parameters increase password length one by one.
We start by clearing lower lengths with a full brute force. This will crack recover every possible password between length one and five.
./hashcat-6.0.0/hashcat.bin -m 100 hashlist --remove -d 2 -a 3 ?a?a?a?a?a -i
Recovered........: 0/12325824 (0.00%) Digests
Time.Started.....: Mon Jul 6 13:44:05 2020 (36 secs)
GPU Time = 36 secs
Cracked = 0
Hash Cracked Per Second = 0
It seems like, passwords shorter than five characters were not allowed by the system back than.
We can smoothly go for longer passwords with this attack, and it could clear a lot of hashes from our list given than SHA1 is an ancient and weak hash function. This tutorial is not cracking hashes with GPU power. It is about using patterns and statistics to break down hashes. The same methods are applicable for stronger and newer hashes.
Let us start with scanning for all digit passwords:
Time.Started.....: Mon Jul 6 12:55:34 2020 (4 secs)
Guess.Mask.......: ?d?d?d?d?d?d [6]
Speed2...........: 81918.2 kH/s (11.50ms) @ Accel:2 Loops:100 Thr:1024 Vec:1
Recovered........: 341872/14518600 (2.35%) Digests
Time.Started.....: Mon Jul 6 12:57:43 2020 (3 secs)
Guess.Mask.......: ?d?d?d?d?d?d?d [7]
Speed2...........: 4022.1 kH/s (7.88ms) @ Accel:2 Loops:125 Thr:1024 Vec:1
Recovered........: 209534/14176728 (1.48%) Digests
Time.Started.....: Mon Jul 6 12:58:56 2020 (6 secs)
Guess.Mask.......: ?d?d?d?d?d?d?d?d [8]
Speed2...........: 17219.4 kH/s (18.15ms) @ Accel:2 Loops:125 Thr:1024 Vec:1
Recovered........: 401539/13967194 (2.87%) Digests
Time.Started.....: Mon Jul 6 13:13:26 2020 (11 secs)
Guess.Mask.......: ?d?d?d?d?d?d?d?d?d [9]
Speed2...........: 86920.6 kH/s (23.35ms) @ Accel:4 Loops:62 Thr:1024 Vec:1
Recovered........: 71985/17264398 (0.42%) Digests
Time.Started.....: Mon Jul 6 13:02:23 2020 (1 min, 4 secs)
Guess.Mask.......: ?d?d?d?d?d?d?d?d?d?d [10]
Speed2...........: 155.9 MH/s (16.98ms) @ Accel:2 Loops:125 Thr:1024 Vec:1
Recovered........: 260366/13493670 (1.93%) Digests
GPU Time = 4 + 3 + 11 + 64 secs
Cracked = 341872 + 209534 + 401539 + 71985 + 260366 = 1.285.296
Hash Cracked Per Second = 15.674,34
Total Cracked So Far = 4.031.094
Remaining Hashes = %76,65
Now we will scan for all lowercase letters passwords. From the earlier attack, we know there can't be any password shorter than five characters.
Time.Started.....: Mon Jul 6 13:18:37 2020 (5 secs)
Guess.Mask.......: ?l?l?l?l?l?l [6]
Speed2...........: 59496.7 kH/s (9.51ms) @ Accel:2 Loops:84 Thr:1024 Vec:1
Recovered........: 132666/13233304 (1.00%) Digests
Time.Started.....: Mon Jul 6 13:19:50 2020 (46 secs)
Guess.Mask.......: ?l?l?l?l?l?l?l [7]
Speed2...........: 174.3 MH/s (9.41ms) @ Accel:4 Loops:64 Thr:1024 Vec:1
Recovered........: 240316/13100638 (1.83%) Digests
Time.Started.....: Mon Jul 6 13:21:31 2020 (17 mins, 54 secs)
Guess.Mask.......: ?l?l?l?l?l?l?l?l [8]
Speed2...........: 191.6 MH/s (4.43ms) @ Accel:2 Loops:128 Thr:1024 Vec:1
Recovered........: 534498/12860322 (4.16%) Digests
GPU Time = 5 + 46 + 17*60 + 54 secs
Cracked = 132666 + 240316 + 534498 = 907.480
Hash Cracked Per Second = 806,65
Total Cracked So Far = 4.938.574
Remaining Hashes = %71,39
If you are sitting near your GPU, you might have felt an increase in room temperature. Unlike wordlist based attacks, this method generates candidates instead of reading them from a file. This method can easily to max out your GPU and use every bit of resource. If you are using a single GPU, you might see flickers and tears on your screens while such an attack is running. When we compare the speeds with earlier attacks:
Pure wordlist
Speed2...........: 13366.2 kH/s (1.06ms) @ Accel:1024 Loops:1 Thr:64 Vec:1
Wordlist with rule list
Speed2...........: 84501.0 kH/s (17.70ms) @ Accel:32 Loops:77 Thr:64 Vec:1
Combinator with single rule
Speed2...........: 147.1 MH/s (3.70ms) @ Accel:2 Loops:128 Thr:1024 Vec:1
Mask attack with large space
Speed2...........: 191.6 MH/s (4.43ms) @ Accel:2 Loops:128 Thr:1024 Vec:1
The last one is the most extended attack we used. Not all LinkedIn members are native English speakers. As we can see, hash per second is not very high for this one. We have chosen to spend some time on eight characters to find new words for our later attacks.
Experts often say that passwords should contain more than letters and digits. Another powerful feature of hashcat is the ability to define custom character sets in rules. We already removed some of the only letter and only digit passwords with our earlier scans.
We need two custom character sets for our last mask attack.
- -1 ?l*.$-_!
all lower letters, "*" , "." , "$" , "-" , "_", "!"
- -2 ?u?l*.$-_!
all uppercase, all lower letters, "*" , "." , "$" , "-" , "_", "!"
Time.Started.....: Mon Jul 6 13:44:45 2020 (9 secs)
Guess.Mask.......: ?2?1?1?1?1?1 [6]
Guess.Charset....: -1 ?l*.$-_!, -2 ?u?l*.$-_!, -3 Undefined, -4 Undefined
Speed2...........: 205.1 MH/s (13.75ms) @ Accel:2 Loops:128 Thr:1024 Vec:1
Recovered........: 17904/12325824 (0.15%) Digests
Time.Started.....: Mon Jul 6 13:48:54 2020 (4 mins, 59 secs)
Guess.Mask.......: ?2?1?1?1?1?1?1 [7]
Guess.Charset....: -1 ?l*.$-_!, -2 ?u?l*.$-_!, -3 Undefined, -4 Undefined
Speed2...........: 210.7 MH/s (5.60ms) @ Accel:2 Loops:128 Thr:1024 Vec:1
Recovered........: 29119/12307920 (0.24%) Digests
GPU Time = 9 + 4 * 60 + 59 secs
Cracked = 17904 + 29119 = 47.023
Hash Cracked Per Second = 157,27
Total Cracked So Far = 4.985.597
Remaining Hashes = %71,12
These were the low hanging fruits. Bunch of ready to use mask lists come with hashcat. These masks were generated from earlier leaks, and using them would be cheating for us.
ls hashcat-6.0.0/masks/
8char-1l-1u-1d-1s-compliant.hcmask rockyou-1-60.hcmask rockyou-4-43200.hcmask rockyou-7-2592000.hcmask
8char-1l-1u-1d-1s-noncompliant.hcmask rockyou-2-1800.hcmask rockyou-5-86400.hcmask
hashcat-default.hcmask rockyou-3-3600.hcmask rockyou-6-864000.hcmask
5.4 Hybrid Wordlist + Mask | 6
While talking about rule attacks, we added 2000 to the end of all our words. What if we wanted to test every word with every possible past or future year in the end? Hybrid attacks help you scan this space.
./hashcat-6.0.0/hashcat.bin -m 100 hashlist --remove -d 2 -a 6 /speed/corncob_lowercase.txt ?d?d?d?d
Time.Started.....: Mon Jul 6 13:58:17 2020 (15 secs)
Guess.Base.......: File (/speed/corncob_lowercase.txt), Left Side
Guess.Mod........: Mask (?d?d?d?d) [4], Right Side
Speed2...........: 38177.7 kH/s (12.81ms) @ Accel:4 Loops:128 Thr:1024 Vec:1
Recovered........: 127489/12278801 (1.04%) Digests
GPU Time =15 secs
Cracked = 127.489
Hash Cracked Per Second =8.499,27
Total Cracked So Far = 5.113.086
Remaining Hashes = %70,38
If we combine this new method with our custom rule set, we create an efficient attack.
- -1 ?l*.$-_!
all digits, all lower letters, "*" , "." , "$" , "-" , "_", "!"
Time.Started.....: Mon Jul 6 14:03:07 2020 (0 secs)
Guess.Base.......: File (/speed/corncob_lowercase.txt), Left Side
Guess.Mod........: Mask (?1) [1], Right Side
Guess.Charset....: -1 ?d?l*.$-_!, -2 Undefined, -3 Undefined, -4 Undefined
Speed2...........: 178.0 MH/s (10.24ms) @ Accel:8 Loops:42 Thr:1024 Vec:1
Recovered........: 0/12151312 (0.00%) Digests
Time.Started.....: Mon Jul 6 14:04:12 2020 (1 sec)
Guess.Base.......: File (/speed/corncob_lowercase.txt), Left Side
Guess.Mod........: Mask (?1?1) [2], Right Side
Guess.Charset....: -1 ?d?l*.$-_!, -2 Undefined, -3 Undefined, -4 Undefined
Speed2...........: 115.7 MH/s (15.62ms) @ Accel:4 Loops:128 Thr:1024 Vec:1
Recovered........: 2604/12151312 (0.02%) Digests
Time.Started.....: Mon Jul 6 14:04:56 2020 (31 secs)
Guess.Base.......: File (/speed/corncob_lowercase.txt), Left Side
Guess.Mod........: Mask (?1?1?1) [3], Right Side
Guess.Charset....: -1 ?d?l*.$-_!, -2 Undefined, -3 Undefined, -4 Undefined
Speed2...........: 137.7 MH/s (3.08ms) @ Accel:4 Loops:128 Thr:1024 Vec:1
Recovered........: 82217/12148708 (0.68%) Digests
Let us remove letters from our charset to speed up our scans.
Time.Started.....: Mon Jul 6 14:08:00 2020 (18 secs)
Guess.Base.......: File (/speed/corncob_lowercase.txt), Left Side
Guess.Mod........: Mask (?1?1?1?1) [4], Right Side
Guess.Charset....: -1 ?d*.$-_!, -2 Undefined, -3 Undefined, -4 Undefined
Speed2...........: 213.6 MH/s (3.07ms) @ Accel:4 Loops:128 Thr:1024 Vec:1
Recovered........: 3200/12062227 (0.03%) Digests
Remaining........: 12059027 (99.97%) Digests
Time.Started.....: Mon Jul 6 14:09:01 2020 (4 mins, 37 secs)
Guess.Base.......: File (/speed/corncob_lowercase.txt), Left Side
Guess.Mod........: Mask (?1?1?1?1?1) [5], Right Side
Guess.Charset....: -1 ?d*.$-_!, -2 Undefined, -3 Undefined, -4 Undefined
Speed2...........: 184.0 MH/s (3.07ms) @ Accel:4 Loops:128 Thr:1024 Vec:1
Recovered........: 29830/12059027 (0.25%) Digests
GPU Time = 0 + 1 + 31 + 18 + 4 * 60 + 37 sec
Cracked = 0 + 2604 + 82217 + 3200 + 29830 = 117.851
Hash Cracked Per Second = 360,40
Total Cracked So Far = 5.230.937
Remaining Hashes = %69,70
5.5 Hybrid Mask + wordlist | 7
This method is very similar to our last method. The difference is in the ordering. This attack puts masks before the wordlist.
Since putting numbers before passwords are not as common as putting them after the words, we go with the same character and digits-based mask.
./hashcat-6.0.0/hashcat.bin -m 100 hashlist --remove -d 2 -a 7 -1 ?d\*.\$-_! ?1 /speed/corncob_lowercase.txt
Time.Started.....: Mon Jul 6 14:15:28 2020 (1 sec)
Guess.Base.......: File (/speed/corncob_lowercase.txt), Right Side
Guess.Mod........: Mask (?1) [1], Left Side
Guess.Charset....: -1 ?d*.$-_!, -2 Undefined, -3 Undefined, -4 Undefined
Speed2...........: 834.5 kH/s (1.65ms) @ Accel:4 Loops:128 Thr:1024 Vec:1
Recovered........: 0/12029197 (0.00%) Digests
Time.Started.....: Mon Jul 6 14:16:09 2020 (1 sec)
Guess.Base.......: File (/speed/corncob_lowercase.txt), Right Side
Guess.Mod........: Mask (?1?1) [2], Left Side
Guess.Charset....: -1 ?d*.$-_!, -2 Undefined, -3 Undefined, -4 Undefined
Speed2...........: 11787.0 kH/s (1.91ms) @ Accel:4 Loops:128 Thr:1024 Vec:1
Recovered........: 37/12029197 (0.00%) Digests
Time.Started.....: Mon Jul 6 14:16:53 2020 (2 secs)
Guess.Base.......: File (/speed/corncob_lowercase.txt), Right Side
Guess.Mod........: Mask (?1?1?1) [3], Left Side
Guess.Charset....: -1 ?d*.$-_!, -2 Undefined, -3 Undefined, -4 Undefined
Speed2...........: 134.1 MH/s (2.82ms) @ Accel:4 Loops:128 Thr:1024 Vec:1
Recovered........: 413/12029160 (0.00%) Digests
Time.Started.....: Mon Jul 6 14:17:44 2020 (21 secs)
Guess.Base.......: File (/speed/corncob_lowercase.txt), Right Side
Guess.Mod........: Mask (?1?1?1?1) [4], Left Side
Guess.Charset....: -1 ?d*.$-_!, -2 Undefined, -3 Undefined, -4 Undefined
Speed2...........: 179.6 MH/s (6.74ms) @ Accel:4 Loops:128 Thr:1024 Vec:1
Recovered........: 34492/12028747 (0.29%) Digests
Time.Started.....: Mon Jul 6 14:18:52 2020 (4 mins, 19 secs)
Guess.Base.......: File (/speed/corncob_lowercase.txt), Right Side
Guess.Mod........: Mask (?1?1?1?1?1) [5], Left Side
Guess.Charset....: -1 ?d*.$-_!, -2 Undefined, -3 Undefined, -4 Undefined
Speed2...........: 231.6 MH/s (20.16ms) @ Accel:4 Loops:128 Thr:1024 Vec:1
Recovered........: 4425/11994255 (0.04%) Digests
GPU Time = 1 + 2 + 21 + 4 * 60 + 19 sec
Cracked =37 + 413 + 34492 + 4425 = 39.367
Hash Cracked Per Second = 139,11
Total Cracked So Far = 5.270.304
Remaining Hashes = %69,47
Now, we tried every different attack in hashcat and recovered only a certain percentage of hashes. Some might think we need more hardware or computation time to recover the rest of the hashes.
6. Using the Information
Nowadays, people often think hash cracking is about hardware power. Hash cracking is about processing information; it is about thinking about the keyspace and statistics and finding patterns.
If you were to toss a perfect coin, both sides have a fifty percent chance. If you toss six coins, can you expect three heads and three tails? Not very likely. During WWII, a mathematician named John Kerrich was imprisoned in a prison camp. During this time, he tossed a coin 100 times and got 5067 heads. Statistics gets its power from numbers, this is called the law of large numbers.
Basicly for statistics to work accurately, you need a large number of samples. Since we are working with a pretty large dataset, this law applies for us.
All we did so far was about extracting information from our hashes. Now we know some of them, and we need to use this information to gather more information. By recovering some hashes from our list, we unknowingly created a very optimized wordlist. How many of the recovered hashes have some form of similarity with the unrecovered hashed?
Hashcat saved recovered hashes in a file called "hashcat.potfile", which currently holds all the recovered hashes. Let's transform this file into a wordlist.
cat hashcat-6.0.0/hashcat.potfile | cut -d: -f2 > ourlist
Let us run our wordlist with all the rules; this would take a while.
Time.Started.....: Mon Jul 6 14:34:39 2020 (2 hour, 13 mins)
Time.Estimated...: Mon Jul 6 15:48:35 2020 (0 secs)
Guess.Base.......: File (ourlist)
Guess.Mod........: Rules (allrules)
Guess.Queue......: 1/1 (100.00%)
Speed.2.........: 122.5 MH/s (3.57ms) @ Accel:64 Loops:16 Thr:64 Vec:1
Recovered........: 4909894/11799033 (41.61%) Digests
GPU Time = 2 hour, 13 mins
Cracked = 4.909.894
Hash Cracked Per Second = 615,27
Total Cracked So Far = 10.180.198
Remaining Hashes = %41,03
As we can see, this new wordlist is exceptionally optimized for our hash list; even with a fundamental attack, we cracked almost 5 million new hashes!
We used three hours of GPU time for the all steps of this guide on a GPU from time period of the leak.
Using a smaller ruleset could yield faster results. But we wanted to exhaust all the known rules for the second part of this tutorial. In the second part, we will create our custom ruleset, custom mask lists, improve our custom dictionary, and even use statistical methods like Markov Chains to generate candidates for hash recovery. To properly evaluate the efficiency of our future custom methods, we allow this scan to run entirely.