I had an external hard drive lying around which I hadn't used for a couple of years. The drive was encrypted and I had no idea what my passphrase was anymore so the data was lost. I decided to avoid this in the future and had a look at how I can access my data if I forget my passphrase or the LUKS header gets corrupted.

When you know the master key it is possible to access your encrypted data even if you forgot your passphrase or the LUKS header is corrupted. In the remainder of the post I will show you how this is done. First of all a 10 MiB image is created for doing the experiments.


# Create 10MiB container
dd if=/dev/zero of=test.img bs=10M count=1
# Create LUKS header
cryptsetup luksFormat --verify-passphrase --cipher=aes-xts-plain64 --hash=sha512  test.img
# Open
cryptsetup luksOpen test.img test
# Create file-system
mkfs.ext2 /dev/mapper/test
# Mount
mount /dev/mapper/test /mnt/test
# Create a file
touch /mnt/test/SecretFile.txt

The next thing to do is dump the master key and to corrupt the LUKS header.


# Dump master key
cryptsetup luksDump --dump-master-key  test.img 

LUKS header information for /dev/loop1
Cipher name:   	aes
Cipher mode:   	xts-plain64
Payload offset:	4096
UUID: 	      5cdbb7db-2ead-42b0-9f86-6634b73447e5
MK bits:       	256
MK dump:	d7 8b eb 4e 6e 3b ea 22 b8 00 cc 27 4e fb b9 68
    1d cb d5 29 cf 06 ac 4a 3f b5 db 00 36 23 de 07

Note that the payload offset is specified in sectors (512bytes), hence the header size is 512*4096=2MiB. In order to access the encrypted data using the master key we still need to now the type of cipher used and its parameters. Next we will corrupt the header by overwriting it completely with zeros. The image has been umounted and closed before proceeding.


# First 80bytes before erasing the header
hexdump -C -n 80 test.img 
00000000  4c 55 4b 53 ba be 00 01  61 65 73 00 00 00 00 00  |LUKS....aes.....|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000020  00 00 00 00 00 00 00 00  78 74 73 2d 70 6c 61 69  |........xts-plai|
00000030  6e 36 34 00 00 00 00 00  00 00 00 00 00 00 00 00  |n64.............|
00000040  00 00 00 00 00 00 00 00  73 68 61 35 31 32 00 00  |........sha512..|
# Erase entire header
dd if=/dev/zero of=test.img conv=notrunc bs=2M count=1
# First 80bytes after erasing the header
hexdump -C -v -n 80 test.img
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

To proceed further the master key has to converted to binary this is done by using the xxd command which is part of the vim-common package.


# Convert hex to binary
echo d78beb4e6e3bea22b800cc274efbb9681dcbd529cf06ac4a3fb5db003623de07 | xxd -r -p > key.bin

Next two methods will be shown to gain access once again to the encrypted data. The first method will write a new LUKS header on the device and the second method will use an external header file, which will leave the original header intact.


# First method, write new header
cryptsetup luksFormat --verify-passphrase --cipher=aes-xts-plain64 --hash=sha512\
--master-key-file=key.bin  test.img
cryptsetup luksOpen test.img test
mount /dev/mapper/test /mnt/test/
ls /mnt/test/
lost+found  SecretFile.txt

The second method will use an external file for the LUKS header, the original header will remain intact. To do so a 2MiB file has to be created first which will contain the header, this is done using the dd command. Usually when using luksOpen the loop device is associated automatically for the image file. Somehow this gives an error in this case and the loop device has to be associated by hand.


# Second method, use separate header file
dd if=/dev/zero of=luks.head bs=2M count=1
cryptsetup luksFormat --verify-passphrase --cipher=aes-xts-plain64 --hash=sha512\
--master-key-file=key.bin --header luks.head --align-payload=4096 test.img

# Weird error
cryptsetup luksOpen -v --header=luks.head test.img test
Command failed with code 15: Block device required

# Manually setup loop device
losetup -f # Find free loop device
losetup /dev/loop0 test.img
cryptsetup luksOpen --header=luks.head /dev/loop0 test
mount /dev/mapper/test /mnt/test
ls /mnt/test/
lost+found  SecretFile.txt

It is interesting to notice that by using an external header file and setting the payload alignment to zero we can create a disk which seems to have only completely random data on it.

2 Comments

Showing 1 - 10 of 2 comments.
HarmtH

Baas!

I sincerely appreciate this walkthrough, as I've spent more than a few hours online attempting to find something like this. The closest I got before this was someone saying, "The question you should ask yourself first is why you would want to do this" and not showing us how to do this at all, which was slightly infuriating, as we should be able to manage our cryptographic security and he/she demeans us, but still, that's not my point. This was a good, detailed tutorial and I appreciate it. Thank you

Leave a Reply