Skip to content

Spiral three: The Dream

The goal of Spiral 3 is to set up a virtual machine on Piception and create an encrypted hidden directory inside it. I will also create an encrypted USB drive connected to Piception and investigate what hardening is needed for a computer connected locally over Ethernet.

  • QEMU VM on Piception
    • Install QEMU on piception
    • Setup Alpine Linux ISO
    • Configure Alpine
    • Create encrypted totem.vault
  • Add a decoy encrypted USB drive on piawake

Install QEMU VM on Piception

Since piception is not connected to Internet I had to download QEMU on piawake and then move it over to piception. Since I don't need QEMU on piawake I only downloaden them there.

sudo apt update
sudo apt install --download-only qemu-system qemu-utils
mkdir ~/packages
cp /var/cache/apt/archives/*.deb ~/packages/

That moved 35 .deb packages to ~/pakages that I then moved over to piception.

ssh piception@10.10.10.2 "mkdir -p ~/packages"
scp ~/packages/*.deb piception@10.10.10.2:~/packages/

The I connected to the piception moved into the package directory and installed everything.

ssh piception@10.10.10.2
cd ~/packages
sudo dpkg -i *.deb

I then verified that QEMU was instaled.

qemu-system-aarch64 --version
qemu-system-aarch64: error while loading shared libraries: libcapstone.so.5: cannot open shared object file: No such file or directory

I got some errors and QEMU did not start. The first attempt only downloaded packages that were not already installed on Piawake, so some required dependencies were missing on Piception. I needed to download the complete dependency tree.

Install QEMU - Take 2

I moved back to piawake and made a new directory.

mkdir ~/qemu-all-packages
cd ~/qemu-all-packages

I created a complete recursive package list called package-list.txt

apt-cache depends --recurse \
  --no-recommends \
  --no-suggests \
  --no-conflicts \
  --no-breaks \
  --no-replaces \
  --no-enhances \
  qemu-system qemu-utils \
  | awk '/^[a-zA-Z0-9]/ {print $1}' \
  | sort -u > package-list.txt

And then I downloaded every package on the list.

while read -r package; do
    apt download "$package"
done < package-list.txt

I then coped it over again.

ssh piception@10.10.10.2 "mkdir -p ~/qemu-all-packages"
scp ./*.deb piception@10.10.10.2:~/qemu-all-packages/

I connected back to piception and installed it again.

cd ~/qemu-all-packages
sudo apt install ./*.deb

This time I got errors and looking into it, it was because there was some GUI packages that were not needed.

Install QEMU - Take 3

I removed packages that I didn't need.

sudo dpkg --remove \
  qemu-system \
  qemu-system-gui \
  qemu-system-mips \
  qemu-system-misc \
  qemu-system-ppc \
  qemu-system-riscv \
  qemu-system-s390x \
  qemu-system-sparc \
  qemu-system-x86 \
  qemu-system-modules-opengl \
  qemu-system-modules-spice \
  qemu-block-extra

I checked which broken packages remained:

dpkg -l | grep '^iU'

I found some more unnecessary packages and removed them.

sudo dpkg --remove libspice-server1 libvirglrenderer1 libiscsi7

I installed the six remaining dependencies:

sudo dpkg -i \
  ./libaio1t64_*_arm64.deb \
  ./libcapstone5_*_arm64.deb \
  ./libibverbs1_*_arm64.deb \
  ./libpixman-1-0_*_arm64.deb \
  ./libpmem1_*_arm64.deb \
  ./librdmacm1t64_*_arm64.deb

At this point, only libpmem1 was still missing two dependencies.

sudo dpkg -i \
  ./libdaxctl1_*_arm64.deb \
  ./libndctl6_*_arm64.deb

I then configured the remaining packages.

sudo dpkg --configure -a

Finally, I verified the installation hoping it would work.

qemu-system-aarch64 --version
qemu-img --version

Copyright (c) 2003-2025 Fabrice Bellard and the QEMU Project developers
Copyright (c) 2003-2025 Fabrice Bellard and the QEMU Project developers

That was way to much work for something I thought would be simple, but it was also probably the most Linux thing ever.

Setup Alpine Linux ISO

Alpine Linux has a small image optimized for virtual systems. I downloaded that to piawake. The ISO is called alpine-virt-3.24.1-aarch64.iso

mkdir -p ~/vm
cd ~/vm
wget https://dl-cdn.alpinelinux.org/alpine/v3.24/releases/aarch64/alpine-virt-3.24.1-aarch64.iso

I then moved it over to piception.

ssh piception@10.10.10.2 "mkdir -p ~/vm"
scp ~/vm/alpine-virt-3.24.1-aarch64.iso piception@10.10.10.2:~/vm/

Next I conected to the piception and made a virtual disk.

cd ~/vm
qemu-img create -f qcow2 dream2.qcow2 512M

Booting up the VM on piception

Next thig was to see if the VM would boot up.

qemu-system-aarch64 -machine virt -cpu cortex-a72 -m 256 -smp 2 -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd -drive file=dream2.qcow2,format=qcow2 -cdrom alpine-virt-3.24.1-aarch64.iso -boot d -nographic

And it worked

Configure Alpine

Next thing was to setup the os I loged in with root and ran setup-alpine

turned out I needed internet for that

Alpine Linux - Take 2

I tried the standard alpine ISO first I when all the way back to piawake and got it from there and coped it to piception.

cd ~/vm
wget https://dl-cdn.alpinelinux.org/alpine/v3.24/releases/aarch64/alpine-standard-3.24.1-aarch64.iso
ls -lh alpine-standard-3.24.1-aarch64.iso
scp alpine-standard-3.24.1-aarch64.iso piception@10.10.10.2:~/vm/

I conected back to piception and I now had alpine-standard-3.24.1-aarch64.iso

I ran it with:

qemu-system-aarch64 -machine virt -cpu cortex-a72 -m 512 -smp 2 -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd -drive file=dream2.qcow2,format=qcow2 -cdrom alpine-standard-3.24.1-aarch64.iso -boot d -nographic

This also failed

Build disk image on piawake

Since I had some errors in the alpine setup because of no Internet connection I decided just to build the disk image on piawake and then move it over. I followed the same steps as above.

This was the setup proccess:

  • Hostname: dream2
  • New Root password
  • IPv4: dhcp
  • IPv6: none
  • Manual networking: n
  • DNS domain: blank
  • Proxy: none
  • NTP: default is fine
  • APK mirror: f
  • User: no
  • SSH: none
  • Disk: vda
  • First disk mode: crypt
  • Second disk mode: sys
  • Passphrase:

The instal ran smothly this time, I ran powerdown and I now had a disk image dream2.qcow2.

I moved the disk image over to piception

scp ~/vm/dream2.qcow2 piception@10.10.10.2:~/vm/

I then jumped over to piception and ran it with QEMU

qemu-system-aarch64 -machine virt -cpu cortex-a72 -m 512 -smp 2 -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd -drive file=dream2.qcow2,format=qcow2 -nographic

It started up without a problem asked for the passprase for the disk encrition and then loggin to dream2.

Normally you would create user, I used root this time since I was in so deep anyway and this was a experiment.

dream2

Create the Totem and protect it

(Piawake) eth0 => (Piception) encrypted VM => (Dream2) #you-are-here

We are already three layers deep, but before I created the totem I decided to encrypt it as well.

I created a directory:

mkdir ~/.dream_deeper

Then I used truncate to create an empty file with a fixed size.

truncate -s 20M totem.vault

I checked it with ls -lh and confirmed it was 20 MB. Next, I formatted it as an ext4 filesystem so it could behave like a disk.

mkfs.ext4 totem.vault

Then I attached it as a loop device and mounted it.

losetup -fP totem.vault
mkdir vault
mount /dev/loop0 vault

After that, a new directory called vault appeared.

dream2:~/.dream_deeper# ls
totem.vault  vault

dream2:~/.dream_deeper# df -h
...
/dev/loop0 17.4M 46.0K 16.0M 0% /root/.dream_deeper/vault

I created a text file inside the mounted filesystem and then unmounted it. After it is unmounted, the vault directory becomes empty because the filesystem is no longer mounted.

echo "The Totem" > vault/totem.txt
umount vault
losetup -d /dev/loop0

Now it was time to encrypt it. Since OpenSSL was already installed, I used it to encrypt the entire vault file.

openssl enc -aes-256-cbc -pbkdf2 -salt \
  -in totem.vault \
  -out totem.vault.enc

It prompted me for an encryption passphrase. After that I removed the unencrypted totem.vault, leaving only totem.vault.enc. It is also possible to remove the empty vault directory and recreate it later when needed.

To access the vault again, I first decrypted it:

openssl enc -d -aes-256-cbc -pbkdf2 \
  -in totem.vault.enc \
  -out totem.vault

Then I attached and mounted it again:

losetup -fP totem.vault
mount /dev/loop0 vault
(Piawake) eth0 => (Piception) => encrypted VM (Dream2) => .dream_deeper => encrypted totem.vault.enc => /vault #You-are-here with The Totem

The workflow is:

  1. Decrypt.
  2. Attach the loop device.
  3. Mount the filesystem.
  4. Use the files.
  5. Unmount the filesystem.
  6. Detach the loop device.
  7. Delete the decrypted copy.

Encrypted USB drive - piawake

I first put a FAT32 USB stick in piawake then I ran lsblk to identify the device:

lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINTS,MODEL

Resaults:

NAME         SIZE FSTYPE MOUNTPOINTS      MODEL
loop0          2G swap                    
sda         28.9G                         DataTraveler 3.0
`-sda1      28.9G vfat   /media/pi/DREAM1 
mmcblk0     29.1G                         
|-mmcblk0p1  512M vfat   /boot/firmware   
`-mmcblk0p2 28.6G ext4   /                
zram0          2G swap   [SWAP]           

The usb stick is /dev/sda1. I then unmouted the usb and ran cryptsetup

sudo umount /dev/sda1
sudo cryptsetup luksFormat /dev/sda1

I got a big warning letter asking if I was sute I wanted to overwrite data. I typed YES then it asked for a paraphrase. After it had finesd I ran this:

sudo cryptsetup open /dev/sda1 dream1
sudo mkfs.ext4 /dev/mapper/dream1
sudo mkdir -p /mnt/dream1
sudo mount /dev/mapper/dream1 /mnt/dream1

Not I could go in the drive:

cd /mnt/dream1
sudo chown pi:pi /mnt/dream1

Now I could write and work on the drive. I wrote a password decoy file.

pass

*** DECOY FILE FOR CYBERSECURITY DEMONSTRATION ***

When finished it's closed like this:

sudo umount /mnt/dream1
sudo cryptsetup close dream1
lsblk

To use it again later:

sudo cryptsetup open /dev/sda1 dream1
sudo mount /dev/mapper/dream1 /mnt/dream1