Solution de OliverSwift pour PizzaJukebox

forensics hardware

17 janvier 2025

Examen de disk.img

Décompression de disk.img.xz

Utilisation de losetup pour examiner l’image:

$ losetup --find --show -P disk.img
/dev/loop20

Utilisation de fdisk :

$ fdisk /dev/loop20
$ sudo fdisk /dev/loop20

Bienvenue dans fdisk (util-linux 2.39.3).
Les modifications resteront en mémoire jusqu'à écriture.
Soyez prudent avant d'utiliser la commande d'écriture.


Commande (m pour l'aide) : p
Disque /dev/loop20 : 1 GiB, 1073741824 octets, 2097152 secteurs
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets
Type d'étiquette de disque : gpt
Identifiant de disque : 9C36475A-7F22-49A1-A62D-68BF250DE8C2

Périphérique  Début     Fin Secteurs Taille Type
/dev/loop20p1 98304 2095103  1996800   975M Données de base Microsoft
/dev/loop20p2  2048   98303    96256    47M Système EFI

Les entrées de la table de partitions ne sont pas dans l'ordre du disque.

On tente de monter ce qu’il y a derrière la partition 1:

$  sudo mount /dev/loop20p1 /mnt
mount: /mnt: type de système de fichiers « crypto_LUKS » inconnu.

Ah !!!! Une partition LUKS. On tente de lancer ‘crypsetup’ dessus. Peu d’espoir sans le mot de passe, mais bon:

$ sudo cryptsetup luksOpen /dev/loop20p1 crypto
Saisissez la phrase secrète pour /dev/loop20p1 :
Aucune clé disponible avec cette phrase secrète.
Saisissez la phrase secrète pour /dev/loop20p1 :
Aucune clé disponible avec cette phrase secrète.

Quelques infructueux essais et après avoir vérifier avec luksDump, on laisse tomber la force brute:

$ cryptsetup luksDump /dev/loop20p1
LUKS header information
Version:       	2
Epoch:         	3
Metadata area: 	16384 [bytes]
Keyslots area: 	16744448 [bytes]
UUID:          	d863a2f4-9b6e-43ed-a605-0986084cfc05
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:      pbkdf2
	Hash:       sha256
	Iterations: 1842
	Salt:       a8 44 3d 89 d4 90 fc 48 18 cc f0 1f cf cc 55 a0
	            4b 00 6d fa 21 e3 c0 48 2f 88 40 0c cc f1 45 c7
	AF stripes: 4000
	AF hash:    sha256
	Area offset:32768 [bytes]
	Area length:258048 [bytes]
	Digest ID:  0
Tokens:
Digests:
  0: pbkdf2
	Hash:       sha256
	Iterations: 232809
	Salt:       f2 61 30 06 59 aa 3a 1c d1 4d e1 69 1c 0c b6 5f
	            aa c4 4c b5 6b be e0 7b 28 52 8a 39 07 63 ed 1b
	Digest:     b7 7b 67 78 65 c5 71 08 0f c1 67 18 bb 58 bd 4c
	            42 f8 ec 73 d6 b4 a5 39 b4 fa 77 3c e2 ee 51 18

Aucune chance. J’ai bien tenté avec le dictionnaire rockyou, mais au bout d’une heure, je me suis dit que ce n’était pas la bonne façon de faire.

Une partition EFI

Mais l’autre partition est une EFI. On la monte:

$ mount /dev/loop20p2 /mnt
$ tree /mnt
/mnt/
└── EFI
    └── boot
        └── bootx64.efi
$ ls -l /mnt/EFI/boot/bootx64.efi
-rwxr-xr-x 1 root root 2883584 août  29 07:51 /mnt/EFI/boot/bootx64.efi

C’est le seul et unique fichier dans la partition EFI.

Pourquoi ne pas tenter de booter cela avec un émulateur.

L’aide de QEMU

Cet émulateur dont l’auteur est Fabrice BELLARD va nous permettre de tenter de booter cette image.

On choisit un bios EFI appelé OVMF. On demande le menu (normal dans une pizzéria), on met 2Go de mémoire (par habitude), on enlève le réseau (apriori pas utile) et on founit notre image de disque.

$ qemu-system-x86_64 -m 2048 -boot menu=on -bios /usr/share/ovmf/OVMF.fd -net none -drive file=disk.img,format=raw

Génial ! Ca boot et on découvre un Grub scripté de manière amusante pour commander des pizzas:

Capture_d_écran_du_2025-01-17_15-26-29

En plus, en bas, on dit qu’il faut lancer qemu avec des options plus optimisées pour l’expérience. On est donc sur la bonne piste. On s’exécute.

$ qemu-system-x86_64 -bios /usr/share/ovmf/OVMF.fd -drive file=disk.img,format=raw -audiodev pa,id=snd0 -machine pcspk-audiodev=snd0 -serial stdio

On tente les pizzas proposées (merci les mélodies, une horreur façon PC des annèes 80/90), mais la plus sympathique (Secret Pizza) nous indique les allergènes: des traces de flag. Ça tombe bien, nous ne sommes pas allégergiques aux flags.

Cependant cette sélection nous demande un nom d’utilisateur et un mot de passe. Forcément c’est secret.

Pas de trace de fichiers aux alentours qui pourraient contenir un indice.

Dump mémoire de la VM

Grâce au moniteur de QEMU on va dumper la mémoire de la VM avec:

(qemu) dump-guest-memory memory.bin

Une recherche (avec strings) sur le dump nous amène (en fouillant bien) au contenu du fichier config de grub (chargé en mémoire bien entendu):

set timeout=-1
set default=5
set color_normal="light-green/red"
set superusers="admin"
# Show some love to the best meme authors
password admin mntain_loves_pineapple_pizza_e3b432
# Opened grub!
echo "Loading..."
echo "If you see this message, you read impressively fast!"
menuentry "--------------------------------------------------" --unrestricted { true }
menuentry "|                  PizzaJukebox                  |" --unrestricted { true }
menuentry "--------------------------------------------------" --unrestricted { true }
menuentry " " --unrestricted { true }
menuentry "-- Pizzas - Classiche --" --unrestricted { true }
menuentry "Napolita (Megalovania)" --unrestricted {
   echo "Delivering Pizza... (please turn on audio)"
   source (memdisk)/boot/grub/5.cfg
   source (memdisk)/boot/grub/1.cfg
menuentry "Regina (Nonna Nieria)" --unrestricted {
   echo "Delivering Pizza... (please turn on audio)"
   source (memdisk)/boot/grub/5.cfg
   source (memdisk)/boot/grub/2.cfg
menuentry "Pinnochio (Gigachadia)" --unrestricted {
   echo "Delivering Pizza... (please turn on audio)"
   source (memdisk)/boot/grub/5.cfg
   source (memdisk)/boot/grub/3.cfg
menuentry "5 Formaggi (Conto)" --unrestricted {
   echo "Delivering Pizza... (please turn on audio)"
   source (memdisk)/boot/grub/5.cfg
   source (memdisk)/boot/grub/4.cfg
menuentry " " --unrestricted { true }
menuentry "-- Pizzas - Specialita Della Casa --" --unrestricted { true }
menuentry "Secret Pizza (alergene: possible traces of flag)" {
   echo "Decrypting secret recipe..."
   insmod luks2
   insmod part_gpt
   cryptomount -k (memdisk)/boot/grub/keyfile -a
   play 1000 784 2 740 2 622 2 440 2 415 2 659 2 831 2 1046 5
   source (memdisk)/boot/grub/5.cfg
   echo "Loading flag in memory..."
   source (crypto0)/6.cfg
menuentry "Exit (will make pizzaiolo sad!)" --unrestricted {
   echo "Exiting... Please come back for more pizza and music!"
   halt
menuentry " " --unrestricted { true }
menuentry "For optimal experience, run me with:" --unrestricted { true }
menuentry "qemu-system-x86_64 -bios OVMF.fd -drive file=disk.img,format=raw -serial stdio \\" --unrestricted { true }
menuentry "    -audiodev pa,id=snd0 -machine pcspk-audiodev=snd0" --unrestricted { true }
(memdisk)/boot/grub/grub.cfg

On retrouve notre script et le menu des pizzas.

En plus on découvre le user admin et un bon mot de passe:

password admin mntain_loves_pineapple_pizza_e3b432

(qui aime les pizzas Hawaïennes ???)

Super, on va goûter à la pizza secrète. On sélectionne la Secret Pizza et on entre user et mot de passe. Et ça se termine ainsi:

Enter username:
admin
Enter password:

Decrypting secret recipe...
Slot "0" opened
     _
   // ''--.._
   ||. (_)  _ '-._
   ||  . _ (_) .  '-_
   || . (_)   __..-'
    \\__..--''

Loading flag in memory...
...
Rickrolled!

La bonne blague, nous sommes Rickrollés.

Alors on va tenter d’utiliser la proposition de taper ‘c’ pour une console GRUB. On entre a nouveau admin et le bon mot de passe et on entre dans la console grub:

                                       GNU GRUB  version 2.12

   Minimal BASH-like line editing is supported. For the first word, TAB lists possible
   command completions. Anywhere else TAB lists possible device or file completions. To
   enable less(1)-like paging, "set pager=1". ESC at any time exits.


grub>

Enfin.

GRUB

Ce bootloader est capable de faire beaucoup de chose. C’est pourquoi on va tenter voir si on peut explorer les contenus des fichiers.

Mais les commandes ne sont pas toutes là, malheureusement. Ni ’ls’, ni ‘cat’, dommage.

Si on reprend le fichier de config on se concentre sur l’entrée Secret Pizza:

menuentry "Secret Pizza (alergene: possible traces of flag)" {
   echo "Decrypting secret recipe..."
   insmod luks2
   insmod part_gpt
   cryptomount -k (memdisk)/boot/grub/keyfile -a
   play 1000 784 2 740 2 622 2 440 2 415 2 659 2 831 2 1046 5
   source (memdisk)/boot/grub/5.cfg
   echo "Loading flag in memory..."
   source (crypto0)/6.cfg

On va donc suivre les instructions pour monter la partition chiffrée:

grub> set color_normal="green/black"
grub> insmod luks2
grub> insmod part_gpt
grub> cryptomount -k (memdisk)/boot/grub/keyfile -a
Slot "0" opened
grub>

On évite les instructions inutiles, play, echo, et le dessin de la pizza (via 5.cfg)

Notez que le ‘set color_normal’ rend la console plus sympa à lire. Juste question de confort.

Ah, nous avons donc une partition (crypto0) de créée ! Mais nous n’avons pas de ’ls’.

Si nous tentons un source sur 6.cfg on sait ce qu’on va obtenir (pitié). Mais, le grub a la complétion sur les commandes et les fichiers avec la touche TAB (c’est écrit au début). Alors on tape:

grub> source (crypto0)/

sans retour charriot, on tape alors la touche TAB:

grub> source (crypto0)/error: file `/boot/grub/x86_64-efi/zfs.mod' not found.
error: file `/boot/grub/x86_64-efi/xfs.mod' not found.
error: file `/boot/grub/x86_64-efi/ufs2.mod' not found.
error: file `/boot/grub/x86_64-efi/ufs1_be.mod' not found.
error: file `/boot/grub/x86_64-efi/ufs1.mod' not found.
error: file `/boot/grub/x86_64-efi/udf.mod' not found.
error: file `/boot/grub/x86_64-efi/squash4.mod' not found.
error: file `/boot/grub/x86_64-efi/sfs.mod' not found.
error: file `/boot/grub/x86_64-efi/romfs.mod' not found.
error: file `/boot/grub/x86_64-efi/reiserfs.mod' not found.
error: file `/boot/grub/x86_64-efi/odc.mod' not found.
error: file `/boot/grub/x86_64-efi/ntfs.mod' not found.
error: file `/boot/grub/x86_64-efi/nilfs2.mod' not found.
error: file `/boot/grub/x86_64-efi/newc.mod' not found.
error: file `/boot/grub/x86_64-efi/minix_be.mod' not found.
error: file `/boot/grub/x86_64-efi/minix3_be.mod' not found.
error: file `/boot/grub/x86_64-efi/minix3.mod' not found.
error: file `/boot/grub/x86_64-efi/minix2_be.mod' not found.
error: file `/boot/grub/x86_64-efi/minix2.mod' not found.
error: file `/boot/grub/x86_64-efi/minix.mod' not found.
error: file `/boot/grub/x86_64-efi/jfs.mod' not found.
error: file `/boot/grub/x86_64-efi/iso9660.mod' not found.
error: file `/boot/grub/x86_64-efi/hfsplus.mod' not found.
error: file `/boot/grub/x86_64-efi/hfs.mod' not found.

Possible files are:

 6.cfg 7.cfg 8.cfg
grub> source (crypto0)/

(Les erreurs sont les tentatives de chargement des modules de lectures de filesystems)

On découvre 2 autres fichiers 7.cfg et 8.cfg. Je tente 7.cfg:

error: terminal `morse' isn't found.
Your flag is
CTE24{20a0a14234319c65898d7e3ace511543}
GG!

Good game. On a notre flag:

CTE24{20a0a14234319c65898d7e3ace511543}

Et voilà.

Ne tentez pas source du 8.cfg. Pour vos oreilles.