diff --git a/platformio.ini b/platformio.ini index 8e8440bd2..4066eab4a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -30,6 +30,7 @@ lib_deps = WireGuard-ESP32 IRremoteESP8266 Time + LibSSH-ESP32 ; bodmer/TFT_eSPI@^2.5.43 ; Esta biblioteca deve estar na pasta lib, devido as alterações no drive do StickC diff --git a/src/arp.cpp b/src/arp.cpp new file mode 100644 index 000000000..aa33b2812 --- /dev/null +++ b/src/arp.cpp @@ -0,0 +1,93 @@ +#include "lwip/opt.h" +#include "esp_eth.h" +#include "lwip/etharp.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "nvs_flash.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ethip6.h" +#include "lwip/ip.h" +#include "lwip/ip4_addr.h" +#include "lwip/prot/udp.h" +#include "display.h" +#include "globals.h" +#include "arp.h" + +// #define ARP_TABLE_SIZE 30 // TODO: this probably is causing inconsistance + + +int etharp_get_entry(size_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth_addr **eth_ret); + + +void print_arp_table() { + struct netif *existing_netif = netif_default; + + if (existing_netif != NULL) { + ip4_addr_t *printed_addresses[ARP_TABLE_SIZE]; + memset(printed_addresses, 0, sizeof(printed_addresses)); + + for (int i = 0; i < ARP_TABLE_SIZE; i++) { + ip4_addr_t *ipaddr; + struct netif *netif_entry; + struct eth_addr *eth_ret; + + int result = etharp_get_entry(i, &ipaddr, &netif_entry, ð_ret); + delay(1000); + + if (result == 0 && ipaddr != NULL) { + // Check if the IP address has already been printed + int is_duplicate = 0; + for (int j = 0; j < ARP_TABLE_SIZE; j++) { + if (printed_addresses[j] != NULL && ip4_addr_cmp(ipaddr, printed_addresses[j])) { + is_duplicate = 1; + break; + } + } + + if (!is_duplicate) { + Serial.print("IP: "); + Serial.print(ip4addr_ntoa(ipaddr)); + tft.println(ip4addr_ntoa(ipaddr)); + Serial.print("\tMAC: "); + + char mac_str[18]; + snprintf(mac_str, sizeof(mac_str), "%02X:%02X:%02X:%02X:%02X:%02X", + eth_ret->addr[0], eth_ret->addr[1], eth_ret->addr[2], + eth_ret->addr[3], eth_ret->addr[4], eth_ret->addr[5]); + + Serial.print(mac_str); + Serial.println(); + + for (int j = 0; j < ARP_TABLE_SIZE; j++) { + if (printed_addresses[j] == NULL) { + printed_addresses[j] = ipaddr; + break; + } + } + } + } + } + } else { + Serial.println("No network interface available."); + } + delay(1000); + tft.fillScreen(TFT_BLACK); +} + +void local_scan_setup() { + tft.fillScreen(TFT_BLACK); + tft.setTextSize(2); + + Serial.printf("starting ARP scan"); + + tft.setTextColor(TFT_DARKGREEN, BGCOLOR); + tft.println(WiFi.localIP().toString().c_str()); + tft.setTextColor(FGCOLOR, BGCOLOR); + print_arp_table(); + +} + diff --git a/src/arp.h b/src/arp.h new file mode 100644 index 000000000..30f25558a --- /dev/null +++ b/src/arp.h @@ -0,0 +1,8 @@ + +#include + +int etharp_get_entry(size_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth_addr **eth_ret); + +void local_scan_setup(); + +void print_arp_table(); \ No newline at end of file diff --git a/src/clients.cpp b/src/clients.cpp new file mode 100644 index 000000000..cdd8d6e87 --- /dev/null +++ b/src/clients.cpp @@ -0,0 +1,412 @@ +//SSH borrowed from https://github.com/m5stack/M5Cardputer :) + +//TODO: Display is kinda glitchy :P figure out some way to show better outputs also + +// SSH libs +#include "libssh_esp32.h" +#include + +// Telnet libs +#include +#include +#include +#include +#include +#include +#include +#include +#include "clients.h" +#include "globals.h" +#include "display.h" +#include "mykeyboard.h" + +// SSH server configuration (initialize as mpty strings) +String ssh_host = ""; +String ssh_user = ""; +String ssh_port = ""; +String ssh_password = ""; + +char* ssh_port_char; + +// M5Cardputer setup +//M5Canvas canvas(&DISP); +String commandBuffer = "> "; +int cursorY = 0; +const int lineHeight = 32; +unsigned long lastKeyPressMillis = 0; +const unsigned long debounceDelay = 200; // Adjust debounce delay as needed + +//ssh_bind sshbind = (ssh_bind)state->input; + +//ssh_init sshbind; +ssh_session my_ssh_session; +ssh_channel channel_ssh; + + +char* stringTochar(String s) +{ + if (s.length() == 0) { + return nullptr; // or handle the case where the string is empty + } + + static char arr[14]; // Make sure it's large enough to hold the IP address + s.toCharArray(arr, sizeof(arr)); + return arr; +} + +bool filterAnsiSequences = true; // Set to false to disable ANSI sequence filtering + + +void ssh_loop() { + + for(;;){ + #ifdef CARDPUTER + if (Keyboard.isChange() && Keyboard.isPressed()) { + unsigned long currentMillis = millis(); + if (currentMillis - lastKeyPressMillis >= debounceDelay) { + lastKeyPressMillis = currentMillis; + Keyboard_Class::KeysState status = Keyboard.keysState(); + + for (auto i : status.word) { + commandBuffer += i; + tft.print(i); + cursorY = tft.getCursorY(); + } + + if (status.del && commandBuffer.length() > 2) { + commandBuffer.remove(commandBuffer.length() - 1); + tft.setCursor( + tft.getCursorX() - 6, + tft.getCursorY()); + tft.print(" "); + tft.setCursor( + tft.getCursorX() - 6, + tft.getCursorY()); + cursorY = tft.getCursorY(); + } + + if (status.enter) { + commandBuffer.trim(); // Trim the command buffer to remove + // accidental TFT_WHITEspaces/newlines + String message = commandBuffer.substring( + 2); // Get the command part, exclude the "> " + ssh_channel_write(channel_ssh, message.c_str(), + message.length()); // Send the command + ssh_channel_write(channel_ssh, "\r", + 1); // Send exactly one carriage return (try + // "\n" or "\r\n" if needed) + + commandBuffer = "> "; // Reset command buffer + tft.print( + '\n'); // Move to the next line on display + cursorY = + tft.getCursorY(); // Update cursor position + } + } + } + + #else + if(checkSelPress()) { + while(checkSelPress()) { yield(); } // timerless debounce + commandBuffer = keyboard(commandBuffer,76,"SSH Command: "); + while(checkSelPress()) { yield(); } // timerless debounce + commandBuffer.trim(); // Trim the command buffer to remove + // accidental TFT_WHITEspaces/newlines + String message = ""; + if(commandBuffer.startsWith("> ")) message = commandBuffer.substring(2); // Get the command part, exclude the "> " + else message = commandBuffer; + ssh_channel_write(channel_ssh, message.c_str(), + message.length()); // Send the command + ssh_channel_write(channel_ssh, "\r", + 1); // Send exactly one carriage return (try + // "\n" or "\r\n" if needed) + + commandBuffer = "> "; // Reset command buffer + tft.print('\n'); // Move to the next line on display + cursorY =tft.getCursorY(); // Update cursor position + } + + #endif + + // Check if the cursor has reached the bottom of the display + if (cursorY > tft.height() - lineHeight) { + tft.setCursor(0, -lineHeight); + cursorY -= lineHeight; + tft.setCursor(tft.getCursorX(), + cursorY); + } + + // Read data from SSH server and display it, handling ANSI sequences + char buffer[128]; // TFT_REDuced buffer size for less memory usage + int nbytes = + ssh_channel_read_nonblocking(channel_ssh, buffer, sizeof(buffer), 0); + bool isAnsiSequence = + false; // To track when we are inside an ANSI sequence + + if (nbytes > 0) { + for (int i = 0; i < nbytes; ++i) { + char c = buffer[i]; + if (filterAnsiSequences) { + if (c == '\033') { + isAnsiSequence = true; // Enter ANSI sequence mode + } else if (isAnsiSequence) { + if (isalpha(c)) { + isAnsiSequence = false; // Exit ANSI sequence mode at + // the end character + } + } else { + if (c == '\r') continue; // Ignore carriage return + tft.write(c); + cursorY = tft.getCursorY(); + } + } else { + if (c == '\r') continue; // Ignore carriage return + tft.write(c); + cursorY = tft.getCursorY(); + } + } + } + + // Handle channel closure and other conditions + if (nbytes < 0 || ssh_channel_is_closed(channel_ssh)) { + ssh_channel_close(channel_ssh); + ssh_channel_free(channel_ssh); + ssh_disconnect(my_ssh_session); + ssh_free(my_ssh_session); + displayRedStripe("\nSSH session closed."); + tft.setTextColor(FGCOLOR, BGCOLOR); + return; // Exit the loop upon session closure + } + } +} + +void ssh_setup(){ + tft.fillScreen(BGCOLOR); + tft.setCursor(0, 0); + Serial.begin(115200); // Initialize serial communication for debugging + Serial.println("Starting Setup"); + + //auto cfg = M5.config(); + //M5Cardputer.begin(cfg, true); + tft.setRotation(1); + tft.setTextSize(1); // Set text size + + cursorY = tft.getCursorY(); + + tft.setCursor(0, 0); + // Prompt for SSH host, username, and password + //tft.print("SSH Host: \n"); + // waitForInput(ssh_host); + ssh_host=keyboard("",76,"SSH HOST"); + //tft.print("SSH Port: \n"); + //waitForInput(ssh_port); + ssh_port=keyboard("",76,"SSH PORT"); + + ssh_port_char = stringTochar(ssh_port); + uint16_t ssh_port_int = atoi(ssh_port_char); + + //tft.print("\nSSH Username: "); + + //waitForInput(ssh_user); + ssh_user=keyboard("",76,"SSH USER"); + //tft.print("\nSSH Password: "); + + //waitForInput(ssh_password); + ssh_password=keyboard("",76,"SSH PASSWORD"); + + Serial.println("BEFORE SSH"); + my_ssh_session = ssh_new(); + Serial.println("AFTER SSH"); + + + + if (my_ssh_session == NULL) { + tft.setTextColor(TFT_RED, BGCOLOR); + displayRedStripe("SSH Shell request error."); + Serial.println("SSH Session creation failed."); + return; + } + ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, ssh_host.c_str()); + ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &ssh_port_int); + ssh_options_set(my_ssh_session, SSH_OPTIONS_USER, ssh_user.c_str()); + Serial.println("AFTER COMPARE AND OPTION SET"); + + if (ssh_connect(my_ssh_session) != SSH_OK) { + tft.setTextColor(TFT_RED, BGCOLOR); + displayRedStripe("SSH Shell request error."); + Serial.println("SSH Connect error."); + ssh_free(my_ssh_session); + return; + } + + if (ssh_userauth_password(my_ssh_session, NULL, ssh_password.c_str()) != + SSH_AUTH_SUCCESS) { + tft.setTextColor(TFT_RED, BGCOLOR); + displayRedStripe("SSH Shell request error."); + Serial.println("SSH Authentication error."); + ssh_disconnect(my_ssh_session); + ssh_free(my_ssh_session); + return; + } + + channel_ssh = ssh_channel_new(my_ssh_session); + if (channel_ssh == NULL || ssh_channel_open_session(channel_ssh) != SSH_OK) { + tft.setTextColor(TFT_RED, BGCOLOR); + displayRedStripe("SSH Shell request error."); + Serial.println("SSH Channel open error."); + ssh_disconnect(my_ssh_session); + ssh_free(my_ssh_session); + return; + } + + if (ssh_channel_request_pty(channel_ssh) != SSH_OK) { + tft.setTextColor(TFT_RED, BGCOLOR); + displayRedStripe("SSH Shell request error."); + Serial.println("SSH PTY request error."); + ssh_channel_close(channel_ssh); + ssh_channel_free(channel_ssh); + ssh_disconnect(my_ssh_session); + ssh_free(my_ssh_session); + return; + } + + if (ssh_channel_request_shell(channel_ssh) != SSH_OK) { + tft.setTextColor(TFT_RED, BGCOLOR); + displayRedStripe("SSH Shell request error."); + Serial.println("SSH Shell request error."); + ssh_channel_close(channel_ssh); + ssh_channel_free(channel_ssh); + ssh_disconnect(my_ssh_session); + ssh_free(my_ssh_session); + return; + } + + + Serial.println("SSH setup completed."); + tft.setTextColor(TFT_GREEN, BGCOLOR); + displayRedStripe("SSH Conected!", TFT_WHITE, TFT_DARKGREEN ); + delay(2000); + tft.fillScreen(BGCOLOR); + tft.setTextColor(TFT_WHITE, BGCOLOR); + ssh_loop(); + +} + + +String telnet_server_string = ""; +String telnet_port_string = ""; +char* telnet_server_ip; +char* telnet_server_port_char; + +int telnet_server_port; + +static int sock; + + +void telnet_loop() { + struct sockaddr_in dest_addr; + dest_addr.sin_addr.s_addr = inet_addr(telnet_server_ip); + dest_addr.sin_family = AF_INET; + dest_addr.sin_port = htons(telnet_server_port); + + sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + if (sock < 0) { + Serial.println("Unable to create socket"); + tft.setTextColor(TFT_RED, BGCOLOR); + displayRedStripe("Unable to create socket"); + tft.setTextColor(FGCOLOR, BGCOLOR); + return; + } + + if (connect(sock, (struct sockaddr*)&dest_addr, sizeof(dest_addr)) != 0) { + Serial.println("Socket connection failed"); + tft.setTextColor(TFT_RED, BGCOLOR); + displayRedStripe("Socket connection failed"); + tft.setTextColor(FGCOLOR, BGCOLOR); + close(sock); + return; + } + + Serial.println("Connected to TELNET server"); + tft.setTextColor(TFT_GREEN, BGCOLOR); + displayRedStripe("Connected to TELNET server", TFT_WHITE, TFT_DARKGREEN ); + tft.setTextColor(FGCOLOR, BGCOLOR); + delay(2000); + tft.fillScreen(BGCOLOR); + tft.setCursor(0, 0); + + String commandInput; + + while (1) { + tft.print("> "); + //waitForInput(commandInput); + commandInput=keyboard("",76,"COMMAND"); + const char *command = commandInput.c_str(); + send(sock, command, strlen(command), 0); + + // You can also receive data from the server + char buffer[128]; + int len = recv(sock, buffer, sizeof(buffer) - 1, 0); + if (len > 0) { + buffer[len] = '\0'; + // Check for Telnet negotiation commands (IAC) + /* + if (buffer[0] == 0xFF) { + // Skip Telnet negotiation command + continue; + } + */ + tft.setTextColor(TFT_WHITE, BGCOLOR); + Serial.printf("Received from server %s\n", buffer); + //tft.printf("Received from server %s\n", buffer); + for (int i = 0; i < len; i++) { + Serial.printf("%02X ", buffer[i]); + } + tft.printf("%s\n", buffer); + + tft.setTextColor(FGCOLOR, BGCOLOR); + + } + + vTaskDelay(1000 / portTICK_PERIOD_MS); + } +} + +void telnet_setup() { + tft.fillScreen(BGCOLOR); + tft.setCursor(0, 0); + Serial.begin(115200); // Initialize serial communication for debugging + Serial.println("Starting Setup"); + + // auto cfg = M5.config(); + // M5Cardputer.begin(cfg, true); + tft.setRotation(1); + tft.setTextSize(2); // Set text size + + cursorY = tft.getCursorY(); + + tft.setCursor(0, 0); + //tft.print("TELNET Host: \n"); + + // Here the telnet_server_ip needs to be a char*, thats why the stringTochar() + + //waitForInput(telnet_server_string); + telnet_server_string=keyboard("",76,"TELNET_SERVER"); + telnet_server_ip = stringTochar(telnet_server_string); + delay(300); + //Serial.println(telnet_server_ip); + + //tft.print("TELNET Port: \n"); + //waitForInput(telnet_port_string); + telnet_port_string=keyboard("",76,"TELNET PORT"); + delay(300); + char arr2[5]; + //telnet_server_port_char = + telnet_port_string.toCharArray(arr2, sizeof(arr2)); + //telnet_server_port_char = stringTochar(telnet_port_string); + telnet_server_port = atoi(arr2); + Serial.println(telnet_server_ip); + Serial.println(telnet_server_port); + + telnet_loop(); +} diff --git a/src/clients.h b/src/clients.h new file mode 100644 index 000000000..253ee073a --- /dev/null +++ b/src/clients.h @@ -0,0 +1,9 @@ + + +void telnet_setup(); + +void ssh_setup(); + +void ssh_loop(); + +char* stringTochar(String s); \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 0329ef89f..55cb5251b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -45,6 +45,8 @@ TFT_eSprite draw = TFT_eSprite(&tft); #include "sniffer.h" #include "tururururu.h" #include "evil_portal.h" +#include "clients.h" +#include "arp.h" #ifdef CARDPUTER @@ -168,12 +170,12 @@ void loop() { }; } options.push_back({"Wifi Atks", [=]() { displayRedStripe("Wifi Atks"); }}); - options.push_back({"TelNET", [=]() { displayRedStripe("TelNET"); }}); - options.push_back({"SSH", [=]() { displayRedStripe("SSH"); }}); + options.push_back({"TelNET", [=]() { telnet_setup(); }}); + options.push_back({"SSH", [=]() { ssh_setup(); }}); options.push_back({"Raw Sniffer", [=]() { sniffer_setup(); }}); options.push_back({"DPWO-ESP32", [=]() { dpwo_setup(); }}); options.push_back({"Evil Portal", [=]() { startEvilPortal(); }}); - options.push_back({"ARP Scan", [=]() { displayRedStripe("ARP Scan"); }}); + options.push_back({"ARP Scan", [=]() { local_scan_setup(); }}); options.push_back({"Wireguard Tun", [=]() { wg_setup(); }}); options.push_back({"Main Menu", [=]() { backToMenu(); }}); delay(200);