// --- 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.")