Compare commits

...

2 Commits

4 changed files with 169 additions and 8 deletions

View File

@@ -3,6 +3,7 @@
#include "theme.h"
#include <M5Cardputer.h>
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());
@@ -159,20 +161,20 @@ void Shell::loop() {
if (M5Cardputer.Keyboard.isChange() && M5Cardputer.Keyboard.isPressed()) {
auto st = M5Cardputer.Keyboard.keysState();
for (char c : st.word) {
if (c == '`') { if (active >= 0) back(); continue; }
if (c == '`' || c == 27) { if (active >= 0) { back(); continue; } }
if (active < 0) {
if (c == ';') { sel = (sel - 1 + nmods) % nmods; drawMenu(); }
else if (c == '.') { sel = (sel + 1) % nmods; drawMenu(); }
else if (c == '\r' || c == ' ') enter(sel);
} else {
mods[active]->onKey(c);
bool consumed = mods[active]->onKey(c);
if (!consumed && c == '`') back();
}
}
if (st.enter && active < 0) enter(sel);
}
if (active < 0) {
// keep the selection glow breathing — repaints only the bar strip (flicker-free)
if (millis() - lastTick > 90) { lastTick = millis(); drawMenu(false); }
return;
}

View File

@@ -21,12 +21,13 @@ public:
void onEnter() override {
active = false;
sent = 0;
say("HID ready, plug USB host");
say("HID ready");
#ifdef HAVE_TINYSB
if (tud_mounted()) {
active = true;
sent = 0;
say("Host detected - injecting");
say("Host detected!");
say("Injecting...");
}
#endif
}

155
src/modules/quickattack.cpp Normal file
View File

@@ -0,0 +1,155 @@
#include "../core/module.h"
#include "../core/ui.h"
#include <HardwareSerial.h>
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(); }

View File

@@ -43,10 +43,13 @@ public:
void tick() override {
if (!connected) return;
while (ser.available()) {
uint32_t start = millis();
while (ser.available() && millis() - start < 10) {
char c = ser.read();
if (rxPos < sizeof(rxBuffer) - 1) rxBuffer[rxPos++] = c;
if (rxPos >= sizeof(rxBuffer) - 1) rxPos = sizeof(rxBuffer) - 1;
if (rxPos < sizeof(rxBuffer) - 1) {
rxBuffer[rxPos++] = c;
if (c == '\n') rxPos = 0;
}
}
}