ShadowHash is an Elixir application which implements distributed hash cracking against a linux shadow file, as well as GPU Accelerated password cracking for select algorithms.
The project is largely an exercise in distributed programming in Elixir and programming using CUDA and NX, and less about creating a robust or competative password cracker.
ShadowHash can operate on a single node, or work distributively on multiple nodes / machines.
-
Ensure you have Erlang OTP installed and Elixir installed (version Elixir 1.17.3 on Erlang 27) Follow the official installation instrucitons here
-
Install and configure your environment for CUDA if you plan to use GPU Accelerated password hashers included in ShadowHash.
- These steps vary depending on your hardware configuration. For Nvidia you can follow the guide here: https://docs.nvidia.com/cuda/cuda-installation-guide-linux/
-
Clone this repository onto your local machine
-
That shadow_client project should be explicitly compiled to ensure it is properly configured to use GPU accelerated password cracking:
> cd ./apps/shadow_client/ > export XLA_TARGET=cuda12 > mix deps.get > mix deps.compile
(depending on your environment, you may need to manually build XLA for GPU accelerated hashing.)
-
Run the test-cases to ensure all is working as expected
> mix test --trace
-
For GPU-based hashing generation, ShadowHash relies on it's own Nx based hashing algorithm. For CPU-based hashing, ShadowHash relies on mkpasswd. It can be installed via your package manager:
> sudo apt install mkpasswd > mkpasswod --version mkpasswd 5.5.22
-
Optional, for generating benchmark plots (generated by using benchmark.sh script), you will need to have gnuplot installed, which can also be acquire via your package manager.
> sudo apt-get install gnuplot > gnuplot --version gnuplot 6.0 patchlevel 0
Using ShadowHash on a single node is straight-forward. Use the --help
switch on the shadow_cli
or shadow_client
task to learn about the available options and usage instructions.
> mix shadow_cli --help
Shadow hash CLI command interface.
Usage is one of following forms:
mix shadow_cli submit [<shadow_path>]
mix shadow_cli status
mix shadow_cli truncate-clients <num_clients>
Switches valid for all verbs:
--data-node : Name of the data node where the scheduler, job and result bank are available
--cookie : Security cookie to use when connecting to the data-node.
--interface : IP Address to advertise to register with as a node (IP Datanode can address you by)
--verbose : Print verbose logging
submit verb - submit a bruteforce job to job bank
<shadow_path> : Optional path to the linux shadow file containing hashed user passwords.
--password : Specify a password in a valid form inline to process with/without specifying a shadow file
--dictionary <dictionary> : Supply a dictionary of passwords that are attempted initially
--user <user> : Supply a username, the passwords for which will be cracked.
Otherwise, attempts to crack all passwords in the shadow file.
--all-chars : Will also bruteforce with non-printable characters
--get-results : Wait for the results and print them out once ready
status verb - Interrogate status of jobs / results
--show-all : Show all jobs (even suspended or inactive jobs.)
truncate-clients verb - Remove clients registered on the system
<num_clients> : Maximum number of clients to keep connected to the system.
> mix shadow_client --help
Shadow file password cracker client (job processing module.)
Usage is: mix shadow_client
--data-node : Name of the data node where the scheduler, job and result bank are available
--cookie : Security cookie to use when connecting to the data-node.
--interface : IP Address to advertise to register with as a node (IP Datanode can address you by)
--verbose : Print verbose logging
--gpu : Supported for md5crypt, will execute the hash algorithm
on the GPU. There is initial overhead to JIT compile to CUDA
but after JIT compiling, significantly faster.
--gpu-warmup : Warm-up GPU bruteforce algorithm. Useful when capturing
timing metrics and you don't want to include start-up overhead
--workers <num> : Number of workers to process bruteforce requests. Defaults
to number of available CPU cores. Be mindful of the memory constraint
ShadowHash is implemented as a MIX task.
-
Start the shadow_hash server
> cd ./apps/shadow_server > iex --name shadow_data@<host address> --cookie <secret> -S mix
-
Spawn one or more local or remote workers:
> cd ./apps/shadow_client > mix shadow_client --data-node shadow_data@<server address> --interface <my address> --cookie <secret> --workers 8
-
Submit a job using the submit command with shadow_cli
> cd ./apps/shadow_cli > mix shadow_cli submit ../../../data/sample_shadow --user user_yescrypt --data-node shadow_data@<server address> --interface <my addres> --get-results --cookie mysecret
-
Interrogate the status of the hashing cluster
> cd ./apps/shadow_cli > mix shadow_cli status --data-node shadow_data@<server address> --interface <my addres> --cookie mysecret
In a multi-node configuration, shadow_hash
will distribute the password cracking work horizontally accross multiple machines and optionally multiple GPUs. Currently this feature is pending implementation.
For generating benchmark metrics, please refer to the benchmark.sh
shell script.
Below is a sample benchmark file produced by benchmark.sh
which benchmarks the hashing performance 10, 4, 3, 2 and 1 distributed nodes each executing 12 password cracking threads
Below is a sample benchmark file produced by benchmark.sh
which benchmarks the hashing performance accross all supported algorithms for different thread counts.
ShadowHash is implemented using agents to maximize scalability and stability. The below sequence diagrams show the general interaction between these agens to achieve the goal of performing a distributed password cracking.
The following sequence diagrams shows the interaction between agents when a job has been submitted and begins getting processed by a worker.
The following sequence diagrams shows the interaction between agents when a job has been submitted successfully processed (password has been cracked.)