Skip to content

Commit

Permalink
feat: add support for disabling/enabling kext/sext
Browse files Browse the repository at this point in the history
  • Loading branch information
hazcod committed Dec 3, 2020
1 parent 475f5d8 commit cdc27b3
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 13 deletions.
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

# maclaunch

Lists and controls your macOS startup items and their startup policy.
Lists and controls all your macOS startup items and their startup policy.

Take back control of your macOS system!

Expand Down Expand Up @@ -31,8 +31,13 @@ Take back control of your macOS system!

## How does it work?

Lists XML/json/binary plist files in LaunchAgents and LaunchDaemons folders which are loaded by launchctl.
When disabling an item, it uses launchctl to natively stop loading that service.
maclaunch will list 3 distinct types of entries on your macOS system that can be persistently installed:

1. Configuration files for LaunchAgents and LaunchDaemons which are loaded by launchctl.
2. Kernel extensions loaded in the kernel.
3. System extensions loaded in userspace.

When disabling an item, it uses `launchctl`, `kextutil` or `systemextensionsctl` to natively stop loading that service.
It does **not** alter the contents in any way or moves the file, so it should work with practically any service.

The name you provide can either be specific to that service or function as a filter to work on multiple services simultaneously.
Expand Down
131 changes: 121 additions & 10 deletions maclaunch.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
#!/usr/bin/env bash

#set -e
#set -x

startup_dirs=(/Library/LaunchAgents /Library/LaunchDaemons ~/Library/LaunchAgents ~/Library/LaunchDaemons)
system_dirs=(/System/Library/LaunchAgents /System/Library/LaunchDaemons)

Expand All @@ -12,6 +9,10 @@ YELLOW='\033[1;33m'
NC='\033[0m'
BOLD='\033[1m'

#
#--------------------------------------------------------------------------------------------------------------------------------------
#

function join_by { local IFS="$1"; shift; echo "$*"; }

