Adding Persistence to the Live ISO

Topic Progress:

9.4. Adding Persistence to the Live ISO with a USB Key

9.4.1. The Persistence Feature: Explanations

Next, we will discuss the steps required to add persistence to a Kali USB key. The nature of a live system is to be ephemeral. All data stored on the live system and all the changes made are lost when you reboot. To remedy this, you can use a feature of live-boot called persistence, which is enabled when the boot parameters include the persistence keyword.

Since modifying the boot menu is a non-trivial task, the Kali live image includes two menu entries by default that enable persistence: Live USB Persistence and Live USB Encrypted Persistence, as shown in Figure 9.1, “Persistence Menu Entries”.

Persistence Menu Entries
Figure 9.1. Persistence Menu Entries

When this feature is enabled, live-boot will scan all partitions looking for file systems labeled persistence (which can be overridden with the persistence-label=value boot parameter) and the installer will set up persistence of the directories which are listed in the persistence.conf file found in that partition (one directory per line). The special value “/ union” enables full persistence of all directories with a union mount, an overlay that stores only the changes when compared to the underlying file system. The data of the persisted directories are stored in the file system that contains the corresponding persistence.conf file.

9.4.2. Setting Up Unencrypted Persistence on a USB Key

In this section, we assume that you have prepared a Kali Live USB Key by following the instructions at Section 2.1.4, "Copying the Image on a DVD-ROM or USB Key" nd that you have used a USB key big enough to hold the ISO image (roughly 4 GB) and the data of the directories that you want to persist. We also assume that the USB key is recognized by Linux as /dev/sdb and that it only contains the two partitions that are part of the default ISO image (/dev/sdb1 and /dev/sdb2). Be very careful when performing this procedure. You can easily destroy important data if you re-partition the wrong drive.

To add a new partition, you must know the size of the image that you copied so that you can make the new partition start after the live image. Then use parted to actually create the partition. The commands below analyze the ISO image named kali-linux-2020.3-live-amd64.iso, which is assumed to be present on the USB key as well:

# parted /dev/sdb print
Model: SanDisk Cruzer Glide (scsi)
Disk /dev/sdb: 16.0GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type     File system  Flags
 1      32.8kB  3516MB  3516MB  primary               boot, hidden
 2      3516MB  3517MB  754kB   primary
# start=$(du --block-size=1MB kali-linux-2020.3-live-amd64.iso | awk '{print $1}')
# echo "Size of image is $start MB"
Size of image is 3518 MB
# parted -a optimal /dev/sdb mkpart primary "${start}MB" 100%
Information: You may need to update /etc/fstab.

# parted /dev/sdb print
Model: SanDisk Cruzer Glide (scsi)
Disk /dev/sdb: 16.0GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type     File system  Flags
 1      32.8kB  3516MB  3516MB  primary               boot, hidden
 2      3516MB  3517MB  754kB   primary
 3      3518MB  16.0GB  12.5GB  primary

With the new /dev/sdb3 partition in place, format it with an ext4 filesystem labelled "persistence" with the help of the mkfs.ext4 command (and its -L option to set the label). The partition is then mounted on the /mnt directory and you add the required persistence.conf configuration file. As always, use caution when formatting any disk. You could lose valuable information if you format the wrong disk or partition.

# mkfs.ext4 -L persistence /dev/sdb3
mke2fs 1.45.6 (20-Mar-2020)
Creating filesystem with 3049472 4k blocks and 762528 inodes
Filesystem UUID: cedc7589-a002-4aae-8963-f5197d6d9d4a
Superblock backups stored on blocks:
  32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208

Allocating group tables: done
Writing inode tables: done
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done
# mount /dev/sdb3 /mnt
# echo "/ union" >/mnt/persistence.conf
# ls -l /mnt
total 20
drwx------ 2 root root 16384 May 10 13:31 lost+found
-rw-r--r-- 1 root root     8 May 10 13:34 persistence.conf
# umount /mnt

The USB key is now ready and can be booted with the "Live USB Persistence" boot menu entry.

9.4.3. Setting Up Encrypted Persistence on a USB Key

live-boot is also able to handle persistence file systems on encrypted partitions. You can thus protect the data of your persistent directories by creating a LUKS encrypted partition holding the persistence data.

