Card-Crack: Cardputer ESP32-S3 home-lab recon toolkit

Manual-trigger firmware toolkit for pentesting owned devices:
- Pin Scan: UART/JTAG/SWD detection (baud est + IDCODE reads)
- V-Sense: target voltage probe w/ logic-family guess
- UART Sniff: passive capture + manual-only frame replay
- USB Enum: ESP32-S3 host, read-only descriptor fingerprinting
- DefCred: single-host factory-default login check, rate-limited

Modular shell (core/ + modules/), PlatformIO build, hardware/safety docs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AAhMHMRAQLQ9hSbBECKNfn
This commit is contained in:
Indiana Holmes
2026-09-10 18:12:42 +00:00
commit 79612197a1
16 changed files with 967 additions and 0 deletions

71
src/core/shell.cpp Normal file
View File

@@ -0,0 +1,71 @@
#include "shell.h"
#include "ui.h"
#include <M5Cardputer.h>
// Module factories (defined in each module .cpp).
Module* makePinScan();
Module* makeVSense();
Module* makeUartSniff();
Module* makeUsbEnum();
Module* makeDefCred();
void Shell::begin() {
add(makePinScan());
add(makeVSense());
add(makeUartSniff());
add(makeUsbEnum());
add(makeDefCred());
M5.Display.fillScreen(ui::bg());
drawMenu();
}
void Shell::drawMenu() {
M5.Display.fillScreen(ui::bg());
ui::titleBar("Card-Crack", CARDCRACK_VERSION);
for (int i = 0; i < nmods; i++) {
bool cur = i == sel;
ui::lineC(i, cur ? ui::accent() : ui::fg(), "%c %-10s %s",
cur ? '>' : ' ', mods[i]->name(), mods[i]->blurb());
}
ui::hintBar("arrows move [enter]open home-lab only");
}
void Shell::enter(int i) {
active = i;
M5.Display.fillScreen(ui::bg());
ui::titleBar(mods[i]->name(), mods[i]->blurb());
mods[i]->onEnter();
mods[i]->draw();
}
void Shell::back() {
if (active >= 0) mods[active]->onExit();
active = -1;
drawMenu();
}
void Shell::loop() {
M5Cardputer.update();
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 (active < 0) {
if (c == ';') { sel = (sel - 1 + nmods) % nmods; drawMenu(); } // up
else if (c == '.') { sel = (sel + 1) % nmods; drawMenu(); } // down
else if (c == '\r' || c == ' ') enter(sel);
} else {
mods[active]->onKey(c);
}
}
if (st.enter && active < 0) enter(sel);
}
// ~30 Hz tick for the active module.
if (active >= 0 && millis() - lastTick > 33) {
lastTick = millis();
mods[active]->tick();
mods[active]->draw();
}
}