diff --git a/CHANGELOG.md b/CHANGELOG.md index 56c8e26d0..68e50e9cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ ### 11.30 + - Added Multi-instance support to launch more than one airgeddon at a time - Improvements on 5Ghz country code check and 5Ghz band capability detection on adapters - Fixed bug to avoid set advanced captive portal on second time if is not desired after setting it previously - Now channel is automatically updated on control window during "DoS pursuit mode" for all Evil Twin attacks diff --git a/airgeddon.sh b/airgeddon.sh index 86aa87408..d0f10cf4d 100755 --- a/airgeddon.sh +++ b/airgeddon.sh @@ -141,9 +141,10 @@ standardpmkid_filename="pmkid_hash.txt" standardpmkidcap_filename="pmkid.cap" timeout_capture_handshake="20" timeout_capture_pmkid="25" -tmpdir="/tmp/" osversionfile_dir="/etc/" plugins_dir="plugins/" +ag_orchestrator_file="ag.orchestrator.txt" +system_tmpdir="/tmp/" minimum_bash_version_required="4.2" resume_message=224 abort_question=12 @@ -238,27 +239,12 @@ mail="v1s1t0r.1s.h3r3@gmail.com" author="v1s1t0r" #Dhcpd, Hostapd and misc Evil Twin vars -ip_range="192.169.1.0" -alt_ip_range="192.167.1.0" -router_ip="192.169.1.1" -alt_router_ip="192.167.1.1" -broadcast_ip="192.169.1.255" -alt_broadcast_ip="192.167.1.255" -range_start="192.169.1.33" -range_stop="192.169.1.100" -alt_range_start="192.167.1.33" -alt_range_stop="192.167.1.100" -std_c_mask="255.255.255.0" -ip_mask="255.255.255.255" -std_c_mask_cidr="24" -ip_mask_cidr="32" -any_mask_cidr="0" -any_ip="0.0.0.0" -any_ipv6="::/0" loopback_ip="127.0.0.1" loopback_ipv6="::1/128" +loopback_interface="lo" routing_tmp_file="ag.iptables_nftables" dhcpd_file="ag.dhcpd.conf" +dhcpd_pid_file="dhcpd.pid" dnsmasq_file="ag.dnsmasq.conf" internet_dns1="8.8.8.8" internet_dns2="8.8.4.4" @@ -397,6 +383,7 @@ crunch_symbolcharset="!#$%/=?{}[]-*:;" hashcat_charsets=("?l" "?u" "?d" "?s") #Tmux vars +airgeddon_uid="" session_name="airgeddon" tmux_main_window="airgeddon-Main" no_hardcore_exit=0 @@ -702,6 +689,7 @@ function debug_print() { "check_pending_of_translation" "clean_env_vars" "contains_element" + "create_instance_orchestrator_file" "create_rcfile" "echo_blue" "echo_brown" @@ -719,7 +707,9 @@ function debug_print() { "flying_saucer" "generate_dynamic_line" "initialize_colors" + "initialize_instance_settings" "initialize_script_settings" + "instance_setter" "interrupt_checkpoint" "language_strings" "last_echo" @@ -728,6 +718,7 @@ function debug_print() { "print_large_separator" "print_simple_separator" "read_yesno" + "register_instance_pid" "remove_warnings" "set_script_paths" "special_text_missed_optional_tool" @@ -1039,7 +1030,6 @@ function wash_json_scan() { debug_print - tmpfiles_toclean=1 rm -rf "${tmpdir}wps_json_data.txt" > /dev/null 2>&1 rm -rf "${tmpdir}wps_fifo" > /dev/null 2>&1 @@ -1320,7 +1310,7 @@ function check_busy_ports() { if [[ -n "${tcp_ports[*]}" ]] && [[ "${#tcp_ports[@]}" -ge 1 ]]; then port_type="tcp" for tcp_port in "${tcp_ports[@]}"; do - if ! check_tcp_udp_port "${tcp_port}" "${port_type}"; then + if ! check_tcp_udp_port "${tcp_port}" "${port_type}" "${interface}"; then busy_port="${tcp_port}" find_process_name_by_port "${tcp_port}" "${port_type}" echo @@ -1334,7 +1324,7 @@ function check_busy_ports() { if [[ -n "${udp_ports[*]}" ]] && [[ "${#udp_ports[@]}" -ge 1 ]]; then port_type="udp" for udp_port in "${udp_ports[@]}"; do - if ! check_tcp_udp_port "${udp_port}" "${port_type}"; then + if ! check_tcp_udp_port "${udp_port}" "${port_type}" "${interface}"; then busy_port="${udp_port}" find_process_name_by_port "${udp_port}" "${port_type}" echo @@ -1348,7 +1338,7 @@ function check_busy_ports() { return 0 } -#Validate if a given tcp/udp port is busy +#Validate if a given tcp/udp port is busy on the given interface #shellcheck disable=SC2207 function check_tcp_udp_port() { @@ -1359,14 +1349,27 @@ function check_tcp_udp_port() { port=$(printf "%04x" "${1}") port_type="${2}" - declare -a busy_ports=($(grep -v "local_address" --no-filename "/proc/net/${port_type}" "/proc/net/${port_type}6" | awk '{print $2$4}' | cut -d ":" -f 2 | sort -u)) + local network_interface + local ip_address + local hex_ip_address + network_interface="${3}" + ip_address=$(ip -4 -o addr show "${network_interface}" 2> /dev/null | awk '{print $4}' | cut -d "/" -f 1) + + if [ -n "${ip_address}" ]; then + hex_ip_address=$(ip_dec_to_hex "${ip_address}") + else + hex_ip_address="" + fi + + declare -a busy_ports=($(awk -v iplist="${hex_ip_address},00000000" 'BEGIN {split(iplist,a,","); for (i in a) ips[a[i]]} /local_address/ {next} {split($2,a,":"); if (a[1] in ips) ports[a[2] $4]} END {for (port in ports) print port}' "/proc/net/${port_type}" "/proc/net/${port_type}6")) + for hexport in "${busy_ports[@]}"; do if [[ "${port_type}" == "tcp" || "${port_type}" == "tcp6" ]]; then if [ "${hexport}" = "${port}0A" ]; then return 1 fi else - if [ "${hexport}" = "${port}07" ]; then + if [[ "${hexport}" = "${port}07" ]] && [[ "${port}" != "0043" ]]; then return 1 fi fi @@ -1396,6 +1399,22 @@ function find_process_name_by_port() { blocking_process_name=$(ss -tupln | grep -oP "${regexp}") } +#Convert an IP address from decimal to hexdecimal returning its value +ip_dec_to_hex() { + + debug_print + + IFS='.' read -r -a octets <<< "${1}" + + local hex + hex="" + for octet in "${octets[@]}"; do + hex="$(printf "%02X%s" "${octet}" "${hex}")" + done + + echo "${hex}" +} + #Validate if a wireless card is supporting VIF (Virtual Interface) function check_vif_support() { @@ -1539,7 +1558,7 @@ function prepare_et_interface() { fi } -#Restore the state of the interfaces after Evil Twin or Enterprise process +#Restore the state of the interfaces after Evil Twin or Enterprise attack process function restore_et_interface() { debug_print @@ -1553,6 +1572,9 @@ function restore_et_interface() { iw dev "${iface_monitor_et_deauth}" del > /dev/null 2>&1 + ip addr del ${et_ip_router}/${std_c_mask} dev "${interface}" > /dev/null 2>&1 + ip route del ${et_ip_range}/${std_c_mask_cidr} dev "${interface}" table local proto static scope link > /dev/null 2>&1 + if [ "${et_initial_state}" = "Managed" ]; then set_mode_without_airmon "${interface}" "managed" ifacemode="Managed" @@ -1583,6 +1605,8 @@ function restore_et_interface() { fi fi fi + + control_routing_status "end" } #Unblock if possible the interface if blocked @@ -2672,7 +2696,7 @@ function select_secondary_interface() { return_to_et_main_menu_from_beef=1 fi return 1 - elif [[ ! ${secondary_iface} =~ ^[[:digit:]]+$ ]] || (( secondary_iface < 1 || secondary_iface > option_counter )); then + elif [[ ! ${secondary_iface} =~ ^[[:digit:]]+$ ]] || ((secondary_iface < 1 || secondary_iface > option_counter)); then if [ "${1}" = "dos_pursuit_mode" ]; then invalid_secondary_iface_selected "dos_pursuit_mode" else @@ -2747,7 +2771,7 @@ function select_interface() { print_hint ${current_menu} read -rp "> " iface - if [[ ! ${iface} =~ ^[[:digit:]]+$ ]] || (( iface < 1 || iface > option_counter )); then + if [[ ! ${iface} =~ ^[[:digit:]]+$ ]] || ((iface < 1 || iface > option_counter)); then invalid_iface_selected else option_counter2=0 @@ -3165,7 +3189,6 @@ function create_certificates_config_files() { debug_print - tmpfiles_toclean=1 rm -rf "${tmpdir}${certsdir}" > /dev/null 2>&1 mkdir "${tmpdir}${certsdir}" > /dev/null 2>&1 @@ -3573,8 +3596,6 @@ function prepare_wep_attack() { debug_print - tmpfiles_toclean=1 - rm -rf "${tmpdir}${wep_attack_file}" > /dev/null 2>&1 rm -rf "${tmpdir}${wep_key_handler}" > /dev/null 2>&1 rm -rf "${tmpdir}${wep_data}"* > /dev/null 2>&1 @@ -3622,6 +3643,7 @@ function set_wep_key_script() { ;; esac } + function start_tmux_processes() { window_name="\${1}" @@ -3721,6 +3743,7 @@ function set_wep_key_script() { if [ "${AIRGEDDON_WINDOWS_HANDLING}" = "tmux" ]; then cat >&8 <<-EOF + #Function to kill tmux windows using window name function kill_tmux_windows() { local TMUX_WINDOWS_LIST=() @@ -3870,6 +3893,7 @@ function set_wep_script() { ;; esac } + function start_tmux_processes() { window_name="\${1}" @@ -3892,6 +3916,8 @@ function set_wep_script() { tmux setw -t "\${window_name}" window-style "\${tmux_color_cmd}" tmux send-keys -t "${session_name}:\${window_name}" "\${command_line}" ENTER } + + #Function to capture PID of a process started inside tmux and setting it to a global variable function get_tmux_process_id() { local process_pid @@ -3902,6 +3928,8 @@ function set_wep_script() { done global_process_pid="\${process_pid}" } + + #Function to kill tmux windows using window name function kill_tmux_window_by_name() { if [ "\${AIRGEDDON_WINDOWS_HANDLING}" = "tmux" ]; then tmux kill-window -t "${session_name}:\${1}" 2> /dev/null @@ -4635,7 +4663,6 @@ function exec_mdkdeauth() { language_strings "${language}" 89 "title" language_strings "${language}" 32 "green" - tmpfiles_toclean=1 rm -rf "${tmpdir}bl.txt" > /dev/null 2>&1 echo "${bssid}" > "${tmpdir}bl.txt" @@ -4667,8 +4694,6 @@ function exec_aireplaydeauth() { language_strings "${language}" 90 "title" language_strings "${language}" 32 "green" - tmpfiles_toclean=1 - echo if [ "${dos_pursuit_mode}" -eq 1 ]; then language_strings "${language}" 506 "yellow" @@ -4699,8 +4724,6 @@ function exec_wdsconfusion() { language_strings "${language}" 91 "title" language_strings "${language}" 32 "green" - tmpfiles_toclean=1 - echo if [ "${dos_pursuit_mode}" -eq 1 ]; then language_strings "${language}" 506 "yellow" @@ -4729,8 +4752,6 @@ function exec_beaconflood() { language_strings "${language}" 92 "title" language_strings "${language}" 32 "green" - tmpfiles_toclean=1 - echo if [ "${dos_pursuit_mode}" -eq 1 ]; then language_strings "${language}" 506 "yellow" @@ -4759,8 +4780,6 @@ function exec_authdos() { language_strings "${language}" 93 "title" language_strings "${language}" 32 "green" - tmpfiles_toclean=1 - echo if [ "${dos_pursuit_mode}" -eq 1 ]; then language_strings "${language}" 506 "yellow" @@ -4789,8 +4808,6 @@ function exec_michaelshutdown() { language_strings "${language}" 94 "title" language_strings "${language}" 32 "green" - tmpfiles_toclean=1 - echo if [ "${dos_pursuit_mode}" -eq 1 ]; then language_strings "${language}" 506 "yellow" @@ -5915,56 +5932,117 @@ function clean_env_vars() { unset AIRGEDDON_AUTO_UPDATE AIRGEDDON_SKIP_INTRO AIRGEDDON_BASIC_COLORS AIRGEDDON_EXTENDED_COLORS AIRGEDDON_AUTO_CHANGE_LANGUAGE AIRGEDDON_SILENT_CHECKS AIRGEDDON_PRINT_HINTS AIRGEDDON_5GHZ_ENABLED AIRGEDDON_FORCE_IPTABLES AIRGEDDON_FORCE_NETWORK_MANAGER_KILLING AIRGEDDON_MDK_VERSION AIRGEDDON_PLUGINS_ENABLED AIRGEDDON_DEVELOPMENT_MODE AIRGEDDON_DEBUG_MODE AIRGEDDON_WINDOWS_HANDLING } +#Control the status of the routing taking into consideration instances orchestration +function control_routing_status() { + + debug_print + + local saved_routing_status_found="" + local original_routing_status="" + local etset="" + local agpid="" + local et_still_running=0 + + if [ "${1}" = "start" ]; then + readarray -t AIRGEDDON_PIDS 2> /dev/null < <(cat < "${system_tmpdir}${ag_orchestrator_file}" 2> /dev/null) + for item in "${AIRGEDDON_PIDS[@]}"; do + [[ "${item}" =~ ^(et)?([0-9]+)(rs[0-1])?$ ]] && etset="${BASH_REMATCH[1]}" && agpid="${BASH_REMATCH[2]}" + if [ -z "${saved_routing_status_found}" ]; then + [[ "${item}" =~ ^(et)?([0-9]+)(rs[0-1])?$ ]] && saved_routing_status_found="${BASH_REMATCH[3]}" + fi + + if [[ "${agpid_to_use}" = "${agpid}" ]] && [[ "${etset}" != "et" ]]; then + sed -ri "s:^(${agpid}):et\1:" "${system_tmpdir}${ag_orchestrator_file}" 2> /dev/null + fi + done + + if [ -z "${saved_routing_status_found}" ]; then + original_routing_status=$(cat /proc/sys/net/ipv4/ip_forward) + sed -ri "s:^(et${agpid_to_use})$:\1rs${original_routing_status}:" "${system_tmpdir}${ag_orchestrator_file}" 2> /dev/null + fi + else + readarray -t AIRGEDDON_PIDS 2> /dev/null < <(cat < "${system_tmpdir}${ag_orchestrator_file}" 2> /dev/null) + for item in "${AIRGEDDON_PIDS[@]}"; do + [[ "${item}" =~ ^(et)?([0-9]+)(rs[0-1])?$ ]] && etset="${BASH_REMATCH[1]}" && agpid="${BASH_REMATCH[2]}" + if [ -z "${saved_routing_status_found}" ]; then + [[ "${item}" =~ ^(et)?([0-9]+)(rs[0-1])?$ ]] && saved_routing_status_found="${BASH_REMATCH[3]}" + fi + + if [[ "${agpid_to_use}" = "${agpid}" ]] && [[ "${etset}" = "et" ]]; then + sed -ri "s:^(et${agpid}):${agpid}:" "${system_tmpdir}${ag_orchestrator_file}" 2> /dev/null + fi + + if [[ "${agpid_to_use}" != "${agpid}" ]] && [[ "${etset}" = "et" ]]; then + et_still_running=1 + fi + done + + if [[ -n "${saved_routing_status_found}" ]] && [[ "${et_still_running}" -eq 0 ]]; then + original_routing_status="${saved_routing_status_found//[^0-9]/}" + echo "${original_routing_status}" > /proc/sys/net/ipv4/ip_forward 2> /dev/null + fi + fi +} + #Clean temporary files function clean_tmpfiles() { debug_print - rm -rf "${tmpdir}bl.txt" > /dev/null 2>&1 - rm -rf "${tmpdir}target.txt" > /dev/null 2>&1 - rm -rf "${tmpdir}handshake"* > /dev/null 2>&1 - rm -rf "${tmpdir}pmkid"* > /dev/null 2>&1 - rm -rf "${tmpdir}nws"* > /dev/null 2>&1 - rm -rf "${tmpdir}clts"* > /dev/null 2>&1 - rm -rf "${tmpdir}wnws.txt" > /dev/null 2>&1 - rm -rf "${tmpdir}hctmp"* > /dev/null 2>&1 - rm -rf "${tmpdir}jtrtmp"* > /dev/null 2>&1 - rm -rf "${tmpdir}${aircrack_pot_tmp}" > /dev/null 2>&1 - rm -rf "${tmpdir}${et_processesfile}" > /dev/null 2>&1 - rm -rf "${tmpdir}${hostapd_file}" > /dev/null 2>&1 - rm -rf "${tmpdir}${hostapd_wpe_file}" > /dev/null 2>&1 - rm -rf "${tmpdir}${hostapd_wpe_log}" > /dev/null 2>&1 - rm -rf "${scriptfolder}${hostapd_wpe_default_log}" > /dev/null 2>&1 - rm -rf "${tmpdir}${dhcpd_file}" > /dev/null 2>&1 - rm -rf "${tmpdir}${dnsmasq_file}" >/dev/null 2>&1 - rm -rf "${tmpdir}${control_et_file}" > /dev/null 2>&1 - rm -rf "${tmpdir}${control_enterprise_file}" > /dev/null 2>&1 - rm -rf "${tmpdir}parsed_file" > /dev/null 2>&1 - rm -rf "${tmpdir}${ettercap_file}"* > /dev/null 2>&1 - rm -rf "${tmpdir}${bettercap_file}"* > /dev/null 2>&1 - rm -rf "${tmpdir}${bettercap_config_file}" > /dev/null 2>&1 - rm -rf "${tmpdir}${bettercap_hook_file}" > /dev/null 2>&1 - rm -rf "${tmpdir}${beef_file}" > /dev/null 2>&1 - if [ "${beef_found}" -eq 1 ]; then - rm -rf "${beef_path}${beef_file}" > /dev/null 2>&1 + if [ "${1}" = "exit_script" ]; then + rm -rf "${tmpdir}" > /dev/null 2>&1 + if is_last_airgeddon_instance; then + delete_instance_orchestrator_file + fi + else + rm -rf "${tmpdir}bl.txt" > /dev/null 2>&1 + rm -rf "${tmpdir}target.txt" > /dev/null 2>&1 + rm -rf "${tmpdir}handshake"* > /dev/null 2>&1 + rm -rf "${tmpdir}pmkid"* > /dev/null 2>&1 + rm -rf "${tmpdir}nws"* > /dev/null 2>&1 + rm -rf "${tmpdir}clts"* > /dev/null 2>&1 + rm -rf "${tmpdir}wnws.txt" > /dev/null 2>&1 + rm -rf "${tmpdir}hctmp"* > /dev/null 2>&1 + rm -rf "${tmpdir}jtrtmp"* > /dev/null 2>&1 + rm -rf "${tmpdir}${aircrack_pot_tmp}" > /dev/null 2>&1 + rm -rf "${tmpdir}${et_processesfile}" > /dev/null 2>&1 + rm -rf "${tmpdir}${hostapd_file}" > /dev/null 2>&1 + rm -rf "${tmpdir}${hostapd_wpe_file}" > /dev/null 2>&1 + rm -rf "${tmpdir}${hostapd_wpe_log}" > /dev/null 2>&1 + rm -rf "${scriptfolder}${hostapd_wpe_default_log}" > /dev/null 2>&1 + rm -rf "${tmpdir}${dhcpd_file}" > /dev/null 2>&1 + rm -rf "${tmpdir}${dnsmasq_file}" >/dev/null 2>&1 + rm -rf "${tmpdir}${control_et_file}" > /dev/null 2>&1 + rm -rf "${tmpdir}${control_enterprise_file}" > /dev/null 2>&1 + rm -rf "${tmpdir}parsed_file" > /dev/null 2>&1 + rm -rf "${tmpdir}${ettercap_file}"* > /dev/null 2>&1 + rm -rf "${tmpdir}${bettercap_file}"* > /dev/null 2>&1 + rm -rf "${tmpdir}${bettercap_config_file}" > /dev/null 2>&1 + rm -rf "${tmpdir}${bettercap_hook_file}" > /dev/null 2>&1 + rm -rf "${tmpdir}${beef_file}" > /dev/null 2>&1 + rm -rf "${tmpdir}${webserver_file}" > /dev/null 2>&1 + rm -rf "${tmpdir}${webdir}" > /dev/null 2>&1 + rm -rf "${tmpdir}${certsdir}" > /dev/null 2>&1 + rm -rf "${tmpdir}${enterprisedir}" > /dev/null 2>&1 + rm -rf "${tmpdir}${asleap_pot_tmp}" > /dev/null 2>&1 + rm -rf "${tmpdir}wps"* > /dev/null 2>&1 + rm -rf "${tmpdir}${wps_attack_script_file}" > /dev/null 2>&1 + rm -rf "${tmpdir}${wps_out_file}" > /dev/null 2>&1 + rm -rf "${tmpdir}${wep_attack_file}" > /dev/null 2>&1 + rm -rf "${tmpdir}${wep_key_handler}" > /dev/null 2>&1 + rm -rf "${tmpdir}${wep_data}"* > /dev/null 2>&1 + rm -rf "${tmpdir}${wepdir}" > /dev/null 2>&1 + rm -rf "${tmpdir}dos_pm"* > /dev/null 2>&1 + rm -rf "${tmpdir}${channelfile}" > /dev/null 2>&1 fi - rm -rf "${tmpdir}${webserver_file}" > /dev/null 2>&1 - rm -rf "${tmpdir}${webdir}" > /dev/null 2>&1 - rm -rf "${tmpdir}${certsdir}" > /dev/null 2>&1 - rm -rf "${tmpdir}${enterprisedir}" > /dev/null 2>&1 - rm -rf "${tmpdir}${asleap_pot_tmp}" > /dev/null 2>&1 + if [ "${dhcpd_path_changed}" -eq 1 ]; then rm -rf "${dhcp_path}" > /dev/null 2>&1 fi - rm -rf "${tmpdir}wps"* > /dev/null 2>&1 - rm -rf "${tmpdir}${wps_attack_script_file}" > /dev/null 2>&1 - rm -rf "${tmpdir}${wps_out_file}" > /dev/null 2>&1 - rm -rf "${tmpdir}${wep_attack_file}" > /dev/null 2>&1 - rm -rf "${tmpdir}${wep_key_handler}" > /dev/null 2>&1 - rm -rf "${tmpdir}${wep_data}"* > /dev/null 2>&1 - rm -rf "${tmpdir}${wepdir}" > /dev/null 2>&1 - rm -rf "${tmpdir}dos_pm"* > /dev/null 2>&1 - rm -rf "${tmpdir}${channelfile}" > /dev/null 2>&1 + + if [ "${beef_found}" -eq 1 ]; then + rm -rf "${beef_path}${beef_file}" > /dev/null 2>&1 + fi } #Manage cleaning firewall rules and restore orginal routing state @@ -5972,17 +6050,13 @@ function clean_routing_rules() { debug_print - if [ -n "${original_routing_state}" ]; then - echo "${original_routing_state}" > /proc/sys/net/ipv4/ip_forward 2> /dev/null - fi - - clean_initialize_iptables_nftables + control_routing_status "end" + clean_initialize_iptables_nftables "end" - if [ "${iptables_saved}" -eq 1 ]; then + if is_last_airgeddon_instance && [[ -n "${system_tmpdir}${routing_tmp_file}" ]]; then restore_iptables_nftables + rm -rf "${system_tmpdir}${routing_tmp_file}" > /dev/null 2>&1 fi - - rm -rf "${tmpdir}${routing_tmp_file}" > /dev/null 2>&1 } #Save iptables/nftables rules @@ -5991,21 +6065,9 @@ function save_iptables_nftables() { debug_print if [ "${iptables_nftables}" -eq 1 ]; then - if hash "iptables-${iptables_cmd}-save" 2> /dev/null; then - if "iptables-${iptables_cmd}-save" > "${tmpdir}${routing_tmp_file}" 2> /dev/null; then - iptables_saved=1 - fi - elif hash "${iptables_cmd}-compat-save" 2> /dev/null; then - if "${iptables_cmd}-compat-save" > "${tmpdir}${routing_tmp_file}" 2> /dev/null; then - iptables_saved=1 - fi - fi + "${iptables_cmd}" list ruleset > "${system_tmpdir}${routing_tmp_file}" 2> /dev/null else - if hash "${iptables_cmd}-save" 2> /dev/null; then - if "${iptables_cmd}-save" > "${tmpdir}${routing_tmp_file}" 2> /dev/null; then - iptables_saved=1 - fi - fi + "${iptables_cmd}-save" > "${system_tmpdir}${routing_tmp_file}" 2> /dev/null fi } @@ -6015,41 +6077,99 @@ function restore_iptables_nftables() { debug_print if [ "${iptables_nftables}" -eq 1 ]; then - if hash "iptables-${iptables_cmd}-restore" 2> /dev/null; then - "iptables-${iptables_cmd}-restore" < "${tmpdir}${routing_tmp_file}" 2> /dev/null - elif hash "${iptables_cmd}-compat-restore" 2> /dev/null; then - "${iptables_cmd}-compat-restore" < "${tmpdir}${routing_tmp_file}" 2> /dev/null - fi + "${iptables_cmd}" -f "${system_tmpdir}${routing_tmp_file}" 2> /dev/null else - if hash "${iptables_cmd}-restore" 2> /dev/null; then - "${iptables_cmd}-restore" < "${tmpdir}${routing_tmp_file}" 2> /dev/null - fi + "${iptables_cmd}-restore" < "${system_tmpdir}${routing_tmp_file}" 2> /dev/null fi } -#Clean and initialize iptables/nftables rules -function clean_initialize_iptables_nftables() { +#Prepare iptables/nftables after a clean to avoid errors +function prepare_iptables_nftables() { debug_print + clean_this_instance_iptables_nftables + if [ "${iptables_nftables}" -eq 1 ]; then - "${iptables_cmd}" add table ip filter 2> /dev/null - "${iptables_cmd}" add chain ip filter INPUT 2> /dev/null - "${iptables_cmd}" add chain ip filter OUTPUT 2> /dev/null - "${iptables_cmd}" add chain ip filter FORWARD 2> /dev/null - "${iptables_cmd}" flush table ip filter 2> /dev/null - "${iptables_cmd}" add table ip nat 2> /dev/null - "${iptables_cmd}" add chain nat PREROUTING "{ type nat hook prerouting priority 0 ; }" 2> /dev/null - "${iptables_cmd}" add chain nat POSTROUTING "{ type nat hook postrouting priority 100 ; }" 2> /dev/null - "${iptables_cmd}" flush table ip nat 2> /dev/null + "${iptables_cmd}" add table ip filter_"${airgeddon_instance_name}" + "${iptables_cmd}" add chain ip filter_"${airgeddon_instance_name}" forward_"${airgeddon_instance_name}" '{type filter hook forward priority 0; policy accept;}' + "${iptables_cmd}" add chain ip filter_"${airgeddon_instance_name}" input_"${airgeddon_instance_name}" '{type filter hook input priority 0;}' + "${iptables_cmd}" add table ip nat_"${airgeddon_instance_name}" + "${iptables_cmd}" add chain ip nat_"${airgeddon_instance_name}" prerouting_"${airgeddon_instance_name}" '{type nat hook prerouting priority -100;}' + "${iptables_cmd}" add chain ip nat_"${airgeddon_instance_name}" postrouting_"${airgeddon_instance_name}" '{type nat hook postrouting priority 100;}' + else + "${iptables_cmd}" -P FORWARD ACCEPT + "${iptables_cmd}" -t filter -N input_"${airgeddon_instance_name}" + "${iptables_cmd}" -A INPUT -j input_"${airgeddon_instance_name}" + "${iptables_cmd}" -t filter -N forward_"${airgeddon_instance_name}" + "${iptables_cmd}" -A FORWARD -j forward_"${airgeddon_instance_name}" + fi +} + +#Clean only this instance iptables/nftables rules +function clean_this_instance_iptables_nftables() { + + debug_print + + if [ "${iptables_nftables}" -eq 1 ]; then + "${iptables_cmd}" delete table filter_"${airgeddon_instance_name}" 2> /dev/null + "${iptables_cmd}" delete table nat_"${airgeddon_instance_name}" 2> /dev/null + else + "${iptables_cmd}" -D INPUT -j input_"${airgeddon_instance_name}" 2> /dev/null + "${iptables_cmd}" -D FORWARD -j forward_"${airgeddon_instance_name}" 2> /dev/null + "${iptables_cmd}" -F input_"${airgeddon_instance_name}" 2> /dev/null + "${iptables_cmd}" -F forward_"${airgeddon_instance_name}" 2> /dev/null + "${iptables_cmd}" -X input_"${airgeddon_instance_name}" 2> /dev/null + "${iptables_cmd}" -X forward_"${airgeddon_instance_name}" 2> /dev/null + fi +} + +#Clean all iptables/nftables rules +function clean_all_iptables_nftables() { + + debug_print + + if [ "${iptables_nftables}" -eq 1 ]; then + "${iptables_cmd}" flush ruleset 2> /dev/null else "${iptables_cmd}" -F 2> /dev/null "${iptables_cmd}" -t nat -F 2> /dev/null + "${iptables_cmd}" -t mangle -F 2> /dev/null + "${iptables_cmd}" -t raw -F 2> /dev/null + "${iptables_cmd}" -t security -F 2> /dev/null + "${iptables_cmd}" -t mangle -X 2> /dev/null + "${iptables_cmd}" -t raw -X 2> /dev/null + "${iptables_cmd}" -t security -X 2> /dev/null + "${iptables_cmd}" -D INPUT -j input_"${airgeddon_instance_name}" 2> /dev/null + "${iptables_cmd}" -D FORWARD -j forward_"${airgeddon_instance_name}" 2> /dev/null + "${iptables_cmd}" -F input_"${airgeddon_instance_name}" 2> /dev/null + "${iptables_cmd}" -F forward_"${airgeddon_instance_name}" 2> /dev/null + "${iptables_cmd}" -X input_"${airgeddon_instance_name}" 2> /dev/null + "${iptables_cmd}" -X forward_"${airgeddon_instance_name}" 2> /dev/null "${iptables_cmd}" -X 2> /dev/null "${iptables_cmd}" -t nat -X 2> /dev/null fi } +#Contains the logic to decide what iptables/nftables rules to clean +function clean_initialize_iptables_nftables() { + + debug_print + + if [ "${1}" = "start" ]; then + if [[ "${clean_all_iptables_nftables}" -eq 1 ]] && is_first_routing_modifier_airgeddon_instance; then + clean_all_iptables_nftables + fi + prepare_iptables_nftables + else + if is_last_airgeddon_instance; then + clean_all_iptables_nftables + else + clean_this_instance_iptables_nftables + fi + fi +} + #Create an array from parameters function store_array() { @@ -6202,6 +6322,176 @@ function print_hint() { print_simple_separator } +#Initialize instances related actions +function initialize_instance_settings() { + + debug_print + + agpid_to_use="${BASHPID}" + + instance_setter + if [ "${AIRGEDDON_WINDOWS_HANDLING}" = "tmux" ]; then + if hash tmux 2> /dev/null; then + local current_tmux_display_name + current_tmux_display_name=$(tmux display-message -p '#W') + if [ "${current_tmux_display_name}" = "${tmux_main_window}" ]; then + create_instance_orchestrator_file + register_instance_pid + fi + fi + else + create_instance_orchestrator_file + register_instance_pid + fi +} + +#Detect number of the alive airgeddon instances and set the next one if apply +function instance_setter() { + + debug_print + + local create_dir=0 + if [ "${AIRGEDDON_WINDOWS_HANDLING}" = "tmux" ]; then + if hash tmux 2> /dev/null; then + local current_tmux_display_name + current_tmux_display_name=$(tmux display-message -p '#W') + if [ "${current_tmux_display_name}" = "${tmux_main_window}" ]; then + create_dir=1 + fi + fi + else + create_dir=1 + fi + + if [ "${create_dir}" -eq 1 ]; then + local dir_number="1" + airgeddon_instance_name="ag${dir_number}" + local airgeddon_instance_dir="${airgeddon_instance_name}/" + + if [ -d "${system_tmpdir}${airgeddon_instance_dir}" ]; then + while true; do + dir_number=$((dir_number + 1)) + airgeddon_instance_name="ag${dir_number}" + airgeddon_instance_dir="${airgeddon_instance_name}/" + if [ ! -d "${system_tmpdir}${airgeddon_instance_dir}" ]; then + break + fi + done + fi + + tmpdir="${system_tmpdir}${airgeddon_instance_dir}" + mkdir -p "${tmpdir}" > /dev/null 2>&1 + fi +} + +#Create orchestrator file if needed +function create_instance_orchestrator_file() { + + debug_print + + if [ ! -f "${system_tmpdir}${ag_orchestrator_file}" ]; then + touch "${system_tmpdir}${ag_orchestrator_file}" > /dev/null 2>&1 + else + local airgeddon_pid_alive=0 + local agpid="" + + readarray -t AIRGEDDON_PIDS 2> /dev/null < <(cat < "${system_tmpdir}${ag_orchestrator_file}" 2> /dev/null) + for item in "${AIRGEDDON_PIDS[@]}"; do + [[ "${item}" =~ ^(et)?([0-9]+)(rs[0-1])?$ ]] && agpid="${BASH_REMATCH[2]}" + if ps -p "${agpid}" > /dev/null 2>&1; then + airgeddon_pid_alive=1 + break + fi + done + + if [ "${airgeddon_pid_alive}" -eq 0 ]; then + rm -rf "${system_tmpdir}${ag_orchestrator_file}" > /dev/null 2>&1 + touch "${system_tmpdir}${ag_orchestrator_file}" > /dev/null 2>&1 + fi + fi +} + +#Delete orchestrator file if exists +function delete_instance_orchestrator_file() { + + debug_print + + if [ -f "${system_tmpdir}${ag_orchestrator_file}" ]; then + rm -rf "${system_tmpdir}${ag_orchestrator_file}" > /dev/null 2>&1 + fi +} + +#Register instance pid into orchestrator file if is not already registered +function register_instance_pid() { + + debug_print + + if [ -f "${system_tmpdir}${ag_orchestrator_file}" ]; then + if ! grep -q "${agpid_to_use}" "${system_tmpdir}${ag_orchestrator_file}"; then + { + echo "${agpid_to_use}" + } >> "${system_tmpdir}${ag_orchestrator_file}" + fi + fi +} + +#Detect and return the number of airgeddon running instances +function detect_running_instances() { + + debug_print + + airgeddon_running_instances_counter=1 + + readarray -t AIRGEDDON_PIDS 2> /dev/null < <(cat < "${system_tmpdir}${ag_orchestrator_file}" 2> /dev/null) + for item in "${AIRGEDDON_PIDS[@]}"; do + [[ "${item}" =~ ^(et)?([0-9]+)(rs[0-1])?$ ]] && agpid="${BASH_REMATCH[2]}" + if [[ "${agpid}" != "${BASHPID}" ]] && ps -p "${agpid}" > /dev/null 2>&1; then + airgeddon_running_instances_counter=$((airgeddon_running_instances_counter + 1)) + fi + done + + return "${airgeddon_running_instances_counter}" +} + +#Check if this instance is the first one modifying routing state +function is_first_routing_modifier_airgeddon_instance() { + + debug_print + + local agpid="" + + readarray -t AIRGEDDON_PIDS 2> /dev/null < <(cat <"${system_tmpdir}${ag_orchestrator_file}" 2> /dev/null) + for item in "${AIRGEDDON_PIDS[@]}"; do + [[ "${item}" =~ ^(et)?([0-9]+)rs[0-1]$ ]] && agpid="${BASH_REMATCH[2]}" + + if [ "${agpid}" = "${BASHPID}" ]; then + clean_all_iptables_nftables=0 + return 0 + fi + done + + return 1 +} + +#Check if this instance is the last airgeddon instance running +function is_last_airgeddon_instance() { + + debug_print + + local agpid="" + + readarray -t AIRGEDDON_PIDS 2> /dev/null < <(cat <"${system_tmpdir}${ag_orchestrator_file}" 2> /dev/null) + for item in "${AIRGEDDON_PIDS[@]}"; do + [[ "${item}" =~ ^(et)?([0-9]+)(rs[0-1])?$ ]] && agpid="${BASH_REMATCH[2]}" + + if [[ "${agpid}" != "${agpid_to_use}" ]] && ps -p "${agpid}" >/dev/null 2>&1; then + return 1 + fi + done + + return 0 +} + #airgeddon main menu function main_menu() { @@ -7828,7 +8118,7 @@ function select_wpa_bssid_target_from_captured_file() { print_hint ${current_menu} target_network_on_file=0 - while [[ ! ${target_network_on_file} =~ ^[[:digit:]]+$ ]] || (( target_network_on_file < 1 || target_network_on_file > option_counter )); do + while [[ ! ${target_network_on_file} =~ ^[[:digit:]]+$ ]] || ((target_network_on_file < 1 || target_network_on_file > option_counter)); do echo language_strings "${language}" 3 "green" read -rp "> " target_network_on_file @@ -7963,7 +8253,7 @@ function aircrack_bruteforce_attack_option() { set_minlength_and_maxlength "personal_handshake" charset_option=0 - while [[ ! ${charset_option} =~ ^[[:digit:]]+$ ]] || (( charset_option < 1 || charset_option > 11 )); do + while [[ ! ${charset_option} =~ ^[[:digit:]]+$ ]] || ((charset_option < 1 || charset_option > 11)); do set_charset "aircrack" done @@ -8010,7 +8300,7 @@ function enterprise_jtr_bruteforce_attack_option() { set_minlength_and_maxlength "enterprise" charset_option=0 - while [[ ! ${charset_option} =~ ^[[:digit:]]+$ ]] || (( charset_option < 1 || charset_option > 11 )); do + while [[ ! ${charset_option} =~ ^[[:digit:]]+$ ]] || ((charset_option < 1 || charset_option > 11)); do set_charset "jtr" done @@ -8085,7 +8375,7 @@ function hashcat_bruteforce_attack_option() { set_minlength_and_maxlength "${1}" charset_option=0 - while [[ ! ${charset_option} =~ ^[[:digit:]]+$ ]] || (( charset_option < 1 || charset_option > 11 )); do + while [[ ! ${charset_option} =~ ^[[:digit:]]+$ ]] || ((charset_option < 1 || charset_option > 11)); do set_charset "hashcat" done @@ -8233,7 +8523,7 @@ function manage_hashcat_pot() { echo "" } >> "${potenteredpath}" - for (( x=0; x<${#enterprise_users[@]}; x++ )); do + for ((x=0; x<${#enterprise_users[@]}; x++)); do { echo "${enterprise_users[${x}]} / ${hashcat_keys[${x}]}" } >> "${potenteredpath}" @@ -8326,7 +8616,7 @@ function manage_jtr_pot() { echo "" } >> "${jtrpotenteredpath}" - for (( x=0; x<${#enterprise_users[@]}; x++ )); do + for ((x=0; x<${#enterprise_users[@]}; x++)); do { echo "${enterprise_users[${x}]} / ${jtr_keys[${x}]}" } >> "${jtrpotenteredpath}" @@ -9097,7 +9387,6 @@ function exec_jtr_dictionary_attack() { debug_print - tmpfiles_toclean=1 rm -rf "${tmpdir}jtrtmp"* > /dev/null 2>&1 jtr_cmd="john \"${jtrenterpriseenteredpath}\" --format=netntlm-naive --wordlist=\"${DICTIONARY}\" --pot=\"${tmpdir}${jtr_pot_tmp}\" --encoding=UTF-8 | tee \"${tmpdir}${jtr_output_file}\" ${colorize}" @@ -9110,7 +9399,6 @@ function exec_jtr_bruteforce_attack() { debug_print - tmpfiles_toclean=1 rm -rf "${tmpdir}jtrtmp"* > /dev/null 2>&1 jtr_cmd="crunch \"${minlength}\" \"${maxlength}\" \"${charset}\" | john \"${jtrenterpriseenteredpath}\" --stdin --format=netntlm-naive --pot=\"${tmpdir}${jtr_pot_tmp}\" --encoding=UTF-8 | tee \"${tmpdir}${jtr_output_file}\" ${colorize}" @@ -9126,11 +9414,9 @@ function exec_hashcat_dictionary_attack() { if [ "${1}" = "personal_handshake" ]; then hashcat_cmd="hashcat -m ${hashcat_handshake_cracking_plugin} -a 0 \"${tmpdir}${hashcat_tmp_file}\" \"${DICTIONARY}\" --potfile-disable -o \"${tmpdir}${hashcat_pot_tmp}\"${hashcat_cmd_fix} | tee \"${tmpdir}${hashcat_output_file}\" ${colorize}" elif [ "${1}" = "personal_pmkid" ]; then - tmpfiles_toclean=1 rm -rf "${tmpdir}hctmp"* > /dev/null 2>&1 hashcat_cmd="hashcat -m ${hashcat_pmkid_cracking_plugin} -a 0 \"${hashcatpmkidenteredpath}\" \"${DICTIONARY}\" --potfile-disable -o \"${tmpdir}${hashcat_pot_tmp}\"${hashcat_cmd_fix} | tee \"${tmpdir}${hashcat_output_file}\" ${colorize}" else - tmpfiles_toclean=1 rm -rf "${tmpdir}hctmp"* > /dev/null 2>&1 hashcat_cmd="hashcat -m ${hashcat_enterprise_cracking_plugin} -a 0 \"${hashcatenterpriseenteredpath}\" \"${DICTIONARY}\" --potfile-disable -o \"${tmpdir}${hashcat_pot_tmp}\"${hashcat_cmd_fix} | tee \"${tmpdir}${hashcat_output_file}\" ${colorize}" fi @@ -9146,11 +9432,9 @@ function exec_hashcat_bruteforce_attack() { if [ "${1}" = "personal_handshake" ]; then hashcat_cmd="hashcat -m ${hashcat_handshake_cracking_plugin} -a 3 \"${tmpdir}${hashcat_tmp_file}\" ${charset} --increment --increment-min=${minlength} --increment-max=${maxlength} --potfile-disable -o \"${tmpdir}${hashcat_pot_tmp}\"${hashcat_cmd_fix} | tee \"${tmpdir}${hashcat_output_file}\" ${colorize}" elif [ "${1}" = "personal_pmkid" ]; then - tmpfiles_toclean=1 rm -rf "${tmpdir}hctmp"* > /dev/null 2>&1 hashcat_cmd="hashcat -m ${hashcat_pmkid_cracking_plugin} -a 3 \"${hashcatpmkidenteredpath}\" ${charset} --increment --increment-min=${minlength} --increment-max=${maxlength} --potfile-disable -o \"${tmpdir}${hashcat_pot_tmp}\"${hashcat_cmd_fix} | tee \"${tmpdir}${hashcat_output_file}\" ${colorize}" else - tmpfiles_toclean=1 rm -rf "${tmpdir}hctmp"* > /dev/null 2>&1 hashcat_cmd="hashcat -m ${hashcat_enterprise_cracking_plugin} -a 3 \"${hashcatenterpriseenteredpath}\" ${charset} --increment --increment-min=${minlength} --increment-max=${maxlength} --potfile-disable -o \"${tmpdir}${hashcat_pot_tmp}\"${hashcat_cmd_fix} | tee \"${tmpdir}${hashcat_output_file}\" ${colorize}" fi @@ -9166,11 +9450,9 @@ function exec_hashcat_rulebased_attack() { if [ "${1}" = "personal_handshake" ]; then hashcat_cmd="hashcat -m ${hashcat_handshake_cracking_plugin} -a 0 \"${tmpdir}${hashcat_tmp_file}\" \"${DICTIONARY}\" -r \"${RULES}\" --potfile-disable -o \"${tmpdir}${hashcat_pot_tmp}\"${hashcat_cmd_fix} | tee \"${tmpdir}${hashcat_output_file}\" ${colorize}" elif [ "${1}" = "personal_pmkid" ]; then - tmpfiles_toclean=1 rm -rf "${tmpdir}hctmp"* > /dev/null 2>&1 hashcat_cmd="hashcat -m ${hashcat_pmkid_cracking_plugin} -a 0 \"${hashcatpmkidenteredpath}\" \"${DICTIONARY}\" -r \"${RULES}\" --potfile-disable -o \"${tmpdir}${hashcat_pot_tmp}\"${hashcat_cmd_fix} | tee \"${tmpdir}${hashcat_output_file}\" ${colorize}" else - tmpfiles_toclean=1 rm -rf "${tmpdir}hctmp"* > /dev/null 2>&1 hashcat_cmd="hashcat -m ${hashcat_enterprise_cracking_plugin} -a 0 \"${hashcatenterpriseenteredpath}\" \"${DICTIONARY}\" -r \"${RULES}\" --potfile-disable -o \"${tmpdir}${hashcat_pot_tmp}\"${hashcat_cmd_fix} | tee \"${tmpdir}${hashcat_output_file}\" ${colorize}" fi @@ -9343,6 +9625,7 @@ function exec_et_onlyap_attack() { set_hostapd_config launch_fake_ap + set_network_interface_data set_dhcp_config set_std_internet_routing_rules launch_dhcp_server @@ -9372,6 +9655,7 @@ function exec_et_sniffing_attack() { set_hostapd_config launch_fake_ap + set_network_interface_data set_dhcp_config set_std_internet_routing_rules launch_dhcp_server @@ -9405,6 +9689,7 @@ function exec_et_sniffing_sslstrip2_attack() { set_hostapd_config launch_fake_ap + set_network_interface_data set_dhcp_config set_std_internet_routing_rules launch_dhcp_server @@ -9438,6 +9723,7 @@ function exec_et_sniffing_sslstrip2_beef_attack() { set_hostapd_config launch_fake_ap + set_network_interface_data set_dhcp_config set_std_internet_routing_rules launch_dhcp_server @@ -9461,7 +9747,6 @@ function exec_et_sniffing_sslstrip2_beef_attack() { language_strings "${language}" 298 "yellow" language_strings "${language}" 115 "read" - kill_beef kill_et_windows if [ "${dos_pursuit_mode}" -eq 1 ]; then @@ -9485,6 +9770,7 @@ function exec_et_captive_portal_attack() { set_hostapd_config launch_fake_ap + set_network_interface_data set_dhcp_config set_std_internet_routing_rules launch_dhcp_server @@ -9516,7 +9802,6 @@ function set_bettercap_config() { debug_print - tmpfiles_toclean=1 rm -rf "${tmpdir}${bettercap_config_file}" > /dev/null 2>&1 if [ "${et_mode}" = "et_sniffing_sslstrip2_beef" ]; then @@ -9569,12 +9854,11 @@ function set_hostapd_config() { debug_print - tmpfiles_toclean=1 rm -rf "${tmpdir}${hostapd_file}" > /dev/null 2>&1 local digit_to_change digit_to_change="${bssid:10:1}" - (( different_mac_digit=("16#${digit_to_change}" + 1 + RANDOM % 15) % 16 )) + ((different_mac_digit=("16#${digit_to_change}" + 1 + RANDOM % 15) % 16)) et_bssid=$(printf %s%X%s\\n "${bssid::10}" "${different_mac_digit}" "${bssid:11}") { @@ -9607,7 +9891,6 @@ function set_hostapd_wpe_config() { debug_print - tmpfiles_toclean=1 rm -rf "${tmpdir}${hostapd_wpe_file}" > /dev/null 2>&1 different_mac_digit=$(tr -dc A-F0-9 < /dev/urandom | fold -w2 | head -n 100 | grep -v "${bssid:10:1}" | head -c 1) @@ -9663,12 +9946,6 @@ function launch_fake_ap() { debug_print - if [ -n "${enterprise_mode}" ]; then - kill "$(ps -C hostapd-wpe --no-headers -o pid | tr -d ' ')" &> /dev/null - else - kill "$(ps -C hostapd --no-headers -o pid | tr -d ' ')" &> /dev/null - fi - if "${AIRGEDDON_FORCE_NETWORK_MANAGER_KILLING:-true}"; then ${airmon} check kill > /dev/null 2>&1 nm_processes_killed=1 @@ -9734,26 +10011,48 @@ function launch_fake_ap() { sleep 3 } -#Create configuration file for dhcpd -function set_dhcp_config() { +#Set network data parameters +function set_network_interface_data() { debug_print - if ! ip route | grep ${ip_range} > /dev/null; then - et_ip_range=${ip_range} - et_ip_router=${router_ip} - et_broadcast_ip=${broadcast_ip} - et_range_start=${range_start} - et_range_stop=${range_stop} - else - et_ip_range=${alt_ip_range} - et_ip_router=${alt_router_ip} - et_broadcast_ip=${alt_broadcast_ip} - et_range_start=${alt_range_start} - et_range_stop=${alt_range_stop} + std_c_mask="255.255.255.0" + ip_mask="255.255.255.255" + std_c_mask_cidr="24" + ip_mask_cidr="32" + any_mask_cidr="0" + any_ip="0.0.0.0" + any_ipv6="::/0" + + first_octet="192" + second_octet="169" + third_octet="1" + fourth_octet="0" + + ip_range="${first_octet}.${second_octet}.${third_octet}.${fourth_octet}" + + if ip route | grep ${ip_range} > /dev/null; then + while true; do + third_octet=$((third_octet + 1)) + ip_range="${first_octet}.${second_octet}.${third_octet}.${fourth_octet}" + if ! ip route | grep ${ip_range} > /dev/null; then + break + fi + done fi - tmpfiles_toclean=1 + et_ip_range="${ip_range}" + et_ip_router="${first_octet}.${second_octet}.${third_octet}.1" + et_broadcast_ip="${first_octet}.${second_octet}.${third_octet}.255" + et_range_start="${first_octet}.${second_octet}.${third_octet}.33" + et_range_stop="${first_octet}.${second_octet}.${third_octet}.100" +} + +#Create configuration file for dhcpd +function set_dhcp_config() { + + debug_print + rm -rf "${tmpdir}${dhcpd_file}" > /dev/null 2>&1 rm -rf "${tmpdir}clts.txt" > /dev/null 2>&1 ip link set "${interface}" up > /dev/null 2>&1 @@ -9856,8 +10155,8 @@ function set_std_internet_routing_rules() { debug_print - if [ "${routing_modified}" -eq 0 ]; then - original_routing_state=$(cat /proc/sys/net/ipv4/ip_forward) + control_routing_status "start" + if [ ! -f "${system_tmpdir}${routing_tmp_file}" ]; then save_iptables_nftables fi @@ -9865,78 +10164,60 @@ function set_std_internet_routing_rules() { ip route add ${et_ip_range}/${std_c_mask_cidr} dev "${interface}" table local proto static scope link > /dev/null 2>&1 routing_modified=1 - clean_initialize_iptables_nftables + clean_initialize_iptables_nftables "start" - if [ "${et_mode}" != "et_captive_portal" ]; then - if [ "${iptables_nftables}" -eq 1 ]; then - "${iptables_cmd}" add rule ip filter FORWARD counter accept - else - "${iptables_cmd}" -P FORWARD ACCEPT - fi - echo "1" > /proc/sys/net/ipv4/ip_forward 2> /dev/null - else - if [ "${iptables_nftables}" -eq 1 ]; then - "${iptables_cmd}" add rule ip filter FORWARD counter drop - else - "${iptables_cmd}" -P FORWARD DROP - fi - echo "0" > /proc/sys/net/ipv4/ip_forward 2> /dev/null - fi + echo "1" > /proc/sys/net/ipv4/ip_forward 2> /dev/null if [ "${et_mode}" = "et_captive_portal" ]; then if [ "${iptables_nftables}" -eq 1 ]; then - "${iptables_cmd}" add rule ip nat PREROUTING tcp dport ${www_port} counter dnat to ${et_ip_router}:${www_port} - "${iptables_cmd}" add rule ip filter INPUT tcp dport ${www_port} counter accept - "${iptables_cmd}" add rule ip filter INPUT tcp dport ${https_port} counter accept - else - "${iptables_cmd}" -t nat -A PREROUTING -p tcp --dport ${www_port} -j DNAT --to-destination ${et_ip_router}:${www_port} - "${iptables_cmd}" -A INPUT -p tcp --destination-port ${www_port} -j ACCEPT - "${iptables_cmd}" -A INPUT -p tcp --destination-port ${https_port} -j ACCEPT - fi - - if [ "${iptables_nftables}" -eq 1 ]; then - "${iptables_cmd}" add rule ip filter INPUT udp dport ${dns_port} counter accept + "${iptables_cmd}" add rule ip nat_"${airgeddon_instance_name}" prerouting_"${airgeddon_instance_name}" iifname "${interface}" tcp dport ${www_port} counter dnat to ${et_ip_router}:${www_port} + "${iptables_cmd}" add rule ip filter_"${airgeddon_instance_name}" input_"${airgeddon_instance_name}" iifname "${interface}" tcp dport ${www_port} counter accept + "${iptables_cmd}" add rule ip filter_"${airgeddon_instance_name}" input_"${airgeddon_instance_name}" iifname "${interface}" tcp dport ${https_port} counter accept + "${iptables_cmd}" add rule ip filter_"${airgeddon_instance_name}" input_"${airgeddon_instance_name}" iifname "${interface}" udp dport ${dns_port} counter accept else - "${iptables_cmd}" -A INPUT -p udp --destination-port ${dns_port} -j ACCEPT + "${iptables_cmd}" -t nat -A PREROUTING -p tcp -i "${interface}" --dport ${www_port} -j DNAT --to-destination ${et_ip_router}:${www_port} + "${iptables_cmd}" -A input_"${airgeddon_instance_name}" -p tcp -i "${interface}" --destination-port ${www_port} -j ACCEPT + "${iptables_cmd}" -A input_"${airgeddon_instance_name}" -p tcp -i "${interface}" --destination-port ${https_port} -j ACCEPT + "${iptables_cmd}" -A input_"${airgeddon_instance_name}" -p udp -i "${interface}" --destination-port ${dns_port} -j ACCEPT fi elif [ "${et_mode}" = "et_sniffing_sslstrip2" ]; then if [ "${iptables_nftables}" -eq 1 ]; then - "${iptables_cmd}" add rule ip filter INPUT tcp dport ${bettercap_proxy_port} counter accept - "${iptables_cmd}" add rule ip filter INPUT udp dport ${bettercap_dns_port} counter accept - "${iptables_cmd}" add rule ip filter INPUT iifname "lo" counter accept + "${iptables_cmd}" add rule ip filter_"${airgeddon_instance_name}" input_"${airgeddon_instance_name}" iifname "${interface}" tcp dport ${bettercap_proxy_port} counter accept + "${iptables_cmd}" add rule ip filter_"${airgeddon_instance_name}" input_"${airgeddon_instance_name}" iifname "${interface}" udp dport ${bettercap_dns_port} counter accept + "${iptables_cmd}" add rule ip filter_"${airgeddon_instance_name}" input_"${airgeddon_instance_name}" iifname "${loopback_interface}" counter accept else - "${iptables_cmd}" -A INPUT -p tcp --destination-port ${bettercap_proxy_port} -j ACCEPT - "${iptables_cmd}" -A INPUT -p udp --destination-port ${bettercap_dns_port} -j ACCEPT - "${iptables_cmd}" -A INPUT -i lo -j ACCEPT + "${iptables_cmd}" -A input_"${airgeddon_instance_name}" -p tcp -i "${interface}" --destination-port ${bettercap_proxy_port} -j ACCEPT + "${iptables_cmd}" -A input_"${airgeddon_instance_name}" -p udp -i "${interface}" --destination-port ${bettercap_dns_port} -j ACCEPT + "${iptables_cmd}" -A input_"${airgeddon_instance_name}" -i "${loopback_interface}" -j ACCEPT fi elif [ "${et_mode}" = "et_sniffing_sslstrip2_beef" ]; then if [ "${iptables_nftables}" -eq 1 ]; then - "${iptables_cmd}" add rule ip filter INPUT tcp dport ${bettercap_proxy_port} counter accept - "${iptables_cmd}" add rule ip filter INPUT udp dport ${bettercap_dns_port} counter accept - "${iptables_cmd}" add rule ip filter INPUT iifname "lo" counter accept - "${iptables_cmd}" add rule ip filter INPUT tcp dport ${beef_port} counter accept + "${iptables_cmd}" add rule ip filter_"${airgeddon_instance_name}" input_"${airgeddon_instance_name}" iifname "${interface}" tcp dport ${bettercap_proxy_port} counter accept + "${iptables_cmd}" add rule ip filter_"${airgeddon_instance_name}" input_"${airgeddon_instance_name}" iifname "${interface}" udp dport ${bettercap_dns_port} counter accept + "${iptables_cmd}" add rule ip filter_"${airgeddon_instance_name}" input_"${airgeddon_instance_name}" iifname "${loopback_interface}" counter accept + "${iptables_cmd}" add rule ip filter_"${airgeddon_instance_name}" input_"${airgeddon_instance_name}" iifname "${interface}" tcp dport ${beef_port} counter accept else - "${iptables_cmd}" -A INPUT -p tcp --destination-port ${bettercap_proxy_port} -j ACCEPT - "${iptables_cmd}" -A INPUT -p udp --destination-port ${bettercap_dns_port} -j ACCEPT - "${iptables_cmd}" -A INPUT -i lo -j ACCEPT - "${iptables_cmd}" -A INPUT -p tcp --destination-port ${beef_port} -j ACCEPT + "${iptables_cmd}" -A input_"${airgeddon_instance_name}" -p tcp -i "${interface}" --destination-port ${bettercap_proxy_port} -j ACCEPT + "${iptables_cmd}" -A input_"${airgeddon_instance_name}" -p udp -i "${interface}" --destination-port ${bettercap_dns_port} -j ACCEPT + "${iptables_cmd}" -A input_"${airgeddon_instance_name}" -i "${loopback_interface}" -j ACCEPT + "${iptables_cmd}" -A input_"${airgeddon_instance_name}" -p tcp -i "${interface}" --destination-port ${beef_port} -j ACCEPT fi fi if [ "${et_mode}" != "et_captive_portal" ]; then if [ "${iptables_nftables}" -eq 1 ]; then - "${iptables_cmd}" add rule nat POSTROUTING ip saddr ${et_ip_range}/${std_c_mask_cidr} oifname "${internet_interface}" counter masquerade + "${iptables_cmd}" add rule nat_"${airgeddon_instance_name}" postrouting_"${airgeddon_instance_name}" ip saddr ${et_ip_range}/${std_c_mask_cidr} oifname "${internet_interface}" counter masquerade else - "${iptables_cmd}" -t nat -A POSTROUTING -o "${internet_interface}" -j MASQUERADE + "${iptables_cmd}" -t nat -A POSTROUTING -s ${et_ip_range}/${std_c_mask} -o ${internet_interface} -j MASQUERADE fi fi if [ "${iptables_nftables}" -eq 1 ]; then - "${iptables_cmd}" add rule ip filter INPUT ip saddr ${et_ip_range}/${std_c_mask_cidr} ip daddr ${et_ip_router}/${ip_mask_cidr} icmp type echo-request ct state new,related,established counter accept - "${iptables_cmd}" add rule ip filter INPUT ip saddr ${et_ip_range}/${std_c_mask_cidr} ip daddr ${et_ip_router}/${ip_mask_cidr} counter drop + "${iptables_cmd}" add rule ip filter_"${airgeddon_instance_name}" input_"${airgeddon_instance_name}" iifname "${interface}" ip daddr ${et_ip_router}/${ip_mask_cidr} icmp type echo-request ct state new,related,established counter accept + "${iptables_cmd}" add rule ip filter_"${airgeddon_instance_name}" input_"${airgeddon_instance_name}" ip daddr ${et_ip_router}/${ip_mask_cidr} counter drop else - "${iptables_cmd}" -A INPUT -p icmp --icmp-type 8 -s ${et_ip_range}/${std_c_mask} -d ${et_ip_router}/${ip_mask} -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT - "${iptables_cmd}" -A INPUT -s ${et_ip_range}/${std_c_mask} -d ${et_ip_router}/${ip_mask} -j DROP + "${iptables_cmd}" -A input_"${airgeddon_instance_name}" -i "${interface}" -p icmp --icmp-type 8 -d ${et_ip_router}/${ip_mask} -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT + "${iptables_cmd}" -A input_"${airgeddon_instance_name}" -d ${et_ip_router}/${ip_mask} -j DROP fi sleep 2 } @@ -9946,8 +10227,6 @@ function launch_dhcp_server() { debug_print - kill "$(ps -C dhcpd --no-headers -o pid | tr -d ' ')" &> /dev/null - recalculate_windows_sizes case ${et_mode} in "et_onlyap") @@ -9960,6 +10239,8 @@ function launch_dhcp_server() { dchcpd_scr_window_position=${g4_middleleft_window} ;; esac + + rm -rf "/var/run/${dhcpd_pid_file}" 2> /dev/null manage_output "-hold -bg \"#000000\" -fg \"#FFC0CB\" -geometry ${dchcpd_scr_window_position} -T \"DHCP\"" "dhcpd -d -cf \"${dhcp_path}\" ${interface} 2>&1 | tee -a ${tmpdir}clts.txt 2>&1" "DHCP" if [ "${AIRGEDDON_WINDOWS_HANDLING}" = "xterm" ]; then et_processes+=($!) @@ -9981,17 +10262,14 @@ function exec_et_deauth() { case ${et_dos_attack} in "${mdk_command}") - kill "$(ps -C "${mdk_command}" --no-headers -o pid | tr -d ' ')" &> /dev/null rm -rf "${tmpdir}bl.txt" > /dev/null 2>&1 echo "${bssid}" > "${tmpdir}bl.txt" deauth_et_cmd="${mdk_command} ${iface_monitor_et_deauth} d -b ${tmpdir}\"bl.txt\" -c ${channel}" ;; "Aireplay") - kill "$(ps -C aireplay-ng --no-headers -o pid | tr -d ' ')" &> /dev/null deauth_et_cmd="aireplay-ng --deauth 0 -a ${bssid} --ignore-negative-one ${iface_monitor_et_deauth}" ;; "Wds Confusion") - kill "$(ps -C "${mdk_command}" --no-headers -o pid | tr -d ' ')" &> /dev/null deauth_et_cmd="${mdk_command} ${iface_monitor_et_deauth} w -e ${essid} -c ${channel}" ;; esac @@ -10038,7 +10316,6 @@ function set_wps_attack_script() { debug_print - tmpfiles_toclean=1 rm -rf "${tmpdir}${wps_attack_script_file}" > /dev/null 2>&1 rm -rf "${tmpdir}${wps_out_file}" > /dev/null 2>&1 @@ -10573,6 +10850,7 @@ function set_enterprise_control_script() { if [ "${AIRGEDDON_WINDOWS_HANDLING}" = "tmux" ]; then cat >&7 <<-EOF + #Function to kill tmux windows using window name function kill_tmux_windows() { local TMUX_WINDOWS_LIST=() @@ -10791,11 +11069,31 @@ function set_et_control_script() { EOF cat >&7 <<-'EOF' - function kill_et_windows() { + + function kill_pid_and_children_recursive() { + + local parent_pid="" + local child_pids="" + + parent_pid="${1}" + child_pids=$(pgrep -P "${parent_pid}" 2> /dev/null) + + for child_pid in ${child_pids}; do + kill_pid_and_children_recursive "${child_pid}" + done + if [ -n "${child_pids}" ]; then + pkill -P "${parent_pid}" &> /dev/null + fi + + kill "${parent_pid}" &> /dev/null + wait "${parent_pid}" 2> /dev/null + } + + function kill_et_processes_control_script() { readarray -t ET_PROCESSES_TO_KILL < <(cat < "${path_to_processes}" 2> /dev/null) for item in "${ET_PROCESSES_TO_KILL[@]}"; do - kill "${item}" &> /dev/null + kill_pid_and_children_recursive "${item}" done } @@ -10810,6 +11108,7 @@ function set_et_control_script() { if [ "${AIRGEDDON_WINDOWS_HANDLING}" = "tmux" ]; then cat >&7 <<-EOF + #Function to kill tmux windows using window name function kill_tmux_windows() { local TMUX_WINDOWS_LIST=() @@ -10906,13 +11205,7 @@ function set_et_control_script() { EOF cat >&7 <<-'EOF' - kill_et_windows - kill "$(ps -C hostapd --no-headers -o pid | tr -d ' ')" &> /dev/null - kill "$(ps -C dhcpd --no-headers -o pid | tr -d ' ')" &> /dev/null - kill "$(ps -C "${mdk_command}" --no-headers -o pid | tr -d ' ')" &> /dev/null - kill "$(ps -C aireplay-ng --no-headers -o pid | tr -d ' ')" &> /dev/null - kill "$(ps -C dnsmasq --no-headers -o pid | tr -d ' ')" &> /dev/null - kill "$(ps -C lighttpd --no-headers -o pid | tr -d ' ')" &> /dev/null + kill_et_processes_control_script EOF if [ "${AIRGEDDON_WINDOWS_HANDLING}" = "tmux" ]; then @@ -11053,12 +11346,14 @@ function launch_dns_blackhole() { recalculate_windows_sizes - tmpfiles_toclean=1 rm -rf "${tmpdir}${dnsmasq_file}" > /dev/null 2>&1 { echo -e "interface=${interface}" echo -e "address=/#/${et_ip_router}" + echo -e "port=${dns_port}" + echo -e "bind-dynamic" + echo -e "except-interface=${loopback_interface}" echo -e "address=/google.com/172.217.5.238" echo -e "address=/gstatic.com/172.217.5.238" echo -e "no-dhcp-interface=${interface}" @@ -11161,6 +11456,7 @@ function set_webserver_config() { echo -e "url.redirect = ( \"^/(.*)$\" => \"http://connectivitycheck.microsoft.com/\")" echo -e "url.redirect-code = 302" echo -e "}" + echo -e "server.bind = \"${et_ip_router}\"\n" echo -e "server.port = ${www_port}\n" echo -e "index-file.names = ( \"${indexfile}\" )\n" echo -e "server.error-handler-404 = \"/\"\n" @@ -11503,7 +11799,6 @@ function launch_webserver() { debug_print - kill "$(ps -C lighttpd --no-headers -o pid | tr -d ' ')" &> /dev/null recalculate_windows_sizes lighttpd_window_position=${g4_bottomright_window} manage_output "-hold -bg \"#000000\" -fg \"#FFFF00\" -geometry ${lighttpd_window_position} -T \"Webserver\"" "lighttpd -D -f \"${tmpdir}${webserver_file}\"" "Webserver" @@ -11547,7 +11842,6 @@ function set_beef_config() { debug_print - tmpfiles_toclean=1 rm -rf "${tmpdir}${beef_file}" > /dev/null 2>&1 beef_db_path="" @@ -11647,21 +11941,6 @@ function set_beef_config() { } >> "${tmpdir}${beef_file}" } -#Kill beef process -#shellcheck disable=SC2009 -function kill_beef() { - - debug_print - - local beef_pid - beef_pid="$(ps -C "${optional_tools_names[17]}" --no-headers -o pid | tr -d ' ')" - if ! kill "${beef_pid}" &> /dev/null; then - if ! kill "$(ps -C "beef" --no-headers -o pid | tr -d ' ')" &> /dev/null; then - kill "$(ps -C "ruby" --no-headers -o pid,cmd | grep "beef" | awk '{print $1}')" &> /dev/null - fi - fi -} - #Detects if your beef is Flexible Brainfuck interpreter instead of BeEF function detect_fake_beef() { @@ -11828,8 +12107,6 @@ function launch_beef() { debug_print - kill_beef - if [ "${beef_found}" -eq 0 ]; then start_beef_service fi @@ -12045,6 +12322,28 @@ function write_et_processes() { fi } +#Kill a given PID and all its subprocesses recursively + function kill_pid_and_children_recursive() { + + debug_print + + local parent_pid="" + local child_pids="" + + parent_pid="${1}" + child_pids=$(pgrep -P "${parent_pid}" 2> /dev/null) + + for child_pid in ${child_pids}; do + kill_pid_and_children_recursive "${child_pid}" + done + if [ -n "${child_pids}" ]; then + pkill -P "${parent_pid}" &> /dev/null + fi + + kill "${parent_pid}" &> /dev/null + wait "${parent_pid}" 2> /dev/null + } + #Kill the Evil Twin and Enterprise processes function kill_et_windows() { @@ -12052,28 +12351,16 @@ function kill_et_windows() { if [ "${dos_pursuit_mode}" -eq 1 ]; then kill_dos_pursuit_mode_processes - case ${et_dos_attack} in - "${mdk_command}"|"Wds Confusion") - kill "$(ps -C "${mdk_command}" --no-headers -o pid | tr -d ' ')" &> /dev/null - ;; - "Aireplay") - kill "$(ps -C aireplay-ng --no-headers -o pid | tr -d ' ')" &> /dev/null - ;; - esac fi for item in "${et_processes[@]}"; do - kill "${item}" &> /dev/null + kill_pid_and_children_recursive "${item}" done if [ -n "${enterprise_mode}" ]; then kill "${enterprise_process_control_window}" &> /dev/null - kill "$(ps -C hostapd-wpe --no-headers -o pid | tr -d ' ')" &> /dev/null else kill "${et_process_control_window}" &> /dev/null - kill "$(ps -C hostapd --no-headers -o pid | tr -d ' ')" &> /dev/null - kill "$(ps -C dnsmasq --no-headers -o pid | tr -d ' ')" &> /dev/null - kill "$(ps -C lighttpd --no-headers -o pid | tr -d ' ')" &> /dev/null fi if [ "${AIRGEDDON_WINDOWS_HANDLING}" = "tmux" ]; then @@ -12087,8 +12374,7 @@ function kill_dos_pursuit_mode_processes() { debug_print for item in "${dos_pursuit_mode_pids[@]}"; do - kill -9 "${item}" &> /dev/null - wait "${item}" 2> /dev/null + kill_pid_and_children_recursive "${item}" done if ! stty sane > /dev/null 2>&1; then @@ -12115,7 +12401,6 @@ function convert_cap_to_hashcat_format() { debug_print - tmpfiles_toclean=1 rm -rf "${tmpdir}hctmp"* > /dev/null 2>&1 if [ "${hccapx_needed}" -eq 0 ]; then echo "1" | timeout -s SIGTERM 3 aircrack-ng "${enteredpath}" -J "${tmpdir}${hashcat_tmp_simple_name_file}" -b "${bssid}" > /dev/null 2>&1 @@ -13234,7 +13519,6 @@ function explore_for_targets_option() { fi language_strings "${language}" 115 "read" - tmpfiles_toclean=1 rm -rf "${tmpdir}nws"* > /dev/null 2>&1 rm -rf "${tmpdir}clts.csv" > /dev/null 2>&1 @@ -13390,7 +13674,6 @@ function explore_for_wps_targets_option() { language_strings "${language}" 411 "yellow" language_strings "${language}" 115 "read" - tmpfiles_toclean=1 rm -rf "${tmpdir}wps"* > /dev/null 2>&1 recalculate_windows_sizes @@ -13518,9 +13801,9 @@ function explore_for_wps_targets_option() { read -rp "> " selected_wps_target_network fi - while [[ ! ${selected_wps_target_network} =~ ^[[:digit:]]+$ ]] || (( selected_wps_target_network < 1 || selected_wps_target_network > wash_counter )) || [[ ${wps_lockeds[${selected_wps_target_network}]} = "Yes" ]]; do + while [[ ! ${selected_wps_target_network} =~ ^[[:digit:]]+$ ]] || ((selected_wps_target_network < 1 || selected_wps_target_network > wash_counter)) || [[ ${wps_lockeds[${selected_wps_target_network}]} = "Yes" ]]; do - if [[ ${selected_wps_target_network} =~ ^[[:digit:]]+$ ]] && (( selected_wps_target_network >= 1 && selected_wps_target_network <= wash_counter )); then + if [[ ${selected_wps_target_network} =~ ^[[:digit:]]+$ ]] && ((selected_wps_target_network >= 1 && selected_wps_target_network <= wash_counter)); then if [ "${wps_lockeds[${selected_wps_target_network}]}" = "Yes" ]; then ask_yesno 350 "no" if [ "${yesno}" = "y" ]; then @@ -13631,7 +13914,7 @@ function select_target() { read -rp "> " selected_target_network fi - while [[ ! ${selected_target_network} =~ ^[[:digit:]]+$ ]] || (( selected_target_network < 1 || selected_target_network > i )); do + while [[ ! ${selected_target_network} =~ ^[[:digit:]]+$ ]] || ((selected_target_network < 1 || selected_target_network > i)); do echo language_strings "${language}" 72 "red" echo @@ -14356,26 +14639,20 @@ function exit_script_option() { echo -e "${green_color} Ok\r${normal_color}" fi - if [ "${tmpfiles_toclean}" -eq 1 ]; then - action_on_exit_taken=1 - language_strings "${language}" 164 "multiline" - clean_tmpfiles - time_loop - echo -e "${green_color} Ok\r${normal_color}" - fi - if [ "${routing_modified}" -eq 1 ]; then action_on_exit_taken=1 language_strings "${language}" 297 "multiline" clean_routing_rules - kill "$(ps -C dhcpd --no-headers -o pid | tr -d ' ')" &> /dev/null - kill "$(ps -C hostapd --no-headers -o pid | tr -d ' ')" &> /dev/null - kill "$(ps -C lighttpd --no-headers -o pid | tr -d ' ')" &> /dev/null - kill_beef time_loop echo -e "${green_color} Ok\r${normal_color}" fi + action_on_exit_taken=1 + language_strings "${language}" 164 "multiline" + clean_tmpfiles "exit_script" + time_loop + echo -e "${green_color} Ok\r${normal_color}" + if [[ "${spoofed_mac}" -eq 1 ]] && [[ "${ifacemode}" = "Managed" ]]; then language_strings "${language}" 418 "multiline" restore_spoofed_macs @@ -14415,16 +14692,10 @@ function hardcore_exit() { eval "${networkmanager_cmd} > /dev/null 2>&1" fi - if [ "${tmpfiles_toclean}" -eq 1 ]; then - clean_tmpfiles - fi + clean_tmpfiles "exit_script" if [ "${routing_modified}" -eq 1 ]; then clean_routing_rules - kill "$(ps -C dhcpd --no-headers -o pid | tr -d ' ')" &> /dev/null - kill "$(ps -C hostapd --no-headers -o pid | tr -d ' ')" &> /dev/null - kill "$(ps -C lighttpd --no-headers -o pid | tr -d ' ')" &> /dev/null - kill_beef fi if [[ "${spoofed_mac}" -eq 1 ]] && [[ "${ifacemode}" = "Managed" ]]; then @@ -14451,7 +14722,7 @@ function time_loop() { debug_print echo -ne " " - for (( j=1; j<=4; j++ )); do + for ((j=1; j<=4; j++)); do echo -ne "." sleep 0.035 done @@ -15587,9 +15858,7 @@ function initialize_script_settings() { nm_processes_killed=0 airmon_fix autochanged_language=0 - tmpfiles_toclean=0 routing_modified=0 - iptables_saved=0 spoofed_mac=0 mac_spoofing_desired=0 dhcpd_path_changed=0 @@ -15622,6 +15891,7 @@ function initialize_script_settings() { custom_certificates_cn="" card_vif_support=0 country_code="00" + clean_all_iptables_nftables=1 } #Detect graphics system @@ -15911,16 +16181,6 @@ function env_vars_values_validation() { fi fi done - - if [ "${AIRGEDDON_WINDOWS_HANDLING}" = "tmux" ]; then - if hash tmux 2> /dev/null; then - transfer_to_tmux - if ! check_inside_tmux; then - exit_code=1 - exit ${exit_code} - fi - fi - fi } #Print possible issues on configuration vars @@ -16061,13 +16321,41 @@ function kill_tmux_session() { fi } +#Initialize tmux if apply +function initialize_tmux() { + + debug_print + + if [ "${1}" = "true" ]; then + if [ -n "${2}" ]; then + airgeddon_uid="${2}" + else + exit ${exit_code} + fi + else + airgeddon_uid="${BASHPID}" + fi + + session_name="airgeddon${airgeddon_uid}" + + if [ "${AIRGEDDON_WINDOWS_HANDLING}" = "tmux" ]; then + if hash tmux 2> /dev/null; then + transfer_to_tmux + if ! check_inside_tmux; then + exit_code=1 + exit ${exit_code} + fi + fi + fi +} + #Starting point of airgeddon script inside newly created tmux session function start_airgeddon_from_tmux() { debug_print tmux rename-window -t "${session_name}" "${tmux_main_window}" - tmux send-keys -t "${session_name}:${tmux_main_window}" "clear;cd ${scriptfolder};bash ${scriptname}" ENTER + tmux send-keys -t "${session_name}:${tmux_main_window}" "clear;cd ${scriptfolder};bash ${scriptname} \"true\" \"${airgeddon_uid}\"" ENTER sleep 0.2 if [ "${1}" = "normal" ]; then tmux attach -t "${session_name}" @@ -16137,24 +16425,11 @@ function check_inside_tmux() { return 1 } -#Close any existing tmux session before opening, to avoid conflicts -#shellcheck disable=SC2009 -function close_existing_airgeddon_tmux_session() { - - debug_print - - if ! check_inside_tmux; then - eval "kill -9 $(ps --no-headers aux | grep -i 'tmux.*airgeddon' | awk '{print $2}' | tr '\n' ' ') > /dev/null 2>&1" - fi -} - #Hand over script execution to tmux and call function to create a new session function transfer_to_tmux() { debug_print - close_existing_airgeddon_tmux_session - if ! check_inside_tmux; then create_tmux_session "${session_name}" "true" else @@ -16576,7 +16851,7 @@ function check_internet_access() { return 1 } -#Check for access to a url using curl +#Check for access to a URL using curl function check_url_curl() { debug_print @@ -16593,7 +16868,7 @@ function check_url_curl() { return 1 } -#Check for access to a url using wget +#Check for access to a URL using wget function check_url_wget() { debug_print @@ -16887,6 +17162,10 @@ function main() { initialize_script_settings initialize_colors env_vars_initialization + if [ "${AIRGEDDON_WINDOWS_HANDLING}" = "tmux" ]; then + initialize_tmux "${1}" "${2}" + fi + initialize_instance_settings detect_distro_phase1 detect_distro_phase2 special_distro_features @@ -16915,7 +17194,7 @@ function main() { set_default_save_path graphics_prerequisites - if [ "${tmux_error}" -eq 1 ]; then + if [[ "${AIRGEDDON_WINDOWS_HANDLING}" = "tmux" ]] && [[ "${tmux_error}" -eq 1 ]]; then language_strings "${language}" 86 "title" echo language_strings "${language}" 621 "yellow" @@ -16994,6 +17273,15 @@ function main() { fi fi + detect_running_instances + if [ "$?" -gt 1 ]; then + echo + language_strings "${language}" 720 "yellow" + echo + language_strings "${language}" 721 "blue" + language_strings "${language}" 115 "read" + fi + echo language_strings "${language}" 8 "blue" print_known_distros diff --git a/language_strings.sh b/language_strings.sh index f8c9627be..2fbaaf731 100644 --- a/language_strings.sh +++ b/language_strings.sh @@ -5191,19 +5191,19 @@ function initialize_language_strings() { arr["ARABIC",296]="جميع معايير الهجوم جاهزة ويمكن أن تبدأ. سيتم فتح العديد من لوحات المفاتيح ، لا تغلقها. عندما تريد إيقاف الهجوم ، اضغط على [Enter] في وحدة التحكم هذه وسيغلق البرنامج البرامج الأخرى تلقائيًا" arr["CHINESE",296]="所有参数和要求都已设置。攻击即将开始。将打开多个窗口,不要关闭任何窗口。当你想停止攻击时,在此窗口上按 [Enter],脚本将自动将它们全部关闭" - arr["ENGLISH",297]="Cleaning nftables/iptables and routing rules" - arr["SPANISH",297]="Limpiando nftables/iptables y reglas de routing" - arr["FRENCH",297]="Effacement des règles de routage nftables/iptables" - arr["CATALAN",297]="Netejant nftables/iptables i regles de routing" - arr["PORTUGUESE",297]="Limpando nftables/iptables e regras de roteamento" - arr["RUSSIAN",297]="Очистка nftables/iptables и правил маршуртизации" - arr["GREEK",297]="Γινεται καθαρισμός των nftables/iptables και των κανόνων δρομολόγησης" - arr["ITALIAN",297]="Pulendo nftables/iptables e le regole di routing" - arr["POLISH",297]="Usuwanie nftables/iptables i reguł routingu" - arr["GERMAN",297]="Bereinigung von nftables/iptables und Routing-Regeln" - arr["TURKISH",297]="Nftables/iptables ve routing rules temizleniyor" - arr["ARABIC",297]="وقواعد التوجيه nftables/iptables تنظيف" - arr["CHINESE",297]="清理 nftables/iptables 和路由规则" + arr["ENGLISH",297]="Cleaning nftables/iptables and routing rules if apply" + arr["SPANISH",297]="Limpiando nftables/iptables y reglas de routing si procede" + arr["FRENCH",297]="En rangeant des règles de routage nftables/iptables s'il y a lieu" + arr["CATALAN",297]="Netejant nftables/iptables i regles de routing si escau" + arr["PORTUGUESE",297]="Limpando as regras do nftables/iptables e de roteamento, se aplicável" + arr["RUSSIAN",297]="Очистка nftables/iptables и правил маршрутизации если применимо" + arr["GREEK",297]="Γίνεται καθαρισμός των nftables/iptables και των routing rules εάν υπάρχουν" + arr["ITALIAN",297]="Pulendo nftables/iptables e le regole di routing se necessario" + arr["POLISH",297]="Usuwanie nftables/iptables i reguł routingu jeśli istnieją" + arr["GERMAN",297]="Bereinigung von nftables/iptables und Routing-Regeln falls zutreffend" + arr["TURKISH",297]="nftables/iptables ve routing rules varsa temizleniyor" + arr["ARABIC",297]="وقواعد التوجيه إذا لزم nftables/iptables تنظيف" + arr["CHINESE",297]="清理 nftables/iptables 路由规则 (如果适用)" arr["ENGLISH",298]="Evil Twin attack has been started. Press [Enter] key on this window to stop it" arr["SPANISH",298]="El ataque Evil Twin ha comenzado. Pulse la tecla [Enter] en esta ventana para pararlo" @@ -11101,17 +11101,45 @@ function initialize_language_strings() { arr["ENGLISH",719]="One of your wireless adapters has a built-in country code different from the one set on your system. When this happens the kernel makes a custom regulatory domain \"\${normal_color}99\${yellow_color}\" which contains only permissions in BOTH reg domains. Either your hardware is from a different region, or you have improperly set your reg domain and limited your functionality on purpose" arr["SPANISH",719]="Uno de tus adaptadores wifi tiene un código de país integrado diferente al configurado en el sistema. Cuando esto sucede, el kernel crea un dominio regulatorio personalizado \"\${normal_color}99\${yellow_color}\" que contiene solo permisos en AMBOS dominios de registro. O tu hardware es de una región diferente o configuraste incorrectamente el dominio de registro y limitando su funcionalidad a propósito" - arr["FRENCH",719]="\${pending_of_translation} L'un de vos adaptateurs Wi-Fi possède un code de pays intégré différent de celui défini sur votre système. Lorsque cela se produit, le noyau crée un domaine réglementaire personnalisé \"\${normal_color}99\${yellow_color}\" qui contient uniquement les autorisations dans les DEUX domaines reg. Soit votre matériel provient d'une région différente, soit vous avez mal défini votre domaine d'enregistrement et limité volontairement vos fonctionnalités" - arr["CATALAN",719]="\${pending_of_translation} Un dels vostres adaptadors wifi té un codi de país integrat diferent del establert al vostre sistema. Quan això succeeix, el nucli crea un domini regulador personalitzat \"\${normal_color}99\${yellow_color}\" que només conté permisos als DOS dominis reg. O el vostre maquinari és d'una regió diferent o heu configurat el vostre domini de registre incorrectament i heu limitat la vostra funcionalitat a propòsit" - arr["PORTUGUESE",719]="\${pending_of_translation} Um de seus adaptadores wi-fi possui um código de país integrado diferente daquele definido em seu sistema. Quando isso acontece, o kernel cria um domínio regulatório personalizado \"\${normal_color}99\${yellow_color}\" que contém apenas permissões em AMBOS os domínios reg. Ou seu hardware é de uma região diferente ou você configurou incorretamente seu domínio de registro e limitou sua funcionalidade propositalmente" - arr["RUSSIAN",719]="\${pending_of_translation} Один из ваших адаптеров Wi-Fi имеет встроенный код страны, отличный от кода, установленного в вашей системе. Когда это происходит, ядро создает собственный нормативный домен \"\${normal_color}99\${yellow_color}\", который содержит разрешения только в ОБОИХ доменах регистрации. Либо ваше оборудование из другого региона, либо вы неправильно настроили рег-домен и намеренно ограничили функциональность" - arr["GREEK",719]="\${pending_of_translation} Ένας από τους προσαρμογείς wifi σας έχει ενσωματωμένο κωδικό χώρας διαφορετικό από αυτόν που έχει οριστεί στο σύστημά σας. Όταν συμβεί αυτό, ο πυρήνας δημιουργεί έναν προσαρμοσμένο ρυθμιστικό τομέα \"\${normal_color}99\${yellow_color}\" ο οποίος περιέχει μόνο δικαιώματα και στους δύο τομείς reg. Είτε το υλικό σας προέρχεται από διαφορετική περιοχή, είτε έχετε ρυθμίσει εσφαλμένα τον τομέα reg σας και έχετε περιορίσει τη λειτουργικότητά σας επίτηδες" - arr["ITALIAN",719]="\${pending_of_translation} Uno dei tuoi adattatori Wi-Fi ha un codice paese integrato diverso da quello impostato sul tuo sistema. Quando ciò accade, il kernel crea un dominio normativo personalizzato \"\${normal_color}99\${yellow_color}\" che contiene solo le autorizzazioni in ENTRAMBI i domini reg. O il tuo hardware proviene da una regione diversa oppure hai impostato in modo errato il tuo dominio reg e limitato di proposito la tua funzionalità" - arr["POLISH",719]="\${pending_of_translation} Jeden z Twoich adapterów Wi-Fi ma wbudowany kod kraju inny niż ten ustawiony w Twoim systemie. Kiedy tak się dzieje, jądro tworzy niestandardową domenę regulacyjną \"\${normal_color}99\${yellow_color}\", która zawiera tylko uprawnienia w OBU domenach rej. Albo Twój sprzęt pochodzi z innego regionu, albo nieprawidłowo ustawiłeś domenę rejestracyjną i celowo ograniczyłeś funkcjonalność" - arr["GERMAN",719]="\${pending_of_translation} Einer Ihrer WLAN-Adapter verfügt über einen integrierten Ländercode, der sich von dem auf Ihrem System unterscheidet. Wenn dies geschieht, erstellt der Kernel eine benutzerdefinierte Regulierungsdomäne \"\${normal_color}99\${yellow_color}\", die nur Berechtigungen in BEIDEN Registrierungsdomänen enthält. Entweder stammt Ihre Hardware aus einer anderen Region oder Sie haben Ihre Reg-Domain falsch eingestellt und Ihre Funktionalität absichtlich eingeschränkt" - arr["TURKISH",719]="\${pending_of_translation} Wifi bağdaştırıcılarınızdan birinde, sisteminizde ayarlanandan farklı yerleşik bir ülke kodu var. Bu gerçekleştiğinde çekirdek, yalnızca HER İKİ Reg etki alanındaki izinleri içeren özel bir düzenleyici etki alanı \"\${normal_color}99\${yellow_color}\" oluşturur. Ya donanımınız farklı bir bölgeye ait ya da reg alan adınızı yanlış ayarladınız ve işlevselliğinizi bilerek sınırladınız" - arr["ARABIC",719]="\${pending_of_translation} يحتوي أحد محولات wifi لديك على رمز بلد مدمج يختلف عن الرمز المعين على نظامك. عندما يحدث هذا، تقوم النواة بإنشاء مجال تنظيمي مخصص \"\${normal_color}99\${yellow_color}\" والذي يحتوي فقط على الأذونات في كلا نطاقي التسجيل. إما أن جهازك ينتمي إلى منطقة مختلفة، أو أنك قمت بتعيين نطاق التسجيل الخاص بك بشكل غير صحيح وقمت بتقييد وظائفك عن قصد" - arr["CHINESE",719]="\${pending_of_translation} 您的其中一款 WiFi 适配器的内置国家/地区代码与您系统上设置的国家/地区代码不同。当发生这种情况时,内核会创建一个自定义监管域 \"\${normal_color}99\${yellow_color}\",其中仅包含两个监管域中的权限。您的硬件来自不同的地区,或者您不正确地设置了您的注册域并故意限制了您的功能" + arr["FRENCH",719]="Une des vos adaptateurs Wi-Fi a un code de pays intégré différent de celui défini sur votre système. Quand cela se produit, le Kernel crée un domaine réglementaire personnalisé \"\${normal_color}99\${yellow_color}\" qui contient uniquement les autorisations dans les DEUX domaines inscrits. Peut votre matériel provient d'une région différente ou vous avez mal défini votre domaine d'enregistrement et limité volontairement vos fonctionnalités" + arr["CATALAN",719]="Un dels vostres adaptadors wifi té un codi de país integrat diferent del establert al vostre sistema. Quan això succeeix, el nucli crea un domini regulador personalitzat \"\${normal_color}99\${yellow_color}\" que només conté permisos als DOS dominis reg. O el vostre maquinari és d'una regió diferent o heu configurat el vostre domini de registre incorrectament i heu limitat la vostra funcionalitat a propòsit" + arr["PORTUGUESE",719]="Um dos seus adaptadores wi-fi possui um código de país integrado diferente do definido em seu sistema. Quando isso acontece, o kernel cria um domínio regulatório personalizado \"\${normal_color}99\${yellow_color}\" que contém apenas permissões em AMBOS. Ou seu hardware é de uma região diferente, ou você configurou incorretamente seu domínio de registro e limitou sua funcionalidade propositalmente" + arr["RUSSIAN",719]="Один из ваших Wi-Fi адаптеров имеет вшитый код страны, отличный от установленного в вашей системе. Когда это происходит, ядро создает кастомный регулятивный домен \"\${normal_color}99\${yellow_color}\", который содержит общие разрешения доступные в ОБОИХ доменах регистрации. Либо ваше оборудование из другого региона, либо вы неправильно настроили регулятивный домен и намеренно ограничили функциональность" + arr["GREEK",719]="Ένας από τους αντάπτορες δικτύου wifi σας έχει ενσωματωμένο κωδικό χώρας διαφορετικό από αυτόν που έχει οριστεί στο σύστημά σας. Όταν συμβαίνει αυτό, ο kernel δημιουργεί ένα custom regulatory domain \"\${normal_color}99\${yellow_color}\" το οποίο περιέχει μόνο δικαιώματα και στα δύο reg domains. Είτε το hardware σας προέρχεται από διαφορετική περιοχή, είτε έχετε ρυθμίσει εσφαλμένα το domain reg σας και έχετε περιορίσει τη λειτουργικότητά σας επίτηδες" + arr["ITALIAN",719]="Uno dei tuoi adattatori Wi-Fi ha un codice paese integrato diverso da quello impostato sul tuo sistema. Quando ciò accade, il kernel crea un dominio normativo personalizzato \"\${normal_color}99\${yellow_color}\" che contiene solo le autorizzazioni in ENTRAMBI i domini di registro. O il tuo hardware proviene da una regione diversa oppure hai impostato in modo errato il tuo dominio di registro limitando quindi a proposito la sua funzionalità" + arr["POLISH",719]="Jeden z Twoich adapterów Wi-Fi ma wbudowany kod kraju inny, niż ustawiony w Twoim systemie. Kiedy tak się dzieje, kernel tworzy niestandardową domenę regulacyjną \"\${normal_color}99\${yellow_color}\", która zawiera tylko uprawnienia w OBYDWU domenach regulacyjnych. Albo Twój sprzęt pochodzi z innego regionu, albo celowo nieprawidłowo ustawiłeś domenę rejestracyjną i ograniczyłeś funkcjonalność" + arr["GERMAN",719]="Einer Ihrer WLAN-Adapter hat einen integrierten Ländercode, der sich von dem auf Ihrem System unterscheidet. Wenn dies geschieht, erstellt der Kernel eine spezielle Regulierungsdomäne \"\${normal_color}99\${yellow_color}\", die nur Berechtigungen in BEIDEN Registrierungsdomänen enthält. Entweder stammt Ihre Hardware aus einer anderen Region oder Sie haben Ihre Reg-Domain falsch eingestellt und die Funktionalität absichtlich eingeschränkt" + arr["TURKISH",719]="Wifi bağdaştırıcılarınızdan birinde, sisteminizde ayarlanandan farklı bir yerleşik ülke kodu var. Bu gerçekleştiğinde Kernel, yalnızca HER İKİ Reg etki alanındaki izinleri içeren özel bir düzenleyici etki alanı \"\${normal_color}99\${yellow_color}\" oluşturur. Ya donanımınız farklı bir bölgeye ait ya da reg alan adınızı yanlış ayarladınız ve işlevselliğinizi bilerek sınırladınız" + arr["ARABIC",719]="والذي يحتوي فقط على الأذونات في كلا نطاقي التسجيل. إما أن جهازك ينتمي إلى منطقة مختلفة، أو أنك قمت بتعيين نطاق التسجيل الخاص بك بشكل غير صحيح وقمت بتقييد وظائفك عن قصد \"\${yellow_color}99\${normal_color}\" بانشاء مجال تنظيمي مخصص kernel علي رمز بلد غير الرمز الموجود علي نظامك. عندما يحدث هذا, يقوم ال wireless adapter يحتوي احدى ال " + arr["CHINESE",719]="您的其中一款 WiFi 适配器的内置国家/地区代码与您系统上设置的国家/地区代码不同。当发生这种情况时,系统内核会创建一个自定义的监管域 \"\${normal_color}99\${yellow_color}\",其中仅包含两个监管域中的权限。发生这种情况可能是您的硬件来自不同的地区,或您不正确地设置了注册域并故意限制了您的功能" + + arr["ENGLISH",720]="It was detected more than one airgeddon instance running. Keep in mind that sharing and using the same wireless adapter in more than one instance at the same time, probably will lead to uncontrolled errors or unexpected results" + arr["SPANISH",720]="Se ha detectado más de una instancia de airgeddon ejecutándose. Ten en cuenta que compartir y utilizar el mismo adaptador inalámbrico en más de una instancia al mismo tiempo probablemente provocará errores no controlados o resultados inesperados" + arr["FRENCH",720]="Il a été détecté plus d'une instance d'airgeddon en exécution. Prendre en compte que le partage et l'utilisation du même adaptateur sans fil dans plusieurs instances au même temps, peut entraîner des erreurs incontrôlées ou des résultats imprévus" + arr["CATALAN",720]="S'ha detectat més d'una instància d'airgeddon en execució. Tingueu en compte que compartir i utilitzar el mateix adaptador sense fil en més d'una instància alhora, probablement provocarà errors incontrolats o resultats inesperats" + arr["PORTUGUESE",720]="Existe mais de uma instância do airgeddon em execução. Tenha em mente que usar o mesmo adaptador wi-fi em mais de uma instância simultaneamente provavelmente levará a erros e resultados inesperados" + arr["RUSSIAN",720]="Было обнаружено, что запущено несколько инстансов airgeddon. Имейте в виду, что совместное использование одного и того же беспроводного адаптера более чем в одном инстансе одновременно может привести к неконтролируемым ошибкам или неожиданным результатам" + arr["GREEK",720]="Εντοπίστηκαν περισσότερο από ένα instance του airgeddon σε λειτουργία. Λάβετε υπόψη ότι η κοινή χρήση του ασύρματου αντάπτορα σε περισσότερα από ένα instance ταυτόχρονα, πιθανότατα θα σας οδηγήσει σε μη ελεγχόμενα σφάλματα ή απροσδόκητα αποτελέσματα" + arr["ITALIAN",720]="È stata rilevata più di un'istanza di airgeddon in esecuzione. Tieni presente che la condivisione e l'utilizzo dello stesso adattatore wireless in più istanze contemporaneamente porterà probabilmente a errori incontrollati o risultati imprevisti" + arr["POLISH",720]="Wykryto, że airgeddon został uruchomiony więcej niż raz. Należy pamiętać, że współdzielenie i używanie tej samej karty bezprzewodowej w więcej niż jednej instancji jednocześnie najprawdopodobniej doprowadzi do niekontrolowanych błędów lub nieoczekiwanych rezultatów" + arr["GERMAN",720]="Es wurde festgestellt, dass mehr als eine Airgeddon-Instanz ausgeführt wird. Beachten Sie, dass die gemeinsame Nutzung und Verwendung desselben WLAN-Adapters in mehreren Instanzen gleichzeitig wahrscheinlich zu unkontrollierten Fehlern oder unerwarteten Ergebnissen führt" + arr["TURKISH",720]="airgeddon'un birden fazla kere aynı anda çalıştığı tespit edildi. Aynı kablosuz bağdaştırıcıyı aynı anda paylaşmanın ve kullanmanın muhtemelen kontrol edilemeyen hatalara veya beklenmeyen sonuçlara yol açacağını unutmayın" + arr["ARABIC",720]="في أكثر من حالة في نفس الوقت، قد يؤدي على الأرجح إلى أخطاء لا يمكن التحكم فيها أو نتائج غير متوقعة wireless adapter قيد التشغيل. يجب العلم أن مشاركة واستخدام نفس airgeddon تم اكتشاف وجود أكثر من " + arr["CHINESE",720]="检测到有多个 airgeddon 实例正在运行。请注意,在多个实例中共享并使用同一个无线适配器可能会导致无法控制的错误或意外结果" + + arr["ENGLISH",721]="Number of running instances: \${normal_color}\${airgeddon_running_instances_counter}" + arr["SPANISH",721]="Número de instancias en ejecución: \${normal_color}\${airgeddon_running_instances_counter}" + arr["FRENCH",721]="Numéro d'instances en exécution: \${normal_color}\${airgeddon_running_instances_counter}" + arr["CATALAN",721]="Nombre d'instàncies en execució: \${normal_color}\${airgeddon_running_instances_counter}" + arr["PORTUGUESE",721]="Número de instâncias em execução: \${normal_color}\${airgeddon_running_instances_counter}" + arr["RUSSIAN",721]="Количество запущенных инстансов: \${normal_color}\${airgeddon_running_instances_counter}" + arr["GREEK",721]="Αριθμός instances που εκτελούνται: \${normal_color}\${airgeddon_running_instances_counter}" + arr["ITALIAN",721]="Numero di istanze in esecuzione: \${normal_color}\${airgeddon_running_instances_counter}" + arr["POLISH",721]="Liczba uruchomionych instancji: \${normal_color}\${airgeddon_running_instances_counter}" + arr["GERMAN",721]="Anzahl der laufenden Instanzen: \${normal_color}\${airgeddon_running_instances_counter}" + arr["TURKISH",721]="Çalışan airgeddon uygulamalarının sayısı: \${normal_color}\${airgeddon_running_instances_counter}" + arr["ARABIC",721]="\${normal_color}\${airgeddon_running_instances_counter}\${blue_color} :عدد المثيلات قيد التشغيل" + arr["CHINESE",721]="正在运行的实例数:\${normal_color}\${airgeddon_running_instances_counter}" } #Expand escaped variables in language strings with their actual values