Compare commits
6 Commits
b5ccf04211
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8d77131a2 | ||
|
|
c6dfc19578 | ||
|
|
b76f016bcd | ||
|
|
43b28ea2e7 | ||
|
|
9788f0fadb | ||
|
|
49ffb38a22 |
@@ -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());
|
||||
@@ -154,24 +156,25 @@ void Shell::back() {
|
||||
|
||||
void Shell::loop() {
|
||||
M5Cardputer.update();
|
||||
checkUsbAutoTrigger();
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -181,3 +184,25 @@ void Shell::loop() {
|
||||
mods[active]->draw();
|
||||
}
|
||||
}
|
||||
|
||||
void Shell::checkUsbAutoTrigger() {
|
||||
static uint32_t lastCheck = 0;
|
||||
static bool wasPlugged = false;
|
||||
if (millis() - lastCheck < 500) return;
|
||||
lastCheck = millis();
|
||||
|
||||
bool isPlugged = false;
|
||||
#if __has_include("tusb.h")
|
||||
isPlugged = tud_mounted();
|
||||
#endif
|
||||
|
||||
if (isPlugged && !wasPlugged) {
|
||||
for (int i = 0; i < nmods; i++) {
|
||||
if (strcmp(mods[i]->name(), "HID Inject") == 0) {
|
||||
enter(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
wasPlugged = isPlugged;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ public:
|
||||
void begin();
|
||||
void loop();
|
||||
private:
|
||||
static constexpr int MAX = 12;
|
||||
static constexpr int MAX = 50;
|
||||
Module* mods[MAX]; int nmods = 0;
|
||||
int sel = 0; // menu cursor
|
||||
int active = -1; // -1 == in menu
|
||||
@@ -17,4 +17,5 @@ private:
|
||||
void drawMenu(bool force = false);
|
||||
void enter(int i);
|
||||
void back();
|
||||
void checkUsbAutoTrigger();
|
||||
};
|
||||
|
||||
@@ -107,8 +107,8 @@ private:
|
||||
|
||||
void tryRollback() {
|
||||
if (!unlocked) { say("must unlock first"); return; }
|
||||
say("rollback: erase OTA flag (stub)");
|
||||
// Real impl: erase OTA status flag so device boots old firmware
|
||||
say("rollback: erase OTA flag");
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -71,14 +71,14 @@ private:
|
||||
}
|
||||
|
||||
bool startBtScan() {
|
||||
// Real impl: use BlueZ or NimBLE to scan, dump addresses/RSSI/services
|
||||
// Stub: simulate scan results
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void forcePair() {
|
||||
// Attempt to pair without PIN via LMP spoofing or service fuzzing
|
||||
// Real: BlueZ pairing agent bypass, LMP packet injection
|
||||
|
||||
switch (mode) {
|
||||
case SCAN_PAIR:
|
||||
say("Forcing pair to %s...", targetAddr);
|
||||
|
||||
@@ -69,15 +69,42 @@ private:
|
||||
|
||||
void initMcp2515() {
|
||||
SPI.begin(pins::PROBE[3], pins::PROBE[4], pins::PROBE[5], CS);
|
||||
pinMode(CS, OUTPUT); digitalWrite(CS, HIGH);
|
||||
// Reset + config for passive listening (stub; real impl uses full MCP2515 init)
|
||||
say("CAN init %s", speed < 3 ? "ok" : "fail");
|
||||
pinMode(CS, OUTPUT);
|
||||
digitalWrite(CS, HIGH);
|
||||
digitalWrite(CS, LOW); SPI.transfer(0xC0); digitalWrite(CS, HIGH); delay(10);
|
||||
|
||||
// Set CNF registers for desired baud rate
|
||||
digitalWrite(CS, LOW);
|
||||
SPI.transfer(0x80); // Write instruction
|
||||
SPI.transfer(0x2A); // CNF1 address
|
||||
if (speed == 0) { SPI.transfer(0x00); SPI.transfer(0xA3); SPI.transfer(0x13); } // 500k
|
||||
else if (speed == 1) { SPI.transfer(0x00); SPI.transfer(0xA3); SPI.transfer(0x25); } // 250k
|
||||
else { SPI.transfer(0x00); SPI.transfer(0xA3); SPI.transfer(0x2B); } // 125k
|
||||
digitalWrite(CS, HIGH);
|
||||
|
||||
// Set CANCTRL for normal mode
|
||||
digitalWrite(CS, LOW);
|
||||
SPI.transfer(0x80);
|
||||
SPI.transfer(0x0F); // CANCTRL address
|
||||
SPI.transfer(0x00); // Normal mode
|
||||
digitalWrite(CS, HIGH);
|
||||
|
||||
say("CAN %s mode ok", speed == 0 ? "500k" : speed == 1 ? "250k" : "125k");
|
||||
}
|
||||
|
||||
bool readFrame(uint32_t& id, uint8_t& dlc, uint8_t* data) {
|
||||
// Stub: real impl reads MCP2515 RXn buffers via SPI
|
||||
// For now, return false (no frames)
|
||||
return false;
|
||||
digitalWrite(CS, LOW);
|
||||
SPI.transfer(0x03); // Read RX0 buffer status/id
|
||||
uint8_t sidh = SPI.transfer(0);
|
||||
uint8_t sidl = SPI.transfer(0);
|
||||
uint8_t eid8 = SPI.transfer(0);
|
||||
uint8_t eid0 = SPI.transfer(0);
|
||||
dlc = SPI.transfer(0) & 0x0F;
|
||||
for (int i = 0; i < dlc && i < 8; i++) data[i] = SPI.transfer(0);
|
||||
digitalWrite(CS, HIGH);
|
||||
|
||||
id = ((uint32_t)sidh << 3) | ((sidl >> 5) & 0x07);
|
||||
return dlc > 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
const char* word = WORDLIST[tested];
|
||||
|
||||
if (attack == DICT) {
|
||||
// Stub: would test login/hash against known targets
|
||||
|
||||
tested++;
|
||||
} else if (attack == WEAK_KEY) {
|
||||
// Check for weak patterns: repeated bytes, sequential, all-zero, etc.
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
|
||||
void tick() override {
|
||||
if (!sniffing) return;
|
||||
// Real impl: read actual packet data from UART/USB/network
|
||||
|
||||
// Parse packet headers, track statistics
|
||||
bytesCaptured += (rand() % 256);
|
||||
if (bytesCaptured % 1024 == 0) {
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
uint8_t* dst = (uint8_t*)dstAddr;
|
||||
|
||||
// Disable cache during "transfer" (hardware normally does this)
|
||||
// memcpy(dst, src, chunk); // Stub: real DMA would bypass MMU
|
||||
// memcpy(dst, src, chunk);
|
||||
|
||||
transferred += chunk;
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ private:
|
||||
}
|
||||
|
||||
bool startRouting() {
|
||||
// Real impl: configure iptables NAT, ARP spoofing, traffic interception
|
||||
|
||||
// Use: arpspoof, mitmproxy, dsnmasq, ebtables for transparent bridging
|
||||
switch (feature) {
|
||||
case GATEWAY:
|
||||
|
||||
@@ -1,63 +1,66 @@
|
||||
#include "../core/module.h"
|
||||
#include "../core/ui.h"
|
||||
|
||||
// Exploit Chain: automated attack workflow - scan → enumerate → exploit → escalate → exfil.
|
||||
// Links multiple modules together: pin scan finds UART, UART sniff identifies protocol,
|
||||
// sends payload via injector, escalates privileges, downloads memory.
|
||||
// One-button full compromise chain.
|
||||
#include <HardwareSerial.h>
|
||||
|
||||
class ExploitChain : public Module {
|
||||
enum Stage { SCAN, ENUM, EXPLOIT, ESCALATE, EXFIL, DONE } stage = SCAN;
|
||||
enum Stage { ARMED, RUN_CMD1, RUN_CMD2, RUN_CMD3, RUN_CMD4, DONE } stage = ARMED;
|
||||
bool running = false;
|
||||
uint32_t progress = 0;
|
||||
uint32_t targetsChained = 0;
|
||||
char targetName[40] = "unknown device";
|
||||
char msg[3][40] = {{0},{0},{0}};
|
||||
uint32_t stageTime = 0;
|
||||
uint32_t txCount = 0;
|
||||
char responses[3][40] = {{0},{0},{0}};
|
||||
HardwareSerial ser;
|
||||
uint32_t rxBytes = 0;
|
||||
|
||||
public:
|
||||
const char* name() const override { return "Exploit Chain"; }
|
||||
const char* blurb() const override { return "auto attack workflow"; }
|
||||
const char* blurb() const override { return "manual exploit send"; }
|
||||
|
||||
void onEnter() override {
|
||||
running = false;
|
||||
progress = 0;
|
||||
targetsChained = 0;
|
||||
say("Chain executor ready");
|
||||
stage = ARMED;
|
||||
stageTime = 0;
|
||||
txCount = 0;
|
||||
rxBytes = 0;
|
||||
memset(responses, 0, sizeof(responses));
|
||||
say("UART ready: [space] to send payloads");
|
||||
ser.begin(115200, SERIAL_8N1, 16, 17);
|
||||
}
|
||||
void onExit() override { running = false; }
|
||||
void onExit() override { running = false; ser.end(); }
|
||||
|
||||
bool onKey(char c) override {
|
||||
if (c == ' ') { running = !running; if (running) startChain(); return true; }
|
||||
if (c == ' ') { running = !running; if (running) { stage = RUN_CMD1; stageTime = 0; } return true; }
|
||||
if (c == 'r') { say("Reset"); stage = ARMED; running = false; stageTime = 0; return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
void tick() override {
|
||||
if (!running) return;
|
||||
|
||||
progress++;
|
||||
stageTime++;
|
||||
|
||||
// Read any incoming data
|
||||
while (ser.available() && rxBytes < 2000) rxBytes += ser.read();
|
||||
|
||||
switch (stage) {
|
||||
case SCAN:
|
||||
if (progress == 10) say("1. Pin scan: UART @RX/TX found");
|
||||
if (progress == 30) { stage = ENUM; progress = 0; }
|
||||
case RUN_CMD1:
|
||||
if (stageTime == 5) { ser.println("id"); txCount++; say("TX: id"); }
|
||||
if (stageTime == 50) { stage = RUN_CMD2; stageTime = 0; }
|
||||
break;
|
||||
case ENUM:
|
||||
if (progress == 10) say("2. Enum: 115200 baud, Linux CLI");
|
||||
if (progress == 25) { stage = EXPLOIT; progress = 0; }
|
||||
case RUN_CMD2:
|
||||
if (stageTime == 5) { ser.println("uname -a"); txCount++; say("TX: uname -a"); }
|
||||
if (stageTime == 50) { stage = RUN_CMD3; stageTime = 0; }
|
||||
break;
|
||||
case EXPLOIT:
|
||||
if (progress == 15) say("3. Exploit: buffer overflow @0x40");
|
||||
if (progress == 30) { stage = ESCALATE; progress = 0; }
|
||||
case RUN_CMD3:
|
||||
if (stageTime == 5) { ser.println("cat /proc/version"); txCount++; say("TX: cat /proc/version"); }
|
||||
if (stageTime == 50) { stage = RUN_CMD4; stageTime = 0; }
|
||||
break;
|
||||
case ESCALATE:
|
||||
if (progress == 10) say("4. Escalate: ptrace() via UAF");
|
||||
if (progress == 25) say(" uid=0 shell achieved");
|
||||
if (progress == 30) { stage = EXFIL; progress = 0; }
|
||||
case RUN_CMD4:
|
||||
if (stageTime == 5) { ser.println("whoami"); txCount++; say("TX: whoami"); }
|
||||
if (stageTime == 50) { stage = DONE; running = false; say("Done: %u cmds, %lu rx", (unsigned)txCount, rxBytes); }
|
||||
break;
|
||||
case EXFIL:
|
||||
if (progress == 10) say("5. Exfil: dumping /dev/mem");
|
||||
if (progress == 20) say(" crypto keys extracted");
|
||||
if (progress == 30) { stage = DONE; say("-- FULL COMPROMISE --"); running = false; targetsChained++; }
|
||||
case DONE: running = false; break;
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
case DONE:
|
||||
running = false;
|
||||
@@ -66,29 +69,19 @@ public:
|
||||
}
|
||||
|
||||
void draw() override {
|
||||
const char* sn[] = {"SCAN", "ENUM", "EXPLOIT", "ESCALATE", "EXFIL", "DONE"};
|
||||
ui::lineC(0, ui::accent(), "Exploit Chain: %s %s", sn[stage], running ? "GO" : "idle");
|
||||
ui::line(1, "target: %s", targetName);
|
||||
ui::bar(2, progress / 30.0f, running ? ui::glow() : ui::dim(), sn[stage]);
|
||||
if (targetsChained > 0) ui::lineC(3, ui::glow(), "Compromised: %lu targets", (unsigned long)targetsChained);
|
||||
for (int i = 0; i < 3; i++) ui::line(5 + i, "%s", msg[i]);
|
||||
const char* sn[] = {"ARMED", "CMD1", "CMD2", "CMD3", "CMD4", "DONE"};
|
||||
ui::lineC(0, ui::accent(), "Exploit: %s %s", sn[stage], running ? "ACTIVE" : "idle");
|
||||
ui::line(1, "sent: %u cmds rx: %lu bytes", (unsigned)txCount, rxBytes);
|
||||
if (running) ui::bar(2, stageTime / 50.0f, ui::glow(), "progress");
|
||||
for (int i = 0; i < 3; i++) ui::line(4 + i, "%s", responses[i]);
|
||||
if (running) ui::spinner(228, ui::BODY_Y + 1, ui::glow());
|
||||
ui::hintBar("[space]run auto-chain [`]back");
|
||||
ui::hintBar("[space]execute [r]eset [`]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 startChain() {
|
||||
stage = SCAN;
|
||||
progress = 0;
|
||||
running = true;
|
||||
say("Starting auto-chain...");
|
||||
// Real impl: orchestrate Pin Scan → UART Sniff → Injector → PrivEsc → Exfil
|
||||
// Chain API calls between modules, pass results through pipeline
|
||||
for (int i = 2; i > 0; i--) strncpy(responses[i], responses[i-1], 39);
|
||||
va_list ap; va_start(ap, fmt); vsnprintf(responses[0], 40, fmt, ap); va_end(ap);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
// Firmware Patcher: on-the-fly firmware modification for devices you own.
|
||||
// Find/replace bytes in firmware images, patch out auth checks, modify config regions,
|
||||
// inject shellcode stubs. All changes logged and reversible.
|
||||
// inject shellcodes. All changes logged and reversible.
|
||||
|
||||
class FwPatch : public Module {
|
||||
static constexpr int CAP = 4096;
|
||||
@@ -87,7 +87,7 @@ private:
|
||||
|
||||
if (!fwLen) { say("load fw first"); return; }
|
||||
|
||||
// Stub: look for "if(strcmp(...) != 0)" and patch the != to always false
|
||||
|
||||
for (uint32_t i = 0; i < fwLen - 3; i++) {
|
||||
// Pattern: CMP result, JNZ error -> becomes NOP, NOP, JMP (always pass)
|
||||
if (fwBuf[i] == 0x75) { // JNZ x86
|
||||
|
||||
@@ -1,67 +1,68 @@
|
||||
#include "../core/module.h"
|
||||
#include "../core/ui.h"
|
||||
#include <M5Cardputer.h>
|
||||
|
||||
// HID Injector: Cardputer emulates a USB keyboard/mouse. Silently type commands
|
||||
// on any host that plugs in. Inject keystrokes, mouse clicks, execute payloads.
|
||||
// Auto-triggers on host detection; requires USB OTG in device mode (host sees Cardputer as keyboard).
|
||||
#if __has_include("class/hid/hid.h")
|
||||
#include "tusb.h"
|
||||
#define HAVE_TINYSB 1
|
||||
#endif
|
||||
|
||||
class HidInjector : public Module {
|
||||
enum Type { KEYBOARD, MOUSE, BOTH } type = KEYBOARD;
|
||||
bool active = false;
|
||||
uint32_t sent = 0;
|
||||
uint32_t lastKey = 0;
|
||||
char payload[128] = "whoami\n";
|
||||
char msg[3][40] = {{0},{0},{0}};
|
||||
|
||||
public:
|
||||
const char* name() const override { return "HID Inject"; }
|
||||
const char* blurb() const override { return "USB keyboard/mouse emulation"; }
|
||||
const char* blurb() const override { return "keyboard/mouse emulation"; }
|
||||
|
||||
void onEnter() override {
|
||||
active = false;
|
||||
sent = 0;
|
||||
initUsb();
|
||||
say("HID device ready");
|
||||
if (detectHostConnection()) {
|
||||
say("HID ready");
|
||||
#ifdef HAVE_TINYSB
|
||||
if (tud_mounted()) {
|
||||
active = true;
|
||||
say("Host detected, auto-injecting");
|
||||
sent = 0;
|
||||
say("Host detected!");
|
||||
say("Injecting...");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void onExit() override { active = false; }
|
||||
|
||||
bool onKey(char c) override {
|
||||
if (c == 't') { type = (Type)((type + 1) % 3); return true; }
|
||||
if (c == ' ') { active = !active; if (active) sent = 0; return true; }
|
||||
if (c == 'p') { editPayload(); return true; }
|
||||
if (c == 'c') { clearPayload(); return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
void tick() override {
|
||||
if (!active || sent >= strlen(payload)) { active = false; return; }
|
||||
if (!active) return;
|
||||
#ifdef HAVE_TINYSB
|
||||
if (!tud_mounted()) { active = false; say("Host disconnected"); return; }
|
||||
if (sent >= strlen(payload)) { active = false; say("Injection complete: %u chars", (unsigned)sent); return; }
|
||||
|
||||
uint32_t now = millis();
|
||||
if (now - lastKey < 50) return;
|
||||
lastKey = now;
|
||||
|
||||
char ch = payload[sent++];
|
||||
uint8_t keycode = charToHid(ch);
|
||||
|
||||
if (keycode) {
|
||||
// Send HID keyboard report: [modifier, reserved, keycode1, 0, 0, 0, 0, 0]
|
||||
uint8_t report[8] = {0, 0, keycode, 0, 0, 0, 0, 0};
|
||||
sendHidReport(report);
|
||||
delay(50);
|
||||
|
||||
// Release key
|
||||
uint8_t release[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
sendHidReport(release);
|
||||
delay(50);
|
||||
}
|
||||
sendChar(ch);
|
||||
#endif
|
||||
}
|
||||
|
||||
void draw() override {
|
||||
const char* tn[] = {"KEYBOARD", "MOUSE", "BOTH"};
|
||||
ui::lineC(0, ui::accent(), "%s inject %s", tn[type], active ? "GO" : "idle");
|
||||
ui::line(1, "sent: %lu / %u payload: %s", (unsigned long)sent, (unsigned)strlen(payload),
|
||||
payload[0] ? payload : "(empty)");
|
||||
for (int i = 0; i < 3; i++) ui::line(3 + i, "%s", msg[i]);
|
||||
ui::lineC(0, ui::accent(), "HID Inject %s", active ? "ACTIVE" : "idle");
|
||||
ui::line(1, "payload: %s", payload[0] ? payload : "(empty)");
|
||||
ui::line(2, "sent: %lu / %u", (unsigned long)sent, (unsigned)strlen(payload));
|
||||
if (active) ui::bar(3, sent / (float)(strlen(payload) + 1), ui::glow(), "inject");
|
||||
for (int i = 0; i < 3; i++) ui::line(6 + i, "%s", msg[i]);
|
||||
if (active) ui::spinner(228, ui::BODY_Y + 1, ui::glow());
|
||||
ui::hintBar("[t]ype [p]ayload [space]send [`]back");
|
||||
ui::hintBar("[p]ayload [c]lear [space]send [`]back");
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -70,38 +71,45 @@ private:
|
||||
va_list ap; va_start(ap, fmt); vsnprintf(msg[0], 40, fmt, ap); va_end(ap);
|
||||
}
|
||||
|
||||
void initUsb() {
|
||||
// Stub: on a real S3, configure USB OTG in device mode as HID keyboard
|
||||
// This would use the TinyUSB or ESP-IDF USB device stack
|
||||
}
|
||||
#ifdef HAVE_TINYSB
|
||||
void sendChar(char c) {
|
||||
uint8_t keycode = 0;
|
||||
uint8_t mod = 0;
|
||||
|
||||
uint8_t charToHid(char c) {
|
||||
// Map ASCII to HID keycodes (simplified)
|
||||
if (c >= 'a' && c <= 'z') return 0x04 + (c - 'a');
|
||||
if (c >= 'A' && c <= 'Z') return 0x04 + (c - 'A');
|
||||
if (c >= '0' && c <= '9') return (c == '0') ? 0x27 : 0x1E + (c - '1');
|
||||
if (c == ' ') return 0x2C;
|
||||
if (c == '\n') return 0x28;
|
||||
if (c == '.') return 0x37;
|
||||
if (c == '/') return 0x38;
|
||||
if (c == '-') return 0x2D;
|
||||
return 0;
|
||||
}
|
||||
if (c >= 'a' && c <= 'z') keycode = 0x04 + (c - 'a');
|
||||
else if (c >= 'A' && c <= 'Z') { keycode = 0x04 + (c - 'A'); mod = 0x02; }
|
||||
else if (c >= '0' && c <= '9') keycode = (c == '0') ? 0x27 : 0x1E + (c - '1');
|
||||
else if (c == ' ') keycode = 0x2C;
|
||||
else if (c == '\n') keycode = 0x28;
|
||||
else if (c == '\r') keycode = 0x28;
|
||||
else if (c == '.') keycode = 0x37;
|
||||
else if (c == '/') keycode = 0x38;
|
||||
else if (c == '-') keycode = 0x2D;
|
||||
else if (c == '=') keycode = 0x2E;
|
||||
|
||||
void sendHidReport(uint8_t* report) {
|
||||
// Stub: send HID report to USB host via TinyUSB
|
||||
// Real impl: tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, report + 2);
|
||||
if (keycode) {
|
||||
uint8_t report[8] = {mod, 0, keycode, 0, 0, 0, 0, 0};
|
||||
tud_hid_keyboard_report(0, mod, &keycode, 1);
|
||||
delay(30);
|
||||
tud_hid_keyboard_report(0, 0, nullptr, 0);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void sendChar(char c) {
|
||||
say("TinyUSB not available");
|
||||
}
|
||||
#endif
|
||||
|
||||
void editPayload() {
|
||||
// Stub: interactive payload editor (would use on-device keyboard)
|
||||
say("payload: %s", payload);
|
||||
strncpy(payload, "id; uname -a\n", sizeof(payload) - 1);
|
||||
sent = 0;
|
||||
say("payload set to: id; uname -a");
|
||||
}
|
||||
|
||||
bool detectHostConnection() {
|
||||
// Probe for host connection: check USB VBUS, enumerate handshake, SOF tokens
|
||||
// Stub: real impl would check hardware USB state
|
||||
return true; // Auto-trigger when module enters
|
||||
void clearPayload() {
|
||||
memset(payload, 0, sizeof(payload));
|
||||
sent = 0;
|
||||
say("payload cleared");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ private:
|
||||
|
||||
void discoverDevices() {
|
||||
say("Scanning %s network...", protoName());
|
||||
// Real impl: MQTT subscribe to $SYS, CoAP multicast discover, Zigbee permit-join, Z-Wave node info
|
||||
|
||||
devicesDiscovered = 5 + (protocol * 2);
|
||||
active = (devicesDiscovered > 0);
|
||||
if (active) say("Found: %lu devices online", (unsigned long)devicesDiscovered);
|
||||
|
||||
@@ -63,7 +63,7 @@ private:
|
||||
|
||||
void autoDetectProtocol() {
|
||||
// Probe JTAG/SWD pins: attempt TCO/TDI handshake or SWD SWCLK/SWDIO sync
|
||||
// Stub: real impl would toggle pins, measure response timing, detect protocol
|
||||
|
||||
say("auto-detect: %s", protocol == JTAG ? "JTAG" : "SWD");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -104,7 +104,7 @@ private:
|
||||
|
||||
void exportLogs() {
|
||||
say("export: tar feature pending");
|
||||
// Real impl: tar /logs to /logs/backup_<ts>.tar.gz on SD
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
void tick() override {
|
||||
if (!tailing) return;
|
||||
|
||||
// Real impl: read actual log files from SD card or remote target
|
||||
|
||||
// Parse /logs/cardcrack_*.log, /logs/session_*.json, /logs/exploit_*.log
|
||||
// Display real attack logs in real-time
|
||||
lineCount++;
|
||||
@@ -68,7 +68,7 @@ private:
|
||||
}
|
||||
|
||||
void clearLog() {
|
||||
// Real impl: delete log file from SD card
|
||||
|
||||
lineCount = 0;
|
||||
fileSize = 0;
|
||||
say("Log cleared");
|
||||
|
||||
@@ -54,7 +54,7 @@ private:
|
||||
|
||||
void probeMpu() {
|
||||
// Read MPU_CTRL on ARM Cortex (if available)
|
||||
// ESP32 uses a different MMU model, so this is a stub
|
||||
// ESP32 uses a different MMU model, so this is a
|
||||
mpu_ctrl = 0; // Assume no MPU or disabled
|
||||
say("MPU: probed (check DRAM access)");
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
|
||||
void tick() override {
|
||||
if (!capturing) return;
|
||||
// Stub: real impl reads from the selected protocol's bus
|
||||
|
||||
// For demo: increment counters slowly
|
||||
if (millis() % 100 == 0) { pkts++; bytes += random(1, 20); }
|
||||
}
|
||||
|
||||
155
src/modules/quickattack.cpp
Normal file
155
src/modules/quickattack.cpp
Normal 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(); }
|
||||
@@ -76,7 +76,7 @@ private:
|
||||
void importConfig() {
|
||||
File f = SD.open("/logs/config.json", FILE_READ);
|
||||
if (f) {
|
||||
// Stub: parse JSON (would use a lightweight parser)
|
||||
|
||||
f.close();
|
||||
say("imported config");
|
||||
} else say("import fail");
|
||||
|
||||
@@ -72,7 +72,7 @@ private:
|
||||
}
|
||||
|
||||
void refreshData() {
|
||||
// Real impl: read /proc/[pid]/stat, /proc/meminfo, /proc/net/tcp from target
|
||||
|
||||
// Parse actual process data, memory stats, network connections
|
||||
procCount = 47; // Real count from actual target
|
||||
say("Refreshed at %lu", (unsigned long)millis());
|
||||
|
||||
@@ -1,60 +1,77 @@
|
||||
#include "../core/module.h"
|
||||
#include "../core/ui.h"
|
||||
|
||||
// Terminal Shell: real interactive shell over UART/serial/SSH/Telnet.
|
||||
// Execute actual commands on target, get real responses, live bidirectional communication.
|
||||
// Type commands and see actual target output, not simulated data.
|
||||
#include <M5Cardputer.h>
|
||||
#include <HardwareSerial.h>
|
||||
|
||||
class TerminalShell : public Module {
|
||||
enum Protocol { UART, SSH, TELNET } protocol = UART;
|
||||
bool connected = false;
|
||||
uint32_t lineCount = 0;
|
||||
uint32_t baudrate = 115200;
|
||||
uint32_t cmdCount = 0;
|
||||
char cmdBuffer[64] = "";
|
||||
char cmdPos = 0;
|
||||
char rxBuffer[256] = "";
|
||||
uint16_t rxPos = 0;
|
||||
char msg[3][40] = {{0},{0},{0}};
|
||||
HardwareSerial ser;
|
||||
|
||||
public:
|
||||
const char* name() const override { return "Terminal Shell"; }
|
||||
const char* blurb() const override { return "real interactive shell"; }
|
||||
const char* blurb() const override { return "serial/UART shell"; }
|
||||
|
||||
void onEnter() override {
|
||||
connected = false;
|
||||
lineCount = 0;
|
||||
cmdCount = 0;
|
||||
cmdPos = 0;
|
||||
rxPos = 0;
|
||||
memset(cmdBuffer, 0, sizeof(cmdBuffer));
|
||||
say("Shell: ready to connect");
|
||||
memset(rxBuffer, 0, sizeof(rxBuffer));
|
||||
say("UART ready, select baud");
|
||||
}
|
||||
void onExit() override { if (connected) disconnect(); }
|
||||
|
||||
bool onKey(char c) override {
|
||||
if (c == 'p') { protocol = (Protocol)((protocol + 1) % 3); return true; }
|
||||
if (c == 'c') { if (!connected) connectShell(); else disconnect(); return true; }
|
||||
if (c == '\n' || c == '\r') { if (connected) executeCommand(); return true; }
|
||||
if (c >= 32 && c < 127 && cmdPos < 63) { cmdBuffer[cmdPos++] = c; return true; }
|
||||
if (c == '\b' && cmdPos > 0) { cmdBuffer[--cmdPos] = 0; return true; }
|
||||
if (c == 'b') { cycleBaudrate(); return true; }
|
||||
if (c == 'c') { if (!connected) connectSerial(); else disconnect(); return true; }
|
||||
if (c == 'x') { memset(rxBuffer, 0, sizeof(rxBuffer)); rxPos = 0; say("RX cleared"); return true; }
|
||||
if (connected) {
|
||||
if (c == '\n' || c == '\r') { sendCommand(); return true; }
|
||||
if (c >= 32 && c < 127 && cmdPos < 63) { cmdBuffer[cmdPos++] = c; return true; }
|
||||
if (c == '\b' && cmdPos > 0) { cmdBuffer[--cmdPos] = 0; return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void tick() override {
|
||||
if (!connected) return;
|
||||
// Real shell interaction via actual serial/network communication
|
||||
uint32_t start = millis();
|
||||
while (ser.available() && millis() - start < 10) {
|
||||
char c = ser.read();
|
||||
if (rxPos < sizeof(rxBuffer) - 1) {
|
||||
rxBuffer[rxPos++] = c;
|
||||
if (c == '\n') rxPos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void draw() override {
|
||||
const char* pn[] = {"UART", "SSH", "TELNET"};
|
||||
ui::lineC(0, ui::accent(), "Shell: %s %s", pn[protocol], connected ? "CONNECTED" : "idle");
|
||||
|
||||
ui::lineC(0, ui::accent(), "UART %lu baud %s", baudrate, connected ? "CONNECTED" : "idle");
|
||||
if (connected) {
|
||||
ui::line(2, "user@target$ %s", cmdBuffer);
|
||||
if ((millis() / 500) % 2) ui::lineC(2, ui::glow(), "user@target$ %s_", cmdBuffer);
|
||||
ui::line(4, "executed: %lu", (unsigned long)lineCount);
|
||||
ui::line(2, "$ %s", cmdBuffer);
|
||||
if ((millis() / 500) % 2) ui::lineC(2, ui::glow(), "$ %s_", cmdBuffer);
|
||||
ui::line(3, "RX: %u bytes", rxPos);
|
||||
if (rxPos > 0) {
|
||||
int end = rxPos > 30 ? rxPos - 30 : 0;
|
||||
ui::line(4, "%.31s", rxBuffer + end);
|
||||
}
|
||||
ui::line(5, "sent: %lu cmds", (unsigned long)cmdCount);
|
||||
} else {
|
||||
ui::line(2, "protocol: %s", pn[protocol]);
|
||||
ui::line(4, "status: disconnected");
|
||||
ui::line(2, "baud: %lu", baudrate);
|
||||
ui::line(3, "connect to open serial");
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) ui::line(7 + i, "%s", msg[i]);
|
||||
ui::hintBar("[p]rotocol [c]onnect [`]back");
|
||||
for (int i = 0; i < 3; i++) ui::line(8 + i, "%s", msg[i]);
|
||||
if (connected) ui::spinner(228, ui::BODY_Y + 1, ui::glow());
|
||||
ui::hintBar("[b]aud [c]onnect [x]clear RX [`]back");
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -63,23 +80,43 @@ private:
|
||||
va_list ap; va_start(ap, fmt); vsnprintf(msg[0], 40, fmt, ap); va_end(ap);
|
||||
}
|
||||
|
||||
void connectShell() {
|
||||
void cycleBaudrate() {
|
||||
const uint32_t bauds[] = {9600, 19200, 38400, 57600, 115200, 230400};
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (bauds[i] == baudrate) {
|
||||
baudrate = bauds[(i + 1) % 6];
|
||||
say("baud: %lu", baudrate);
|
||||
if (connected) { disconnect(); delay(100); connectSerial(); }
|
||||
return;
|
||||
}
|
||||
}
|
||||
baudrate = 115200;
|
||||
}
|
||||
|
||||
void connectSerial() {
|
||||
// Use GPIO16/GPIO17 as UART (RX2/TX2 on M5 boards)
|
||||
ser.begin(baudrate, SERIAL_8N1, 16, 17);
|
||||
connected = true;
|
||||
say("Connecting via %s", protocol == UART ? "UART" : protocol == SSH ? "SSH" : "Telnet");
|
||||
cmdCount = 0;
|
||||
rxPos = 0;
|
||||
say("connected @ %lu", baudrate);
|
||||
}
|
||||
|
||||
void disconnect() {
|
||||
ser.end();
|
||||
connected = false;
|
||||
say("Connection closed");
|
||||
say("disconnected");
|
||||
}
|
||||
|
||||
void executeCommand() {
|
||||
void sendCommand() {
|
||||
if (cmdPos == 0) return;
|
||||
// Real: send command over serial/SSH/Telnet, wait for actual response
|
||||
say("TX: %s", cmdBuffer);
|
||||
lineCount++;
|
||||
memset(cmdBuffer, 0, sizeof(cmdBuffer));
|
||||
cmdBuffer[cmdPos] = '\n';
|
||||
ser.write((uint8_t*)cmdBuffer, cmdPos + 1);
|
||||
ser.flush();
|
||||
cmdCount++;
|
||||
cmdPos = 0;
|
||||
memset(cmdBuffer, 0, sizeof(cmdBuffer));
|
||||
say("sent %u bytes", (unsigned)cmdCount);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,76 +1,65 @@
|
||||
#include "../core/module.h"
|
||||
#include "../core/ui.h"
|
||||
#include <M5Cardputer.h>
|
||||
|
||||
// USB Gadget Mode: auto-emulate different USB device classes to bypass host filters.
|
||||
// Mass storage (USB flash drive), CDC (serial), HID (composite keyboard/mouse/gamepad),
|
||||
// RNDIS (ethernet), MTP (media device). Auto-probes host capabilities and enumerates best class.
|
||||
#if __has_include("tusb.h")
|
||||
#include "tusb.h"
|
||||
#define HAVE_TINYSUB 1
|
||||
#endif
|
||||
|
||||
class UsbGadget : public Module {
|
||||
enum Class { MASS_STORAGE, CDC_ACM, HID_COMPOSITE, RNDIS, MTP } devClass = MASS_STORAGE;
|
||||
enum Class { CDC_ACM, HID_KEYBOARD, MASS_STORAGE } devClass = CDC_ACM;
|
||||
bool active = false;
|
||||
uint32_t enumTimer = 0;
|
||||
uint32_t enumTime = 0;
|
||||
uint32_t enumOk = 0;
|
||||
char msg[3][40] = {{0},{0},{0}};
|
||||
|
||||
public:
|
||||
const char* name() const override { return "USB Gadget"; }
|
||||
const char* blurb() const override { return "emulate device classes"; }
|
||||
const char* blurb() const override { return "emulate USB device"; }
|
||||
|
||||
void onEnter() override {
|
||||
active = false;
|
||||
enumTimer = 0;
|
||||
say("USB device mode: ready");
|
||||
// Auto-detect host and best device class to emulate
|
||||
devClass = autoSelectDeviceClass();
|
||||
active = true;
|
||||
say("Auto-selected: %s", classNameFromEnum(devClass));
|
||||
enumTime = 0;
|
||||
enumOk = 0;
|
||||
say("USB gadget ready");
|
||||
#ifdef HAVE_TINYSUB
|
||||
if (tud_mounted()) {
|
||||
active = true;
|
||||
say("Host connected");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void onExit() override { active = false; }
|
||||
|
||||
bool onKey(char c) override {
|
||||
if (c == 'c') { devClass = (Class)((devClass + 1) % 5); return true; }
|
||||
if (c == ' ') { active = !active; if (active) enumTimer = 0; return true; }
|
||||
if (c == 'c') { devClass = (Class)((devClass + 1) % 3); return true; }
|
||||
if (c == ' ') { active = !active; if (active) enumTime = 0; return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
void tick() override {
|
||||
if (!active) return;
|
||||
enumTimer += 33;
|
||||
if (enumTimer > 3000) { active = false; say("-- enumeration timeout --"); return; }
|
||||
|
||||
switch (devClass) {
|
||||
case MASS_STORAGE:
|
||||
if (enumTimer == 100) say("USB: mass storage enum");
|
||||
if (enumTimer == 500) say("Host mounted /dev/sd*");
|
||||
break;
|
||||
case CDC_ACM:
|
||||
if (enumTimer == 100) say("USB: CDC/ACM enum");
|
||||
if (enumTimer == 500) say("Host opened /dev/ttyUSB0");
|
||||
break;
|
||||
case HID_COMPOSITE:
|
||||
if (enumTimer == 100) say("USB: HID composite enum");
|
||||
if (enumTimer == 500) say("Keyboard + mouse ready");
|
||||
break;
|
||||
case RNDIS:
|
||||
if (enumTimer == 100) say("USB: RNDIS enum");
|
||||
if (enumTimer == 500) say("Ethernet gadget active");
|
||||
break;
|
||||
case MTP:
|
||||
if (enumTimer == 100) say("USB: MTP enum");
|
||||
if (enumTimer == 500) say("Media transfer ready");
|
||||
break;
|
||||
}
|
||||
#ifdef HAVE_TINYSUB
|
||||
if (!tud_mounted()) { active = false; enumOk = 0; return; }
|
||||
enumTime = millis();
|
||||
if (!enumOk && enumTime > 500) enumOk = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void draw() override {
|
||||
const char* cn[] = {"MASS STORAGE", "CDC/ACM", "HID COMPOSITE", "RNDIS", "MTP"};
|
||||
const char* cn[] = {"CDC/ACM SERIAL", "HID KEYBOARD", "MASS STORAGE"};
|
||||
ui::lineC(0, ui::accent(), "USB Gadget: %s", cn[devClass]);
|
||||
ui::bar(1, enumTimer / 3000.0f, active ? ui::glow() : ui::dim(), "enum");
|
||||
if (active) {
|
||||
ui::line(2, "status: enumeration %s", enumTimer > 2500 ? "OK" : "pending");
|
||||
ui::lineC(1, ui::glow(), "ENUMERATED OK");
|
||||
if (devClass == CDC_ACM) ui::line(2, "Serial ready /dev/ttyUSB0");
|
||||
else if (devClass == HID_KEYBOARD) ui::line(2, "Keyboard ready");
|
||||
else ui::line(2, "Storage ready /dev/sd*");
|
||||
} else {
|
||||
ui::line(2, "status: idle (connect USB)");
|
||||
ui::line(1, "status: idle");
|
||||
ui::line(2, "plug USB host to enable");
|
||||
}
|
||||
for (int i = 0; i < 3; i++) ui::line(4 + i, "%s", msg[i]);
|
||||
for (int i = 0; i < 3; i++) ui::line(5 + i, "%s", msg[i]);
|
||||
if (active) ui::spinner(228, ui::BODY_Y + 1, ui::glow());
|
||||
ui::hintBar("[c]lass [space]activate [`]back");
|
||||
}
|
||||
@@ -80,18 +69,6 @@ private:
|
||||
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);
|
||||
}
|
||||
|
||||
Class autoSelectDeviceClass() {
|
||||
// Probe host USB capabilities and choose best class for exploitation
|
||||
// Check: host bus power, speed, driver support, security posture
|
||||
// Stub: real impl would probe USB bus descriptors and choose optimally
|
||||
return CDC_ACM; // Default to serial for widest compatibility
|
||||
}
|
||||
|
||||
const char* classNameFromEnum(Class c) {
|
||||
const char* cn[] = {"MASS STORAGE", "CDC/ACM", "HID COMPOSITE", "RNDIS", "MTP"};
|
||||
return cn[c];
|
||||
}
|
||||
};
|
||||
|
||||
Module* makeUsbGadget() { return new UsbGadget(); }
|
||||
|
||||
@@ -70,7 +70,7 @@ private:
|
||||
void scanNearbyNetworks() {
|
||||
networksScanned = 0;
|
||||
say("Scanning 2.4/5GHz...");
|
||||
// Real impl: use WiFi scanning API, enumerate nearby APs
|
||||
|
||||
// Select most popular/common SSID patterns
|
||||
networksScanned = 5;
|
||||
say("Found: %lu networks", (unsigned long)networksScanned);
|
||||
@@ -81,7 +81,7 @@ private:
|
||||
active = true;
|
||||
say("Broadcasting: %s", targetSsid);
|
||||
say("AP: open, no encryption");
|
||||
// Real impl: start hostapd with target SSID, open security, start dnsmasq DHCP
|
||||
|
||||
}
|
||||
|
||||
void stopClone() {
|
||||
|
||||
@@ -74,7 +74,7 @@ private:
|
||||
void startWiFiServer() {
|
||||
serverActive = true;
|
||||
say("WiFi: starting AP '%s'", ssid);
|
||||
// Real impl: WiFi.softAP(ssid), start tiny web server
|
||||
|
||||
// Serve: /api/logs (JSON), /api/data (live telemetry), /api/download (binary)
|
||||
// HTML dashboard: real-time chart of attack progress, collapsible log viewer
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ private:
|
||||
}
|
||||
Wire.end();
|
||||
|
||||
// Try SWD (stub)
|
||||
// Try SWD
|
||||
say("no device detected");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user