Add deploy.py: multi-device build/flash/provision with JSON config. Add espmon/: real-time ESP32 fleet monitoring daemon. Remove tools/flasher/ and tools/provisioning/ (superseded).
169 lines
4.5 KiB
Markdown
169 lines
4.5 KiB
Markdown
# Epsilon Tools
|
|
|
|
```
|
|
tools/
|
|
deploy.py Unified build, provision & flash pipeline
|
|
deploy.example.json Batch config template
|
|
C3PO/ C2 server (TCP + TUI + Web)
|
|
nanoPB/ Protobuf definitions (c2.proto)
|
|
```
|
|
|
|
## Prerequisites
|
|
|
|
- Python 3.8+
|
|
- ESP-IDF v5.3.2 (`source ~/esp-idf/export.sh`)
|
|
- esptool (`pip install esptool`)
|
|
|
|
---
|
|
|
|
## Deploy (`deploy.py`)
|
|
|
|
Single pipeline: **build** firmware, **generate** crypto keys, **provision** factory NVS, **flash** all partitions, **register** keys in C2 keystore.
|
|
|
|
### Usage
|
|
|
|
```bash
|
|
# Interactive wizard
|
|
python deploy.py
|
|
|
|
# Single device (WiFi + OTA)
|
|
python deploy.py -p /dev/ttyUSB0 -d ce4f626b \
|
|
--wifi MySSID MyPass --srv 192.168.1.51
|
|
|
|
# Single device (WiFi, no OTA)
|
|
python deploy.py -p /dev/ttyUSB0 -d a91dd021 --no-ota \
|
|
--wifi MySSID MyPass --srv 192.168.1.51
|
|
|
|
# Batch deploy
|
|
python deploy.py --config deploy.example.json
|
|
```
|
|
|
|
### Modes
|
|
|
|
| Flag | Effect |
|
|
|------|--------|
|
|
| *(default)* | Full pipeline: build + provision + flash |
|
|
| `--provision-only` | Generate key + flash factory NVS only |
|
|
| `--flash-only` | Flash existing build (skip rebuild) |
|
|
| `--build-only` | Build firmware only (no flash) |
|
|
| `--erase` | Erase entire flash before writing |
|
|
| `--monitor` | Open serial monitor after flash |
|
|
|
|
### OTA vs Non-OTA
|
|
|
|
| | OTA | Non-OTA (`--no-ota`) |
|
|
|---|---|---|
|
|
| Partition table | `partitions.csv` | `partitions_noota.csv` |
|
|
| App partitions | 2 x 1.875 MB (ota_0/ota_1) | 1 x 3.875 MB (factory) |
|
|
| Firmware updates | HTTPS OTA | Manual reflash |
|
|
| mbedTLS cert bundle | Yes | No |
|
|
|
|
### Flash Map
|
|
|
|
```
|
|
Offset OTA Non-OTA
|
|
------ --- -------
|
|
0x1000 bootloader bootloader
|
|
0x8000 partition table partition table
|
|
0xD000 ota data --
|
|
0x10000 factory NVS (key) factory NVS (key)
|
|
0x20000 app (ota_0) app (factory, 3.875 MB)
|
|
```
|
|
|
|
### Batch Config
|
|
|
|
`deploy.example.json`:
|
|
|
|
```json
|
|
{
|
|
"devices": [
|
|
{
|
|
"device_id": "ce4f626b",
|
|
"port": "/dev/ttyUSB0",
|
|
"srv_ip": "192.168.1.51",
|
|
"srv_port": 2626,
|
|
"network_mode": "wifi",
|
|
"wifi_ssid": "MyWiFi",
|
|
"wifi_pass": "MyPassword",
|
|
"module_network": true,
|
|
"ota_enabled": true
|
|
},
|
|
{
|
|
"device_id": "a91dd021",
|
|
"port": "/dev/ttyUSB1",
|
|
"srv_ip": "192.168.1.51",
|
|
"srv_port": 2626,
|
|
"network_mode": "wifi",
|
|
"wifi_ssid": "MyWiFi",
|
|
"wifi_pass": "MyPassword",
|
|
"module_network": true,
|
|
"module_fakeap": true,
|
|
"ota_enabled": false
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Config Fields
|
|
|
|
| Field | Default | Description |
|
|
|-------|---------|-------------|
|
|
| `device_id` | random | 8 hex chars unique ID |
|
|
| `port` | -- | Serial port |
|
|
| `srv_ip` | `192.168.1.100` | C2 server IP |
|
|
| `srv_port` | `2626` | C2 server port |
|
|
| `network_mode` | `wifi` | `wifi` or `gprs` |
|
|
| `wifi_ssid` | -- | WiFi SSID |
|
|
| `wifi_pass` | -- | WiFi password |
|
|
| `gprs_apn` | `sl2sfr` | GPRS APN |
|
|
| `hostname` | random | Device hostname on network |
|
|
| `module_network` | `true` | ping, arp, proxy, dos |
|
|
| `module_fakeap` | `false` | Fake AP, captive portal, sniffer |
|
|
| `module_recon` | `false` | Reconnaissance |
|
|
| `recon_camera` | `false` | ESP32-CAM |
|
|
| `recon_ble_trilat` | `false` | BLE trilateration |
|
|
| `ota_enabled` | `true` | OTA firmware updates |
|
|
| `master_key` | random | 64 hex chars (override auto-gen) |
|
|
|
|
### Crypto
|
|
|
|
Each deploy generates a **256-bit master key** per device:
|
|
|
|
1. Random 32-byte key generated (or provided via `--key`)
|
|
2. Written to factory NVS (`fctry` @ `0x10000`, namespace `crypto`, key `master_key`)
|
|
3. Registered in `C3PO/keys.json`
|
|
4. On boot, firmware derives encryption key via **HKDF-SHA256** (salt=device_id, info=`espilon-c2-v1`)
|
|
5. All C2 traffic encrypted with **ChaCha20-Poly1305 AEAD** (12-byte nonce + 16-byte tag)
|
|
|
|
---
|
|
|
|
## C2 Server (`C3PO/`)
|
|
|
|
Command & Control server for deployed ESP32 agents.
|
|
|
|
- Threaded TCP server with per-device encrypted communications
|
|
- ChaCha20-Poly1305 AEAD + HKDF key derivation
|
|
- Device registry + master key keystore (`keys.json`)
|
|
- TUI (Textual) + Web dashboard
|
|
- Camera UDP receiver + MLAT support
|
|
- Command dispatch: single device, group, or broadcast
|
|
|
|
```bash
|
|
cd C3PO && python3 c3po.py
|
|
```
|
|
|
|
See [C3PO/README.md](C3PO/README.md) for details.
|
|
|
|
---
|
|
|
|
## Proto Definitions (`nanoPB/`)
|
|
|
|
nanoPB protobuf definitions for ESP32 <-> C2 wire protocol.
|
|
|
|
- `c2.proto` -- `Command` and `AgentMessage` messages
|
|
- `c2.options` -- nanoPB field size constraints
|
|
|
|
---
|
|
|
|
**Authors:** @off-path, @eun0us
|