Housekeeping (#7)

* fix LED killing

* do not autostart unneeded services

ntp: we don't want to leak in attack mode and arming mode doesn't even
have internet.  user's who want this can start it themselves
dnsmasq: we should start this when needed rather than killing it when
not needed, speed boot by not starting then killing

* NETMODE: use dnsmasq

netmode was improperly calling odhcpd when we use dnsmasq, just call
dnsmasq

* start dnsmasq when needed

have shark service start dnsmasq in arming mode and stop it in attack
and off mode

* randomize mac with macchanger

currently mac is randomized because it is unable to read the actual mac.
If there gets fixed then the mac won't be randomized.  Let's
intentionally randomize the mac to be sure we are random enough

* ensure netmode dhcp_server provides default gateway

* prototype out switching between gateway and no gateway

* actually disable gateway in arming mode

* disable openvpn

I don't know why this is trying to start, but let's not

* better LED anti-suicide

* permissions count

* execute_payload: fix shellcheck warnings

* convert BATTERY to posix

runtime cut from 0.051s to 0.021s on average

* shellcheck cleanup

simplify script while doing it, use faster sh instead of bash

* DO_A_BARREL_ROOL: this was posix anyway, so use posix

* execute_payload: mostly posix, consider refactor

* cleanup LED a bit

partially elminate bashisms when possible to do cleanly
shellcheck fixes for anti-hari kari (and it's faster)

* POSIX NETMODE

this was already posix except for function definitions

* POSIX shark_framework

fix minor logic error and posixify

* shark_framework: save an awk

* SWITCH: posix

* LED: fix logic for SC2015 warnings

* move wait_for_link and add wait_for_no_link

a few additional fixes based on testing

* fix macchanger and wait_for_link

* remove unneeded note

* This is where you change the mac address

* We do not need network in off mode, no services anyway

* ensure no dhcp during attack mode until requested

* bash or python, but not php

* The function is simple enough to not need a comment --Foxtrot
dev
Zero_Chaos 2020-01-23 21:44:17 -05:00 committed by Marc
parent 6cb3073db3
commit 5aa0ef7c56
9 changed files with 205 additions and 132 deletions

View File

@ -26,6 +26,18 @@ echo $(uci get system.@system[0].hostname) > /proc/sys/kernel/hostname
/etc/init.d/odhcpd disable
/etc/init.d/odhcpd stop
# Disable dnsmasq (controlled by shark service or NETMODE)
/etc/init.d/dnsmasq disable
/etc/init.d/dnsmasq stop
# Disable ntpd
/etc/init.d/sysntpd disable
/etc/init.d/sysntpd stop
# Disable openvpn
/etc/init.d/openvpn disable
/etc/init.d/openvpn stop
# Disable uHTTPd web server
/etc/init.d/uhttpd disable
/etc/init.d/uhttpd stop

View File

@ -1,25 +1,25 @@
#!/bin/bash
#!/bin/sh
function setup() {
echo $1 > /sys/class/gpio/export 2>/dev/null
echo in > /sys/class/gpio/gpio$1/direction 2>/dev/null
setup() {
echo "${1}" > /sys/class/gpio/export 2>/dev/null
echo in > "/sys/class/gpio/gpio${1}/direction" 2>/dev/null
}
function check_gpio() {
if [ ! -d /sys/class/gpio/gpio$1 ]; then
setup $1
check_gpio() {
if [ ! -d "/sys/class/gpio/gpio${1}" ]; then
setup "${1}"
fi
state=$(cat /sys/class/gpio/gpio$1/value)
echo $state
state=$(cat "/sys/class/gpio/gpio${1}/value")
echo "${state}"
}
gpio40=$(check_gpio 40)
gpio41=$(check_gpio 41)
if [ $gpio40 -eq "0" ] && [ $gpio41 -eq "0" ]; then
if [ "${gpio40}" -eq "0" ] && [ "${gpio41}" -eq "0" ]; then
echo "discharging"
elif [ $gpio40 -eq "0" ]; then
elif [ "${gpio40}" -eq "0" ]; then
echo "full"
elif [ $gpio41 -eq "0" ]; then
elif [ "${gpio41}" -eq "0" ]; then
echo "charging"
fi

View File

@ -1,2 +1,18 @@
#!/bin/bash
while true;do LED R;LED Y;LED G;LED C;LED B;LED M;done > /dev/null 2>&1 &
#!/bin/sh
roll() {
while true; do
LED R
LED Y
LED G
LED C
LED B
LED M
done
}
if pgrep -f DO_A_BARREL_ROLL | grep -qvE "$$|${PPID}"; then
kill "$(pgrep -f DO_A_BARREL_ROLL | grep -vE "$$|${PPID}" | tr '\n' ' ')" > /dev/null 2>&1
fi
roll > /dev/null 2>&1 &

View File

@ -8,7 +8,11 @@ colors=(0 0 0)
pattern=(1 0 0 0 0 0)
function convert() {
echo $([[ $1 -lt 20 ]] && echo 0.02 || echo $1 1000 | awk '{ print $1/$2 }')
if [ "${1}" -lt 20 ]; then
echo 0.02
else
echo "${1}" 1000 | awk '{ print $1/$2 }'
fi
}
function parse_color() {
@ -42,7 +46,7 @@ function parse_color() {
function parse_pattern() {
local INVERTED="0"
[[ "$(echo $1 | head -c1)" == "I" ]] && {
[[ "$(echo ${1} | head -c1)" == "I" ]] && {
INVERTED="1"
}
case $1 in
@ -99,7 +103,7 @@ function parse_state() {
"FAIL" | FAIL[1-3])
parse_color "R"
parse_pattern "SLOW"
pattern[3]=$(convert $(echo -n 1000 | head -c $((5-$STATENUM))))
pattern[3]=$(convert "$(echo -n 1000 | head -c $((5-STATENUM)))")
;;
"ATTACK" | STAGE[1-5])
parse_color "Y"
@ -135,39 +139,47 @@ function clear_led() {
}
function light_led() {
echo ${colors[0]} > $RED_LED 2>&1
echo ${colors[1]} > $GREEN_LED 2>&1
echo ${colors[2]} > $BLUE_LED 2>&1
echo "${colors[0]}" > $RED_LED 2>&1
echo "${colors[1]}" > $GREEN_LED 2>&1
echo "${colors[2]}" > $BLUE_LED 2>&1
}
function blink_loop() {
local sc=1
until [[ "$sc" == "10" ]]; do
for i in $(seq 1 ${pattern[2]}); do
[[ "${pattern[1]}" == "0" ]] && light_led || clear_led
sleep ${pattern[3]}
[[ "${pattern[1]}" == "0" ]] && clear_led || light_led
sleep ${pattern[3]}
if [ "${pattern[1]}" == "0" ];then
light_led
else
clear_led
fi
sleep "${pattern[3]}"
if [ "${pattern[1]}" == "0" ];then
clear_led
else
light_led
fi
sleep "${pattern[3]}"
done
sleep ${pattern[4]}
sleep "${pattern[4]}"
[[ "${pattern[5]}" == "0" ]] && sc=$((sc+1))
done
[[ "${pattern[5]}" == "0" ]] && light_led
}
function run_led() {
parse_state $1 || {
parse_color $1 || return 1
[[ "$#" == "2" ]] && parse_pattern $2
parse_state "${1}" || {
parse_color "${1}" || return 1
[[ "$#" == "2" ]] && parse_pattern "${2}"
}
[[ "${pattern[0]}" == "1" ]] && {
if [ "${pattern[0]}" == "1" ];then
light_led &
return 0
} || {
else
blink_loop &
return 0
}
fi
return 1
}
@ -243,5 +255,12 @@ Examples:
EOF
}
pkill -9 LED &> /dev/null
run_led $@ || show_usage
#so pgrep/pkill exclude their own pid, but not their parent
#the parent is this script, which we don't want to kill
if pgrep -f LED | grep -qvE "$$|${PPID}"; then
kill "$(pgrep -f LED | grep -vE "$$|${PPID}" | tr '\n' ' ')" > /dev/null 2>&1
fi
if pgrep -f DO_A_BARREL_ROLL | grep -qvE "$$|${PPID}"; then
kill "$(pgrep -f DO_A_BARREL_ROLL | grep -vE "$$|${PPID}" | tr '\n' ' ')" > /dev/null 2>&1
fi
run_led "$@" || show_usage

View File

@ -1,34 +1,37 @@
#!/bin/bash
#!/bin/sh
function show_usage() {
show_usage() {
echo "Usage: $0 [DHCP_CLIENT|DHCP_SERVER|AUTO]"
echo ""
}
function shut_it_all_down() {
#we are restarting, possibly with new config, or reversing dhcp roles
#kill 'em all, let the user sort them out
/etc/init.d/odhcpd stop
pkill -9 dnsmasq #odhcpd starts dnsmasq but fails to stop it
shut_it_all_down() {
/etc/init.d/dnsmasq stop
pkill -9 dnsmasq #just in case
pkill -9 udhcpc #this is the observed dhcp client
pkill -9 odhcpcd #just in case
}
function configure_client() {
configure_dhcp_client() {
shut_it_all_down
uci set network.lan.proto='dhcp'
}
function configure_server() {
configure_dhcp_server() {
shut_it_all_down
uci set network.lan.proto='static'
uci set network.lan.ipaddr='172.16.24.1'
uci set network.lan.netmask='255.255.255.0'
uci set network.lan.ip6assign='60'
/etc/init.d/odhcpd start
#remove old dhcp options before setting new
uci -q delete dhcp.lan.dhcp_option
uci add_list dhcp.lan.dhcp_option="3,172.16.24.1"
#disables gateway
#uci add_list dhcp.lan.dhcp_option="3"
/etc/init.d/dnsmasq start
}
function blink() {
blink() {
count 3
while [ "${count}" -gt 0 ]; do
LED "${1}"
@ -41,10 +44,10 @@ function blink() {
case $1 in
"DHCP_CLIENT")
configure_client
configure_dhcp_client
;;
"DHCP_SERVER")
configure_server
configure_dhcp_server
;;
"AUTO")
#make sure nothing interferes
@ -54,10 +57,10 @@ case $1 in
if echo "${sniffed}" | grep -q 'DHCP-Message Option 53, length 1: Discover' && \
! echo "${sniffed}" | grep -q 'DHCP-Message Option 53, length 1: Request'; then
#we saw a dhcp discover but no dhcp request, so someone wants a dhcp server and didn't find one
configure_server
configure_dhcp_server
echo 'blink SETUP Y' | at now
else
configure_client
configure_dhcp_client
echo 'blink SETUP W' | at now
fi
;;

View File

@ -1,11 +1,11 @@
#!/bin/bash
#!/bin/sh
function setup() {
setup() {
echo "${1}" > /sys/class/gpio/export
echo in > "/sys/class/gpio/gpio${1}/direction"
}
function check_gpio() {
check_gpio() {
if [ ! -d "/sys/class/gpio/gpio${1}" ]; then
setup "${1}"
fi

View File

@ -1,12 +1,6 @@
#!/bin/bash
# List of directories to clean
DIRS=(
~/.ssh
/root/loot
)
#!/bin/sh
# Clean up each directory
for d in ${DIRS[@]}; do
[[ -d $d ]] && rm -rf $d
for d in "${HOME}/.ssh" "/root/loot"; do
[ -d "${d}" ] && rm -rf "${d}"
done

55
usr/bin/execute_payload Normal file → Executable file
View File

@ -1,34 +1,51 @@
#!/bin/bash
LOG="logger -t Shark [*]"
$LOG "Executing PAYLOAD"
$LOG "Prepping PAYLOAD environment"
if [ ! -d /root/loot ]; then
mkdir -p /root/loot;
fi
wait_for_link() {
LED SETUP
until swconfig dev switch0 port 0 get link | grep -q 'link:up'; do
sleep 1
done
LED LINKSETUP
}
wait_for_no_link() {
LED LINKSETUP
until swconfig dev switch0 port 0 get link | grep -q 'link:down'; do
sleep 1
done
LED SETUP
}
payload_path="/root/payload"
payload=$(ls $payload_path/payload* 2>/dev/null | tail -n1)
payload=$(find "${payload_path}"/payload* 2>/dev/null | tail -n1)
extension_path="/root/payload/extensions/"
if [ -d "${extension_path}" ] && [ -n "$(ls -A ${extension_path})" ]; then
for extension in ${extension_path}*; do
source "${extension}"
done
eval "$(declare -F | sed -e 's/-f /-fx /')"
for extension in "${extension_path}"*; do
# shellcheck source=/dev/null
. "${extension}"
done
#declare is the only non-posix, and likely isn't needed
eval "$(declare -F | sed -e 's/-f /-fx /')"
fi
wait_for_link
$LOG "Running requested PAYLOAD"
case $(basename "${payload}") in
"payload.py")
python "${payload}" &> /dev/null
;;
"payload.php")
php-cli "${payload}" &> /dev/null
;;
"payload" | "payload.sh" | "payload.txt")
sed -i 's/\r//g' $payload
bash -C "${payload}" &> /dev/null
;;
*)
/usr/bin/LED FAIL
;;
"payload.py")
python "${payload}" > /dev/null 2>&1
;;
"payload" | "payload.sh" | "payload.txt")
sed -i 's/\r//g' "${payload}"
bash -C "${payload}" > /dev/null 2>&1
;;
*)
/usr/bin/LED FAIL
;;
esac

View File

@ -1,12 +1,12 @@
#!/bin/bash
#!/bin/sh
LOG="logger -t Shark [*]"
LOG_ERR="logger -t Shark -p 3 [!]"
export LOG="logger -t Shark [*]"
export LOG_ERR="logger -t Shark -p 3 [!]"
MODE="OFF"
SWITCH_POSITION=$(/usr/bin/SWITCH)
function upgrade_leds() {
upgrade_leds() {
/usr/bin/LED OFF
while true
do
@ -22,16 +22,16 @@ function upgrade_leds() {
# $1: Upgrade file
# $2: MD5 file
# $3: Upgrade file size in bytes
function extract_md5() {
dd if=$1 of=$2 skip=$3 bs=1 count=33
extract_md5() {
dd if="${1}" of="${2}" skip="${3}" bs=1 count=33
}
# $1: Upgrade file
# $2: MD5 file
function verify_md5() {
expected=$(cat $2)
checksum=$(md5sum $1 | awk '{print $1}')
[[ $expected = $checksum ]] && {
verify_md5() {
expected=$(cat "${2}")
checksum=$(md5sum "${1}" | awk '{print $1}')
[ "${expected}" = "${checksum}" ] && {
return 0
}
return 1
@ -39,50 +39,50 @@ function verify_md5() {
# $1: Upgrade file
# $2: Upgrade file size in bytes
function truncate_upgrade() {
dd if=/dev/null of=$1 bs=1 seek=$2
truncate_upgrade() {
dd if=/dev/null of="${1}" bs=1 seek="${2}"
}
function execute_upgrade() {
execute_upgrade() {
# Check for upgrade file in default location
$LOG "Checking for firmware upgrade"
upgrade_file=$(ls /root/upgrade-*.bin 2>/dev/null | tail -n1)
upgrade_file=$(find /root/upgrade-*.bin -type f 2>/dev/null | tail -n1)
[[ -f $upgrade_file ]] && {
if [ -f "${upgrade_file}" ]; then
# Upgrade file found
$LOG "Firmware upgrade found"
$LOG "Verifying firmware upgrade"
upgrade_file_size=$(( $(ls -l $upgrade_file | awk '{print $5}') - 33 ))
upgrade_file_size=$(( $(wc -c "${upgrade_file}") - 33 ))
# Extract md5sum from upgrade file
extract_md5 $upgrade_file /tmp/upgrade.md5 $upgrade_file_size
extract_md5 "${upgrade_file}" /tmp/upgrade.md5 "${upgrade_file_size}"
cp $upgrade_file /tmp/upgrade.bin
truncate_upgrade /tmp/upgrade.bin $upgrade_file_size
cp "${upgrade_file}" /tmp/upgrade.bin
truncate_upgrade /tmp/upgrade.bin "${upgrade_file_size}"
# Verify upgrade file
verify_md5 /tmp/upgrade.bin /tmp/upgrade.md5 || {
if ! verify_md5 /tmp/upgrade.bin /tmp/upgrade.md5; then
# Upgrade file not verified; exit
$LOG "Firmware upgrade not verified. File may be corrupt"
LED FAIL &
return 1
}
fi
$LOG "Firmware upgrade verified"
LED OFF && LED SUCCESS
# Check battery state first
$LOG "Checking device power state"
battery_state=$(/usr/bin/BATTERY)
[[ $battery_state = "discharging" ]] && {
if [ "${battery_state}" = "discharging" ]; then
# Device is not plugged in
$LOG "Device is not powered. Do not attempt firmware upgrade"
return 1
}
fi
$LOG "Device is powered"
# Remove upgrade file
rm -rf $upgrade_file
rm -rf "${upgrade_file}"
sync
# Upgrade file verified; run upgrade
@ -91,88 +91,99 @@ function execute_upgrade() {
echo "sysupgrade -n /tmp/upgrade.bin" | at now
exit
} || {
else
# Upgrade file not found; enter arming mode
$LOG "Firmware upgrade not found"
return 1
}
fi
}
function wait_for_link() {
LED LINKSETUP
until swconfig dev switch0 port 0 get link | grep -q 'link:up'; do
sleep 1
done
LED SETUP
}
function configure_network() {
configure_network() {
cp "/usr/lib/hak5/shark/config/${SWITCH_POSITION}/network" /etc/config/network
/etc/init.d/network restart
}
function start_http() {
start_http() {
/etc/init.d/uhttpd start
}
function stop_http() {
stop_http() {
/etc/init.d/uhttpd stop
}
function start_ssh() {
start_ssh() {
/etc/init.d/sshd start
}
function stop_ssh() {
stop_ssh() {
/etc/init.d/sshd stop
}
function enter_attack_mode() {
start_dnsmasq() {
#remove old dhcp options before setting new
uci -q delete dhcp.lan.dhcp_option
#disables gateway, netmode re-enables it
uci add_list dhcp.lan.dhcp_option="3"
uci commit
/etc/init.d/dnsmasq start
}
stop_dnsmasq() {
/etc/init.d/dnsmasq stop
}
enter_attack_mode() {
$LOG "Entering ATTACK mode"
MODE="ATTACK"
/usr/bin/LED OFF
stop_dnsmasq
ip link set eth0 down
macchanger -r eth0
configure_network
#nothing starts this, but ensure it only runs with
pkill -9 udhcpc
stop_http
stop_ssh
wait_for_link
echo "execute_payload" | at now
enter_idle_mode
}
function enter_arming_mode() {
enter_arming_mode() {
$LOG "Entering ARMING mode"
MODE="ARMING"
/usr/bin/LED OFF
configure_network
start_dnsmasq
start_http
start_ssh
enter_idle_mode
}
function enter_off_mode() {
enter_off_mode() {
$LOG "Entering OFF mode"
MODE="OFF"
/usr/bin/LED OFF
/etc/init.d/network stop
stop_dnsmasq
stop_http
stop_ssh
enter_idle_mode
}
function enter_idle_mode() {
enter_idle_mode() {
$LOG "Entering IDLE mode"
while true
do
if [[ $MODE = "ARMING" ]] || [[ $MODE = "OFF" ]]; then
if [ "${MODE}" = "ARMING" ] || [ "${MODE}" = "OFF" ]; then
#ARMING mode is basically always idle which means this overrides user LED
#status once per second. Don't override user status with idle status.
#pgrep LED > /dev/null || /usr/bin/LED whatever
BATTERY_STATE=$(/usr/bin/BATTERY)
case $BATTERY_STATE in
"charging")
@ -183,8 +194,9 @@ function enter_idle_mode() {
;;
*)
pgrep LED > /dev/null || /usr/bin/LED Y SLOW
if [[ $MODE = "OFF" ]]; then
sleep 2 && halt
if [ "${MODE}" = "OFF" ]; then
sleep 2
halt
fi
;;
esac
@ -193,17 +205,17 @@ function enter_idle_mode() {
SWITCH_POSITION=$(/usr/bin/SWITCH)
case $SWITCH_POSITION in
"switch3")
if [[ $MODE != "ATTACK" ]]; then
if [ "${MODE}" != "ATTACK" ]; then
enter_attack_mode
fi
;;
"switch2")
if [[ $MODE != "ARMING" ]]; then
if [ "${MODE}" != "ARMING" ]; then
execute_upgrade || enter_arming_mode
fi
;;
*)
if [[ $MODE != "OFF" ]]; then
if [ "${MODE}" != "OFF" ]; then
enter_off_mode
fi
;;
@ -213,7 +225,7 @@ function enter_idle_mode() {
}
function run() {
run() {
case $SWITCH_POSITION in
"switch3")
enter_attack_mode
@ -230,4 +242,4 @@ function run() {
# Start framework after a short wait
sleep 2
run &> /dev/null &
run > /dev/null 2>&1 &