Files

WifiWizard.src
  • // --- GreyScript Wi-Fi Cracker & Connector From Shrimp/tails ---
  • // --- Configuration ---
  • default_wifi_device = "wlan0" // Change this if your wifi card has a different name
  • enable_debug_prints = false
  • if not params.len == 0 then
  • if params[0] == "debug" then
  • enable_debug_prints = true
  • end if
  • end if
  • // --- Helper Function for Debug Printing ---
  • debug_print = function(message)
  • if enable_debug_prints then print("[DEBUG] " + message)
  • end function
  • // --- Load Libraries ---
  • print("Loading libraries...")
  • // Load crypto library for cracking
  • crypto = include_lib("/lib/crypto.so")
  • if crypto == null then
  • print("Error: Failed to load crypto library (/lib/crypto.so). Cannot perform cracking.")
  • // Decide if you want to exit or maybe proceed to connect only if password known?
  • // For this script's purpose (cracking & connecting), we'll exit.
  • exit()
  • end if
  • print("Crypto library loaded.")
  • // --- Get Host Computer ---
  • hostComputer = get_shell.host_computer
  • if hostComputer == null then
  • print("Error: Could not get host computer object.")
  • exit()
  • end if
  • print("Host computer object obtained.")
  • // --- Select Network Device ---
  • wifi_device = default_wifi_device
  • print("Using network device: " + wifi_device)
  • // --- Scan for Networks ---
  • print("\nScanning for Wi-Fi networks on " + wifi_device + "...")
  • networks = hostComputer.wifi_networks(wifi_device)
  • if networks == null then
  • print("Error: Failed to scan for networks. Is '" + wifi_device + "' a valid Wi-Fi device?")
  • exit()
  • end if
  • if networks.len == 0 then
  • print("No Wi-Fi networks found in range.")
  • exit()
  • end if
  • // --- Display Networks and Get Selection ---
  • print("Available Networks:")
  • valid_indices = [] // Keep track of indices actually printed
  • network_details = {} // Store parsed details for later use {index: {bssid:.., essid:.., pwr:..}}
  • for index in range(0, networks.len - 1)
  • network_info = networks[index]
  • debug_print("Processing network line " + index + ": '" + network_info + "'")
  • if network_info != null and network_info != "" then
  • parsed = network_info.split(" ")
  • debug_print(" Parsed parts count: " + parsed.len)
  • if parsed.len >= 3 then
  • bssid_d = parsed[0]
  • pwr_str_original = parsed[1] // Keep original for display if needed
  • pwr_str_for_parse = pwr_str_original // Work with a copy for parsing
  • debug_print(" Initial pwr_str_for_parse: '" + pwr_str_for_parse + "' (type: " + typeof(pwr_str_for_parse) + ")")
  • // Parse ESSID carefully, handling potential spaces
  • essid_d = ""
  • if parsed.len > 2 then
  • essid_parts = network_info.split(" ") // Split into max 3 parts
  • debug_print(" network info value: " + network_info)
  • if essid_parts.len > 2 then
  • essid_d = essid_parts[2]
  • end if
  • end if
  • display_essid = essid_d
  • if essid_d == "" then display_essid = "[No ESSID/Hidden]" end if
  • debug_print(" Parsed ESSID: '" + essid_d + "'")
  • // --- EVEN MORE ROBUST Power Parsing ---
  • pwr_int = null
  • // Check 1: Is the initial power value a string?
  • if typeof(pwr_str_for_parse) == "string" then
  • debug_print(" pwr_str_for_parse is initially a string: '" + pwr_str_for_parse + "'")
  • // Check 2: Check for and remove "%"
  • // Ensure it's still a string before checking len and slicing
  • if typeof(pwr_str_for_parse) == "string" and pwr_str_for_parse.len >= 1 and pwr_str_for_parse[-1:] == "%" then
  • debug_print(" Found '%' suffix. Removing.")
  • // Ensure it's still a string before slicing
  • if typeof(pwr_str_for_parse) == "string" then
  • pwr_str_for_parse = pwr_str_for_parse[:-1]
  • debug_print(" pwr_str_for_parse after removing %: '" + pwr_str_for_parse + "'")
  • else
  • debug_print(" Cannot remove %: pwr_str_for_parse is not a string anymore.")
  • end if
  • end if
  • // Check 3: Check for and remove "dbm"
  • // Ensure it's still a string before checking len
  • if typeof(pwr_str_for_parse) == "string" and pwr_str_for_parse.len >= 3 then
  • // Ensure it's still a string before slicing and calling lower
  • if typeof(pwr_str_for_parse) == "string" then
  • pwr_lower_check = pwr_str_for_parse[-3:].lower
  • // Check type *after* calling .lower
  • if typeof(pwr_lower_check) == "string" and pwr_lower_check == "dbm" then
  • debug_print(" Found 'dbm' suffix. Removing.")
  • // Ensure it's still a string before slicing
  • if typeof(pwr_str_for_parse) == "string" then
  • pwr_str_for_parse = pwr_str_for_parse[:-3]
  • debug_print(" pwr_str_for_parse after removing dbm: '" + pwr_str_for_parse + "'")
  • else
  • debug_print(" Cannot remove dbm: pwr_str_for_parse is not a string anymore.")
  • end if
  • end if
  • else
  • debug_print(" Cannot check for dbm: pwr_str_for_parse is not a string.")
  • end if
  • end if
  • // Check 4: Attempt .to_int
  • // Ensure it's still a string before attempting conversion
  • if typeof(pwr_str_for_parse) == "string" then
  • debug_print(" Attempting .to_int on string: '" + pwr_str_for_parse + "'")
  • pwr_int = pwr_str_for_parse.to_int
  • else
  • debug_print(" Cannot attempt .to_int because pwr_str_for_parse is not a string (type: " + typeof(pwr_str_for_parse) + ")")
  • end if
  • else // Initial pwr_str_for_parse was not a string
  • debug_print(" Initial pwr_str_for_parse was not a string.")
  • print("Warning: Power value (" + pwr_str_original + ") for network " + index + " is not a string.")
  • // Attempt .to_int directly on the original value just in case it's already a number
  • if typeof(pwr_str_for_parse) == "number" then
  • pwr_int = pwr_str_for_parse
  • debug_print(" Original power value was already a number: " + pwr_int)
  • end if
  • end if
  • // Final check and default for pwr_int
  • debug_print(" Result of conversion attempt: " + pwr_int + " (type: " + typeof(pwr_int) + ")")
  • if typeof(pwr_int) != "number" then
  • if typeof(pwr_str_for_parse) == "string" then // Only warn if we expected conversion
  • print("Warning: Could not convert power '" + pwr_str_for_parse + "' to number for network " + index + ".")
  • end if
  • pwr_int = -99 // Default if parse fails or original wasn't string/number
  • end if
  • // --- END EVEN MORE ROBUST Power Parsing ---
  • // Display the original power string with suffix
  • print(index + ".) " + display_essid + " (" + bssid_d + ") Power: " + pwr_str_original)
  • valid_indices.push(index)
  • // Store the *parsed integer power*
  • network_details[index] = {"bssid": bssid_d, "essid": essid_d, "pwr": pwr_int}
  • else
  • debug_print(" Skipping line " + index + ": Not enough parts after split (" + parsed.len + ")")
  • print(index + ".) [Malformed network data]: " + network_info)
  • end if
  • end if
  • end for
  • if valid_indices.len == 0 then
  • print("No valid network data found to select from.")
  • exit()
  • end if
  • selectedIndex_str = user_input("\nEnter the number of the network to CRACK and connect to: ")
  • selectedIndex = selectedIndex_str.to_int
  • if typeof(selectedIndex) != "number" or not valid_indices.hasIndex(selectedIndex) then
  • print("Error: Invalid selection.")
  • exit()
  • end if
  • // --- Extract Target Network Details ---
  • target_details = network_details[selectedIndex]
  • target_bssid = target_details.bssid
  • target_essid = target_details.essid // This might be ""
  • target_pwr = target_details.pwr // This is now the parsed integer
  • print("\nSelected Network for Cracking:")
  • // --- MODIFIED: Changed inline conditional to if/else block ---
  • if target_essid != "" then
  • print(" ESSID: " + target_essid)
  • else
  • print(" ESSID: [No ESSID/Hidden]")
  • end if
  • // --- END MODIFICATION ---
  • print(" BSSID: " + target_bssid)
  • print(" Power (parsed): " + target_pwr) // Display the integer power used for calculation
  • // --- ADDED ERROR HANDLING for Empty ESSID ---
  • if target_essid == null or target_essid == "" then
  • print("\nError: The selected network has no ESSID (network name).")
  • print("Aireplay requires an ESSID to function.")
  • print("Cannot proceed with cracking this network.")
  • exit() // Stop the script
  • end if
  • // --- END ERROR HANDLING ---
  • // --- Cracking Process ---
  • cracked_password = null
  • monitor_mode_active = false
  • // 1. Enable Monitor Mode
  • print("\nAttempting to start monitor mode on " + wifi_device + "...")
  • airmonResult = crypto.airmon("start", wifi_device)
  • if typeof(airmonResult) == "number" and airmonResult == 1 then
  • print("Monitor mode enabled successfully.")
  • monitor_mode_active = true
  • else
  • print("Error starting monitor mode:")
  • if typeof(airmonResult) == "string" then
  • print(airmonResult)
  • else
  • print("Unknown error code.")
  • end if
  • // Cannot proceed without monitor mode
  • exit()
  • end if
  • // 2. Run Aireplay
  • print("\nStarting packet capture (aireplay)...")
  • // Calculate recommended ACKs (ensure power is valid integer)
  • potentialAcks = 10000 // Default ACKs if power is invalid
  • // Use the parsed integer power 'target_pwr'
  • if typeof(target_pwr) == "number" and target_pwr > -99 then
  • // Ensure division by zero doesn't happen if pwr = -15
  • divisor = target_pwr + 15
  • if divisor == 0 then divisor = 1 end if // Avoid division by zero
  • potentialAcks = floor(300000 / divisor)
  • if potentialAcks <= 0 then potentialAcks = 10000 end if // Ensure positive ACKs
  • end if
  • print("Attempting to capture up to " + potentialAcks + " ACKs. This may take time...")
  • print("(Press Ctrl+C to stop capture early if needed, but cracking may fail)")
  • // Determine capture file path *before* running aireplay
  • // CORRECTED: Directly use the global 'current_path' variable. Removed redundant check.
  • dir = current_path
  • if not dir[-1:] == "/" then dir = dir + "/" end if // Ensure trailing slash
  • capture_file_path = dir + "file.cap"
  • print("Capture file expected at: " + capture_file_path)
  • // Directly call aireplay (ESSID is now guaranteed non-empty)
  • debug_print("Calling aireplay with: BSSID='" + target_bssid + "', ESSID='" + target_essid + "', ACKs=" + potentialAcks)
  • aireplayResult = crypto.aireplay(target_bssid, target_essid, potentialAcks)
  • // MOVED: Wait call added here
  • print("Aireplay finished or skipped. Waiting 3 seconds before proceeding...")
  • wait(3) // Pause execution for 3 seconds AFTER aireplay attempt
  • // Check result *after* the call
  • if typeof(aireplayResult) == "string" then
  • print("Error during aireplay step: " + aireplayResult)
  • // Attempt cleanup before exiting
  • if monitor_mode_active then
  • crypto.airmon("stop", wifi_device)
  • end if
  • exit()
  • else if aireplayResult == null then
  • print("Aireplay command finished or was stopped without returning an error string.")
  • else
  • print("Warning: Unexpected result type from aireplay: " + typeof(aireplayResult))
  • print("Result value: " + aireplayResult)
  • end if
  • // 3. Run Aircrack
  • print("\nAttempting to crack password (aircrack)...")
  • // Check if capture file exists first using the determined path
  • // Assumption: file_exists function exists
  • // CORRECTED: Simplified check as capture_file_path should always be set now.
  • debug_print("Checking for capture file: '" + capture_file_path + "'")
  • capture = hostComputer.File(capture_file_path)
  • debug_print("Checking for capture file: '" + capture + "'")
  • debug_print("Checking for capture file: '" + capture.size + "'")
  • if capture.size == null then
  • print("Error: Capture file '" + capture_file_path + "' not found after aireplay.")
  • print("Make sure you are running this script from the directory where aireplay saves the file, or check permissions.")
  • print("Cracking aborted.")
  • else
  • print("Capture file found at '" + capture_file_path + "'. Running aircrack...")
  • debug_print("Calling aircrack with path: '" + capture_file_path + "'")
  • cracked_password = crypto.aircrack(capture_file_path) // Use the full path
  • if cracked_password == null then
  • print("Password cracking failed. Insufficient data or password not found.")
  • else
  • print("Success! Password likely found.")
  • debug_print("Cracked password result (type " + typeof(cracked_password) + "): " + cracked_password) // Careful printing this even in debug
  • end if
  • end if
  • // 4. Disable Monitor Mode (Cleanup)
  • if monitor_mode_active then
  • print("\nStopping monitor mode...")
  • stopResult = crypto.airmon("stop", wifi_device)
  • if typeof(stopResult) != "number" or stopResult != 1 then
  • print("Warning: Failed to stop monitor mode.")
  • else
  • print("Monitor mode stopped.")
  • end if
  • monitor_mode_active = false // Update flag
  • end if
  • // --- Attempt Connection (if password was cracked) ---
  • print("\n--------------------")
  • if cracked_password != null then
  • print("Attempting to connect using cracked password...")
  • debug_print("Calling connect_wifi with: device='" + wifi_device + "', BSSID='" + target_bssid + "', ESSID='" + target_essid + "', password=***")
  • connectionResult = hostComputer.connect_wifi(wifi_device, target_bssid, target_essid, cracked_password)
  • // Report Connection Result
  • if typeof(connectionResult) == "number" and connectionResult == 1 then
  • print("Success! Connected to '" + target_essid + " password: " + cracked_password + "'.")
  • if hostComputer.is_network_active then
  • print("Internet connection is active.")
  • else
  • print("Warning: Connected to Wi-Fi, but internet access might not be active yet.")
  • end if
  • else if typeof(connectionResult) == "string" then
  • print("Error connecting to '" + target_essid + "' using cracked password:")
  • print(connectionResult)
  • else if connectionResult == null then
  • print("Error: Connection function failed due to invalid parameters (check types).")
  • else
  • print("Unknown connection result: " + connectionResult)
  • end if
  • else
  • print("Password cracking failed or was skipped. Cannot attempt connection.")
  • end if
  • print("--------------------")
  • print("Script finished.")