The initial steps are the same up to the creation of the partition but instead of formatting it with an ext4 file system, use cryptsetup to initialize it as a LUKS container. Then open that container and setup the ext4 file system in the same way as in the non-encrypted setup, but instead of using the /dev/sdb3 partition, use the virtual partition created by cryptsetup. This virtual partition represents the decrypted content of the encrypted partition, which is available in /dev/mapper under the name that you assigned it. In the example below, we will use the name kali_persistence. Again, ensure that you are using the correct drive and partition.

# cryptsetup --verbose --verify-passphrase luksFormat /dev/sdb3

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

Are you sure? (Type uppercase yes): YES
Enter passphrase for /dev/sdb3:
Verify passphrase:
Key slot 0 created.
Command successful.
# cryptsetup luksOpen /dev/sdb3 kali_persistence
Enter passphrase for /dev/sdb3:
# mkfs.ext4 -L persistence /dev/mapper/kali_persistence
mke2fs 1.45.6 (20-Mar-2020)
Creating filesystem with 3045376 4k blocks and 761856 inodes
Filesystem UUID: 22adeb99-e32d-43e7-b9df-f04389dd0ba4
Superblock backups stored on blocks:
  32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208

Allocating group tables: done
Writing inode tables: done
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done

# mount /dev/mapper/kali_persistence /mnt
# echo "/ union" >/mnt/persistence.conf
# umount /mnt
# cryptsetup luksClose /dev/mapper/kali_persistence

9.4.4. Using Multiple Persistence Stores

If you have multiple use-cases for your Kali live system, you can use multiple filesystems with different labels and indicate on the boot command line which (set of) filesystems should be used for the persistence feature: this is done with the help of the persistence-label=label boot parameter.

Let's assume that you are a professional pen-tester. When you work for a customer, you use an encrypted persistence partition to protect the confidentiality of your data in case the USB key is stolen or compromised. At the same time, you want to be able to showcase Kali and some promotional material stored in an unencrypted partition of the same USB key. Since you don't want to manually edit the boot parameters on each boot, you want to build a custom live image with dedicated boot menu entries.

The first step is to build the custom live ISO (following Section 9.3, "Building Custom Kali Live ISO Images" and in particular Section 9.3.4, "Using Hooks to Tweak the Contents of the Image"). The main customization is to modify kali-config/common/hooks/live/persistence-menu.binary to make it look like this (note the persistence-label parameters):

#!/bin/sh

if [ ! -d isolinux ]; then
    cd binary
fi

cat >>isolinux/live.cfg <

Next, we will build our custom ISO and copy it to the USB key. Then we will create and initialize the two partitions and files systems that will be used for persistence. The first partition is unencrypted (labeled “demo”), and the second is encrypted (labeled “work”). Assuming /dev/sdb is our USB key and the size of our custom ISO image is 3000 MB, it would look like this:

# parted /dev/sdb mkpart primary 3000 MB 55%
# parted /dev/sdb mkpart primary 55% 100%
# mkfs.ext4 -L demo /dev/sdb3
[...]
# mount /dev/sdb3 /mnt
# echo "/ union" >/mnt/persistence.conf
# umount /mnt
# cryptsetup --verbose --verify-passphrase luksFormat /dev/sdb4
[...]
# cryptsetup luksOpen /dev/sdb4 kali_persistence
[...]
# mkfs.ext4 -L work /dev/mapper/kali_persistence
[...]
# mount /dev/mapper/kali_persistence /mnt
# echo "/ union" >/mnt/persistence.conf
# umount /mnt
# cryptsetup luksClose /dev/mapper/kali_persistence

And that's all. You can now boot the USB key and select from the new boot menu entries as needed!

Adding a Nuke Password for Extra Safety


Kali provides a cryptsetup-nuke-password package that modifies cryptsetup's early boot scripts to implement a new feature: you can set a nuke password which—when used—will destroy all keys used to manage the encrypted partition.

This can be useful when you travel a lot and need a quick way to ensure your data cannot be recovered. When booting, just type the nuke password instead of the real one and it will then be impossible for anyone (including you) to access your data.

Before using that feature, it is thus wise to make a backup copy of your encryption keys and keep them at some secure place.

You can configure a nuke password with this command (assuming that you have the package installed):

dpkg-reconfigure cryptsetup-nuke-password

More information about this feature can be found in the following tutorial:

https://www.kali.org/tutorials/nuke-kali-linux-luks/