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/bash

Based 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:

193069ceb0461e1d40d216e32c79c704

One 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.hash

Some 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 pass
  • Use 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-128

Introduction to Hashcat

eldeim@htb[/htb]$ hashcat -a 0 -m 0 <hashes> [wordlist, rule, mask, ...]

In the command above:

  • -a is used to specify the attack mode

  • -m is used to specify the hash 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 2025

A 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.rule

As 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 2025

Mask 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:

Symbol
Charset

?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 2025

Lab - Questions

  • Use a dictionary attack to crack the first password hash. (Hash: e3e3ec5831ad5e7288241960e5d4fdb8)

hashcat -a 0 -m 0 e3e3ec5831ad5e7288241960e5d4fdb8 /usr/share/wordlists/rockyou.txt
  • Use 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.rule
  • Use 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

password

We 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.list

In 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, 1998

  • He 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, USA

  • He has a pet cat named Bella

  • He has a wife named Maria

  • He has a son named Alex

  • He 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
0805

Add combinations (most common patterns people use):

bellaalex
mariamark
markmaria
markbella

In 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.list

97268a8ae45ac7d15c3cea4ce6ea550b

→ 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.rule

Cracking 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+22Zh59Gzmmtzo6rAffCx2UtaS6

As 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 completed

We can then view the resulting hash:

eldeim@htb[/htb]$ john ssh.hash --show

SSH.private:1234

1 password hash cracked, 0 left

Cracking 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 left

The 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 left

Lab - 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.xlsx

We 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*0057c1ae71b0023424ba705607dc0df1d9a786974bb957a821cfd7e39129eb15
john 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.zip

Once 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.zip

Cracking 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 password

When 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.txt

Cracking 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$d59f37e70696f7eab6b8f95ae93bd53f3f7067d5e33c0394b3d8e2d1fdb885cb86c1b978f6cc12ed26de0889cd2196b0510bbcd2a8c89187ba8ec54f

Once 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 2025

After 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 dislocker

Next, 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/bitlockermount

We 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/bitlockermount

If everything was done correctly, we can now browse the files:

eldeim@htb[/htb]$ cd /media/bitlockermount/
eldeim@htb[/htb]$ ls -la

Once 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/bitlocker

Lab - 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.txt

Now, 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/bitlockermount

Now configure the VHD -->

sudo losetup -f -P Private.vhd
sudo dislocker /dev/loop0p2 -ufrancisco -- /media/bitlocker

Note: -u

Now, verify the the /dev/loop0p* something -->

ls /dev/loop0*
/dev/loop0  /dev/loop0p1

Now, unlock the bitlocker -->

sudo mount -o loop /media/bitlocker/dislocker-file /media/bitlockermount

To finished, enter to the directory create and mounted -->

sudo ls -l /media/bitlockermount
cd /media/bitlockermount

Last updated