#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <WiFi.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define BUTTON_UP 32
#define BUTTON_DOWN 33
#define BUTTON_SELECT 25
#define BUTTON_BACK 26
#define NUM_OF_LINES 5
#define MAX_LOGS 50
#define MAX_TEMP_BUFFER 40
#define FRAME_SPEED 20
#define BUTTON_CLICK_DELAY 150
#define SCROLL_SPEED 20
#define BRIGHTNESS_STEP 51
enum menu_type {
MAIN_MENU,
WIFI_MENU,
BLUETOOTH_MENU,
PACKET_MONITOR_MENU,
SETTINGS_MENU
};
enum log_level {
LOG_INFO,
LOG_WARN,
LOG_ERROR,
LOG_DEBUG
};
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
menu_type current_menu = MAIN_MENU;
int selected_item = 0;
int starting_line = 0;
bool tool_opened = false;
unsigned int brightness_level = 3 * BRIGHTNESS_STEP;
void (*active_tool)() = nullptr;
bool func_setup_finished = false;
char* log_buffer[MAX_LOGS];
int log_buffer_index = 0;
char* temp_buffer[MAX_TEMP_BUFFER];
int temp_buffer_index = 0;
const char* ssid = "ESP32_Logs";
const char* password = "12345678";
int scroll_offset = 0;
unsigned long last_scroll_time = 0;
unsigned long last_frame_time = 0;
unsigned long last_button_press = 0;
const char* main_menu_items[] = {
"WiFi Tools",
"Bluetooth Tools",
"Packet Monitor",
"Settings"
};
const int main_menu_size = sizeof(main_menu_items) / sizeof(main_menu_items[0]);
const char* wifi_menu_items[] = {
"WiFi Scanner",
"Deauth Attack",
"Beacon Spammer",
"Probe Sniffer",
"Captive Portal",
"MAC Spoof",
"SSID Cloner",
"WiFi Jammer",
"Hidden SSID Revealer",
"Passive Client Tracker"
};
const int wifi_menu_size = sizeof(wifi_menu_items) / sizeof(wifi_menu_items[0]);
const char* bluetooth_menu_items[] = {
"BLE Scanner",
"BLE Advertiser",
"BLE Jammer",
"BLE HID Injector",
"BLE Spam Advertisements",
"BLE MAC Spoof",
"BLE Tracker"
};
const int bluetooth_menu_size = sizeof(bluetooth_menu_items) / sizeof(bluetooth_menu_items[0]);
const char* packet_monitor_menu_items[] = {
"Start Monitor",
"Filter by Type",
"Filter by MAC",
"Filter by SSID",
"Packet Counter",
"Signal Strength Viewer",
"Channel Viewer"
};
const int packet_monitor_menu_size = sizeof(packet_monitor_menu_items) / sizeof(packet_monitor_menu_items[0]);
const char* settings_menu_items[] = {
"Screen Brightness",
"Restart Device",
"MAC Spoofing",
"View Logs on ESP",
"View Logs on Web",
"I2C Scanner"
};
const int settings_menu_size = sizeof(settings_menu_items) / sizeof(settings_menu_items[0]);
void log_message(log_level level, const char* msg) {
if (log_buffer_index >= MAX_LOGS) {
free(log_buffer[0]);
for (int i = 1; i < MAX_LOGS; i++) {
log_buffer[i - 1] = log_buffer[i];
}
log_buffer_index = MAX_LOGS - 1;
}
const char* tag;
switch (level) {
case LOG_INFO: tag = "[INFO] "; break;
case LOG_WARN: tag = "[WARN] "; break;
case LOG_ERROR: tag = "[ERROR] "; break;
case LOG_DEBUG: tag = "[DEBUG] "; break;
}
size_t size = strlen(tag) + strlen(msg) + 1;
log_buffer[log_buffer_index] = (char*)malloc(128);
if (log_buffer[log_buffer_index]) {
snprintf(log_buffer[log_buffer_index], 128, "%s%s", tag, msg);
Serial.println(log_buffer[log_buffer_index]);
log_buffer_index++;
}
}
void draw_indicator(int level) {
int num_bars = 5;
int bar_width = 6;
int bar_spacing = 2;
int max_height = 8;
int total_width = num_bars * bar_width + (num_bars - 1) * bar_spacing;
int base_x = (SCREEN_WIDTH - total_width) / 2;
int base_y = SCREEN_HEIGHT - 1;
for (int i = 0; i < num_bars; i++) {
int height = max_height + i * 3;
int x = base_x + i * (bar_width + bar_spacing);
int y = base_y - height;
if (i < level) {
display.fillRect(x, y, bar_width, height, SSD1306_WHITE);
} else {
display.drawRect(x, y, bar_width, height, SSD1306_WHITE);
}
}
}
void draw_list(const char* items[], int num_items, bool same_start_of_line, const char* temp) {
display.clearDisplay();
display.setTextSize(1);
unsigned long now = millis();
for (int i = 0; i < min(NUM_OF_LINES, num_items - starting_line); i++) {
int item_index = starting_line + i;
const char* text = items[item_index];
char line_buffer[128];
if (same_start_of_line && temp != nullptr) {
snprintf(line_buffer, sizeof(line_buffer), "%s%s", temp, text);
text = line_buffer;
}
int16_t x1, y1;
uint16_t w, h;
display.getTextBounds(text, 0, 0, &x1, &y1, &w, &h);
int y = i * 13;
int text_x;
if (item_index == selected_item) {
display.fillRect(0, y, SCREEN_WIDTH, 13, SSD1306_WHITE);
display.setTextColor(SSD1306_BLACK);
if (w > SCREEN_WIDTH - 10) {
if (now - last_scroll_time > SCROLL_SPEED) {
scroll_offset++;
if (scroll_offset > w) {
scroll_offset = -SCREEN_WIDTH;
}
last_scroll_time = now;
}
text_x = 9 - scroll_offset;
} else {
scroll_offset = 0;
text_x = 9;
}
} else {
display.setTextColor(SSD1306_WHITE);
text_x = 4;
}
display.setCursor(text_x, y + 2);
display.print(text);
}
display.display();
}
// WiFI funkcije
void wifi_scanner_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("WiFi Scanner");
display.display();
}
void deauth_attack_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Deauth Attack");
display.display();
}
void beacon_spammer_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Beacon Spammer");
display.display();
}
void probe_sniffer_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Probe Sniffer");
display.display();
}
void captive_portal_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Captive Portal");
display.display();
}
void mac_spoof_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("MAC Spoof");
display.display();
}
void ssid_cloner_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("SSID Cloner");
display.display();
}
void wifi_jammer_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("WiFi Jammer");
display.display();
}
void hidden_ssid_revealer_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Hidden SSID Revealer");
display.display();
}
void passive_client_tracker_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Passive Client Tracker");
display.display();
}
// Bluetooth funkcije
void ble_scanner_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("BLE Scanner");
display.display();
}
void ble_advertiser_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("BLE Advertiser");
display.display();
}
void ble_jammer_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("BLE Jammer");
display.display();
}
void ble_hid_injector_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("BLE HID Injector");
display.display();
}
void ble_spam_advertisements_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("BLE Spam Ads");
display.display();
}
void ble_mac_spoof_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("BLE MAC Spoof");
display.display();
}
void ble_tracker_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("BLE Tracker");
display.display();
}
// Packet monitor funkcije
void packet_monitor_start_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Monitor Started");
display.display();
}
void packet_filter_type_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Filter by Type");
display.display();
}
void packet_filter_mac_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Filter by MAC");
display.display();
}
void packet_filter_ssid_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Filter by SSID");
display.display();
}
void packet_counter_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Packet Counter");
display.display();
}
void signal_strength_viewer_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Signal Viewer");
display.display();
}
void channel_viewer_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Channel Viewer");
display.display();
}
// Settings funkcije
void set_brightness_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Screen Brightness");
if (digitalRead(BUTTON_UP) == LOW && brightness_level + BRIGHTNESS_STEP <= 255) {
brightness_level += BRIGHTNESS_STEP;
}
if (digitalRead(BUTTON_DOWN) == LOW && brightness_level - BRIGHTNESS_STEP >= 0) {
brightness_level -= BRIGHTNESS_STEP;
}
display.ssd1306_command(SSD1306_SETCONTRAST);
display.ssd1306_command(brightness_level);
draw_indicator(brightness_level / BRIGHTNESS_STEP);
display.display();
}
void restart_device_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Restarting...");
display.display();
delay(1000);
ESP.restart();
}
void mac_spoofing_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("MAC Spoofing");
display.display();
}
void view_logs_on_esp_tool() {
if (!func_setup_finished) {
func_setup_finished = true;
selected_item = log_buffer_index - 1;
starting_line = max(log_buffer_index - NUM_OF_LINES, 0);
}
draw_list((const char**)log_buffer, log_buffer_index, false, "");
}
void view_logs_on_web_tool() {
if (!func_setup_finished) {
func_setup_finished = true;
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Logs Web Server");
display.print("SSID:");
display.println(ssid);
display.print("Pass:");
display.println(password);
display.print("IP: ");
display.println("192.168.1.2");
display.display();
}
}
void i2c_scanner_tool() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
if (!func_setup_finished) {
for (byte address = 1; address < 127; address++) {
Wire.beginTransmission(address);
if (Wire.endTransmission() == 0) {
char* msg = (char*)malloc(50);
if (msg != nullptr) {
snprintf(msg, 50, "%02X", address);
temp_buffer[temp_buffer_index++] = msg;
}
delay(10);
}
}
for (int i = 0; i < temp_buffer_index; i++) {
Serial.print("I2C Dev: 0x");
Serial.println(temp_buffer[i]);
}
func_setup_finished = true;
}
if (temp_buffer_index == 0) {
display.clearDisplay();
display.setCursor(0, 10);
display.println("No devices found.");
Serial.println("No devices found.");
} else {
draw_list((const char**)temp_buffer, temp_buffer_index, true, "I2C Dev: 0x");
}
display.display();
}
void navigate_to_submenu() {
if (current_menu == MAIN_MENU) {
switch (selected_item) {
case 0:
current_menu = WIFI_MENU;
log_message(LOG_INFO, "Entered WiFi Menu");
break;
case 1:
current_menu = BLUETOOTH_MENU;
log_message(LOG_INFO, "Entered Bluetooth Menu");
break;
case 2:
current_menu = PACKET_MONITOR_MENU;
log_message(LOG_INFO, "Entered Packet Monitor Menu");
break;
case 3:
current_menu = SETTINGS_MENU;
log_message(LOG_INFO, "Entered Settings Menu");
break;
}
} else {
tool_opened = true;
switch (current_menu) {
case WIFI_MENU:
switch (selected_item) {
case 0: active_tool = wifi_scanner_tool; log_message(LOG_INFO, "Opened WiFi Scanner"); break;
case 1: active_tool = deauth_attack_tool; log_message(LOG_INFO, "Opened Deauth Attack"); break;
case 2: active_tool = beacon_spammer_tool; log_message(LOG_INFO, "Opened Beacon Spammer"); break;
case 3: active_tool = probe_sniffer_tool; log_message(LOG_INFO, "Opened Probe Sniffer"); break;
case 4: active_tool = captive_portal_tool; log_message(LOG_INFO, "Opened Captive Portal"); break;
case 5: active_tool = mac_spoof_tool; log_message(LOG_INFO, "Opened MAC Spoof Tool"); break;
case 6: active_tool = ssid_cloner_tool; log_message(LOG_INFO, "Opened SSID Cloner"); break;
case 7: active_tool = wifi_jammer_tool; log_message(LOG_INFO, "Opened WiFi Jammer"); break;
case 8: active_tool = hidden_ssid_revealer_tool; log_message(LOG_INFO, "Opened Hidden SSID Revealer"); break;
case 9: active_tool = passive_client_tracker_tool; log_message(LOG_INFO, "Opened Passive Client Tracker"); break;
}
break;
case BLUETOOTH_MENU:
switch (selected_item) {
case 0: active_tool = ble_scanner_tool; log_message(LOG_INFO, "Opened BLE Scanner"); break;
case 1: active_tool = ble_advertiser_tool; log_message(LOG_INFO, "Opened BLE Advertiser"); break;
case 2: active_tool = ble_jammer_tool; log_message(LOG_INFO, "Opened BLE Jammer"); break;
case 3: active_tool = ble_hid_injector_tool; log_message(LOG_INFO, "Opened BLE HID Injector"); break;
case 4: active_tool = ble_spam_advertisements_tool; log_message(LOG_INFO, "Opened BLE Spam Advertisements"); break;
case 5: active_tool = ble_mac_spoof_tool; log_message(LOG_INFO, "Opened BLE MAC Spoof Tool"); break;
case 6: active_tool = ble_tracker_tool; log_message(LOG_INFO, "Opened BLE Tracker"); break;
}
break;
case PACKET_MONITOR_MENU:
switch (selected_item) {
case 0: active_tool = packet_monitor_start_tool; log_message(LOG_INFO, "Started Packet Monitor"); break;
case 1: active_tool = packet_filter_type_tool; log_message(LOG_INFO, "Opened Packet Filter by Type"); break;
case 2: active_tool = packet_filter_mac_tool; log_message(LOG_INFO, "Opened Packet Filter by MAC"); break;
case 3: active_tool = packet_filter_ssid_tool; log_message(LOG_INFO, "Opened Packet Filter by SSID"); break;
case 4: active_tool = packet_counter_tool; log_message(LOG_INFO, "Opened Packet Counter"); break;
case 5: active_tool = signal_strength_viewer_tool; log_message(LOG_INFO, "Opened Signal Strength Viewer"); break;
case 6: active_tool = channel_viewer_tool; log_message(LOG_INFO, "Opened Channel Viewer"); break;
}
break;
case SETTINGS_MENU:
switch (selected_item) {
case 0: active_tool = set_brightness_tool; log_message(LOG_INFO, "Opened Screen Brightness Tool"); break;
case 1: active_tool = restart_device_tool; log_message(LOG_INFO, "Triggered Device Restart"); break;
case 2: active_tool = mac_spoofing_tool; log_message(LOG_INFO, "Opened MAC Spoofing Tool"); break;
case 3: active_tool = view_logs_on_esp_tool; log_message(LOG_INFO, "Viewing Logs on ESP"); break;
case 4: active_tool = view_logs_on_web_tool; log_message(LOG_INFO, "Viewing Logs on Web"); break;
case 5: active_tool = i2c_scanner_tool; log_message(LOG_INFO, "Opened I2C Scanner Tool"); break;
}
break;
}
}
}
void draw_menu() {
display.clearDisplay();
display.setTextSize(1);
const char** items = nullptr;
int item_count = 0;
switch (current_menu) {
case MAIN_MENU:
items = main_menu_items;
item_count = main_menu_size;
break;
case WIFI_MENU:
items = wifi_menu_items;
item_count = wifi_menu_size;
break;
case BLUETOOTH_MENU:
items = bluetooth_menu_items;
item_count = bluetooth_menu_size;
break;
case PACKET_MONITOR_MENU:
items = packet_monitor_menu_items;
item_count = packet_monitor_menu_size;
break;
case SETTINGS_MENU:
items = settings_menu_items;
item_count = settings_menu_size;
break;
}
draw_list(items, item_count, false, "");
}
void handle_menu_input() {
if (!tool_opened) {
if (digitalRead(BUTTON_UP) == LOW) {
selected_item--;
if (selected_item < 0) selected_item = 0;
if (selected_item < starting_line) starting_line--;
scroll_offset = 0;
last_scroll_time = 0;
last_button_press = millis();
}
if (digitalRead(BUTTON_DOWN) == LOW) {
int max_items = 0;
switch (current_menu) {
case MAIN_MENU: max_items = main_menu_size;
case WIFI_MENU: max_items = wifi_menu_size;
case BLUETOOTH_MENU: max_items = bluetooth_menu_size;
case PACKET_MONITOR_MENU: max_items = packet_monitor_menu_size;
case SETTINGS_MENU: max_items = settings_menu_size;
}
selected_item++;
if (selected_item >= max_items) selected_item = max_items - 1;
if (selected_item >= starting_line + NUM_OF_LINES) starting_line++;
scroll_offset = 0;
last_scroll_time = 0;
last_button_press = millis();
}
if (digitalRead(BUTTON_SELECT) == LOW) {
starting_line = 0;
navigate_to_submenu();
selected_item = 0;
scroll_offset = 0;
last_scroll_time = 0;
last_button_press = millis();
}
if (digitalRead(BUTTON_BACK) == LOW) {
if (current_menu != MAIN_MENU) {
current_menu = MAIN_MENU;
selected_item = 0;
starting_line = 0;
int scroll_offset = 0;
unsigned long last_scroll_time = 0;
}
last_button_press = millis();
}
} else {
if (digitalRead(BUTTON_UP) == LOW) {
selected_item--;
if (selected_item < 0) selected_item = 0;
if (selected_item < starting_line) starting_line--;
scroll_offset = 0;
last_scroll_time = 0;
last_button_press = millis();
}
if (digitalRead(BUTTON_DOWN) == LOW) {
selected_item++;
if (active_tool == view_logs_on_esp_tool && selected_item >= log_buffer_index) {
selected_item = log_buffer_index - 1;
}
if (temp_buffer_index !=0 && selected_item >= temp_buffer_index) {
selected_item = temp_buffer_index - 1;
}
if (selected_item >= starting_line + NUM_OF_LINES) starting_line++;
scroll_offset = 0;
last_scroll_time = 0;
last_button_press = millis();
}
if (digitalRead(BUTTON_BACK) == LOW) {
func_setup_finished = false;
tool_opened = false;
if (active_tool == i2c_scanner_tool) {
for (int i = 0; i < temp_buffer_index; i++) {
free(temp_buffer[i]);
temp_buffer[i] = nullptr;
}
temp_buffer_index = 0;
}
active_tool = nullptr;
starting_line = 0;
selected_item = 0;
scroll_offset = 0;
last_scroll_time = 0;
last_button_press = millis();
}
}
}
void setup() {
Serial.begin(115200);
log_message(LOG_INFO, "ESP32 turned on");
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("SSD1306 init failed");
while (1);
}
display.setTextWrap(false);
log_message(LOG_INFO, "Display initialized");
Wire.begin();
pinMode(32, INPUT_PULLUP);
pinMode(33, INPUT_PULLUP);
pinMode(25, INPUT_PULLUP);
pinMode(26, INPUT_PULLUP);
log_message(LOG_INFO, "Buttons initialized");
log_message(LOG_INFO, "Setup finished");
}
void loop() {
unsigned long now = millis();
if (now - last_button_press >= BUTTON_CLICK_DELAY) {
handle_menu_input();
}
if (now - last_frame_time >= FRAME_SPEED) {
last_frame_time = now;
if (tool_opened && active_tool != nullptr) {
active_tool();
} else {
draw_menu();
}
}
}