diff --git a/fluxion b/fluxion index cd71421..d25116c 100755 --- a/fluxion +++ b/fluxion @@ -811,8 +811,201 @@ function fluxion_get_interface() { } +# ============== < 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. +function fluxion_get_target_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 operation 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) + readarray FLUXIONTargetCandidates < <(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 FLUXIONTargetCandidatesClients < <(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 [ ${#FLUXIONTargetCandidates[@]} -eq 0 ]; then + echo -e "$FLUXIONVLine $FLUXIONScannerDetectedNothingNotice" + sleep 3 + return 4 + fi +} +function fluxion_get_target() { + # Assure a valid wireless interface for scanning was given. + if [ ! "$1" ] || ! interface_is_wireless "$1"; then return 1; fi + + 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_get_target_candidates $interface "" "bg";; + + "$FLUXIONScannerChannelOptionAll (5GHz)") + fluxion_get_target_candidates $interface "" "a";; + + "$FLUXIONScannerChannelOptionAll (2.4GHz & 5Ghz)") + fluxion_get_target_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_get_target_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 "${candidates[@]}"; 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 "${candidatesClients[@]}" | 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. + # Just 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, so I gotta work around it... + # The function is 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 + + FLUXIONGetTargetMAC=${IOQueryFormatFields[7]} + FLUXIONGetTargetSSID=${IOQueryFormatFields[1]} + FLUXIONGetTargetChannel=${IOQueryFormatFields[5]} + + FLUXIONGetTargetEncryption=${IOQueryFormatFields[6]} + + FLUXIONGetTargetMakerID=${APTargetMAC:0:8} + FLUXIONGetTargetMaker=$( + macchanger -l | grep ${FLUXIONGetTargetMakerID,,} | cut -d ' ' -f 5- + ) + + # 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 '_' + FLUXIONGetTargetSSIDClean=$( + echo "$FLUXIONGetTargetSSID" | 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 -r rogueMACHex=$(printf %02X $((0x${APTargetMAC:13:1} + 1))) + FLUXIONGetTargetRogueMAC="${FLUXIONGetTargetMAC::13}${rogueMACHex:1:1}${FLUXIONGetTargetRogueMAC:14:4}" +}