Still Under DDOS, but here is a status update anyway. The Tor network is breaking.
/d/OpSec icon

/d/OpSec

17,155 subscribers

Anonymous Planet Onion

Discussion of OpSec, Threat Models, Protection, Assessment & Countermeasures.

Vendors: /d/vendor_handbook.

While the focus of this community's OpSec discussions may center around Dark Net (DN) activity, all members of this sub are encouraged to think about, discuss, and share ideas relating to OpSec.

[OPSEC Guide by Corqo] - Kill Switch with Hidden Restoration Modification - Buskill Alternative

by /u/corqo · 3 votes · 2 months ago

Emergency Kill Switch with Hidden Data Restoration Modification

OPSEC Guide by Corqo

Overview

This kill switch is based on the original Buskill Qubes kill switch with a some modifications to allow for a hidden method of data restoration with plausible deniability. Essentially, with this approach, we will make several modifications to the original buskill kill switch bash script. I will include a code block with the original and modified bash scripts and also a diff of the two scripts so that you can see where the modifications were made.

The Concept

The original buskill kill switch detects if the luks partition is luks1 or luks2, if it is luks2 it attempts to locate the offset that the luks header ends at (the end byte) and the encrypted data starts at. If the script is not able to locate this offset value the script wipes the first 20MB of the drive. Most of the modifications made to this script is to have it only wipe up to the exact end byte of the luks partition header. Because if we wipe past that, then even if we restore the luks header to the partition, the encrypted data will be corrupted and we won't be able to boot into our OS. Because we want to be able to leverage the plausible deniability that a veracrypt partition grants us to back up our luks header and be able to restore it after activating the kill switch. We will need all the data after the luks header end byte to remain untouched. The other modification made is to remove the bash scripts guessing of which luks partition should be wiped, instead I removed this logic and manually specified my luks partition UUID so there is no guess work and if I have a luks external hard drive connected when I have to activate the kill switch, that doesn't get wiped in error.

How the data restoration works is that we will take a DD (bit-by-bit) copy of the first 16 MB (roughly) of the luks v2 partition and store it in a hidden veracrypt partition on 4 to 5 micro sd cards. Then we will stash those micro sd cards in various locations outside of your residence so that if you ever accidentally activate your kill switch you can enter the secret veracrypt paritions password and live boot on your burner laptop and DD (bit-by-bit copy) your luks header back onto your drive restoring it.

And if law enforcement busts down your door and they locate one of the micro sd cards containing the hidden veracrypt partition and the decoy partition, you can provide them the password to the decoy veracrypt partition which could contain some random non incriminating things such as a luks header for a completely different system, bitcoin wallet with non-illicit bitcoin, pictures of your big swinging dick, I don't know, get creative. Either way, there is no way for them to know that there is a hidden veracrypt partition which gives you plausible deniability and thus protects you from rubber hose crypto-analysis.

Instructions

1. Install Qubes OS to a burner device that will be used for this purpose.

1a. if you already have a Qubes OS install, then backup any data that you can't afford to loose if you screw up following these instructions.

2. Get the items needed ready: 3 to 5 micro SD cards (minimum 4GB), a burner device with Qubes OS installed, a micro sd card reader, and some patience.

3. Boot into Qubes and verify that your luks partition is a version 2 partition and your offset is the standard for version 2 partitions (should be 16777216 bytes). Command is below to check this (in dom0).

sudo cryptsetup luksDump <luks-partition> | grep -iE "(offset|version)"

Note: Replace "<luks-partition>" with the path to your luks partition, for example /dev/sdb2 or /dev/sda2 or etc. 4. Once you have confirmed that your luks partition version is "2" and your offset is "16777216" you can proceed to the next step and be relatively assured that as long as you follow the instructions exactly, you won't break your install. 5. Now we need to take a bit-by-bit backup of the luks header data that will be wiped when the kill switch is activated. command:

