luksury Writeup - Insomnihack Final 2024

Author: Ernesto Martínez García

Tags: ctf

This post shows the writeup for the “luksury” challenge from he Insomnihack Final of 2024.

Challenge consisted in a LUKS2 encrypted disk image you had to bruteforce:

1
2
[ecomaikgolf@laptop ../insomnihack/luks/]$ file disk.img 
disk.img: LUKS encrypted file, ver 2, header size 16384, ID 4, algo sha256, salt 0xad7174d78159f31..., UUID: 6dbc6504-4250-4be3-a6d1-40625f28fcc7, crc 0xc1daabbc4f25841c..., at 0x1000 {"keyslots":{"1":{"type":"luks2","key_size":64,"af":{"type":"luks1","stripes":4000,"hash":"sha256"},"area":{"type":"raw","offse

The challenge also clearly hinted the usage of rockyou.txt to bruteforce the password.

As it’s LUKS2, we couldn’t directly use hashcash and we used bruteforce-luks as it seemed good & quick enough. The problem was that the program would hang on trying the first key, also if you tried to interact with the disk file in your own system, it also hanged.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
[ecomaikgolf@laptop ../insomnihack/luks/]$ cryptsetup luksDump disk.img 
LUKS header information
Version:       	2
Epoch:         	4
Metadata area: 	16384 [bytes]
Keyslots area: 	16744448 [bytes]
UUID:          	6dbc6504-4250-4be3-a6d1-40625f28fcc7
Label:         	(no label)
Subsystem:     	(no subsystem)
Flags:       	(no flags)

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

Keyslots:
  0: luks2
	Key:        512 bits
	Priority:   normal
	Cipher:     aes-xts-plain64
	Cipher key: 512 bits
	PBKDF:      argon2id
	Time cost:  1042
	Memory:     1048576
	Threads:    4
	Salt:       34 2f d0 85 8b 43 4a f3 ff 7a dc 72 84 e9 b1 65 
	           11 f9 1c dc a1 dd 10 11 e4 72 2b 59 24 2f 11 13 
	AF stripes: 4000
	AF hash:    sha256
	Area offset:290816 [bytes]
	Area length:258048 [bytes]
	Digest ID:  0
  1: luks2
	Key:        512 bits
	Priority:   normal
	Cipher:     aes-xts-plain64
	Cipher key: 512 bits
	PBKDF:      argon2id
	Time cost:  4
	Memory:     32
	Threads:    1
	Salt:       8c 96 41 da 89 db 3e 58 7d a0 f7 a0 96 24 70 a4 
	           58 b3 ff 6a 30 ad 20 a7 b4 9a cc 79 24 17 ee 71 
	AF stripes: 4000
	AF hash:    sha256
	Area offset:32768 [bytes]
	Area length:258048 [bytes]
	Digest ID:  0
Tokens:
Digests:
  0: pbkdf2
	Hash:       sha256
	Iterations: 1000
	Salt:       7b d3 b2 97 10 05 1f 2d 4a 72 dc fd 12 ec c7 bf 
	           25 c8 f4 db 2a cb 3c b8 86 43 f9 5a 59 4d 28 6d 
	Digest:     c2 6d 32 80 f3 bc 4b 9d 2e 08 fe 09 37 ee f1 f5 
	           44 fe af eb 39 a4 04 9f 08 ee 1d 38 20 1a b0 82

As we can see, the problem is that we have a massive key in the first slot, with an insane time and memory cost. bruteforce-luks (or any other LUKS operation) would try to match the entered passphrase with the first one and would nuke itself.

So we have to remove that keyslot. I thought that cryptsetup for sanity would ask any other passphrase for the opreation to succeed, so I could bruteforce that operation as it wouldn’t check the keyslot I want to remove, but it seemsthat cryptsetup has an option to disable that check.

1
2
[ecomaikgolf@laptop ../insomnihack/luks/]$ cryptsetup -q luksKillSlot disk.img 0 
[ecomaikgolf@laptop ../insomnihack/luks/]$ 

Now we run the bruteforcer

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
[ecomaikgolf@laptop ../insomnihack/luks/]$ bruteforce-luks -t 8 -v 1 -f rockyou.txt disk.img 
Warning: using dictionary mode, ignoring options -b, -e, -l, -m and -s.

Tried passwords: 416
Tried passwords per second: 416.000000
Last tried password: ladybug

......

Tried passwords: 10953
Tried passwords per second: 421.269231
Last tried password: celtic88

Password found: deluxe

Now you can just decrypt, mount the disk, and the flag was in a PDF.