LUKS, hashcat, and hidden volumes

TL;DR: You can encrypt/protect a volume/partition using LUKS, and then nest another encrypted volume inside it (using VeraCrypt or similar), which results in the hash for the LUKS volume not being validated correctly using hashcat.

Why is this an issue?

Brute forcing LUKS2 volumes is computationally intensive, and current validation processes may result in incomplete or inaccurate results. The following are notes related to testing and validation of encrypted volumes which do not have a root filesystem.

Create a LUKS device (default version is 2). Password is set as 'password'

$ cryptsetup luksFormat /dev/sdc

WARNING!
========
This will overwrite data on /dev/sdc irrevocably.

Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/sdc:
Verify passphrase:

Verify /dev/sdc is now a LUKS device

$ cryptsetup luksDump /dev/sdc
LUKS header information
Version:        2
Epoch:          3
Metadata area:  16384 [bytes]
Keyslots area:  16744448 [bytes]
UUID:           f4bd2ee4-969d-4022-b61e-23524e83f592
Label:          (no label)
Subsystem:      (no subsystem)
Flags:          (no flags)

Data segments:
  0: crypt
        offset: 16777216 [bytes]
        length: (whole device)
        cipher: aes-xts-plain64
        sector: 512 [bytes]

Keyslots:
  0: luks2
        Key:        512 bits
        Priority:   normal
        Cipher:     aes-xts-plain64
        Cipher key: 512 bits
        PBKDF:      argon2id
        Time cost:  5
        Memory:     1048576
        Threads:    4
        Salt:       60 a0 ab 32 26 09 c0 7b 1c bf 08 a0 2a 2f a6 0f
                    3b ab aa 65 d3 33 73 05 ac e1 72 a8 b9 a8 6d 44
        AF stripes: 4000
        AF hash:    sha256
        Area offset:32768 [bytes]
        Area length:258048 [bytes]
        Digest ID:  0
Tokens:
Digests:
  0: pbkdf2
        Hash:       sha256
        Iterations: 118724
        Salt:       50 d4 e4 45 2e 30 1a b9 a7 72 4e b6 eb 94 de cb
                    d7 f6 f1 93 65 c7 76 fb 22 6f d9 d5 9f 3f 1a 3d
        Digest:     93 25 02 6f f6 82 09 72 d5 19 b3 74 44 aa 10 65
                    a0 6a 61 5c bf 4c fc 13 2a bf fc f8 73 9a ab 91

Run luks2hashcat against /dev/sdc

Verify the contents of sdc.hash, noting the first line of values (luks,2,argon2id,sha256, etc etc) aligns with the values we observed above. Note the end of the file (after the final $ placeholder) only contains zeroes - we'll come back to that shortly.

Let's run hashcat (v7.1.2, which supports argon2) against the hash with a simple dictionary attack (-a 0) and using 100 words in passwords.list (which contains 'password' as a candidate)

Strange - should've identified the correct password, right? That's because the LUKS container doesn't contain any data, and appears to be required to prove decryption.

Let's go back to /dev/sdc and create an ext4 filesystem, then compare our hashes and try again.

A quick comparison between sdc.hash and sdc.ext4.hash shows that the data portion we identified above, is now populated with data (since there's a filesystem, the container is no longer empty and actually contains data).

If we run hashcat again using the same command, we'll see the password is now cracked.

This raised the question - does the data portion of the hash have to be verified by opening/mounting the container/filesystem etc before the password candidate will be identified as valid? What if the encrypted block device/partition was intended to be mounted by another program (VeraCrypt, for example) - how will this complicate recovery efforts?

Using a fresh /dev/sdc, we'll do the following;

  1. Create a LUKS2 volume, password is password.

  2. Leave the block device unformatted (no filesystem).

  3. Mount the LUKS2 volume as 'sdc'

  4. Encrypt /dev/mapper/sdc using VeraCrypt, 'veracrypt' as the password

Completing steps 1 to 3, and then running luks2hashcat against /dev/sdc, we can see the data portion is still zeroes. So we'll create a VeraCrypt container (using /dev/mapper/sdc)

Verify there is no filesystem on /dev/sdc, or sdc (/dev/mapper/sdc)

Mount VeraCrypt container and verify

Unmount both the VeraCrypt and LUKS volumes.

Calculate the hash for /dev/sdc (expecting a non-zero footer)

Run hashcat again.. no results.

Last updated