From d3e90d708a8d09568af14612e0b40f449ac135ee Mon Sep 17 00:00:00 2001 From: Just Call Me Koko Date: Thu, 13 Oct 2022 15:20:26 -0400 Subject: [PATCH] Add raw cap and manual deauth --- esp32_marauder/CommandLine.cpp | 44 ++++++++--- esp32_marauder/CommandLine.h | 4 +- esp32_marauder/MenuFunctions.cpp | 11 +++ esp32_marauder/WiFiScan.cpp | 122 +++++++++++++++++++++++++++++++ esp32_marauder/WiFiScan.h | 7 ++ esp32_marauder/configs.h | 14 ++-- esp32_marauder/lang_var.h | 3 +- 7 files changed, 187 insertions(+), 18 deletions(-) diff --git a/esp32_marauder/CommandLine.cpp b/esp32_marauder/CommandLine.cpp index 71fe30c..6eddd6d 100644 --- a/esp32_marauder/CommandLine.cpp +++ b/esp32_marauder/CommandLine.cpp @@ -116,6 +116,7 @@ void CommandLine::runCommand(String input) { // WiFi sniff/scan Serial.println(HELP_SCANAP_CMD); + Serial.println(HELP_SNIFF_RAW_CMD); Serial.println(HELP_SNIFF_BEACON_CMD); Serial.println(HELP_SNIFF_PROBE_CMD); Serial.println(HELP_SNIFF_PWN_CMD); @@ -248,6 +249,15 @@ void CommandLine::runCommand(String input) { wifi_scan_obj.StartScan(WIFI_SCAN_TARGET_AP_FULL, TFT_MAGENTA); } } + // Raw sniff + else if (cmd_args.get(0) == SNIFF_RAW_CMD) { + Serial.println("Starting Raw sniff. Stop with " + (String)STOPSCAN_CMD); + #ifdef HAS_SCREEN + display_obj.clearScreen(); + menu_function_obj.drawStatusBar(); + #endif + wifi_scan_obj.StartScan(WIFI_SCAN_RAW_CAPTURE, TFT_WHITE); + } // Beacon sniff else if (cmd_args.get(0) == SNIFF_BEACON_CMD) { Serial.println("Starting Beacon sniff. Stop with " + (String)STOPSCAN_CMD); @@ -322,6 +332,8 @@ void CommandLine::runCommand(String input) { int list_beacon_sw = this->argSearch(&cmd_args, "-l"); int rand_beacon_sw = this->argSearch(&cmd_args, "-r"); int ap_beacon_sw = this->argSearch(&cmd_args, "-a"); + int src_addr_sw = this->argSearch(&cmd_args, "-s"); + int dst_addr_sw = this->argSearch(&cmd_args, "-d"); if (attack_type_switch == -1) { Serial.println("You must specify an attack type"); @@ -333,16 +345,30 @@ void CommandLine::runCommand(String input) { // Branch on attack type // Deauth if (attack_type == ATTACK_TYPE_DEAUTH) { - if (!this->apSelected()) { - Serial.println("You don't have any targets selected. Use " + (String)SEL_CMD); - return; + if (src_addr_sw == -1) { + if (!this->apSelected()) { + Serial.println("You don't have any targets selected. Use " + (String)SEL_CMD); + return; + } + #ifdef HAS_SCREEN + display_obj.clearScreen(); + menu_function_obj.drawStatusBar(); + #endif + Serial.println("Starting Deauthentication attack. Stop with " + (String)STOPSCAN_CMD); + wifi_scan_obj.StartScan(WIFI_ATTACK_DEAUTH, TFT_RED); + } + else { + String src_mac_str = cmd_args.get(src_addr_sw + 1); + sscanf(src_mac_str.c_str(), "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx", + &wifi_scan_obj.src_mac[0], &wifi_scan_obj.src_mac[1], &wifi_scan_obj.src_mac[2], &wifi_scan_obj.src_mac[3], &wifi_scan_obj.src_mac[4], &wifi_scan_obj.src_mac[5]); + + #ifdef HAS_SCREEN + display_obj.clearScreen(); + menu_function_obj.drawStatusBar(); + #endif + Serial.println("Starting Manual Deauthentication attack. Stop with " + (String)STOPSCAN_CMD); + wifi_scan_obj.StartScan(WIFI_ATTACK_DEAUTH_MANUAL, TFT_RED); } - #ifdef HAS_SCREEN - display_obj.clearScreen(); - menu_function_obj.drawStatusBar(); - #endif - Serial.println("Starting Deauthentication attack. Stop with " + (String)STOPSCAN_CMD); - wifi_scan_obj.StartScan(WIFI_ATTACK_DEAUTH, TFT_RED); } // Beacon else if (attack_type == ATTACK_TYPE_BEACON) { diff --git a/esp32_marauder/CommandLine.h b/esp32_marauder/CommandLine.h index 8c7ab5d..9616b82 100644 --- a/esp32_marauder/CommandLine.h +++ b/esp32_marauder/CommandLine.h @@ -38,6 +38,7 @@ const char PROGMEM SETTINGS_CMD[] = "settings"; // WiFi sniff/scan const char PROGMEM SCANAP_CMD[] = "scanap"; +const char PROGMEM SNIFF_RAW_CMD[] = "sniffraw"; const char PROGMEM SNIFF_BEACON_CMD[] = "sniffbeacon"; const char PROGMEM SNIFF_PROBE_CMD[] = "sniffprobe"; const char PROGMEM SNIFF_PWN_CMD[] = "sniffpwn"; @@ -76,6 +77,7 @@ const char PROGMEM HELP_SETTINGS_CMD[] = "settings [-s enable/disable> // WiFi sniff/scan const char PROGMEM HELP_SCANAP_CMD[] = "scanap"; +const char PROGMEM HELP_SNIFF_RAW_CMD[] = "sniffraw"; const char PROGMEM HELP_SNIFF_BEACON_CMD[] = "sniffbeacon"; const char PROGMEM HELP_SNIFF_PROBE_CMD[] = "sniffprobe"; const char PROGMEM HELP_SNIFF_PWN_CMD[] = "sniffpwn"; @@ -85,7 +87,7 @@ const char PROGMEM HELP_SNIFF_PMKID_CMD[] = "sniffpmkid [-c ]"; const char PROGMEM HELP_STOPSCAN_CMD[] = "stopscan"; // WiFi attack -const char PROGMEM HELP_ATTACK_CMD[] = "attack -t "; +const char PROGMEM HELP_ATTACK_CMD[] = "attack -t ]/probe/rickroll>"; // WiFi Aux const char PROGMEM HELP_LIST_AP_CMD_A[] = "list -s"; diff --git a/esp32_marauder/MenuFunctions.cpp b/esp32_marauder/MenuFunctions.cpp index 4bc0f1c..4a76bb9 100644 --- a/esp32_marauder/MenuFunctions.cpp +++ b/esp32_marauder/MenuFunctions.cpp @@ -840,6 +840,7 @@ void MenuFunctions::main(uint32_t currentTime) (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AP_SPAM) && (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AUTH) && (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH) && + (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH_MANUAL) && (wifi_scan_obj.currentScanMode != WIFI_ATTACK_MIMIC) && (wifi_scan_obj.currentScanMode != WIFI_ATTACK_RICK_ROLL)) display_obj.displayBuffer(); @@ -865,6 +866,7 @@ void MenuFunctions::main(uint32_t currentTime) { // Stop the current scan if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) || + (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) || (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) || (wifi_scan_obj.currentScanMode == WIFI_SCAN_TARGET_AP) || (wifi_scan_obj.currentScanMode == WIFI_SCAN_TARGET_AP_FULL) || @@ -876,6 +878,7 @@ void MenuFunctions::main(uint32_t currentTime) (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AP_SPAM) || (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AUTH) || (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH) || + (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH_MANUAL) || (wifi_scan_obj.currentScanMode == WIFI_ATTACK_MIMIC) || (wifi_scan_obj.currentScanMode == WIFI_ATTACK_RICK_ROLL) || (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BEACON_LIST) || @@ -911,6 +914,7 @@ void MenuFunctions::main(uint32_t currentTime) { // Stop the current scan if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) || + (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) || (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) || (wifi_scan_obj.currentScanMode == WIFI_SCAN_TARGET_AP) || (wifi_scan_obj.currentScanMode == WIFI_SCAN_TARGET_AP_FULL) || @@ -922,6 +926,7 @@ void MenuFunctions::main(uint32_t currentTime) (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AP_SPAM) || (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AUTH) || (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH) || + (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH_MANUAL) || (wifi_scan_obj.currentScanMode == WIFI_ATTACK_MIMIC) || (wifi_scan_obj.currentScanMode == WIFI_ATTACK_RICK_ROLL) || (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BEACON_LIST) || @@ -957,6 +962,7 @@ void MenuFunctions::main(uint32_t currentTime) (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AP_SPAM) && (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AUTH) && (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH) && + (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH_MANUAL) && (wifi_scan_obj.currentScanMode != WIFI_ATTACK_MIMIC) && (wifi_scan_obj.currentScanMode != WIFI_ATTACK_RICK_ROLL)) //(wifi_scan_obj.currentScanMode != WIFI_ATTACK_BEACON_LIST)) @@ -1563,6 +1569,11 @@ void MenuFunctions::RunSetup() this->drawStatusBar(); wifi_scan_obj.StartScan(WIFI_SCAN_TARGET_AP, TFT_MAGENTA); }); + addNodes(&wifiSnifferMenu, text_table1[58], TFT_WHITE, NULL, PACKET_MONITOR, [this]() { + display_obj.clearScreen(); + this->drawStatusBar(); + wifi_scan_obj.StartScan(WIFI_SCAN_RAW_CAPTURE, TFT_WHITE); + }); // Build WiFi attack menu wifiAttackMenu.parentMenu = &wifiMenu; // Main Menu is second menu parent diff --git a/esp32_marauder/WiFiScan.cpp b/esp32_marauder/WiFiScan.cpp index 10e812a..d993d21 100644 --- a/esp32_marauder/WiFiScan.cpp +++ b/esp32_marauder/WiFiScan.cpp @@ -281,6 +281,8 @@ void WiFiScan::StartScan(uint8_t scan_mode, uint16_t color) RunEapolScan(scan_mode, color); else if (scan_mode == WIFI_SCAN_AP) RunBeaconScan(scan_mode, color); + else if (scan_mode == WIFI_SCAN_RAW_CAPTURE) + RunRawScan(scan_mode, color); else if (scan_mode == WIFI_SCAN_TARGET_AP) RunAPScan(scan_mode, color); else if (scan_mode == WIFI_SCAN_TARGET_AP_FULL) @@ -304,6 +306,8 @@ void WiFiScan::StartScan(uint8_t scan_mode, uint16_t color) this->startWiFiAttacks(scan_mode, color, text_table4[7]); else if (scan_mode == WIFI_ATTACK_DEAUTH) this->startWiFiAttacks(scan_mode, color, text_table4[8]); + else if (scan_mode == WIFI_ATTACK_DEAUTH_MANUAL) + this->startWiFiAttacks(scan_mode, color, text_table4[8]); else if (scan_mode == WIFI_ATTACK_AP_SPAM) this->startWiFiAttacks(scan_mode, color, " AP Beacon Spam "); else if (scan_mode == BT_SCAN_ALL) { @@ -413,6 +417,7 @@ void WiFiScan::StopScan(uint8_t scan_mode) { if ((currentScanMode == WIFI_SCAN_PROBE) || (currentScanMode == WIFI_SCAN_AP) || + (currentScanMode == WIFI_SCAN_RAW_CAPTURE) || (currentScanMode == WIFI_SCAN_TARGET_AP) || (currentScanMode == WIFI_SCAN_TARGET_AP_FULL) || (currentScanMode == WIFI_SCAN_PWN) || @@ -425,6 +430,7 @@ void WiFiScan::StopScan(uint8_t scan_mode) (currentScanMode == WIFI_ATTACK_BEACON_SPAM) || (currentScanMode == WIFI_ATTACK_AUTH) || (currentScanMode == WIFI_ATTACK_DEAUTH) || + (currentScanMode == WIFI_ATTACK_DEAUTH_MANUAL) || (currentScanMode == WIFI_ATTACK_MIMIC) || (currentScanMode == WIFI_ATTACK_RICK_ROLL) || (currentScanMode == WIFI_PACKET_MONITOR) || @@ -1061,6 +1067,43 @@ void WiFiScan::RunBeaconScan(uint8_t scan_mode, uint16_t color) initTime = millis(); } +void WiFiScan::RunRawScan(uint8_t scan_mode, uint16_t color) +{ + sd_obj.openCapture("raw"); + + #ifdef MARAUDER_FLIPPER + flipper_led.sniffLED(); + #endif + + #ifdef HAS_SCREEN + display_obj.TOP_FIXED_AREA_2 = 48; + display_obj.tteBar = true; + display_obj.print_delay_1 = 15; + display_obj.print_delay_2 = 10; + display_obj.initScrollValues(true); + display_obj.tft.setTextWrap(false); + display_obj.tft.setTextColor(TFT_WHITE, color); + #ifndef MARAUDER_MINI + display_obj.tft.fillRect(0,16,240,16, color); + display_obj.tft.drawCentreString(text_table1[58],120,16,2); + display_obj.touchToExit(); + #endif + display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK); + display_obj.setupScrollArea(display_obj.TOP_FIXED_AREA_2, BOT_FIXED_AREA); + #endif + + esp_wifi_init(&cfg); + esp_wifi_set_storage(WIFI_STORAGE_RAM); + esp_wifi_set_mode(WIFI_MODE_NULL); + esp_wifi_start(); + esp_wifi_set_promiscuous(true); + esp_wifi_set_promiscuous_filter(&filt); + esp_wifi_set_promiscuous_rx_cb(&rawSnifferCallback); + esp_wifi_set_channel(set_channel, WIFI_SECOND_CHAN_NONE); + this->wifi_initialized = true; + initTime = millis(); +} + void WiFiScan::RunDeauthScan(uint8_t scan_mode, uint16_t color) { sd_obj.openCapture("deauth"); @@ -1752,6 +1795,65 @@ void WiFiScan::beaconSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type } } +void WiFiScan::rawSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) +{ + bool save_packet = settings_obj.loadSetting(text_table4[7]); + + wifi_promiscuous_pkt_t *snifferPacket = (wifi_promiscuous_pkt_t*)buf; + WifiMgmtHdr *frameControl = (WifiMgmtHdr*)snifferPacket->payload; + wifi_pkt_rx_ctrl_t ctrl = (wifi_pkt_rx_ctrl_t)snifferPacket->rx_ctrl; + int len = snifferPacket->rx_ctrl.sig_len; + + String display_string = ""; + + if (type == WIFI_PKT_MGMT) + { + len -= 4; + int fctl = ntohs(frameControl->fctl); + const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)snifferPacket->payload; + const WifiMgmtHdr *hdr = &ipkt->hdr; + } + + Serial.print("RSSI: "); + Serial.print(snifferPacket->rx_ctrl.rssi); + Serial.print(" Ch: "); + Serial.print(snifferPacket->rx_ctrl.channel); + Serial.print(" BSSID: "); + char addr[] = "00:00:00:00:00:00"; + getMAC(addr, snifferPacket->payload, 10); + Serial.print(addr); + display_string.concat(text_table4[0]); + display_string.concat(snifferPacket->rx_ctrl.rssi); + + display_string.concat(" "); + display_string.concat(addr); + + int temp_len = display_string.length(); + + #ifdef HAS_SCREEN + for (int i = 0; i < 40 - temp_len; i++) + { + display_string.concat(" "); + } + + Serial.print(" "); + + if (display_obj.display_buffer->size() == 0) + { + display_obj.loading = true; + display_obj.display_buffer->add(display_string); + display_obj.loading = false; + } + #endif + + + + Serial.println(); + + if (save_packet) + sd_obj.addPacket(snifferPacket->payload, len); +} + void WiFiScan::deauthSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) { bool save_packet = settings_obj.loadSetting(text_table4[7]); @@ -3105,6 +3207,26 @@ void WiFiScan::main(uint32_t currentTime) packets_sent = 0; } } + else if (currentScanMode == WIFI_ATTACK_DEAUTH_MANUAL) { + for (int i = 0; i < 55; i++) + this->sendDeauthFrame(this->src_mac, this->set_channel); + + if (currentTime - initTime >= 1000) { + initTime = millis(); + String displayString = ""; + String displayString2 = ""; + displayString.concat(text18); + displayString.concat(packets_sent); + for (int x = 0; x < STANDARD_FONT_CHAR_LIMIT; x++) + displayString2.concat(" "); + #ifdef HAS_SCREEN + display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK); + display_obj.showCenterText(displayString2, 160); + display_obj.showCenterText(displayString, 160); + #endif + packets_sent = 0; + } + } else if ((currentScanMode == WIFI_ATTACK_MIMIC)) { // Need this for loop because getTouch causes ~10ms delay // which makes beacon spam less effective diff --git a/esp32_marauder/WiFiScan.h b/esp32_marauder/WiFiScan.h index 8bf3c1a..1f8ecec 100644 --- a/esp32_marauder/WiFiScan.h +++ b/esp32_marauder/WiFiScan.h @@ -62,6 +62,8 @@ #define WIFI_ATTACK_AP_SPAM 21 #define WIFI_SCAN_TARGET_AP_FULL 22 #define WIFI_SCAN_ACTIVE_EAPOL 23 +#define WIFI_ATTACK_DEAUTH_MANUAL 24 +#define WIFI_SCAN_RAW_CAPTURE 25 #define GRAPH_REFRESH 100 @@ -249,6 +251,7 @@ class WiFiScan void RunEspressifScan(uint8_t scan_mode, uint16_t color); void RunPwnScan(uint8_t scan_mode, uint16_t color); void RunBeaconScan(uint8_t scan_mode, uint16_t color); + void RunRawScan(uint8_t scan_mode, uint16_t color); void RunDeauthScan(uint8_t scan_mode, uint16_t color); void RunEapolScan(uint8_t scan_mode, uint16_t color); void RunProbeScan(uint8_t scan_mode, uint16_t color); @@ -280,6 +283,9 @@ class WiFiScan String old_free_ram = ""; String connected_network = ""; + byte dst_mac[6] = {}; + byte src_mac[6] = {}; + //lv_obj_t * scr = lv_cont_create(NULL, NULL); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); @@ -315,6 +321,7 @@ class WiFiScan static void espressifSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type); static void pwnSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type); static void beaconSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type); + static void rawSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type); static void apSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type); static void apSnifferCallbackFull(void* buf, wifi_promiscuous_pkt_type_t type); static void deauthSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type); diff --git a/esp32_marauder/configs.h b/esp32_marauder/configs.h index 1c6e47a..6222d19 100644 --- a/esp32_marauder/configs.h +++ b/esp32_marauder/configs.h @@ -5,13 +5,13 @@ #define POLISH_POTATO //#define MARAUDER_MINI - //#define MARAUDER_V4 + #define MARAUDER_V4 //#define MARAUDER_V6 //#define MARAUDER_KIT //#define GENERIC_ESP32 - #define MARAUDER_FLIPPER + //#define MARAUDER_FLIPPER - #define MARAUDER_VERSION "v0.9.15" + #define MARAUDER_VERSION "v0.9.16" //// BUTTON DEFINITIONS #ifdef MARAUDER_MINI @@ -55,7 +55,7 @@ //#define MENU_FONT &FreeMonoBold9pt7b //#define MENU_FONT &FreeSans9pt7b //#define MENU_FONT &FreeSansBold9pt7b - #define BUTTON_ARRAY_LEN 9 + #define BUTTON_ARRAY_LEN 10 #define STATUS_BAR_WIDTH 16 #define LVGL_TICK_PERIOD 6 @@ -109,7 +109,7 @@ //#define MENU_FONT &FreeMonoBold9pt7b //#define MENU_FONT &FreeSans9pt7b //#define MENU_FONT &FreeSansBold9pt7b - #define BUTTON_ARRAY_LEN 9 + #define BUTTON_ARRAY_LEN 10 #define STATUS_BAR_WIDTH 16 #define LVGL_TICK_PERIOD 6 @@ -164,7 +164,7 @@ //#define MENU_FONT &FreeMonoBold9pt7b //#define MENU_FONT &FreeSans9pt7b //#define MENU_FONT &FreeSansBold9pt7b - #define BUTTON_ARRAY_LEN 9 + #define BUTTON_ARRAY_LEN 10 #define STATUS_BAR_WIDTH 16 #define LVGL_TICK_PERIOD 6 @@ -231,7 +231,7 @@ //#define MENU_FONT &FreeMonoBold9pt7b //#define MENU_FONT &FreeSans9pt7b //#define MENU_FONT &FreeSansBold9pt7b - #define BUTTON_ARRAY_LEN 9 + #define BUTTON_ARRAY_LEN 10 #define STATUS_BAR_WIDTH (TFT_HEIGHT/16) #define LVGL_TICK_PERIOD 6 diff --git a/esp32_marauder/lang_var.h b/esp32_marauder/lang_var.h index a6f982c..b8bf6b8 100644 --- a/esp32_marauder/lang_var.h +++ b/esp32_marauder/lang_var.h @@ -96,6 +96,7 @@ PROGMEM const char text1_54[] = "Deauth Flood"; PROGMEM const char text1_55[] = "Join WiFi"; PROGMEM const char text1_56[] = "Select APs"; PROGMEM const char text1_57[] = "AP Clone Spam"; +PROGMEM const char text1_58[] = "Raw Capture"; //SDInterface.cpp texts @@ -172,7 +173,7 @@ PROGMEM const char text4_44[] = " AP Scan "; //Making tables PROGMEM const char *text_table0[] = {text0_0,text0_1, text0_2, text0_3, text0_4, text0_5, text0_6, text0_7, text0_8}; -PROGMEM const char *text_table1[] = {text1_0,text1_1,text1_2,text1_3,text1_4,text1_5,text1_6,text1_7,text1_8,text1_9,text1_10,text1_11,text1_12,text1_13,text1_14,text1_15,text1_16,text1_17,text1_18,text1_19,text1_20,text1_21,text1_22,text1_23,text1_24,text1_25,text1_26,text1_27,text1_28,text1_29,text1_30,text1_31,text1_32,text1_33,text1_34,text1_35,text1_36,text1_37,text1_38,text1_39,text1_40,text1_41,text1_42,text1_43,text1_44,text1_45,text1_46,text1_47,text1_48,text1_49,text1_50,text1_51,text1_52,text1_53,text1_54,text1_55,text1_56,text1_57}; +PROGMEM const char *text_table1[] = {text1_0,text1_1,text1_2,text1_3,text1_4,text1_5,text1_6,text1_7,text1_8,text1_9,text1_10,text1_11,text1_12,text1_13,text1_14,text1_15,text1_16,text1_17,text1_18,text1_19,text1_20,text1_21,text1_22,text1_23,text1_24,text1_25,text1_26,text1_27,text1_28,text1_29,text1_30,text1_31,text1_32,text1_33,text1_34,text1_35,text1_36,text1_37,text1_38,text1_39,text1_40,text1_41,text1_42,text1_43,text1_44,text1_45,text1_46,text1_47,text1_48,text1_49,text1_50,text1_51,text1_52,text1_53,text1_54,text1_55,text1_56,text1_57,text1_58}; PROGMEM const char *text_table2[] = {text2_0,text2_1,text2_2,text2_3,text2_4,text2_5,text2_6,text2_7,text2_8,text2_9,text2_10,text2_11,text2_12,text2_13,text2_14}; PROGMEM const char *text_table3[] = {text3_0,text3_1,text3_2,text3_3,text3_4,text3_5}; PROGMEM const char *text_table4[] = {text4_0,text4_1,text4_2,text4_3,text4_4,text4_5,text4_6,text4_7,text1_54,text4_9,text4_10,text4_11,text4_12,text4_13,text4_14,text4_15,text4_16,text4_17,text4_18,text4_19,text4_20,text4_21,text4_22,text4_23,text4_24,text4_25,text4_26,text4_27,text4_28,text4_29,text4_30,text4_31,text4_32,text4_33,text4_34,text4_35,text4_36,text4_37,text4_38,text4_39,text4_40,text4_41,text4_42,text4_43,text4_44};