This repository contains workshop materials and labs for hands-on security analysis of a toy hardware wallet running on RP2040 dev board (Raspberry Pi Pico).
AUTHORIZED ACTIVITY Participants are authorized to analyze, test, and intentionally interact with security weaknesses ONLY in the hardware, firmware, and materials provided as part of this workshop. LIMITED SCOPE This authorization applies solely to designated workshop exercises and equipment. Techniques discussed or demonstrated must be used only where lawful and with proper authorization. WORKSHOP EQUIPMENT Workshop devices are provided for hands-on experimentation. Devices may be modified, stressed, or rendered inoperable as part of the exercises. PERSONAL SYSTEM RESPONSIBILITY Participants are responsible for the safety, integrity, and security of their personal computers, software, operating systems, and data. ETHICAL & LAWFUL USE Participants agree to apply acquired knowledge responsibly, ethically, and in compliance with applicable laws. ACCEPTANCE OF TERMS Participation in the workshop constitutes acknowledgment and acceptance of this disclaimer.
- Reconstructing Hardware Wallet Exploits
This workshop reconstructs a realistic exploit chain against intentionally vulnerable wallet firmware: a timing side-channel to recover the PIN, a buffer over-read to leak internal memory, and a stack overflow to hijack control flow (ret2win). Plus a bonus ROP lab for code-reuse exploitation. The goal is to understand how implementation bugs in protocol parsing and state handling become practical attacks. And also how to mitigate them with constant-time checks, strict bounds validation, and safer serialization.
labs/: Guided exercises and attack labsclient/: USB/client-side interaction scripts
Follow the labs in order:
- Lab 1: Timing Side-Channel PIN Recovery
- Lab 2: Flash Memory Over-Read and Function Pointer Leak
- Lab 3: Remote Stack Overflow and Return Address Hijack
- Lab 4 (Bonus): ROP Exploitation to Print Attacker-Controlled String
Use the platform-specific steps below to install Python 3.10 (latest patch), create a virtual environment, and install Python dependencies.
brew update
brew install python@3.10
python3.10 --version
python3.10 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install -r requirements.txtsudo apt update
sudo apt install -y python3.10 python3.10-venv
python3.10 --version
python3.10 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install -r requirements.txt- Install Python 3.10 (latest patch) from https://www.python.org/downloads/windows/
- During install, enable
Add python.exe to PATH. - In PowerShell, run:
py -3.10 --version
py -3.10 -m venv .venv
.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
pip install -r requirements.txtpython --version
pip list
pytest --versionUse the prebuilt workshop firmware at bin/toy_wallet.uf2 to flash your board.
- Disconnect the RP2040 board from USB.
- Press and hold the BOOTSEL button.
- While holding BOOTSEL, plug the board into USB, then release the button.
- A mass-storage drive named
RPI-RP2should appear. - Copy
bin/toy_wallet.uf2to that drive. - Wait for the board to reboot automatically (the
RPI-RP2drive will disappear).
cp bin/toy_wallet.uf2 /Volumes/RPI-RP2/Copy the file to the mounted RPI-RP2 drive using your file manager, or from terminal:
cp bin/toy_wallet.uf2 /media/$USER/RPI-RP2/- Open File Explorer and locate the
RPI-RP2drive. - Copy
bin/toy_wallet.uf2from this repository onto that drive. - Wait for automatic reboot.
After reboot, continue with the Hardware Setup steps below to verify USB CDC interfaces.
- Connect the RP2040 dev board (Raspberry Pi Pico) to your laptop using your own or provided USB-C data cable.
- Wait a few seconds for USB enumeration to complete.
- Confirm that two USB CDC serial interfaces are visible and accessible from user space.
Check for two serial devices:
ls /dev/cu.usbmodem*You should see two entries (names vary by machine).
Quick access check from Python:
python -m serial.tools.list_ports -vCheck kernel detection:
dmesg | tail -n 40Check for two serial devices:
ls /dev/ttyACM*You should see two entries (for example /dev/ttyACM0 and /dev/ttyACM1).
If permissions are denied, add your user to dialout and re-login:
sudo usermod -a -G dialout $USERQuick access check from Python:
python -m serial.tools.list_ports -v- Connect the board and confirm Windows sees two COM ports in Device Manager -> Ports (COM & LPT).
- In PowerShell, list serial ports:
mode- Check from Python that ports are visible to user-space programs:
python -m serial.tools.list_ports -vclient/ux.py is a minimal serial console for the device UX/log channel (CDC 0), intended as a lightweight replacement for screen on macOS, Linux, and Windows.
- If run without a port argument, it auto-discovers the toy wallet by VID/PID and selects CDC 0.
- During discovery it treats any interface that responds to
pingwithokas CDC 1 (host protocol), then uses the other interface as CDC 0. - Interactive mode streams CDC 0 output and forwards your key presses to the device.
- Exit shortcut:
Ctrl-]
Examples:
Linux/macOS auto-discovery:
python3 client/ux.pyLinux explicit CDC0 port:
python3 client/ux.py /dev/ttyACM0macOS explicit CDC0 port:
python3 client/ux.py /dev/cu.usbmodem2101Windows (PowerShell) auto-discovery:
python client/ux.pyWindows explicit CDC0 port:
python client/ux.py COM5Optional tuning flags:
python3 client/ux.py --vid 0xCAFE --pid 0x4002 --banner-pulse 0.5- Use a known good data USB-C cable; many charging cables do not expose data lines.
- Avoid USB hubs at first; plug directly into the laptop.
- Reconnect the board and rerun the port listing commands.
- If Linux shows permission errors, verify
dialoutgroup membership and re-login. - If Windows does not show COM ports, reconnect the board and recheck Device Manager.