canbus: reverse-engineer OneControl IDS-CAN bus (read fully mapped, write auth-gated)
Tapped the X180T's CAN bus via CANable 2.0 at the monitor panel's terminator port. The bus is NOT RV-C — it's Lippert's proprietary IDS-CAN (250k, 11-bit IDs, (page<<8)|node, 1 Hz broadcasts). Read side fully mapped from live captures: - device classes (page-2 type byte: 0x0A tank, 0x1E switched load, 0x21 motor) - node map for this rig (Catalina 263BHSCK): tanks 27/E2/7D/FE, lights 2A/F8, heater 95, pump 61, awning 75 (+ direction & live motor current) - battery voltage on 29-bit extended frames Write side: commands are DLC-0 ext frames 0006<node><op>, but auth-gated by a rolling challenge-response (page 42/43). Replay confirmed dead (spoofed cansend did not actuate). Not the BLE TEA cypher. response=f(challenge) is deterministic (no session state) so crackable offline later — seeded 42 pairs in sniff/2A-auth-pairs.txt. Includes raw captures (sniff/*.log, force-added past *.log ignore), a read-only esp32_can ESPHome skeleton, and the log-can.sh sniff helper. Full writeup in canbus/README.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
# Lippert IDS-CAN command-auth challenge/response pairs
|
||||
# node 2A (exterior lights), captured 2026-06-11, app-driven on/off x~20
|
||||
# format: <challenge_hex> <response_hex> (both 4 bytes, from page42/page43 payload bytes 3-6)
|
||||
9577DE9B C033B197
|
||||
1ADF97F8 F48604B6
|
||||
E09D5B01 44A5C15E
|
||||
DEA757A0 04DD9CBA
|
||||
8862C15F 29AA626F
|
||||
E14DB9AE 25373B94
|
||||
23A3ED5D 3250A48A
|
||||
F3A3B602 A6E58995
|
||||
FC5F3883 47780DAF
|
||||
16B2AE10 28FE5A23
|
||||
11C34FD9 6A1B9415
|
||||
2FFC637D 0A5CE05B
|
||||
DB284B0C 052D2687
|
||||
FA14432F 71EDD5F4
|
||||
B140D087 356CFD45
|
||||
20337B7E 81D3136A
|
||||
968F0543 F91AB4A3
|
||||
28DA207A 781A423E
|
||||
AB4040DE 5B652F23
|
||||
7A3CA469 48DF5FCF
|
||||
AFDFBC25 2E52F019
|
||||
B7394203 C62B24EE
|
||||
ECA9CD68 361924A5
|
||||
83198E6B 7E9DF4D9
|
||||
4D3F6429 86793E68
|
||||
0804DD8B 953137D5
|
||||
E1525A39 1091BB17
|
||||
C77CAA9B F9746AAC
|
||||
B98C209C 46385C66
|
||||
BBE34815 F717E80E
|
||||
2DAA8E0C BB1CF451
|
||||
D4AAC54D FD806835
|
||||
E1ECB36C FE26F014
|
||||
BF066519 4F23CAAF
|
||||
DA8EF86C ED575807
|
||||
0FD2C9B9 6B0EF761
|
||||
4B192BC2 0DC60551
|
||||
A0421A64 54A5AD6D
|
||||
2BE06274 BD49B339
|
||||
8FF0B6E5 C18D49F2
|
||||
45FE7D5E 0A44BB97
|
||||
BAA07C27 54E5C64B
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Executable
+37
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env bash
|
||||
# Bring up the CANable at RV-C speed and log timestamped raw frames.
|
||||
#
|
||||
# Usage:
|
||||
# ./log-can.sh # bring up can0 @ 250k, live candump
|
||||
# ./log-can.sh rec NAME # also tee a timestamped log to NAME-<date>.log
|
||||
# ./log-can.sh sniff # cansniffer color-diff view (toggle a load, watch bytes)
|
||||
# ./log-can.sh down # take the interface down
|
||||
#
|
||||
# Requires: can-utils (pacman -S can-utils). CANable 2.0 with candleLight/gs_usb
|
||||
# firmware enumerates as a native socketcan device (default can0).
|
||||
|
||||
set -euo pipefail
|
||||
IFACE="${IFACE:-can0}"
|
||||
BITRATE=250000 # RV-C is always 250k
|
||||
CMD="${1:-up}"
|
||||
|
||||
up() {
|
||||
if ! ip link show "$IFACE" &>/dev/null; then
|
||||
echo "No $IFACE — is the CANable plugged in? (dmesg | grep -i gs_usb)" >&2
|
||||
exit 1
|
||||
fi
|
||||
sudo ip link set "$IFACE" down 2>/dev/null || true
|
||||
sudo ip link set "$IFACE" up type can bitrate "$BITRATE"
|
||||
echo "$IFACE up @ ${BITRATE} bps"
|
||||
}
|
||||
|
||||
case "$CMD" in
|
||||
up) up; exec candump -ta -x "$IFACE" ;;
|
||||
rec) up
|
||||
name="${2:-onecontrol}"; out="$(dirname "$0")/${name}-$(date +%F_%H%M%S).log"
|
||||
echo "logging -> $out (Ctrl-C to stop)"
|
||||
exec candump -ta -x "$IFACE" | tee "$out" ;;
|
||||
sniff) up; exec cansniffer -c "$IFACE" ;;
|
||||
down) sudo ip link set "$IFACE" down; echo "$IFACE down" ;;
|
||||
*) echo "usage: $0 {up|rec NAME|sniff|down}" >&2; exit 2 ;;
|
||||
esac
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user