Move command registry from components/command/ into components/core/. New modules: mod_canbus, mod_honeypot, mod_fallback, mod_redteam, mod_ota. Replace mod_proxy with tun_core (multiplexed SOCKS5 tunnel). Kconfig extended with per-module settings and async worker config.
342 lines
12 KiB
Markdown
342 lines
12 KiB
Markdown
# CAN Bus Module (mod_canbus)
|
|
|
|
Automotive CAN bus offensive module for Espilon, built on the **MCP2515** SPI controller. Supports passive sniffing, frame injection, ISO-TP transport, UDS diagnostics, OBD-II decoding, fuzzing, and replay.
|
|
|
|
> **Authorization required**: CAN bus interaction with vehicles must be performed only on owned hardware or with explicit written authorization. Unauthorized access to vehicle networks is illegal.
|
|
|
|
---
|
|
|
|
## Table of Contents
|
|
|
|
- [Hardware Requirements](#hardware-requirements)
|
|
- [Wiring](#wiring)
|
|
- [Configuration](#configuration)
|
|
- [Architecture](#architecture)
|
|
- [Commands Reference](#commands-reference)
|
|
- [Core Commands](#core-commands)
|
|
- [UDS Diagnostic Commands](#uds-diagnostic-commands)
|
|
- [OBD-II Commands](#obd-ii-commands)
|
|
- [Fuzzing Commands](#fuzzing-commands)
|
|
- [Frame Format](#frame-format)
|
|
- [C3PO Integration](#c3po-integration)
|
|
- [Usage Examples](#usage-examples)
|
|
- [Troubleshooting](#troubleshooting)
|
|
|
|
---
|
|
|
|
## Hardware Requirements
|
|
|
|
| Component | Role | Cost |
|
|
|-----------|------|------|
|
|
| **MCP2515 module** | CAN 2.0B controller + TJA1050 transceiver | ~3 EUR |
|
|
| **ESP32** | Main MCU (any variant with SPI) | ~5 EUR |
|
|
|
|
Most MCP2515 modules sold online already integrate the TJA1050 CAN transceiver. Check the oscillator crystal on your module — common values are **8 MHz** and **16 MHz** (must match Kconfig `CANBUS_OSC_MHZ`).
|
|
|
|
---
|
|
|
|
## Wiring
|
|
|
|
Default GPIO mapping (configurable via `idf.py menuconfig`):
|
|
|
|
```
|
|
MCP2515 Module ESP32 (VSPI)
|
|
────────────── ────────────
|
|
VCC → 3.3V
|
|
GND → GND
|
|
CS → GPIO 5
|
|
MOSI (SI) → GPIO 23
|
|
MISO (SO) → GPIO 19
|
|
SCK → GPIO 18
|
|
INT → GPIO 4 (active low)
|
|
```
|
|
|
|
Connect **CAN_H** and **CAN_L** on the MCP2515 module to the target CAN bus. For OBD-II: pin 6 (CAN_H) and pin 14 (CAN_L).
|
|
|
|
---
|
|
|
|
## Configuration
|
|
|
|
Enable the module in `idf.py menuconfig` under **Modules > CAN Bus Module (MCP2515)**.
|
|
|
|
### Kconfig Options
|
|
|
|
| Option | Default | Description |
|
|
|--------|---------|-------------|
|
|
| `CONFIG_MODULE_CANBUS` | n | Enable the CAN bus module |
|
|
| `CANBUS_SPI_HOST` | 3 (VSPI) | SPI host: 2=HSPI, 3=VSPI |
|
|
| `CANBUS_PIN_MOSI` | 23 | SPI MOSI GPIO |
|
|
| `CANBUS_PIN_MISO` | 19 | SPI MISO GPIO |
|
|
| `CANBUS_PIN_SCK` | 18 | SPI SCK GPIO |
|
|
| `CANBUS_PIN_CS` | 5 | SPI Chip Select GPIO |
|
|
| `CANBUS_PIN_INT` | 4 | MCP2515 interrupt GPIO (active low) |
|
|
| `CANBUS_OSC_MHZ` | 8 | Oscillator frequency on MCP2515 module |
|
|
| `CANBUS_DEFAULT_BITRATE` | 500000 | Default bus speed (bps) |
|
|
| `CANBUS_SPI_CLOCK_HZ` | 10000000 | SPI clock (max 10 MHz) |
|
|
| `CANBUS_RECORD_BUFFER` | 512 | Frame ring buffer size (64-2048) |
|
|
| `CANBUS_ISO_TP` | y | ISO-TP transport layer (required for UDS/OBD) |
|
|
| `CANBUS_UDS` | y | UDS diagnostic services (requires ISO-TP) |
|
|
| `CANBUS_OBD` | y | OBD-II PID decoder (requires ISO-TP) |
|
|
| `CANBUS_FUZZ` | y | CAN fuzzing engine |
|
|
|
|
### Supported Bitrates
|
|
|
|
| Bitrate | Use Case | 8 MHz | 16 MHz |
|
|
|---------|----------|-------|--------|
|
|
| 1 Mbps | High-speed CAN | - | Yes |
|
|
| 500 kbps | Standard automotive | Yes | Yes |
|
|
| 250 kbps | J1939 (trucks) | Yes | Yes |
|
|
| 125 kbps | Low-speed CAN | Yes | Yes |
|
|
| 100 kbps | Diagnostic | Yes | Yes |
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────┐
|
|
│ cmd_canbus.c — C2 command handlers (27 cmds)│
|
|
│ ↕ │
|
|
│ canbus_uds.c — UDS (ISO 14229) services │
|
|
│ canbus_obd.c — OBD-II PID decoder │
|
|
│ canbus_fuzz.c — Fuzzing engine │
|
|
│ ↕ │
|
|
│ canbus_isotp.c — ISO-TP (ISO 15765-2) │
|
|
│ ↕ │
|
|
│ canbus_driver.c — MCP2515 SPI driver + RX task │
|
|
│ ↕ │
|
|
│ canbus_config.c — NVS persistence │
|
|
│ ↕ │
|
|
│ ESP-IDF SPI Master — Hardware SPI bus │
|
|
└─────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### File Manifest
|
|
|
|
| File | Lines | Layer |
|
|
|------|-------|-------|
|
|
| `canbus_driver.c/.h` | ~920 | MCP2515 SPI + RX/TX + ISR |
|
|
| `canbus_isotp.c/.h` | ~480 | Multi-frame CAN transport |
|
|
| `canbus_uds.c/.h` | ~440 | Automotive diagnostics |
|
|
| `canbus_obd.c/.h` | ~390 | OBD-II PID decode |
|
|
| `canbus_fuzz.c/.h` | ~390 | Fuzz testing engine |
|
|
| `canbus_config.c/.h` | ~360 | NVS persistence |
|
|
| `cmd_canbus.c/.h` | ~1360 | Command handlers + registration |
|
|
| **Total** | **~4350** | |
|
|
|
|
### NVS Persistence
|
|
|
|
Namespace: `"can_cfg"`
|
|
|
|
| Key | Type | Content |
|
|
|-----|------|---------|
|
|
| `bitrate` | i32 | Saved CAN speed |
|
|
| `osc_mhz` | u8 | Oscillator frequency |
|
|
| `sw_filters` | blob | Up to 16 software filter IDs |
|
|
| `ecus` | blob | Discovered UDS ECU IDs |
|
|
|
|
---
|
|
|
|
## Commands Reference
|
|
|
|
### Core Commands
|
|
|
|
| Command | Args | Async | Description |
|
|
|---------|------|-------|-------------|
|
|
| `can_start [bitrate] [mode]` | 0-2 | No | Init MCP2515, start bus. Mode: `normal` (default), `listen`, `loopback` |
|
|
| `can_stop` | 0 | No | Stop bus, set MCP2515 to config mode |
|
|
| `can_send <id_hex> <data_hex>` | 2 | No | Send a single frame. Ex: `can_send 0x7DF 0201000000000000` |
|
|
| `can_filter_add <id_hex>` | 1 | No | Add software filter (pass only matching IDs) |
|
|
| `can_filter_del <id_hex>` | 1 | No | Remove a software filter |
|
|
| `can_filter_list` | 0 | No | List active software filters |
|
|
| `can_filter_clear` | 0 | No | Clear all filters (accept everything) |
|
|
| `can_status` | 0 | No | Show bus state, config, RX/TX counters, error counters |
|
|
| `can_sniff [duration_s]` | 0-1 | **Yes** | Stream frames to C2 for N seconds (default: 10) |
|
|
| `can_record [duration_s]` | 0-1 | **Yes** | Record to local ring buffer for N seconds (default: 10) |
|
|
| `can_dump` | 0 | **Yes** | Send recorded buffer to C2 |
|
|
| `can_replay [speed_pct]` | 0-1 | **Yes** | Replay recorded buffer. 100=real-time, 0=max speed |
|
|
|
|
### UDS Diagnostic Commands
|
|
|
|
*Requires `CONFIG_CANBUS_UDS=y` (depends on ISO-TP)*
|
|
|
|
| Command | Args | Async | Description |
|
|
|---------|------|-------|-------------|
|
|
| `can_scan_ecu` | 0 | **Yes** | Discover ECUs: scans 0x7E0-0x7E7, 0x700-0x7DF |
|
|
| `can_uds <tx_id> <service_hex> [data_hex]` | 2-3 | **Yes** | Raw UDS request |
|
|
| `can_uds_session <tx_id> <type>` | 2 | No | DiagnosticSessionControl (1=default, 2=prog, 3=extended) |
|
|
| `can_uds_read <tx_id> <did_hex>` | 2 | **Yes** | ReadDataByIdentifier |
|
|
| `can_uds_dump <tx_id> <addr_hex> <size>` | 3 | **Yes** | ReadMemoryByAddress (streamed) |
|
|
| `can_uds_auth <tx_id> [level]` | 1-2 | **Yes** | SecurityAccess seed request |
|
|
|
|
### OBD-II Commands
|
|
|
|
*Requires `CONFIG_CANBUS_OBD=y` (depends on ISO-TP)*
|
|
|
|
| Command | Args | Async | Description |
|
|
|---------|------|-------|-------------|
|
|
| `can_obd <pid_hex>` | 1 | **Yes** | Query single PID, returns decoded value |
|
|
| `can_obd_vin` | 0 | **Yes** | Read Vehicle Identification Number |
|
|
| `can_obd_dtc` | 0 | **Yes** | Read Diagnostic Trouble Codes |
|
|
| `can_obd_supported` | 0 | **Yes** | List supported PIDs |
|
|
| `can_obd_monitor <pids> [interval_ms]` | 1-2 | **Yes** | Stream PIDs to C2 continuously |
|
|
| `can_obd_monitor_stop` | 0 | No | Stop monitoring |
|
|
|
|
### Fuzzing Commands
|
|
|
|
*Requires `CONFIG_CANBUS_FUZZ=y`*
|
|
|
|
| Command | Args | Async | Description |
|
|
|---------|------|-------|-------------|
|
|
| `can_fuzz_id [start] [end] [delay_ms]` | 0-3 | **Yes** | Iterate all CAN IDs with fixed payload |
|
|
| `can_fuzz_data <id_hex> [seed_hex] [delay_ms]` | 1-3 | **Yes** | Mutate data bytes for fixed ID |
|
|
| `can_fuzz_random [delay_ms] [count]` | 0-2 | **Yes** | Random ID + random data |
|
|
| `can_fuzz_stop` | 0 | No | Stop fuzzing |
|
|
|
|
---
|
|
|
|
## Frame Format
|
|
|
|
Frames streamed to C2 use the format:
|
|
|
|
```
|
|
CAN|<timestamp_ms>|<id_hex>|<dlc>|<data_hex>
|
|
```
|
|
|
|
**Example:**
|
|
```
|
|
CAN|1708000123456|0x123|8|DEADBEEF01020304
|
|
```
|
|
|
|
### Special Markers
|
|
|
|
| Marker | Meaning |
|
|
|--------|---------|
|
|
| `SNIFF_END` | End of sniff session |
|
|
| `DUMP_START\|<count>` | Beginning of frame dump |
|
|
| `DUMP_END` | End of frame dump |
|
|
| `UDS_RSP\|<rx_id>\|<hex>` | UDS response |
|
|
| `MEM_DUMP\|<addr>\|<size>` | Start of memory dump |
|
|
| `MEM\|<addr>\|<hex_data>` | Memory block |
|
|
| `MEM_DUMP_END` | End of memory dump |
|
|
| `ECU\|<tx_id>\|<rx_id>` | Discovered ECU |
|
|
|
|
---
|
|
|
|
## C3PO Integration
|
|
|
|
### REST API
|
|
|
|
CAN frames received from agents are stored in a server-side ring buffer (10,000 frames max).
|
|
|
|
| Endpoint | Method | Description |
|
|
|----------|--------|-------------|
|
|
| `/api/can/frames` | GET | List frames. Params: `device_id`, `can_id`, `limit`, `offset` |
|
|
| `/api/can/stats` | GET | Frame stats. Params: `device_id` |
|
|
| `/api/can/frames/export` | GET | Download CSV. Params: `device_id` |
|
|
|
|
### TUI Commands
|
|
|
|
From the C3PO interactive TUI:
|
|
|
|
```
|
|
can stats [device_id] — Frame count, unique CAN IDs
|
|
can frames [device_id] [limit] — Display last N frames
|
|
can clear — Clear frame store
|
|
```
|
|
|
|
### Transport Integration
|
|
|
|
CAN frames arrive via `AGENT_DATA` messages with the `CAN|` prefix. The transport layer automatically parses and stores them in `CanStore`.
|
|
|
|
---
|
|
|
|
## Usage Examples
|
|
|
|
### Basic Sniffing (Listen-Only)
|
|
|
|
```
|
|
> can_start 500000 listen # Start in stealth mode (no ACK on bus)
|
|
> can_sniff 30 # Stream frames for 30 seconds
|
|
> can_stop
|
|
```
|
|
|
|
### Record and Replay
|
|
|
|
```
|
|
> can_start 500000 listen
|
|
> can_record 60 # Record for 60 seconds
|
|
> can_stop
|
|
|
|
> can_start 500000 normal # Switch to normal mode for TX
|
|
> can_replay 100 # Replay at real-time speed
|
|
```
|
|
|
|
### OBD-II Vehicle Diagnostics
|
|
|
|
```
|
|
> can_start 500000 # Standard automotive bitrate
|
|
> can_obd_supported # List what the car supports
|
|
> can_obd 0C # Engine RPM
|
|
> can_obd 0D # Vehicle speed (km/h)
|
|
> can_obd_vin # VIN number
|
|
> can_obd_dtc # Read trouble codes
|
|
> can_obd_monitor 0C,0D 500 # Stream RPM + speed every 500ms
|
|
```
|
|
|
|
### UDS ECU Exploration
|
|
|
|
```
|
|
> can_start 500000
|
|
> can_scan_ecu # Find ECUs on bus
|
|
> can_uds_session 0x7E0 3 # Extended session on ECU 0x7E0
|
|
> can_uds_read 0x7E0 F190 # Read VIN via DID
|
|
> can_uds_read 0x7E0 F191 # Hardware version
|
|
> can_uds_auth 0x7E0 1 # SecurityAccess level 1
|
|
> can_uds_dump 0x7E0 0x00000000 4096 # Dump 4KB from address 0
|
|
```
|
|
|
|
### Fuzzing (Isolated Bus Only!)
|
|
|
|
```
|
|
> can_start 500000
|
|
> can_fuzz_id 0x000 0x7FF 10 # Scan all standard IDs, 10ms delay
|
|
> can_fuzz_data 0x7E0 0000000000000000 5 # Mutate bytes on ECU ID
|
|
> can_fuzz_stop
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### MCP2515 not detected
|
|
|
|
- Verify wiring (CS, MOSI, MISO, SCK)
|
|
- Check `CANBUS_OSC_MHZ` matches the crystal on your module (8 vs 16 MHz)
|
|
- Try `can_start 500000 loopback` — if loopback works, wiring to the bus is the issue
|
|
|
|
### No frames received
|
|
|
|
- Confirm bus speed matches the target (500k for cars, 250k for trucks)
|
|
- Try `listen` mode first: `can_start 500000 listen`
|
|
- Check CAN_H / CAN_L connections and termination (120 ohm)
|
|
- Use `can_status` to check error counters — high RX errors indicate speed mismatch
|
|
|
|
### Bus-off state
|
|
|
|
- TEC exceeded 255 — the MCP2515 disconnected from the bus
|
|
- `can_stop` then `can_start` to reset
|
|
- Check for wiring issues or speed mismatch
|
|
|
|
### RX overflow
|
|
|
|
- Bus traffic exceeds processing speed
|
|
- Reduce bus load or add hardware filters: `can_filter_add <id>`
|
|
- Increase `CANBUS_RECORD_BUFFER` in menuconfig
|
|
|
|
### SPI communication errors
|
|
|
|
- Reduce `CANBUS_SPI_CLOCK_HZ` (try 8000000 or 4000000)
|
|
- Check for long wires or loose connections
|
|
- Ensure no other device shares the SPI bus
|