touch ./luks-header.img && dd if=<luks-partition> of=./luks-header.img bs=1 count=16777216

If your offset is different than 16777216, then replace the count=16777216 with the value of your offset from the cryptsetup luksDump command. 5a. I would recommend generating a second luks header backup by dd'ing to a different file and then diff the two images with:

diff luks-header-1.img luks-header-2.img

and if there is any differences in the image, then don't proceed as you probably screwed up somewhere or one of your header backups is corrupted. 6. Once you have the luks header backup, go ahead and format each of those micro sd cards with a hidden veracrypt partition. I won't explain how to do this as if you are following a guide like this, you should be able to figure out how to do that. 7. Open the hidden veracrypt parition copy the luks header image backup file to each of the hidden veracrypt partitions. 8. Close the hidden veracrypt partition and open the decoy partition and populate it with some data that will act as a decoy. 9. Now that you have 3 to 5 micro sd cards with a hidden veracrypt partition with the backup of the luks partition header, we can now move onto setting up the killswitch bash script. 10. Please see the two bash scripts I have included below. The "Original" one is the original buskill killswitch from the buskill website. Do not use this script with this approach as only the modified script will allow for data restoration. The modified script which allows for data restoration

#!/bin/bash
#set -x

LOCK_CMD="DISPLAY=:0 xscreensaver-command -lock"
WHICH="/usr/bin/which"
CRYPTSETUP=`${WHICH} --skip-alias cryptsetup` || echo "ERROR: Unable to find cryptsetup"
XSCREENSAVER_CMD=`${WHICH} --skip-alias xscreensaver-command` || echo "ERROR: Unable to find ls"
LS=`${WHICH} --skip-alias ls` || echo "ERROR: Unable to find ls"
CP=`${WHICH} --skip-alias cp` || echo "ERROR: Unable to find cp"
MV=`${WHICH} --skip-alias mv` || echo "ERROR: Unable to find mv"
LN=`${WHICH} --skip-alias ln` || echo "ERROR: Unable to find ln"
MKDIR=`${WHICH} --skip-alias mkdir` || echo "ERROR: Unable to find mkdir"
MOUNT=`${WHICH} --skip-alias mount` || echo "ERROR: Unable to find mount"
CAT=`${WHICH} --skip-alias cat` || echo "ERROR: Unable to find cat"
GREP=`${WHICH} --skip-alias grep` || echo "ERROR: Unable to find grep"
ECHO=`${WHICH} --skip-alias echo` || echo "ERROR: Unable to find echo"
AWK=`${WHICH} --skip-alias awk` || echo "ERROR: Unable to find awk"
HEAD=`${WHICH} --skip-alias head` || echo "ERROR: Unable to find head"
LSBLK=`${WHICH} --skip-alias lsblk` || echo "ERROR: Unable to find lsblk"
OD=`${WHICH} --skip-alias od` || echo "ERROR: Unable to find od"
SUDO=`${WHICH} --skip-alias sudo` || echo "ERROR: Unable to find sudo"
CHMOD=`${WHICH} --skip-alias chmod` || echo "ERROR: Unable to find chmod"
BASH=`${WHICH} --skip-alias bash` || echo "ERROR: Unable to find bash"
NOHUP=`${WHICH} --skip-alias nohup` || echo "ERROR: Unable to find nohup"
SLEEP=`${WHICH} --skip-alias sleep` || echo "ERROR: Unable to find sleep"
QVM_KILL=`${WHICH} --skip-alias qvm-kill` || echo "ERROR: Unable to find qvm-kill"
POWEROFF=`${WHICH} --skip-alias poweroff` || echo "ERROR: Unable to find poweroff"
CHROOT=`${WHICH} --skip-alias chroot` || echo "ERROR: Unable to find chroot"
SYNC=`${WHICH} --skip-alias sync` || echo "ERROR: Unable to find sync"
LDD=`${WHICH} --skip-alias ldd` || echo "ERROR: Unable to find ldd"
XARGS=`${WHICH} --skip-alias xargs` || echo "ERROR: Unable to find xargs"