function usage {
Expand Down Expand Up @@ -59,7 +60,7 @@ function listKernelExtensions {

getKernelExtensions | while IFS= read -r kextLine; do

kextLoaded=$(echo "$kextLine" | cut -d ' ' -f 3)
kextLoaded="$(echo "$kextLine" | cut -d ' ' -f 3)"
kextName="$(echo "$kextLine" | cut -d ' ' -f 7)"
kextVersion="$(echo "$kextLine" | grep -o '\((.*)\)')"

Expand Down Expand Up @@ -98,6 +99,56 @@ function listKernelExtensions {
done
}

function disableKernelExtensions {
local filter="$1"

getKernelExtensions | while IFS= read -r kextLine; do

kextLoaded="$(echo "$kextLine" | cut -d ' ' -f 3)"
kextName="$(echo "$kextLine" | cut -d ' ' -f 7)"

if ! [[ "$kextName" =~ $filter ]]; then
continue
fi

if [ "$kextLoaded" == "0" ]; then
#error "kernel extension is already unloaded"
continue
fi

if ! kmutil load -b "$kextName" 1>/dev/null; then
error "could not disable kernel extension"
fi

echo -e "${GREEN}Disabled ${STRONG}${kextName}${NC}"
done
}

function enableKernelExtensions {
local filter="$1"

getKernelExtensions | while IFS= read -r kextLine; do

kextLoaded="$(echo "$kextLine" | cut -d ' ' -f 3)"
kextName="$(echo "$kextLine" | cut -d ' ' -f 7)"

if ! [[ "$kextName" =~ $filter ]]; then
continue
fi

if ! [ "$kextLoaded" == "0" ]; then
#error "kernel extension is already loaded"
continue
fi

if ! kmutil unload -b "$kextName" 1>/dev/null; then
error "could not disable kernel extension"
fi

echo -e "${GREEN}Enabled ${STRONG}${kextName}${NC}"
done
}

function getSystemExtensions {
systemextensionsctl list 2>/dev/null | tail -n+2 | grep -v '^---' | grep -v '^enabled' | tr -s ' '
}
Expand All @@ -111,6 +162,10 @@ function listSystemExtensions {
extName="$(echo "$fullName" | cut -d ' ' -f 1)"
extVersion="$(echo "$fullName" | grep -o '\((.*)\)')"

if [ -n "$filter" ] && ! [[ "$extName" =~ $filter ]]; then
continue
fi

local loaded
if [ "$(echo "$extLine" | cut -d$'\t' -f 2)" == "*" ]; then
loaded="${ORANGE}enabled${NC}"
Expand All @@ -126,7 +181,52 @@ function listSystemExtensions {
done
}

function listItems {
function enableSystemExtensions {
local filter="$1"

getSystemExtensions | while IFS= read -r extLine; do

extName="$(echo "$extLine" | cut -d$'\t' -f 4 | cut -d ' ' -f 1)"

if ! [[ "$extName" =~ $filter ]]; then
continue
fi

if [ "$(echo "$extLine" | cut -d$'\t' -f 2)" == "*" ]; then
# error "this system extension is already enabled"
continue
fi

#TODO: implement load system extension via CLI
error "enabling system extensions is not yet implemented"
done
}

function disableSystemExtensions {
local filter="$1"

getSystemExtensions | while IFS= read -r extLine; do

extName="$(echo "$extLine" | cut -d$'\t' -f 4 | cut -d ' ' -f 1)"

if ! [[ "$extName" =~ $filter ]]; then
continue
fi

if ! [ "$(echo "$extLine" | cut -d$'\t' -f 2)" == "*" ]; then
# error "this system extension is already disabled"
continue
fi

if ! systemextensionsctl uninstall '-' "$extName"; then
error "could not disable system extension"
fi

echo -e "${GREEN}Enabled ${STRONG}${extName}${NC}"
done
}

function listLaunchItems {
local filter="$2"

itemDirectories=("${startup_dirs[@]}")
Expand Down Expand Up @@ -262,7 +362,7 @@ function listItems {
done< <(find "${itemDirectories[@]}" -type f -iname '*.plist*' -print0 2>/dev/null)
}

function enableItems {
function enableLaunchItems {
disabled_items="$(launchctl print-disabled user/"$(id -u)")"

while IFS= read -r -d '' startupFile; do
Expand Down Expand Up @@ -296,7 +396,7 @@ function enableItems {
done< <(find "${startup_dirs[@]}" "${system_dirs[@]}" \( -iname "*$1*.plist" -o -iname "*$1*.plist.disabled" \) -print0 2>/dev/null)
}

function disableItems {
function disableLaunchItems {
disabled_items="$(launchctl print-disabled user/"$(id -u)")"

while IFS= read -r -d '' startupFile; do
Expand Down Expand Up @@ -330,6 +430,10 @@ function disableItems {
done< <(find "${startup_dirs[@]}" "${system_dirs[@]}" \( -iname "*$1*.plist" -o -iname "*$1*.plist.disabled" \) -print0 2>/dev/null)
}

#
#--------------------------------------------------------------------------------------------------------------------------------------
#

if [ $# -lt 1 ] || [ $# -gt 2 ]; then
usage
fi
Expand All @@ -341,22 +445,29 @@ case "$1" in
usage
fi
fi
listItems "$1" "$2"
listLaunchItems "$1" "$2"
listKernelExtensions "$2"
listSystemExtensions "$2"
;;

"disable")
if [ $# -ne 2 ]; then
usage
fi
disableItems "$2"
disableLaunchItems "$2"
disableKernelExtensions "$2"
disableSystemExtensions "$2"
;;

"enable")
if [ $# -ne 2 ]; then
usage
fi
enableItems "$2"
enableLaunchItems "$2"
enableKernelExtensions "$2"
enableSystemExtensions "$2"
;;

*)
usage
;;
Expand Down

0 comments on commit cdc27b3

Please sign in to comment.