diff --git a/src/core/shell.cpp b/src/core/shell.cpp index 3734d12..b02bbd7 100644 --- a/src/core/shell.cpp +++ b/src/core/shell.cpp @@ -3,6 +3,7 @@ #include "theme.h" #include +Module* makeQuickAttack(); Module* makePinScan(); Module* makeVSense(); Module* makeUartSniff(); @@ -54,6 +55,7 @@ Module* makeLogViewer(); void Shell::begin() { theme::load(); + add(makeQuickAttack()); add(makePinScan()); add(makeVSense()); add(makeUartSniff()); diff --git a/src/modules/quickattack.cpp b/src/modules/quickattack.cpp new file mode 100644 index 0000000..129fdd4 --- /dev/null +++ b/src/modules/quickattack.cpp @@ -0,0 +1,155 @@ +#include "../core/module.h" +#include "../core/ui.h" +#include + +class QuickAttack : public Module { + enum Mode { DETECT, HID_INJECT, SERIAL_SHELL, DONE } mode = DETECT; + bool running = false; + uint32_t progress = 0; + uint32_t commands_sent = 0; + char response[256] = ""; + HardwareSerial ser; + char msg[3][40] = {{0},{0},{0}}; + +public: + const char* name() const override { return "Quick Attack"; } + const char* blurb() const override { return "one-button compromise"; } + + void onEnter() override { + running = false; + mode = DETECT; + progress = 0; + commands_sent = 0; + memset(response, 0, sizeof(response)); + say("Auto-detect + attack"); + ser.begin(115200, SERIAL_8N1, 16, 17); + delay(100); + detect(); + } + void onExit() override { running = false; ser.end(); } + + bool onKey(char c) override { + if (c == ' ') { if (!running) startAttack(); else running = false; return true; } + if (c == 'd') { mode = DETECT; progress = 0; detect(); return true; } + if (c == 's') { sendCommand("id"); return true; } + if (c == 'w') { sendCommand("whoami"); return true; } + return false; + } + + void tick() override { + if (!running) return; + progress++; + + if (mode == HID_INJECT) { +#ifdef HAVE_TINYSUB + if (progress < 50) { + static const char* cmds[] = {"id\n", "uname -a\n", "cat /proc/version\n"}; + if (progress == 10) { sendHidString(cmds[0]); } + if (progress == 25) { sendHidString(cmds[1]); } + if (progress == 40) { sendHidString(cmds[2]); } + } else { + mode = DONE; + running = false; + say("HID injection complete"); + } +#endif + } else if (mode == SERIAL_SHELL) { + while (ser.available()) { + char c = ser.read(); + if (strlen(response) < sizeof(response) - 1) { + response[strlen(response)] = c; + } + } + if (progress > 100) { + mode = DONE; + running = false; + say("Shell commands sent: %u", (unsigned)commands_sent); + } + } + } + + void draw() override { + const char* modes[] = {"DETECT", "HID_INJECT", "SHELL", "DONE"}; + ui::lineC(0, ui::accent(), "Quick Attack: %s", modes[mode]); + ui::line(1, "status: %s", running ? "RUNNING" : "ready"); + + if (mode == DETECT) { + ui::line(2, "detecting target..."); + } else if (mode == HID_INJECT) { + ui::bar(2, progress / 50.0f, ui::glow(), "inject"); + ui::line(3, "typing commands..."); + } else if (mode == SERIAL_SHELL) { + ui::line(2, "commands sent: %u", (unsigned)commands_sent); + if (response[0]) ui::line(3, "RX: %.30s", response); + } else { + ui::lineC(2, ui::glow(), "COMPLETE"); + } + + for (int i = 0; i < 3; i++) ui::line(7 + i, "%s", msg[i]); + if (running) ui::spinner(228, ui::BODY_Y + 1, ui::glow()); + ui::hintBar("[space]attack [s]end-id [w]hoami [d]etect [`]back"); + } + +private: + void say(const char* fmt, ...) { + for (int i = 2; i > 0; i--) strncpy(msg[i], msg[i-1], 39); + va_list ap; va_start(ap, fmt); vsnprintf(msg[0], 40, fmt, ap); va_end(ap); + } + + void detect() { + say("Probing..."); +#ifdef HAVE_TINYSUB + if (tud_mounted()) { + mode = HID_INJECT; + say("USB device: HID mode"); + return; + } +#endif + ser.write("\r\n"); + delay(200); + if (ser.available()) { + mode = SERIAL_SHELL; + say("UART detected: shell mode"); + } else { + say("No target detected"); + } + } + + void startAttack() { + running = true; + progress = 0; + commands_sent = 0; + memset(response, 0, sizeof(response)); + say("Attacking..."); + } + + void sendCommand(const char* cmd) { + ser.print(cmd); + ser.flush(); + commands_sent++; + say("TX: %s", cmd); + } + + void sendHidString(const char* str) { +#ifdef HAVE_TINYSUB + for (size_t i = 0; i < strlen(str); i++) { + uint8_t keycode = 0; + if (str[i] >= 'a' && str[i] <= 'z') keycode = 0x04 + (str[i] - 'a'); + else if (str[i] >= 'A' && str[i] <= 'Z') keycode = 0x04 + (str[i] - 'A'); + else if (str[i] >= '0' && str[i] <= '9') keycode = (str[i] == '0') ? 0x27 : 0x1E + (str[i] - '1'); + else if (str[i] == ' ') keycode = 0x2C; + else if (str[i] == '\n') keycode = 0x28; + else if (str[i] == '-') keycode = 0x2D; + + if (keycode) { + tud_hid_keyboard_report(0, 0, &keycode, 1); + delay(30); + tud_hid_keyboard_report(0, 0, nullptr, 0); + } + } +#endif + commands_sent++; + } +}; + +Module* makeQuickAttack() { return new QuickAttack(); }