CHROOT_PATH='/dev/shm/buskill/chroot'
DIE_SCRIPT='/usr/bin/die.sh'

##############
# ROOT CHECK #
##############

# re-run as root
if [[ $EUID -ne 0 ]]; then
    exec ${SUDO} ${BASH} "$0" "$@"
fi

###########
# CONFIRM #
###########

# for safety, exit if this script is executed without a '--yes' argument
${ECHO} "${@}" | ${GREP} '\--yes' &> /dev/null
if [ $? -ne 0 ]; then
	${ECHO} "WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING"
	${ECHO} "================================================================================"
	${ECHO} "WARNING: THIS IS EXPERIMENTAL SOFTWARE THAT IS DESIGNED TO CAUSE PERMANENT,  COMPLETE AND IRREVERSIBLE DATA LOSS!"
	${ECHO} "================================================================================"
	${ECHO} "WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING"
	${ECHO}
	${ECHO} "cowardly refusing to execute without the '--yes' argument for your protection. If really you want to proceed with damaging your system, retry with the '--yes' argument"
	exit 1
fi

###########################
# (DELAYED) HARD SHUTDOWN #
###########################

# The most secure encrypted computer is an encrypted computer that is *off*
# This is our highest priority; initiate a hard-shutdown to occur in 1
# minute regardless of what happens later in this script

${NOHUP} ${SLEEP} 60 && ${ECHO} o > /proc/sysrq-trigger &
${NOHUP} ${SLEEP} 61 && ${POWEROFF} --poweroff --no-sync --no-wall --force &
${NOHUP} ${SLEEP} 62 && shutdown -h now &

###############
# LOCK SCREEN #
###############

# first action: lock the screen!
${SUDO} -u "${SUDO_USER}" ${BASH} -c "${LOCK_CMD}" &

################
# KILL ALL VMs #
################

# doing this sooner will decrease the time needed to hard shutdown later
# See https://github.com/QubesOS/qubes-issues/issues/5887
${QVM_KILL} --all &

#####################
# WIPE LUKS VOLUMES #
#####################

# overwrite luks headers
${ECHO} "INFO: shredding LUKS header (plaintext metadata and keyslots with encrypted master decryption key)"
writes=''
oldIFS="${IFS}"
IFS=$'\n'
for line in $( ${LSBLK} --list --output 'UUID,FSTYPE' | ${GREP} 'crypt' ); do

	device="/dev/disk/by-uuid/<REPLACE-PART-UUID-HERE>"
	${ECHO} -e "\t${device}"

	###########################
	# OVERWRITE LUKS KEYSLOTS #
	###########################

	# erases all keyslots, making the LUKS container "permanently inaccessible"
	${CRYPTSETUP} luksErase --batch-mode "${device}" || ${HEAD} --bytes 16777216 /dev/urandom > ${device} &

	# store the pid of the above write tasks so we can try to wait for it to
	# flush to disk later -- before triggering a brutal hard-shutdown
	writes="${writes} $!"

	#####################################
	# OVERWRITE LUKS PLAINTEXT METADATA #
	#####################################

	luksVersion=`${OD} --skip-bytes 6 --read-bytes 2 --format d2 --endian=big --address-radix "n" "${device}"`

	# get the end byte to overwrite. For more info, see:
	# https://security.stackexchange.com/questions/227359/how-to-determine-start-and-end-bytes-of-luks-header
	if [[ $luksVersion -eq 1 ]]; then
		# LUKS1: https://gitlab.com/cryptsetup/cryptsetup/-/wikis/LUKS-standard/on-disk-format.pdf

	 	# in LUKS1, the whole header ends at 512 * the `payload-offset`
		# this is actually more than we need (includes keyslots), but
		# it's the fastest/easiest to bound to fetch in LUKS1
		payloadOffset=`${OD} --skip-bytes 104 --read-bytes 4 --format d4 --endian=big --address-radix "n" "${device}"`
		luksEndByte=$(( 512 * ${payloadOffset} ))

	elif [[ $luksVersion -eq 2 ]]; then
		# LUKS2: https://gitlab.com/cryptsetup/LUKS2-docs/blob/master/luks2_doc_wip.pdf

		# in LUKS2, the end of the plaintext metadata area is twice the
		# size of the `hdr_size` field
		hdr_size=`${OD} --skip-bytes 8 --read-bytes 8 --format d8 --endian=big --address-radix "n" "${device}"`
		luksEndByte=16777216

	else
		# version unclear; just overwrite 20 MiB
		luksEndByte=16777216

	fi
		
	# finally, shred that plaintext metadata; we do this in a new file descriptor
	# to prevent bash from truncating if ${device} is a file
	exec 5<> "${device}"
	${HEAD} --bytes "${luksEndByte}" /dev/urandom >&5 &
	writes="${writes} $!"
	exec 5>&-
