Categories
SysOps

How to perform dictionary attack on LUKS passphrase

Perform a dictionary attack on the forgotten LUKS passphrase to access the encrypted device.

Prerequisites

Store LUKS header backup as using the whole device can be very cumbersome.

$ file luks_header_backup
luks_header_backup: LUKS encrypted file, ver 1 [aes, xts-plain64, sha256] UUID: ac32a865-2716-43e3-8db9-798d4279a3a3

For hashcat you will also need the first sector from the payload.

$ sudo dd if=/dev/sdb1 of=extended-luks-header bs=1M count=5
5+0 records in
5+0 records out
5242880 bytes (5.2 MB, 5.0 MiB) copied, 0.0273016 s, 192 MB/s

Create a dictionary file with every possible passphrase combination, one per line.

$ cat passphrases-dictionary
somepasssphrase
potentialpasssphrase
maybethispassphrase
[...]

bruteforce-luks

Install bruterforce-luks package.

$ sudo apt-get install bruteforce-luks

You can always get the source directly from bruteforce-luks GitHub repository.

$ bruteforce-luks

bruteforce-luks 1.3.1

Usage: bruteforce-luks [options] <path to LUKS volume>

Options:
  -b <string>  Beginning of the password.
                 default: ""
  -e <string>  End of the password.
                 default: ""
  -f <file>    Read the passwords from a file instead of generating them.
  -h           Show help and quit.
  -l <length>  Minimum password length (beginning and end included).
                 default: 1
  -m <length>  Maximum password length (beginning and end included).
                 default: 8
  -s <string>  Password character set.
                 default: "0123456789ABCDEFGHIJKLMNOPQRSTU
                           VWXYZabcdefghijklmnopqrstuvwxyz"
  -t <n>       Number of threads to use.
                 default: 1
  -v <n>       Print progress info every n seconds.
  -w <file>    Restore the state of a previous session if the file exists,
               then write the state to the file regularly (~ every minute).

Sending a USR1 signal to a running bruteforce-luks process
makes it print progress info to standard error and continue.

Error: missing path to LUKS volume.

To perform dictionary attack using bruteforce-luks version 1.3.1 you need to define the number of threads (see additional notes section), amount of time between printing progress information, session file that can be used to continue attack later, a file that contains possible passphrases, and LUKS header backup.

$ bruteforce-luks -t 4 -v 60 -w state_file -f passphrases-dictionary luks_header_backup

Warning: using dictionary mode, ignoring options -b, -e, -l, -m and -s.

Warning: restoring state, ignoring options -b, -e, -f, -l, -m and -s.

Tried passwords: 2858
Tried passwords per second: 1.576393
Last tried password: anypassphrase1

[...]

The state file contains basic information and current progress.

$ cat state_file
luks luks_header_backup
time 356922
dictionary passphrases-disctionay
662870

hashcat

Install hashcat package.

$ sudo apt-get install hashcat

I will use version 5.1.0.

$ hashcat --version
v5.1.0

To perform dictionary attack using hashcat version 5.1.0 you need to force execution (in case that OpenCL does not have any GPU available), define LUKS hash type, attack mode (straight), file to store found passphrase, file that contains possible passphrases, and extended LUKS header backup.

$ hashcat --force --hash-type 14600 --attack-mode 0 --outfile recovered_passphrase ./extended_luks_header  passphrases-dictionary
hashcat (v5.1.0) starting...
OpenCL Platform #1: The pocl project
====================================
* Device #1: pthread-Intel(R) Core(TM) i7-5600U CPU @ 2.60GHz, 256/740 MB allocatable, 1MCU

Hashes: 2 digests; 2 unique digests, 2 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1

Applicable optimizers:
* Zero-Byte
* Slow-Hash-SIMD-LOOP

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256

Watchdog: Hardware monitoring interface not found on your system.
Watchdog: Temperature abort trigger disabled.

* Device #1: build_opts '-cl-std=CL1.2 -I OpenCL -I /usr/share/hashcat/OpenCL -D LOCAL_MEM_TYPE=2 -D VENDOR_ID=64 -D CUDA_ARCH=0 -D AMD_ROCM=0 -D VECT_SIZE=8 -D DEVICE_TYPE=2 -D DGST_R0=0 -D DGST_R1=1 -D DGST_R2=2 -D DGST_R3=3 -D DGST_ELEM=16 -D KERN_TYPE=14621 -D _unroll'
Dictionary cache hit:
* Filename..: passphrases-dictionary
* Passwords.: 2556
* Bytes.....: 43464
* Keyspace..: 2556
* Runtime...: 0 secs

- Device #1: autotuned kernel-accel to 256                                                           
- Device #1: autotuned kernel-loops to 256                                                           
[s]tatus [p]ause [r]esume [b]ypass [c]heckpoint [q]uit => s

Session..........: hashcat
Status...........: Running
Hash.Type........: LUKS
Hash.Target......: /root/new-header.luks
Time.Started.....: Sun Jan  6 02:39:52 2019 (8 mins, 42 secs)
Time.Estimated...: Sun Jan  6 02:50:22 2019 (1 min, 48 secs)
Guess.Base.......: File (/root/notebook/l5)
Guess.Queue......: 1/1 (100.00%)
Speed.Dev.#1.....:        5 H/s (19.29ms)
Recovered........: 0/1 (0.00%) Digests, 0/1 (0.00%) Salts
Progress.........: 2048/2556 (80.13%)
Rejected.........: 0/2048 (0.00%)
Restore.Point....: 2048/2556 (80.13%)
Candidates.#1....: linux@click@2018! -> debian-linux-2018!
HWMon.Dev.#1.....: N/A

[...]

Use -s option to skip the number of words.

$ hashcat --force --hash-type 14600 -s 1002 --attack-mode 0  --outfile recovered_passphrase ./extended_luks_header  passphrases-dictionary

Additional notes

Display the number of CPUs to define used threads.

$ LC_ALL=C lscpu | awk -F: '/^CPU\(s\):/ { gsub(" ","",$2); print $2}'
4

If you cannot force hashcat to start and do not have additional GPU (error clGetDeviceIDs(): CL_DEVICE_NOT_FOUND), then install a “native” target, which allows running OpenCL kernels on the host CPU.

$ sudo apt-get install pocl-opencl-icd