Efficient Cracking Strategies with John the Ripper

This is the second post of a two-part series on why and how to crack passwords. The first part focused on how to use the “John the ripper” tool, while this second part will focus on the overall password cracking process and a suggested approach to efficient password cracking.The following strategy is one we have found to work well when attempting password cracking without GPU assist – in that case, since you don’t have the sheer power of a GPU to assist you in your password cracking efforts, it becomes more important to use the right John The Ripper modes, at the right time and in the right order. It goes without saying that even with a GPU, being intentional about your password cracking strategy will improve your results. In our experience, using those specific modes in that particular order will give you the most bang for your buck, with the first mode cracking the most passwords in the shortest amount of time, the next one taking longer and yielding less passwords, and so on and so forth – you can keep going until you’re satisfied with the results.

See below for command assistance:

Password cracking strategy:

SINGLE mode cracking with default set of mangling rules
./john --format=NT --fork=4 --single path_to_NTDS_file

repeat loopback mode with ‘All’ set of mangling rules until no new passwords are found
./john --format=NT --fork=4 --loopback --rules=All path_to_NTDS_file

WORDLIST mode cracking with the ‘rockyou’ wordlist (easy to find on the Internet) and the default set of mangling rules (–rules)
./john --format=NT --fork=4 --wordlist=rockyou.txt --rules path_to_NTDS_file

repeat loopback mode with ‘All’ set of mangling rules until no new passwords are found
./john --format=NT --fork=4 --loopback --rules=All path_to_NTDS_file

WORDLIST mode cracking with the ‘rockyou’ wordlist and the ‘Jumbo’ set of mangling rules
./john --format=NT --fork=4 --wordlist=rockyou.txt --rules=Jumbo path_to_NTDS_file

repeat loopback mode with ‘All’ set of mangling rules until no new passwords are found
./john --format=NT --fork=4 --loopback --rules=All path_to_NTDS_file

WORDLIST mode cracking with the ‘rockyou’ wordlist and the ‘hashcat’ set of mangling rules
./john --format=NT --fork=4 --wordlist=rockyou.txt --rules=hashcat path_to_NTDS_file

repeat loopback mode with ‘All’ set of mangling rules until no new passwords are found
./john --format=NT --fork=4 --loopback --rules=All path_to_NTDS_file

MARKOV mode cracking
./john --format=NT --fork=4 --markov=300 --max-run=120 path_to_NTDS_file
./genmkvpwd stats 0 12
./john --format=NT --fork=4 --markov=needed_level path_to_NTDS_file

repeat loopback mode with ‘All’ set of mangling rules until no new passwords are found
./john --format=NT --fork=4 --loopback --rules=All path_to_NTDS_file

SUBSETS mode cracking, with a maximum password length of 8
./john --format=NT --fork=4 --subsets --max-length=8 path_to_NTDS_file

repeat loopback mode with ‘All’ set of mangling rules until no new passwords are found
./john --format=NT --fork=4 --loopback --rules=All path_to_NTDS_file

INCREMENTAL mode, with a reasonable max length; can then be increased to the next length up using –min-length=N –max-length=N so as to not repeat previous run
./john --format=NT --fork=4 --incremental --max-length=6 path_to_NTDS_file

repeat loopback mode with ‘All’ set of mangling rules until no new passwords are found
./john --format=NT --fork=4 --loopback --rules=All path_to_NTDS_file

Optionally, look for common/repeating words in passwords, create a custom wordlist containing them (in lower case), and do something similar to the below
Apply all mangling rules to the custom wordlist (WL); most likely redundant with some other modes
./john --format=NT --fork=4 --wordlist=WL --rules=All path_to_NTDS_file

Generate all case permutations (–rules=ShiftToggle) from the custom wordlist, and apply a mask to the results (we are doing mode stacking)
./john --format=NT --fork=4 --wordlist=WL --rules=ShiftToggle --mask='?w?a?a?a?a' path_to_NTDS_file

Generate all case permutations (–rules=ShiftToggle) from the custom wordlist, apply a mask to those results (mode stacking), and then also stack the ‘leet’ external mode (further mode stacking)
./john --format=NT --fork=4 --wordlist=WL --rules=ShiftToggle --mask='?w?a?a?a?a' --external=leet path_to_NTDS_file

As a last resort, the regexp mode (undocumented) and an external mode

Useful script snippets
Below are a few script snippets that can be useful in your password cracking efforts:

Pull hashes from your AD and only select enabled user accounts – no disabled user accounts, and no machine accounts – uses the impacket tool, available on GitHub
impacket/examples/secretsdump.py -k -dc-ip IP_of_domain_controller -outputfile crack -user-status domain_name/domain_admin_account@domain_controller_hostname

grep -F '(status=Enabled)' crack.ntds | cut -d: -f1-7 | cut -d' ' -f1 > crack_enabled.ntds

grep -E '^[^$:]+:' crack_enabled.ntds > crack_enabled_user_accounts_only.ntds

Get a password tally
./john --format=NT --show crack_enabled_user_accounts_only.ntds | grep -E '^domain_name' | cut -d: -f2 | sort | uniq -c | sort -k1bnr,1 | awk '{$1=$1};1'



Get a password tally, augmented with information from AD
#!/bin/zsh

# USAGE: 1st parameter is hash file, 2nd parameter is minimum number of repeats for hashes

hashes=$(cut -d: -f4 $1 | sort | uniq -c | sort -k1bnr,1 | awk '{$1=$1};1')

echo 'Enter password:'
read -s pass

while read repeats hash; do
        if [[ $repeats -ge $2 ]]; then
                echo '***********************************************************************************'
                echo 'hash' '\e[93m'$hash'\e[0m' 'repeated' $repeats 'times'
                cracked=$(john --format=NT --show $1 | grep $hash)
                if (( $? )); then
                        echo '   password not cracked\n'
                else
                        echo '   password is:' '\e[31m'$(head -n1 <<< $cracked | cut -d: -f2)'\e[0m\n'
                fi
                ldapsearch -x -w $pass -D domain_admin_account@domain_name -h domain_controller_hostname -o ldif-wrap=no -b 'domain_base_DN' -f =(grep $hash $1| \
                        cut -d: -f1 | cut -d\\ -f2) '(&(objectCategory=person)(sAMAccountName=%s))' displayName description title sAMAccountName 2>&1 | grep -E '^(dn|displayName|description|title|sAMAccountName)' | \
                        while read line; do if [[ $line != dn:* ]]; then if [[ $line == displayName* ]]; then echo ' \e[32m'$line'\e[0m'; else echo ' '$line; fi; else echo $line; fi; done
                echo '***********************************************************************************'
        fi
done <<< $hashes

Subscribe to our Newsletter

Stay ahead of the curve with Coverden's insights. Subscribe to our Newsletter for timely updates, expert perspectives, and actionable takeaways tailored for security professionals. Deepen your understanding and enhance your security strategies.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.