done
IFS="${oldIFS}"

#######################
# WAIT ON DISK WRITES #
#######################

# xargs is our leading/trailing whitespace trim() function
writes=`${ECHO} "${writes}" | ${XARGS}`

# wait until all the write tasks above have completed
# note: do *not* put quotes around this arg or the whitespace will break wait
# note: without the conditional, wait will wait indefinitely when $writes is empty
if [[ ${writes} ]]; then wait ${writes}; fi

# clear write buffer to ensure headers overwrites are actually synced to disks
sync; echo 3 > /proc/sys/vm/drop_caches

#################
# CREATE CHROOT #
#################

# we have to create a ramfs chroot with cryptsetup, poweroff, and a few other
# basic depends for after we luksSuspend our rootfs from under our feet

${MKDIR} -p "${CHROOT_PATH}/proc"
${MKDIR} -p "${CHROOT_PATH}/sys"
${MKDIR} -p "${CHROOT_PATH}/dev"
${MKDIR} -p "${CHROOT_PATH}/pts"
${MKDIR} -p "${CHROOT_PATH}/bin"
${MKDIR} -p "${CHROOT_PATH}/lib64"
${MKDIR} -p "${CHROOT_PATH}/lib/systemd"
${MKDIR} -p "${CHROOT_PATH}/usr/sbin"
${MKDIR} -p "${CHROOT_PATH}/usr/bin"

${MOUNT} -t proc none "${CHROOT_PATH}/proc"
${MOUNT} -t sysfs none "${CHROOT_PATH}/sys"
${MOUNT} -o bind /dev "${CHROOT_PATH}/dev"
${MOUNT} -o bind /dev/pts "${CHROOT_PATH}/dev/pts"

# copy-in our binaries and their depends
binaries="${BASH} ${CRYPTSETUP} ${ECHO} ${LS} ${NOHUP} ${SLEEP} ${XARGS} ${SYNC} ${POWEROFF}"
for binary in ${binaries}; do
	${CP} -vf "${binary}" "${CHROOT_PATH}/${binary}"
	libs="$( ${LDD} "${binary}" | ${GREP} -Eo '/lib.*\.so(\.[0-9]*)*' )"
	for lib in ${libs}; do
		${CP} -vf "${lib}" "${CHROOT_PATH}/${lib}"
	done
done

# fix around some libs and symlink issues
${MV} "${CHROOT_PATH}/lib" "${CHROOT_PATH}/usr/lib"
${LN} -s "usr/lib" "${CHROOT_PATH}/lib"

${CAT} << EOF > "${CHROOT_PATH}/${DIE_SCRIPT}"
#!${BASH}

# let's give ourselves 10 more seconds to wipe luks keys from RAM
${NOHUP} ${SLEEP} 10 && ${ECHO} o > /proc/sysrq-trigger &
${NOHUP} ${SLEEP} 11 && ${POWEROFF} --poweroff --no-sync --no-wall --force &

