Concept
My blog post explaining what this is all about and why this might be a good idea.
Checking iso9660
I’m starting with a distribution of Parrot Linux because it is coincidentally very similar to how I want my system to be. It has made many very sensible choices about interface (Mate, for example) and browser hardening (Noscript). It also has a load into cache option (which I think Debian itself does too, but this one is very easy to use).
The first thing to do is to obtain the ISO image.
wget https://mirrordirector.archive.parrotsec.org/\
parrot/iso/3.7/Parrot-lite-3.7_amd64.iso
Normally you would install this on a USB flash drive with a simple
dd
transfer. But before doing that, it’s good to check its ISO9660
system. Here’s what it looks like from the iso file as downloaded.
:->[usb64][/mnt/sda/xed/os]$ xorriso -dev stdio:Parrot-lite-3.7_amd64.iso
xorriso 1.4.6 : RockRidge filesystem manipulator, libburnia project.
xorriso : NOTE : ISO image bears MBR with -boot_image any partition_offset=16
xorriso : NOTE : Loading ISO image tree from LBA 0
xorriso : UPDATE : 1260 nodes read in 1 seconds
xorriso : NOTE : Detected El-Torito boot information which currently is set to be discarded
Drive current: -dev 'stdio:Parrot-lite-3.7_amd64.iso'
Media current: stdio file, overwriteable
Media status : is written , is appendable
Boot record : El Torito , MBR isohybrid cyl-align-on
Media summary: 1 session, 592760 data blocks, 1158m data, 69.4g free
Volume id : 'ParrotSec'
Note especially the line with "ISO image bears MBR". This seems critical in getting it to boot (from flash drives anyway).
For reference, here’s what the iso looks like installed on a flash drive.
$ _ xorriso -dev stdio:/dev/sdg1
xorriso 1.4.6 : RockRidge filesystem manipulator, libburnia project.
xorriso : NOTE : Loading ISO image tree from LBA 0
xorriso : UPDATE : 1260 nodes read in 1 seconds
Drive current: -dev 'stdio:/dev/sdg1'
Media current: stdio file, overwriteable
Media status : is written , is appendable
Boot record : (system area only) , not-recognized
Media summary: 1 session, 592744 data blocks, 1158m data, 0 free
Volume id : 'ParrotSec'
Modifying the iso9660 file system
A USB flash drive system is really emulating a live CD (or DVD), some kind of optical media. That means its real file system at that level is iso9660. This is a read only file system (because of traditional CDs) and to change it you have to extract all its files to a new writeable file system, make your changes, and then remaster a new iso9660 file system image.
This webpage covers Debian iso
mastering tools. You may need to start with apt-get install xorriso
.
To get started, the iso image file (note loop
option) must be
mounted and then its contents replicated somewhere writeable.
sudo mount -o ro,loop -t iso9660 Parrot-lite-3.7_amd64.iso /mnt/iso
rsync -aP /mnt/iso /tmp/isocontents
Now make your changes to /tmp/isocontents
. Specifically, see the
next section on doing the same kind of routine with the
squashfs. These are nested operations; basically you need to "gosub"
to the next section and return here when that is complete.
Go on, go do that now and then come back here.
Once you have a new squashfs image file the way you want it replace the one in your writeable iso directory.
sudo cp squashcontents/filesystem.squashfs isocontents/live/filesystem.squashfs
Now it’s almost time to compose a new iso9660 system. Before you can do that, you need to extract a master boot record from the original iso image to use in the new one. This avoids generating a new one from scratch which may not be quite right. Here’s how to get the first 512 bytes (the MBR) from the iso image. This is used later.
sudo dd if=Parrot-lite-3.7_amd64.iso bs=512 count=1 of=./orig.mbr
Once you have a master boot record in a file that you can use, run
the messy command xorrisofs
as seen
here.
sudo xorrisofs -v -J -r \
-V ParrotSec \
-o Parrot-lite-3.7_amd64-xed.iso \
-isohybrid-mbr orig.mbr \
-c isolinux/boot.cat \
-b isolinux/isolinux.bin \
-no-emul-boot \
-boot-load-size 4 \
-boot-info-table \
-eltorito-alt-boot \
-e boot/grub/efi.img \
-no-emul-boot \
-isohybrid-gpt-basdat \
/tmp/isocontents
This runs quite quickly and should produce a new bootable iso image
file, Parrot-lite-3.7_amd64-xed.iso
from the contents of
/tmp/isocontents
. This iso file should be able to be installed on a
USB flash drive directly with something like this.
sudo dd if=Parrot-lite-3.7_amd64-xed.iso of=/dev/sdg status=progress
If you’re not sure about which exact drive should be the target
(of
=output file) device, use the lsblk
command before and after
inserting the target USB drive. Needless to say that it is very, very
bad to use dd
to write over an important hard drive by mistake. And
of course your USB flash drive will forsake its previous contents.
At this point, you should be able to tell your computer’s BIOS to boot the USB drive (see my notes on this for clues). You can then choose to load into "RAM Mode" at the boot menu and once it boots, you can remove the flash drive. 100% integrity. Enjoy!
Modifying the squashfs file system
The main location for all the files of the live distribution reside in a squashfs filesystem. Like the iso9660 system that encapsulates it, this must be unpacked into a normal (ext4?) file system, modified and then repacked back into a squashfs.
sudo mkdir /tmp/squashfs_contents
cd /tmp/squashfs_contents
sudo unsquashfs /tmp/isocontents/live/filesystem.squashfs
This will fill up your current directory with the contents of the
squashfs system. Make your changes to squashfs_contents
.
Again, go to the next section, make the content changes and return here. You need to mentally keep track of your stack depth.
When you are finished making your changes, you have to repack all that back up.
sudo mksquashfs squashfs-root/ filesystem.squashfs \
-noappend -always-use-fragments -comp xz
This can take several minutes and it will admirably fully use all of your CPU cores.
Once you have a new squashfs file containing your custom stuff, you
have to put that new file into the isocontents
file tree, overwriting the
original filesystem.squashfs
. At this point, return to the iso section and resume packing that up.
Modifying the actual stuff you care about
Here’s where you finally get to change the things that are meaningful
to the end user. Given all that trouble to change things, what can be
changed? The first place to look is probably /etc/skel
. This is both
obvious and weird. It’s obvious because it’s the traditional place to
put things that will be instilled into new accounts upon creation;
it’s weird because you don’t think of it as needing to create an
account. But these Debian live systems do create a new account on
boot, just like the Guest systems (which presumably use the same
location).
For example, if you want your own .bashrc
to be active for the user
(UID=1000) user, replace the one in /etc/skel
in the squashfs. When
the live image boots, the user
account will get created with your
.bashrc
and you’ll get what you want.
/home/user/.config/dconf/user
It seems that the .config/dconf/user
file is particularly important
for settings. It’s in some annoying registresque format. Thankfully
Parrot comes with dconf-editor
. You can make your changes using the
System Control Center menus the normal way. Once it’s how you like it,
isolate the new updated user
file, offload it to where you are
customizing, and just overwrite the one in your image’s skeleton.
After making your actual desired improvements to the system, return to the squash section to pack everything up.
Other Resources
-
A good write up of a slightly different procedure than mine but very similar and maybe helpful.
-
Debian’s Live Systems Project Manual.
-
An Ubuntu.com article titled "LiveCD Customization From Scratch".