If you are reading this you are probably familiar with “Recovery Images” for ChromeOS.
They allow you to boot a USB and install a new fresh version of ChromeOS if you manage to break something.
How do they work?
Before we talk about modifying them I wanted to mention how they work.
Partitions
There are 12 partitions on the Recovery Image. Only three are useful.
ROOT-A
/RootFS
- This is the partition that contains all the programs, scripts, etc. that can be executed.
KERN-A
- This is the kernel for the Recovery Image.
stateful
- This partition contains heavily encrypted user data. Basically everything in
/home/*
- This partition contains heavily encrypted user data. Basically everything in
DM-Verity
All of the partitions except ROOT-A
are checked by something called dm-verity
.
Basically dm-verity
is an algorithm that verifies the integrity of files to make sure they have been modified.ROOT-A
is actually checked by dm-verity
in verified mode, however if you boot the USB from developer mode it won’t be checked.
Developer Mode vs Verified
You probably know what devmode is so I won’t explain it in detail however I did want to clarify some things.
Your data will be wiped when transitioning from Developer Mode to Verified, but how?
Simple! All of your user data is stored on thatstateful
partition and it will just wipe that partition.As a mentioned already, you can only modify the
ROOT-A
partition in devmode, not verified. This is because verified boot will checkROOT-A
withdm-verity
How does the system actually recover?
There are a couple of scripts stored in the ROOT-A
found in /usr/sbin/
.
chromeos-install
- This is the actual script that will install a fresh version of ChromeOS
chromeos-recovery
- This is the script that invokes
chromeos-install
as it takes some arguments
- This is the script that invokes
chromeos-postint
- After the install is complete (or an update happens) this script will be executed
How do I modify a Recovery Image?
First you need to be in some sort of Linux environment. While you could try WSL I’m not sure if it works. I recommend doing it in a liveboot or running a VM (or even better just daily drive Linux!)
- First obtain a Recovery Image. To find them visit https://cros.tech and search your Chromebook model
- Once the image is finished downloading extract the
.zip
file, then you should have a.bin
file - Create a directory and move the recovery image there, then download and place this script in that directory.
- Then run these commands in your terminal:
loopdev=$(losetup -f)
losetup -P "$loopdev" "./PATH_TO_RECOVERY_IMAGE.bin"
chmod +x ssd_util.sh
./ssd_util.sh --remove_rootfs_verification --no_resign_kernel -i "$loopdev" --partitions 2
sync
ROOT=$(mktemp -d)
mount "${loopdev}p3" "$ROOT"
The RootFS of the Recovery Image has been mounted and you can start modifying it!
However, we are not quite done yet, the chromeos-recovery
script is run inside of a chroot
jail” and is very sandboxed. Lucky Mercury Workshop made a script that performs a chroot
escape as well as gains PID1
code execution!
To get started open chromeos-recovery
with your favorite text editor and replace it with:
USB_MNT=/usb
set +x
# Chroot Escape
echo 0 >/proc/sys/kernel/yama/ptrace_scope
if ! [ "$(cat /proc/sys/kernel/yama/ptrace_scope)" = "0" ]; then
echo "failed to enable ptrace"
sleep 1d
fi
sleep 1
# PID1 Code Execution
clamide -p 1 --syscall execve "str:$USB_MNT/usr/sbin/bootstrap-shell"
spinner=$(pgrep sh | tail -1)
kill -9 $spinner
pkill -f frecon
pkill -f tail
Then make a new file called bootstrap-shell
under /usr/sbin
.
Whatever code you place in this file will be executed freely!
However here are some notes you probably want:
- The code is executed as
bushboxsh
, notbash
- It runs as
PID1
(initramfs
), meaning if it dies the kernel will panic - You can access
freecon
! If you are unaware,freencon
is Google’s replacement for a kernel console and can do some extra graphical stuff.
Finishing up your modifications
Once you have made your modifications there is still some clean up to do, open your terminal and run these commands:
curl -sL "https://github.com/CoolElectronics/clamide/releases/latest/download/clamide" -o "clamide"
cp clamide "$ROOT/usr/sbin/clamide"
chmod +x "$ROOT/usr/sbin/clamide"
chmod +x "$ROOT/usr/sbin/chromeos-recovery"
chmod +x "$ROOT/usr/sbin/bootstrap-shell"
sync
umount "$ROOT"
losetup -d "$loopdev"
rm -rf "$ROOT"
And there you have it, your own modified ChromeOS Recovery Image!
But how do I use it?
Simple!
- Take the
.bin
file and flash it to a USB using a tool likedd
, the ChromeOS Recovery Utility, etc. - Boot the USB like you would boot sh1mmer
esc + refresh + power
ctrl + d
enter
esc + refresh + power
- Insert USB