#################################
# WIPE DECRYPTION KEYS FROM RAM #
#################################

# suspend each currently-decrypted LUKS volume
${ECHO} "INFO: removing decryption keys from memory"
waits=''
for device in \$( ${LS} -1 "/dev/mapper" ); do

	${ECHO} -e "\t\${device}";
	${CRYPTSETUP} luksSuspend "\${device}" &

	waits="\${waits} $!"

done
${ECHO} "INFO: finished luksSuspend calls"

# xargs is our leading/trailing whitespace trim() function
waits=`${ECHO} "\${waits}" | ${XARGS}`

if [[ \${waits} ]]; then wait \${waits}; fi
${ECHO} "INFO: finished waiting"

# clear page caches in memory (again)
sync; echo 3 > /proc/sys/vm/drop_caches
${ECHO} "INFO: finished syncing"

#############################
# (IMMEDIATE) HARD SHUTDOWN #
#############################
${ECHO} "INFO: Powering Down"

# do whatever works; this is important.
${ECHO} o > /proc/sysrq-trigger &
${SLEEP} 1
${POWEROFF} --poweroff --no-sync --no-wall --force &
EOF
${CHMOD} +x "${CHROOT_PATH}/${DIE_SCRIPT}"

# finally, enter the chroot and call the above die.sh script inside it
${CHROOT} "${CHROOT_PATH}" "${DIE_SCRIPT}"

The diff of the two scripts

user@host:~$ diff original.sh modified.sh 
20,23c20
< 
< BUSKILL_LOCK='/etc/qubes-rpc/buskill.lock'
< [ -f ${BUSKILL_LOCK} ] || echo "ERROR: Unable to find buskill.lock"
< 
---
> LOCK_CMD="DISPLAY=:0 xscreensaver-command -lock"
25a23
> XSCREENSAVER_CMD=`${WHICH} --skip-alias xscreensaver-command` || echo "ERROR: Unable to find ls"
97c95
< ${SUDO} -u "${SUDO_USER}" ${BASH} -c "${BUSKILL_LOCK}" &
---
> ${SUDO} -u "${SUDO_USER}" ${BASH} -c "${LOCK_CMD}" &
118c116
< 	device="/dev/disk/by-uuid/`${ECHO} \"${line}\" | ${AWK} '{print \$1}'`"
---
> 	device="/dev/disk/by-uuid/<REPLACE-PART-UUID-HERE>"
126c124
< 	${CRYPTSETUP} luksErase --batch-mode "${device}" || ${HEAD} --bytes 20M /dev/urandom > ${device} &
---
> 	${CRYPTSETUP} luksErase --batch-mode "${device}" || ${HEAD} --bytes 16777216 /dev/urandom > ${device} &
155c153
< 		luksEndByte=$(( 2 * ${hdr_size} ))
---
> 		luksEndByte=16777216
159c157
< 		luksEndByte=20971520
---
> 		luksEndByte=16777216

IMPORTANT: The only modification that needs to be made to the modified bash script is you need to replace "<REPLACE-PART-UUID-HERE>" with the PART UUID of your luks partition Restoration Proceedure 1. Locate one of your micro sd cards 2. Live boot tails os on the device that you activated the kill switch on. 3. Plug in the micro sd card and use the veracrypt unlocker that is included with Tails to open the hidden veracrypt partition. 4. run "fdisk -l" to identify which partition is the encrypted luks partition containing the Qubes OS install. 5. once you are cetain you know which partition was affected by the kill switch run the following DD command against it.

dd if=<path-to-luks-header-backup> of=<luks-partition-path> bs=1 status=progress

6. Power down and if you followed the instructions exactly, you will be able to boot back into your qubes install.

I originally released this guide on KickAss, but their private onion appears to be down, so I'm releasing here as I saw a post asking about if anyone was using Buskill so I thought I would share this here.