Password Cracking Techniques
Introduction to Password Cracking
Take the password Soccer06! for example. The corresponding MD5 and SHA-256 hashes can be generated with the following commands:
bmdyy@htb:~$ echo -n Soccer06! | md5sum
40291c1d19ee11a7df8495c4cccefdfa -
bmdyy@htb:~$ echo -n Soccer06! | sha256sum
a025dc6fabb09c2b8bfe23b5944635f9b68433ebd9a1a09453dd4fee00766d93 -Introduction to John The Ripper
Single crack mode
Imagine we as attackers came across the file passwd with the following contents:
r0lf:$6$ues25dIanlctrWxg$nZHVz2z4kCy1760Ee28M1xtHdGoy0C2cYzZ8l2sVa1kIa8K9gAcdBP.GI6ng/qA4oaMrgElZ1Cb9OeXO4Fvy3/:0:0:Rolf Sebastian:/home/r0lf:/bin/bashBased on the contents of the file, it can be inferred that the victim has the username r0lf, the real name Rolf Sebastian, and the home directory /home/r0lf. Single crack mode will use this information to generate candidate passwords and test them against the hash. We can run the attack with the following command:
eldeim@htb[/htb]$ john --single passwd
Using default input encoding: UTF-8
Loaded 1 password hash (sha512crypt, crypt(3) $6$ [SHA512 256/256 AVX2 4x])
Cost 1 (iteration count) is 5000 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
[...SNIP...] (r0lf)
1g 0:00:00:00 DONE 1/3 (2025-04-10 07:47) 12.50g/s 5400p/s 5400c/s 5400C/s NAITSABESFL0R..rSebastiannaitsabeSr
Use the "--show" option to display all of the cracked passwords reliably
Session completed.In this case, the password hash was successfully cracked.
Wordlist mode
Wordlist mode is used to crack passwords with a dictionary attack, meaning it attempts all passwords in a supplied wordlist against the password hash. The basic syntax for the command is as follows:
eldeim@htb[/htb]$ john --wordlist=<wordlist_file> <hash_file>The wordlist file (or files) used for cracking password hashes must be in plain text format, with one word per line. Multiple wordlists can be specified by separating them with a comma. Rules, either custom or built-in, can be specified by using the --rules argument. These can be applied to generate candidate passwords using transformations such as appending numbers, capitalizing letters and adding special characters.
Incremental mode
Incremental mode is a powerful, brute-force-style password cracking mode that generates candidate passwords based on a statistical model (Markov chains). It is designed to test all character combinations defined by a specific character set, prioritizing more likely passwords based on training data.
eldeim@htb[/htb]$ john --incremental <hash_file>By default, JtR uses predefined incremental modes specified in its configuration file (john.conf), which define character sets and password lengths. You can customize these or define your own to target passwords that use special characters or specific patterns.
eldeim@htb[/htb]$ grep '# Incremental modes' -A 100 /etc/john/john.conf
# Incremental modes
# This is for one-off uses (make your own custom.chr).
# A charset can now also be named directly from command-line, so no config
# entry needed: --incremental=whatever.chr
[Incremental:Custom]
File = $JOHN/custom.chr
MinLen = 0
# The theoretical CharCount is 211, we've got 196.
[Incremental:UTF8]
File = $JOHN/utf8.chr
MinLen = 0
CharCount = 196
# This is CP1252, a super-set of ISO-8859-1.
# The theoretical CharCount is 219, we've got 203.
[Incremental:Latin1]
File = $JOHN/latin1.chr
MinLen = 0
CharCount = 203
[Incremental:ASCII]
File = $JOHN/ascii.chr
MinLen = 0
MaxLen = 13
CharCount = 95
...SNIP...Note: This mode can be resource-intensive and slow, especially for long or complex passwords. Customizing the character set and length can improve performance and focus the attack.
Identifying hash formats
Sometimes, password hashes may appear in an unknown format, and even John the Ripper (JtR) may not be able to identify them with complete certainty. For example, consider the following hash:
193069ceb0461e1d40d216e32c79c704One way to get an idea is to consult JtR's sample hash documentation, or this list by PentestMonkey. Both sources list multiple example hashes as well as the corresponding JtR format. Another option is to use a tool like hashID, which checks supplied hashes against a built-in list to suggest potential formats. By adding the -j flag, hashID will, in addition to the hash format, list the corresponding JtR format:
eldeim@htb[/htb]$ hashid -j 193069ceb0461e1d40d216e32c79c704
Analyzing '193069ceb0461e1d40d216e32c79c704'
[+] MD2 [JtR Format: md2]
[+] MD5 [JtR Format: raw-md5]
[+] MD4 [JtR Format: raw-md4]
[+] Double MD5
[+] LM [JtR Format: lm]
[+] RIPEMD-128 [JtR Format: ripemd-128]
[+] Haval-128 [JtR Format: haval-128-4]
[+] Tiger-128
[+] Skein-256(128)
[+] Skein-512(128)
[+] Lotus Notes/Domino 5 [JtR Format: lotus5]
[+] Skype
[+] Snefru-128 [JtR Format: snefru-128]
[+] NTLM [JtR Format: nt]
[+] Domain Cached Credentials [JtR Format: mscach]
[+] Domain Cached Credentials 2 [JtR Format: mscach2]
[+] DNSSEC(NSEC3)
[+] RAdmin v2.x [JtR Format: radmin]Cracking files
It is also possible to crack password-protected or encrypted files with JtR. Multiple "2john" tools come with JtR that can be used to process files and produce hashes compatible with JtR. The generalized syntax for these tools is:
eldeim@htb[/htb]$ <tool> <file_to_crack> > file.hashSome of the tools included with JtR are:
Tool
Description
pdf2john
Converts PDF documents for John
ssh2john
Converts SSH private keys for John
mscash2john
Converts MS Cash hashes for John
keychain2john
Converts OS X keychain files for John
rar2john
Converts RAR archives for John
pfx2john
Converts PKCS#12 files for John
truecrypt_volume2john
Converts TrueCrypt volumes for John
keepass2john
Converts KeePass databases for John
vncpcap2john
Converts VNC PCAP files for John
putty2john
Converts PuTTY private keys for John
zip2john
Converts ZIP archives for John
hccap2john
Converts WPA/WPA2 handshake captures for John
office2john
Converts MS Office documents for John
wpa2john
Converts WPA/WPA2 handshakes for John
...SNIP...
...SNIP...
An even larger collection can be found on the Pwnbox:
eldeim@htb[/htb]$ locate *2john*
/usr/bin/bitlocker2john
/usr/bin/dmg2john
/usr/bin/gpg2john
/usr/bin/hccap2john
/usr/bin/keepass2john
/usr/bin/putty2john
/usr/bin/racf2john
/usr/bin/rar2john
/usr/bin/uaf2john
/usr/bin/vncpcap2john
/usr/bin/wlanhcx2john
/usr/bin/wpapcap2john
/usr/bin/zip2john
/usr/share/john/1password2john.py
/usr/share/john/7z2john.pl
/usr/share/john/DPAPImk2john.py
/usr/share/john/adxcsouf2john.py
/usr/share/john/aem2john.py
/usr/share/john/aix2john.pl
/usr/share/john/aix2john.py
/usr/share/john/andotp2john.py
/usr/share/john/androidbackup2john.py
...SNIP...Lab - Questions
Use single-crack mode to crack r0lf's password.
## Set the passwd into a file
nano pass
r0lf:$6$ues25dIanlctrWxg$nZHVz2z4kCy1760Ee28M1xtHdGoy0C2cYzZ8l2sVa1kIa8K9gAcdBP.GI6ng/qA4oaMrgElZ1Cb9OeXO4Fvy3/:0:0:Rolf Sebastian:/home/r0lf:/bin/bash
## Then, execute a simple jhon confg
john --single passUse wordlist-mode with rockyou.txt to crack the RIPEMD-128 password.
## We have a hash ripemd-128
193069ceb0461e1d40d216e32c79c704
### Set into file and run jhon with the flag of ripemd
john --wordlist=/usr/share/wordlists/rockyou.txt hash --format=ripemd-128Introduction to Hashcat
eldeim@htb[/htb]$ hashcat -a 0 -m 0 <hashes> [wordlist, rule, mask, ...]In the command above:
-ais used to specify theattack mode-mis used to specify thehash type<hashes>is a either a hash string, or a file containing one or more password hashes of the same type[wordlist, rule, mask, ...]is a placeholder for additional arguments that depend on the attack mode
Hash types
Hashcat supports hundreds of different hash types, each of which is assigned a ID. A list of associated IDs can be generated by running hashcat --help.
eldeim@htb[/htb]$ hashcat --help
...SNIP...
- [ Hash modes ] -
# | Name | Category
======+============================================================+======================================
900 | MD4 | Raw Hash
0 | MD5 | Raw Hash
100 | SHA1 | Raw Hash
1300 | SHA2-224 | Raw Hash
1400 | SHA2-256 | Raw Hash
10800 | SHA2-384 | Raw Hash
1700 | SHA2-512 | Raw Hash
17300 | SHA3-224 | Raw Hash
17400 | SHA3-256 | Raw Hash
17500 | SHA3-384 | Raw Hash
17600 | SHA3-512 | Raw Hash
6000 | RIPEMD-160 | Raw Hash
600 | BLAKE2b-512 | Raw Hash
11700 | GOST R 34.11-2012 (Streebog) 256-bit, big-endian | Raw Hash
11800 | GOST R 34.11-2012 (Streebog) 512-bit, big-endian | Raw Hash
6900 | GOST R 34.11-94 | Raw Hash
17010 | GPG (AES-128/AES-256 (SHA-1($pass))) | Raw Hash
5100 | Half MD5 | Raw Hash
17700 | Keccak-224 | Raw Hash
17800 | Keccak-256 | Raw Hash
17900 | Keccak-384 | Raw Hash
18000 | Keccak-512 | Raw Hash
6100 | Whirlpool | Raw Hash
10100 | SipHash | Raw Hash
70 | md5(utf16le($pass)) | Raw Hash
170 | sha1(utf16le($pass)) | Raw Hash
1470 | sha256(utf16le($pass)) | Raw Hash
...SNIP...The hashcat website hosts a comprehensive list of example hashes which can assist in manually identifying an unknown hash type and determining the corresponding Hashcat hash mode identifier.
Alternatively, hashID can be used to quickly identify the hashcat hash type by specifying the -m argument.
eldeim@htb[/htb]$ hashid -m '$1$FNr44XZC$wQxY6HHLrgrGX0e1195k.1'
Analyzing '$1$FNr44XZC$wQxY6HHLrgrGX0e1195k.1'
[+] MD5 Crypt [Hashcat Mode: 500]
[+] Cisco-IOS(MD5) [Hashcat Mode: 500]
[+] FreeBSD MD5 [Hashcat Mode: 500]Dictionary attack
ldeim@htb[/htb]$ hashcat -a 0 -m 0 e3e3ec5831ad5e7288241960e5d4fdb8 /usr/share/wordlists/rockyou.txt
...SNIP...
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 0 (MD5)
Hash.Target......: e3e3ec5831ad5e7288241960e5d4fdb8
Time.Started.....: Sat Apr 19 08:58:44 2025 (0 secs)
Time.Estimated...: Sat Apr 19 08:58:44 2025 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 1706.6 kH/s (0.14ms) @ Accel:512 Loops:1 Thr:1 Vec:8
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 28672/14344385 (0.20%)
Rejected.........: 0/28672 (0.00%)
Restore.Point....: 27648/14344385 (0.19%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Device Generator
Candidates.#1....: 010292 -> spongebob9
Hardware.Mon.#1..: Util: 40%
Started: Sat Apr 19 08:58:43 2025
Stopped: Sat Apr 19 08:58:46 2025A wordlist alone is often not enough to crack a password hash. As was the case with JtR, rules can be used to perform specific modifications to passwords to generate even more guesses. The rule files that come with hashcat are typically found under /usr/share/hashcat/rules:
eldeim@htb[/htb]$ ls -l /usr/share/hashcat/rules
total 2852
-rw-r--r-- 1 root root 309439 Apr 24 2024 Incisive-leetspeak.rule
-rw-r--r-- 1 root root 35802 Apr 24 2024 InsidePro-HashManager.rule
-rw-r--r-- 1 root root 20580 Apr 24 2024 InsidePro-PasswordsPro.rule
-rw-r--r-- 1 root root 64068 Apr 24 2024 T0XlC-insert_00-99_1950-2050_toprules_0_F.rule
-rw-r--r-- 1 root root 2027 Apr 24 2024 T0XlC-insert_space_and_special_0_F.rule
-rw-r--r-- 1 root root 34437 Apr 24 2024 T0XlC-insert_top_100_passwords_1_G.rule
-rw-r--r-- 1 root root 34813 Apr 24 2024 T0XlC.rule
-rw-r--r-- 1 root root 1289 Apr 24 2024 T0XlC_3_rule.rule
-rw-r--r-- 1 root root 168700 Apr 24 2024 T0XlC_insert_HTML_entities_0_Z.rule
-rw-r--r-- 1 root root 197418 Apr 24 2024 T0XlCv2.rule
-rw-r--r-- 1 root root 933 Apr 24 2024 best64.rule
-rw-r--r-- 1 root root 754 Apr 24 2024 combinator.rule
-rw-r--r-- 1 root root 200739 Apr 24 2024 d3ad0ne.rule
-rw-r--r-- 1 root root 788063 Apr 24 2024 dive.rule
-rw-r--r-- 1 root root 78068 Apr 24 2024 generated.rule
-rw-r--r-- 1 root root 483425 Apr 24 2024 generated2.rule
drwxr-xr-x 2 root root 4096 Oct 19 15:30 hybrid
-rw-r--r-- 1 root root 298 Apr 24 2024 leetspeak.rule
-rw-r--r-- 1 root root 1280 Apr 24 2024 oscommerce.rule
-rw-r--r-- 1 root root 301161 Apr 24 2024 rockyou-30000.rule
-rw-r--r-- 1 root root 1563 Apr 24 2024 specific.rule
-rw-r--r-- 1 root root 45 Apr 24 2024 toggles1.rule
-rw-r--r-- 1 root root 570 Apr 24 2024 toggles2.rule
-rw-r--r-- 1 root root 3755 Apr 24 2024 toggles3.rule
-rw-r--r-- 1 root root 16040 Apr 24 2024 toggles4.rule
-rw-r--r-- 1 root root 49073 Apr 24 2024 toggles5.rule
-rw-r--r-- 1 root root 55346 Apr 24 2024 unix-ninja-leetspeak.ruleAs another example, imagine an additional md5 hash was leaked from the SQL database: 1b0556a75770563578569ae21392630c. We weren't able to crack it using rockyou.txt alone, so in a subsequent attempt, we might apply some common rule-based transformations. One ruleset we could try is best64.rule, which contains 64 standard password modifications—such as appending numbers or substituting characters with their "leet" equivalents. To perform this kind of attack, we would append the -r <ruleset> option to the command, as shown below:
eldeim@htb[/htb]$ hashcat -a 0 -m 0 1b0556a75770563578569ae21392630c /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule
...SNIP...
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 0 (MD5)
Hash.Target......: 1b0556a75770563578569ae21392630c
Time.Started.....: Sat Apr 19 09:16:35 2025 (0 secs)
Time.Estimated...: Sat Apr 19 09:16:35 2025 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Mod........: Rules (/usr/share/hashcat/rules/best64.rule)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 13624.4 kH/s (5.40ms) @ Accel:512 Loops:77 Thr:1 Vec:8
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 236544/1104517645 (0.02%)
Rejected.........: 0/236544 (0.00%)
Restore.Point....: 2048/14344385 (0.01%)
Restore.Sub.#1...: Salt:0 Amplifier:0-77 Iteration:0-77
Candidate.Engine.: Device Generator
Candidates.#1....: slimshady -> drousd
Hardware.Mon.#1..: Util: 47%
Started: Sat Apr 19 09:16:35 2025
Stopped: Sat Apr 19 09:16:37 2025Mask attack
Mask attack (-a 3) is a type of brute-force attack in which the keyspace is explicitly defined by the user. For example, if we know that a password is eight characters long, rather than attempting every possible combination, we might define a mask that tests combinations of six letters followed by two numbers.
A mask is defined by combining a sequence of symbols, each representing a built-in or custom character set. Hashcat includes several built-in character sets:
?l
abcdefghijklmnopqrstuvwxyz
?u
ABCDEFGHIJKLMNOPQRSTUVWXYZ
?d
0123456789
?h
0123456789abcdef
?H
0123456789ABCDEF
?s
«space»!"#$%&'()*+,-./:;<=>?@[]^_`{
?a
?l?u?d?s
?b
0x00 - 0xff
Custom charsets can be defined with the -1, -2, -3, and -4 arguments, then referred to with ?1, ?2, ?3, and ?4.
Let's say that we specifically want to try passwords which start with an uppercase letter, continue with four lowercase letters, a digit, and then a symbol. The resulting hashcat mask would be ?u?l?l?l?l?d?s.
eldeim@htb[/htb]$ hashcat -a 3 -m 0 1e293d6912d074c0fd15844d803400dd '?u?l?l?l?l?d?s'
...SNIP...
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 0 (MD5)
Hash.Target......: 1e293d6912d074c0fd15844d803400dd
Time.Started.....: Sat Apr 19 09:43:02 2025 (4 secs)
Time.Estimated...: Sat Apr 19 09:43:06 2025 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Mask.......: ?u?l?l?l?l?d?s [7]
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 101.6 MH/s (9.29ms) @ Accel:512 Loops:1024 Thr:1 Vec:8
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 456237056/3920854080 (11.64%)
Rejected.........: 0/456237056 (0.00%)
Restore.Point....: 25600/223080 (11.48%)
Restore.Sub.#1...: Salt:0 Amplifier:5120-6144 Iteration:0-1024
Candidate.Engine.: Device Generator
Candidates.#1....: Uayvf7- -> Dikqn5!
Hardware.Mon.#1..: Util: 98%
Started: Sat Apr 19 09:42:46 2025
Stopped: Sat Apr 19 09:43:08 2025Lab - Questions
Use a dictionary attack to crack the first password hash. (Hash: e3e3ec5831ad5e7288241960e5d4fdb8)
hashcat -a 0 -m 0 e3e3ec5831ad5e7288241960e5d4fdb8 /usr/share/wordlists/rockyou.txtUse a dictionary attack with rules to crack the second password hash. (Hash: 1b0556a75770563578569ae21392630c)
For this occasion, we need use someone more of complicity, use:
hashcat -a 0 -m 0 1b0556a75770563578569ae21392630c /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.ruleUse a mask attack to crack the third password hash. (Hash: 1e293d6912d074c0fd15844d803400dd)
Here, we need use a mask attack -->
hashcat -a 3 -m 0 1e293d6912d074c0fd15844d803400dd '?u?l?l?l?l?d?s'
?l = lowercase?d = números?u = uppercase?s = símbolos
Writing Custom Wordlists and Rules
Commonly, users use the following additions for their password to fit the most common password policies:
Description
Password Syntax
First letter is uppercase
Password
Adding numbers
Password123
Adding year
Password2022
Adding month
Password02
Last character is an exclamation mark
Password2022!
Adding special characters
P@ssw0rd2022!
Let's look at a simple example using a password list with only one entry.
eldeim@htb[/htb]$ cat password.list
passwordWe can use Hashcat to combine lists of potential names and labels with specific mutation rules to create custom wordlists. Hashcat uses a specific syntax to define characters, words, and their transformations. The complete syntax is documented in the official Hashcat rule-based attack documentation, but the examples below are sufficient to understand how Hashcat mutates input words.
Function
Description
:
Do nothing
l
Lowercase all letters
u
Uppercase all letters
c
Capitalize the first letter and lowercase others
sXY
Replace all instances of X with Y
$!
Add the exclamation character at the end
Each rule is written on a new line and determines how a given word should be transformed. If we write the functions shown above into a file, it may look like this:
[!bash!]$ cat custom.rule
:
c
so0
c so0
sa@
c sa@
c sa@ so0
$!
$! c
$! so0
$! sa@
$! c so0
$! c sa@
$! so0 sa@
$! c so0 sa@We can use the following command to apply the rules in custom.rule to each word in password.list and store the mutated results in mut_password.list.
[!bash!]$ hashcat --force password.list -r custom.rule --stdout | sort -u > mut_password.listIn this case, the single input word will produce fifteen mutated variants.
[!bash!]$ cat mut_password.list
password
Password
passw0rd
Passw0rd
p@ssword
P@ssword
P@ssw0rd
password!
Password!
passw0rd!
p@ssword!
Passw0rd!
P@ssword!
p@ssw0rd!
P@ssw0rd!Lab - Questions
For this sections exercise, imagine that we compromised the password hash of a work email belonging to Mark White. After performing a bit of OSINT, we have gathered the following information about Mark:
He was born on
August 5, 1998He works at
Nexura, Ltd.The company's password policy requires passwords to be at least 12 characters long, to contain at least one uppercase letter, at least one lowercase letter, at least one symbol and at least one number
He lives in
San Francisco, CA, USAHe has a pet cat named
BellaHe has a wife named
MariaHe has a son named
AlexHe is a big fan of
baseball
The password hash is: 97268a8ae45ac7d15c3cea4ce6ea550b. Use the techniques covered in this section to generate a custom wordlist and ruleset targeting Mark specifically, and crack the password.
Personal Info
Name: Mark White
Born: August 5, 1998
Location: San Francisco
Pet cat: Bella
Wife: Maria
Son: Alex
Hobby: Baseball
Company Info
Company: Nexura
Password Policy
≥12 characters
1 uppercase
1 lowercase
1 symbol
1 number
What is Mark's password?
Once, we craft a new dictionary with name mark.txt
mark
markwhite
white
nexura
bella
maria
alex
baseball
sf
sanfrancisco
august
aug
1998
98
05
805
0805Add combinations (most common patterns people use):
bellaalex
mariamark
markmaria
markbellaIn addition, now craft a new dicctionay with mutation rules, mark-rules.txt
Likely patterns Mark would choose:
Capitalize first letter
Append year or birthday (1998, 98, 0805)
Append "!","@" or "$"
$1 $9 $9 $8 $!Combine rules to ensure uppercase + number + symbol.
Now, generete the mutated dicctionay -->
hashcat --stdout mark.txt -r mark-rules.txt | sort -u > mark_mutated.list97268a8ae45ac7d15c3cea4ce6ea550b
→ 32 hex chars → MD5Finally I cracked the password using the rule
best64:
hashcat -m 0 -a 0 97268a8ae45ac7d15c3cea4ce6ea550b mark_mutated.list -r /usr/share/hashcat/rules/best64.ruleCracking Protected Files
Hunting for Encrypted Files
Many different extensions correspond to encrypted files—a useful reference list can be found on FileInfo. As an example, consider this command we might use to locate commonly encrypted files on a Linux system:
eldeim@htb[/htb]$ for ext in $(echo ".xls .xls* .xltx .od* .doc .doc* .pdf .pot .pot* .pp*");do echo -e "\nFile extension: " $ext; find / -name *$ext 2>/dev/null | grep -v "lib\|fonts\|share\|core" ;done
File extension: .xls
File extension: .xls*
File extension: .xltx
File extension: .od*
/home/cry0l1t3/Docs/document-temp.odt
/home/cry0l1t3/Docs/product-improvements.odp
/home/cry0l1t3/Docs/mgmt-spreadsheet.ods
...SNIP...Hunting for SSH keys
Certain files, such as SSH keys, do not have standard file extension. In cases like these, it may be possible to identify files by standard content such as header and footer values. For example, SSH private keys always begin with -----BEGIN [...SNIP...] PRIVATE KEY-----. We can use tools like grep to recursively search the file system for them during post-exploitation.
eldeim@htb[/htb]$ grep -rnE '^\-{5}BEGIN [A-Z0-9]+ PRIVATE KEY\-{5}$' /* 2>/dev/null
/home/jsmith/.ssh/id_ed25519:1:-----BEGIN OPENSSH PRIVATE KEY-----
/home/jsmith/.ssh/SSH.private:1:-----BEGIN RSA PRIVATE KEY-----
/home/jsmith/Documents/id_rsa:1:-----BEGIN OPENSSH PRIVATE KEY-----
<SNIP>Some SSH keys are encrypted with a passphrase. With older PEM formats, it was possible to tell if an SSH key is encrypted based on the header, which contains the encryption method in use. Modern SSH keys, however, appear the same whether encrypted or not.
eldeim@htb[/htb]$ cat /home/jsmith/.ssh/SSH.private
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,2109D25CC91F8DBFCEB0F7589066B2CC
8Uboy0afrTahejVGmB7kgvxkqJLOczb1I0/hEzPU1leCqhCKBlxYldM2s65jhflD
4/OH4ENhU7qpJ62KlrnZhFX8UwYBmebNDvG12oE7i21hB/9UqZmmHktjD3+OYTsD
<SNIP>One way to tell whether an SSH key is encrypted or not, is to try reading the key with ssh-keygen.
eldeim@htb[/htb]$ ssh-keygen -yf ~/.ssh/id_ed25519
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIpNefJd834VkD5iq+22Zh59Gzmmtzo6rAffCx2UtaS6As shown below, attempting to read a password-protected SSH key will prompt the user for a passphrase:
eldeim@htb[/htb]$ ssh-keygen -yf ~/.ssh/id_rsa
Enter passphrase for "/home/jsmith/.ssh/id_rsa":Cracking encrypted SSH keys
As mentioned in a previous section, JtR has many different scripts for extracting hashes from files—which we can then proceed to crack. We can find these scripts on our system using the following command:
eldeim@htb[/htb]$ locate *2john*
/usr/bin/bitlocker2john
/usr/bin/dmg2john
/usr/bin/gpg2john
/usr/bin/hccap2john
/usr/bin/keepass2john
/usr/bin/putty2john
/usr/bin/racf2john
/usr/bin/rar2john
/usr/bin/uaf2john
/usr/bin/vncpcap2john
/usr/bin/wlanhcx2john
/usr/bin/wpapcap2john
/usr/bin/zip2john
/usr/share/john/1password2john.py
/usr/share/john/7z2john.pl
/usr/share/john/DPAPImk2john.py
/usr/share/john/adxcsouf2john.py
/usr/share/john/aem2john.py
/usr/share/john/aix2john.pl
/usr/share/john/aix2john.py
/usr/share/john/andotp2john.py
/usr/share/john/androidbackup2john.py
<SNIP>For example, we could use the Python script ssh2john.py to acquire the corresponding hash for an encrypted SSH key, and then use JtR to try and crack it.
eldeim@htb[/htb]$ ssh2john.py SSH.private > ssh.hash
eldeim@htb[/htb]$ john --wordlist=rockyou.txt ssh.hash
Using default input encoding: UTF-8
Loaded 1 password hash (SSH [RSA/DSA/EC/OPENSSH (SSH private keys) 32/64])
Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 0 for all loaded hashes
Cost 2 (iteration count) is 1 for all loaded hashes
Will run 2 OpenMP threads
Note: This format may emit false positives, so it will keep trying even after
finding a possible candidate.
Press 'q' or Ctrl-C to abort, almost any other key for status
1234 (SSH.private)
1g 0:00:00:00 DONE (2022-02-08 03:03) 16.66g/s 1747Kp/s 1747Kc/s 1747KC/s Knightsing..Babying
Session completedWe can then view the resulting hash:
eldeim@htb[/htb]$ john ssh.hash --show
SSH.private:1234
1 password hash cracked, 0 leftCracking password-protected documents
Over the course of our careers, we are likely to encounter a wide variety of documents that are password-protected to restrict access to authorized individuals. Today, most reports, documentation, and information sheets are commonly distributed as Microsoft Office documents or PDFs. John the Ripper (JtR) includes a Python script called office2john.py, which can be used to extract password hashes from all common Office document formats. These hashes can then be supplied to JtR or Hashcat for offline cracking. The cracking procedure remains consistent with other hash types.
eldeim@htb[/htb]$ office2john.py Protected.docx > protected-docx.hash
eldeim@htb[/htb]$ john --wordlist=rockyou.txt protected-docx.hash
eldeim@htb[/htb]$ john protected-docx.hash --show
Protected.docx:1234
1 password hash cracked, 0 leftThe process for cracking PDF files is quite similar, as we simply swap out office2john.py for pdf2john.py.
eldeim@htb[/htb]$ pdf2john.py PDF.pdf > pdf.hash
eldeim@htb[/htb]$ john --wordlist=rockyou.txt pdf.hash
eldeim@htb[/htb]$ john pdf.hash --show
PDF.pdf:1234
1 password hash cracked, 0 leftLab - Questions
Download the attached ZIP archive (cracking-protected-files.zip), and crack the file within. What is the password?
First, unzip the file use gunzip -->
unzip cracking-protected-files.zip
Archive: cracking-protected-files.zip
inflating: Confidential.xlsxWe obtain a file xlsx that is equal that a excel, get his hash with office2jhon an crack it -->
office2john Confidential.xlsx
Confidential.xlsx:$office$*2013*100000*256*16*cb0e251cdec92e97eeb38e595cd4eb09*58758c88f3bb25e43e1e21adbd4b6e50*0057c1ae71b0023424ba705607dc0df1d9a786974bb957a821cfd7e39129eb15john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt Cracking Protected Archives
Besides standalone files, we will often run across archives and compressed files—such as ZIP files—which are protected with a password.
There are many types of archive files. Some of the more commonly encountered file extensions include tar, gz, rar, zip, vmdb/vmx, cpt, truecrypt, bitlocker, kdbx, deb, 7z, and gzip.
A comprehensive list of archive file types can be found on FileInfo. Rather than typing them out manually, we can also query the data using a one-liner, apply filters as needed, and save the results to a file. At the time of writing, the website lists 365 archive file types.
eldeim@htb[/htb]$ curl -s https://fileinfo.com/filetypes/compressed | html2text | awk '{print tolower($1)}' | grep "\." | tee -a compressed_ext.txt
.mint
.zhelp
.b6z
.fzpz
.zst
.apz
.ufs.uzip
.vrpackage
.sfg
.gzip
.xapk
.rar
.pkg.tar.xz
<SNIP>Note that not all archive types support native password protection, and in such cases, additional tools are often used to encrypt the files. For example, TAR files are commonly encrypted using openssl or gpg.
Cracking ZIP files
The ZIP format is often heavily used in Windows environments to compress many files into one file. The process of cracking an encrypted ZIP file is similar to what we have seen already, except for using a different script to extract the hashes.
eldeim@htb[/htb]$ zip2john ZIP.zip > zip.hash
eldeim@htb[/htb]$ cat zip.hash
ZIP.zip/customers.csv:$pkzip2$1*2*2*0*2a*1e*490e7510*0*42*0*2a*490e*409b*ef1e7feb7c1cf701a6ada7132e6a5c6c84c032401536faf7493df0294b0d5afc3464f14ec081cc0e18cb*$/pkzip2$:customers.csv:ZIP.zip::ZIP.zipOnce we have extracted the hash, we can use JtR to crack it with the desired password list.
eldeim@htb[/htb]$ john --wordlist=rockyou.txt zip.hash
eldeim@htb[/htb]$ john zip.hash --show
ZIP.zip/customers.csv:1234:customers.csv:ZIP.zip::ZIP.zipCracking OpenSSL encrypted GZIP files
It is not always immediately apparent whether a file is password-protected, particularly when the file extension corresponds to a format that does not natively support password protection. As previously discussed, openssl can be used to encrypt files in the GZIP format. To determine the actual format of a file, we can use the file command, which provides detailed information about its contents. For example:
eldeim@htb[/htb]$ file GZIP.gzip
GZIP.gzip: openssl enc'd data with salted passwordWhen cracking OpenSSL encrypted files, we may encounter various challenges, including numerous false positives or complete failure to identify the correct password. To mitigate this, a more reliable approach is to use the openssl tool within a for loop that attempts to extract the contents directly, succeeding only if the correct password is found.
The following one-liner may produce several GZIP-related error messages, which can be safely ignored. If the correct password list is used, as in this example, we will see another file successfully extracted from the archive.
eldeim@htb[/htb]$ for i in $(cat rockyou.txt);do openssl enc -aes-256-cbc -d -in GZIP.gzip -k $i 2>/dev/null| tar xz;done
gzip: stdin: not in gzip format
tar: Child returned status 1
tar: Error is not recoverable: exiting now
gzip: stdin: not in gzip format
tar: Child returned status 1
tar: Error is not recoverable: exiting now
<SNIP>Once the for loop has finished, we can check the current directory for a newly extracted file.
eldeim@htb[/htb]$ ls
customers.csv GZIP.gzip rockyou.txtCracking BitLocker-encrypted drives
BitLocker is a full-disk encryption feature developed by Microsoft for the Windows operating system. Available since Windows Vista, it uses the AES encryption algorithm with either 128-bit or 256-bit key lengths. If the password or PIN used for BitLocker is forgotten, decryption can still be performed using a recovery key—a 48-digit string generated during the setup process.
In enterprise environments, virtual drives are sometimes used to store personal information, documents, or notes on company-issued devices to prevent unauthorized access. To crack a BitLocker encrypted drive, we can use a script called bitlocker2john to four different hashes: the first two correspond to the BitLocker password, while the latter two represent the recovery key. Because the recovery key is very long and randomly generated, it is generally not practical to guess—unless partial knowledge is available. Therefore, we will focus on cracking the password using the first hash ($bitlocker$0$...).
eldeim@htb[/htb]$ bitlocker2john -i Backup.vhd > backup.hashes
eldeim@htb[/htb]$ grep "bitlocker\$0" backup.hashes > backup.hash
eldeim@htb[/htb]$ cat backup.hash
$bitlocker$0$16$02b329c0453b9273f2fc1b927443b5fe$1048576$12$00b0a67f961dd80103000000$60$d59f37e70696f7eab6b8f95ae93bd53f3f7067d5e33c0394b3d8e2d1fdb885cb86c1b978f6cc12ed26de0889cd2196b0510bbcd2a8c89187ba8ec54fOnce a hash is generated, either JtR or hashcat can be used to crack it. For this example, we will look at the procedure with hashcat. The hashcat mode associated with the $bitlocker$0$... hash is -m 22100. We supply the hash, specify the wordlist, and define the hash mode. Since this encryption uses strong AES encryption, cracking may take considerable time depending on hardware performance.
eldeim@htb[/htb]$ hashcat -a 0 -m 22100 '$bitlocker$0$16$02b329c0453b9273f2fc1b927443b5fe$1048576$12$00b0a67f961dd80103000000$60$d59f37e70696f7eab6b8f95ae93bd53f3f7067d5e33c0394b3d8e2d1fdb885cb86c1b978f6cc12ed26de0889cd2196b0510bbcd2a8c89187ba8ec54f' /usr/share/wordlists/rockyou.txt
<SNIP>
$bitlocker$0$16$02b329c0453b9273f2fc1b927443b5fe$1048576$12$00b0a67f961dd80103000000$60$d59f37e70696f7eab6b8f95ae93bd53f3f7067d5e33c0394b3d8e2d1fdb885cb86c1b978f6cc12ed26de0889cd2196b0510bbcd2a8c89187ba8ec54f:1234qwer
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 22100 (BitLocker)
Hash.Target......: $bitlocker$0$16$02b329c0453b9273f2fc1b927443b5fe$10...8ec54f
Time.Started.....: Sat Apr 19 17:49:25 2025 (1 min, 56 secs)
Time.Estimated...: Sat Apr 19 17:51:21 2025 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 25 H/s (9.28ms) @ Accel:64 Loops:4096 Thr:1 Vec:8
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 2880/14344385 (0.02%)
Rejected.........: 0/2880 (0.00%)
Restore.Point....: 2816/14344385 (0.02%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:1044480-1048576
Candidate.Engine.: Device Generator
Candidates.#1....: pirate -> soccer9
Hardware.Mon.#1..: Util:100%
Started: Sat Apr 19 17:49:05 2025
Stopped: Sat Apr 19 17:51:22 2025After successfully cracking the password, we can access the encrypted drive.
Mounting BitLocker-encrypted drives in Windows
The easiest method for mounting a BitLocker-encrypted virtual drive on Windows is to double-click the .vhd file. Since it is encrypted, Windows will initially show an error. After mounting, simply double-click the BitLocker volume to be prompted for the password.

Mounting BitLocker-encrypted drives in Linux (or macOS)
It is also possible to mount BitLocker-encrypted drives in Linux (or macOS). To do this, we can use a tool called dislocker. First, we need to install the package using apt:
eldeim@htb[/htb]$ sudo apt-get install dislockerNext, we create two folders which we will use to mount the VHD.
eldeim@htb[/htb]$ sudo mkdir -p /media/bitlocker
eldeim@htb[/htb]$ sudo mkdir -p /media/bitlockermountWe then use losetup to configure the VHD as loop device, decrypt the drive using dislocker, and finally mount the decrypted volume:
eldeim@htb[/htb]$ sudo losetup -f -P Backup.vhd
eldeim@htb[/htb]$ sudo dislocker /dev/loop0p2 -u1234qwer -- /media/bitlocker
eldeim@htb[/htb]$ sudo mount -o loop /media/bitlocker/dislocker-file /media/bitlockermountIf everything was done correctly, we can now browse the files:
eldeim@htb[/htb]$ cd /media/bitlockermount/
eldeim@htb[/htb]$ ls -laOnce we have analyzed the files on the mounted drive, we can unmount it using the following commands:
eldeim@htb[/htb]$ sudo umount /media/bitlockermount
eldeim@htb[/htb]$ sudo umount /media/bitlockerLab - Questions
Run the above target then navigate to http://ip:port/download, then extract the downloaded file. Inside, you will find a password-protected VHD file. Crack the password for the VHD and submit the recovered password as your answer.

Berofe of unzip the file, obtain the Private.vhd, so... get the hash -->
sudo apt-get install dislocker
bitlocker2john -i Private.vhd > hashbit.txtNow, filter to obtain only the hash and save it to after crack it -->
grep "bitlocker\$0" hashbit.txt > hash-good-bit.txt
## Crack
hashcat -a 0 -m 22100 hash-good-bit.txt /usr/share/wordlists/rockyou.txt
Mount the BitLocker-encrypted VHD and enter the contents of flag.txt as your answer.
Now create the two folder -->
sudo mkdir -p /media/bitlocker
sudo mkdir -p /media/bitlockermountNow configure the VHD -->
sudo losetup -f -P Private.vhd
sudo dislocker /dev/loop0p2 -ufrancisco -- /media/bitlockerNote: -u
Now, verify the the /dev/loop0p* something -->
ls /dev/loop0*
/dev/loop0 /dev/loop0p1Now, unlock the bitlocker -->
sudo mount -o loop /media/bitlocker/dislocker-file /media/bitlockermountTo finished, enter to the directory create and mounted -->
sudo ls -l /media/bitlockermount
cd /media/bitlockermountLast updated