When to use / when not to use
- Prerequisite: you have an ARXML or in-vehicle software package but are not sure whether it is Classic or Adaptive → the in-vehicle section of [[re-analyze/system-fingerprints]]
- Use: you have vehicle CAN bus traffic (candump logs / .asc / .blf) and need to parse messages and signals
- Use: reverse engineering of in-vehicle devices (head unit, T-Box, IVI, ECU update packages)
- Use: OBD-II / UDS diagnostic session analysis (reading DTCs, security access, calibration read/write)
- Use: ECU firmware extraction and subsequent unpacking (together with [[re-firmware]])
- Use:AUTOSAR Classic software(SWC/runnable/RTE/BSW) — the execution graph is determined by configuration and code generation and cannot be understood with an ordinary call graph ([[autosar-classic]])
- Do not use: you only have an ECU firmware file and no bus access (go directly to [[re-fw-extract]])
- Do not use: you need to run the firmware to observe behavior ([[re-fw-emulate]])
- Do not use: you need JTAG/SWD to read flash ([[re-hardware-io]])
- Red line: test only on vehicles and test benches that you own or are authorized for (see step 5)
Tool preparation
Verify all tools before use. Tests on real vehicles/real buses are physically isolated by default — the highest principle of [[re-analyze/platform-tips]]: only vehicles/benches that you own or are authorized to test may be connected; start in the lab with a vcan virtual bus, do not connect to a real vehicle.
can-utils — candump/cansend/cangen/canplayer main tools
- Linux:
apt install can-utils(Debian/Ubuntu)/dnf install can-utils(Fedora) / Arch: no official package → AUR (can-utils) or build from source (git clone https://github.com/linux-can/can-utils && cd can-utils && ./autogen.sh && ./configure && make) - macOS/Windows: no official package (SocketCAN is a Linux kernel feature) → Linux version inside WSL/virtual machine
- Verify:
candump --help;cansend --help
socketcan — Linux kernel CAN stack (vcan virtual bus / can-isotp)
- Linux: kernel built-in module (kernels 5.10+ include can-isotp):
modprobe can vcan can-isotp;ip linkcomes from iproute2 (included in the base system) - macOS/Windows: not supported → WSL2/virtual machine (requires Linux 5.10+)
- Verify:
modprobe vcan && ip link add dev vcan0 type vcan && ip link set up vcan0 && ip -details link show vcan0
USB-CAN adapter — gs_usb family (canable/candlelight), plug and play
- Linux: kernel built-in gs_usb driver (drivers/net/can/usb/gs_usb.c); after plugging in,
dmesgshould register can0 (in some distributions the CAN driver is in the modules-extra package,modprobe gs_usbwhen an error is reported, install the corresponding extra package) - macOS/Windows: use the vendor driver + vendor software, or pass through via a virtual machine
- Verify:
modprobe gs_usb;ip -details link show can0
wireshark / tshark — CAN/ISO-TP/UDS parsing
- Install as in [[re-netcap]] tool preparation (apt/dnf/pacman/brew/choco); CAN (socketcan / Vector ASCII / BSLogger), ISO-TP, UDS (ISO 14229) dissectors are built in
- Verify:
tshark --version;candump-llogs can be opened directly with File → Open
python-can — scripted parsing (cross-platform)
- All platforms:
pip install python-can - Linux:
apt install python3-can(Debian/Ubuntu)/dnf install python3-can(Fedora)/pacman -S python-can(Arch extra) - Verify:
python3 -c "import can; print(can.__version__)"
OBD-II / UDS diagnostic libraries
- python-obd (ELM327 adapter, OBD-II standard services): no official package →
pip install obd; verifypython3 -c "import obd" - udsoncan (UDS ISO 14229 client): no official package →
pip install udsoncan isotp; Verifypython3 -c "import udsoncan, isotp" - Note: udsoncan with IsoTPSocketConnection requires the Linux can-isotp kernel module (5.10+) or socketcan; when there is no kernel module, use PythonIsoTpConnection (goes through python-can, cross-platform but with slightly worse timing)
scapy — automotive protocol layer (automotive package, optional)
- All platforms:
pip install scapy(includingscapy.contrib.automotiveandscapy.layers.can) - Verify:
python3 -c "from scapy.contrib.automotive.uds import UDS; from scapy.contrib.automotive.doip import DoIP; from scapy.layers.can import CAN; print('ok')"
Procedure
Execute in order, and record the result of each step.
-
CAN access (USB-CAN / socketcan):
- Start without hardware (vcan virtual bus):
sudo modprobe can vcan can-isotp sudo ip link add dev vcan0 type vcan sudo ip link set up vcan0 - USB-CAN (gs_usb family):
sudo modprobe gs_usb sudo ip link set can0 up type can bitrate 500000 # 500 kbit/s 经典波特率 ip -details link show can0 # 确认 bitrate / state UP - The baud rate must match the bus (wrong baud rate = flood of error frames, see pitfall 3)
- Start without hardware (vcan virtual bus):
-
candump packet capture:
candump -t a can0 # 实时查看(绝对时间戳) candump -l can0 # 落盘日志(默认文件名带时间戳;无轮转——需要轮转交给 logrotate/外部脚本;Wireshark 可直接打开) candump can0 -n 100 # 只抓 100 帧 candump can0,7E0:7FF # ID 过滤:接口名后接 can_id:mask(逗号分隔);掩码 7FF = 精确匹配 7E0,区间过滤用 7F8(匹配 7E0~7E7);CAN 无地址(见坑 1) candump -f can.log can0 # 注意 -f 是"日志写入文件",不是过滤参数 -
Message ID / period / signal decoding:
cansniffer can0 # 按 ID 聚类、周期与变化字节高亮 candump can0 | awk '{print $2}' | sort | uniq -c # 按 ID 统计帧数(默认输出第 2 列是 ID;注意 -c 是颜色模式,不是计数) canbusload can0@500000 # 总线负载率 %- Periodic messages (common fixed intervals of 10/50/100 ms) → continuous signals such as RPM/vehicle speed; event messages (irregular) → switches/buttons
- Signal unpacking: first determine byte order (Intel little-endian vs Motorola big-endian, see pitfall 2) → observe byte-by-byte changes (cansniffer highlights changing bytes) → use cantools to unpack according to the DBC definition (
pip install cantools) - Produce an ID table: ID / period / length / suspected signal / byte order
-
UDS / OBD diagnostics:
- OBD-II quick health check (standard diagnostic pair 0x7E0/0x7E8, ELM327 adapter):
import obd conn = obd.OBD() # 自动探测适配器串口 conn.query(obd.commands.SPEED) # 车速 conn.query(obd.commands.GET_DTC) # 故障码 - UDS (ISO 14229, manufacturer diagnostic IDs are not fixed, capture packets first to confirm):
import udsoncan, isotp from udsoncan.connections import IsoTPSocketConnection from udsoncan.client import Client, ClientConfig from udsoncan.services import DiagnosticSessionControl, DataIdentifier # 关键:DID 的 payload 怎么编解码,由 config['data_identifiers'] 决定—— # 该 DID 不在映射里时,udsoncan 在发送请求**之前**就抛 ConfigError #("contains no definition for data identifier 0xf190");映射里有但 codec 不是 # DidCodec 实例则抛 ValueError("is not a valid DidCodec")。 # 配置只需给出要覆盖的键:Client 会用 udsoncan.configs.default_client_config 补齐其余项, # 所以 data_identifiers 之外不必逐项照抄默认值。 config = ClientConfig() config['data_identifiers'] = { 0xF190: ..., # VIN 的标准 DID;codec = 17 字节 ASCII(用库自带的类型,或自定义 DidCodec 子类) } conn = IsoTPSocketConnection('can0', isotp.Address(isotp.AddressingMode.Normal_11bits, rxid=0x7E8, txid=0x7E0)) with Client(conn, request_timeout=2, config=config) as client: client.change_session(DiagnosticSessionControl.Session.extendedDiagnosticSession) vin = client.read_data_by_identifier(DataIdentifier.VIN) - Reading/writing a DID requires configuring the codec first:
read_data_by_identifier/write_data_by_identifierdepends on thedata_identifiersin the client configuration (DID → codec mapping) —the response is just a byte string; without the codec there is no way to decode it, udsoncan will terminate with a configuration error rather than "return raw bytes". Official examples are always written asClient(..., config=MyCar.config)and note that the codec for the VIN is configured in the client configuration. If you only want to see the raw payload, do not go through the DID decoding path; use a low-level interface that does not decode - Service quick reference: 0x10 session control / 0x22 read data by identifier / 0x27 security access (seed-key) / 0x2E write data / 0x31 routine control / 0x3E tester present / 0x11 ECU reset / 0x34-0x36-0x37 firmware download flow
- Open the candump log in Wireshark → the ISO-TP/UDS dissector automatically decodes the diagnostic session
- OBD-II quick health check (standard diagnostic pair 0x7E0/0x7E8, ELM327 adapter):
-
ECU firmware:
- UDS download flow: the core of the standard transfer is
0x34 RequestDownload → 0x36 TransferData × N → 0x37 RequestTransferExit; actual ECU programming usually first enters the0x10programming session according to OEM requirements, executes0x27(security access) when the service is protected by a security level, and erase/integrity checks mostly go through the OEM-defined0x31(routine control); the process may require0x3Ekeep-alive, and at the end may0x11reset — the specific sequence is recovered from ECU behavior/ODX/firmware, do not assume a fixed order. Or use0x23to read memory and obtain the firmware → convert to [[re-fw-extract]] for unpacking (ECU/head unit firmware follows the same flow as IoT firmware) - Directly obtained upgrade package file → [[re-fw-extract]]; firmware ELF → [[re-binary-core]]; requires hardware flash reading → [[re-hardware-io]]
- UDS download flow: the core of the standard transfer is
IVI / T-Box / V2X paths
Branch by target form factor (decision rules):
- IVI (in-vehicle infotainment system): The essence is an Android/Linux system—the application layer goes through [[re-apk]], the system image goes through [[re-firmware]]; focus on the OEM customization layer (launcher, diagnostic interfaces, ADB/debug ports)
- T-Box (Telematics Box): Cellular module (AT command interface), MCU firmware ([[re-fw-extract]] extraction and analysis), remote control protocol (vehicle control commands—door locks/AC/start, via [[re-protocol]])
- V2X (Vehicle-to-Everything communication): DSRC / C-V2X frame structure → [[re-protocol]] / [[re-ics]] paths (protocol state machine reconstruction, PC5/Uu interface distinction); physical layer signal acquisition goes through [[re-sdr]]
- Decision rules: application layer → mobile/system paths ([[re-apk]] / [[re-firmware]]); communication layer → protocol paths ([[re-protocol]] / [[re-ics]]); firmware layer → firmware paths ([[re-fw-extract]] / [[re-fw-rootfs]])
Branches (references)
- [[autosar-classic]] —— Configuration-driven + code generationexecution graph: RunnableEntity is activated by RTEEvent and mapped via RTE glue to OS Task or ISR2(RTE has no independent scheduling capability),A runnable with no caller is not dead code;Implicit access(
Rte_IRead_*/Rte_IWrite_*) performs snapshot and write-back at runnable boundaries ("consumer sees old value" may be semantics);E_OS_ACCESScomes from OS-Application ownership/protection(default deny, authorization comes from configuration), not a parameter error; for concurrency anomalies, check the OS configuration first (Task mapping, priority, preemption) - [[autosar-adaptive]] —— Manifest-driven lifecycle: POSIX processes + ARA functional clusters;Modelled Process ≠ OS process(do not compare 1:1);"bin exists but process does not"—check Function Group State / Machine State first(EM translates states into process sets); Execution Manifest can give the same executable different configurations per state; when EM switches, it terminates first and then starts according to dependencies
Cross-domain federation
- [[re-firmware]]: this skill is its automotive branch (after ECU firmware extraction → unpacking → rootfs → emulation)
- [[re-fw-extract]] / [[re-fw-rootfs]] / [[re-fw-emulate]]: ECU/head unit firmware unpacking, file system analysis, emulation
- [[re-hardware-io]]: OBD port packet capture (CAN/UART), JTAG/SWD flash reading
- [[re-protocol]]: reconstruction of automotive Ethernet protocols such as DoIP (UDS over Ethernet, port 13400); CAN proprietary protocols go to [[re-proto-rev]]
- [[re-sandbox]]: virtual CAN / DoIP testbed isolation; firmware emulation defaults to network isolation ([[re-analyze/platform-tips]] highest principle)
- [[re-binary-core]]: deep static analysis of ELF inside firmware
- [[re-crypto-id]] / [[re-crypto-decrypt]]: seed-key algorithms, CAN encryption variants
Common pitfalls and traps
- CAN has no concept of addresses → filtering/attribution errors: Symptom—wanting to "filter by target ECU" but either missing frames or capturing everything; Cause—CAN frames have no source/destination addresses, only an 11/29-bit arbitration ID, and the ID serves both as priority and "identity" (the smaller the ID, the higher the priority); Countermeasure—first capture everything (candump), then cluster and classify by ID (cansniffer, or pipe candump output through awk/sort/uniq for statistics), use
candump can0,ID:maskto filter, do not presuppose a host concept - Signal bit packing errors: Symptom — signal values are garbled (negative/huge RPM, multi-byte fields misaligned); Cause — signals are packed across bytes and bits, Intel (little-endian)/Motorola (big-endian) byte orders are mixed, and signals need not be aligned to byte boundaries; Countermeasure — determine the byte order before unpacking, define the bit layout with DBC + cantools, and cross-validate against real vehicle readings/known ranges
- Baud rate mismatch and bus load: Symptom —
candumperror frames flooding the screen (error frame), or cycle jitter under high load, making the captured period untrustworthy; Cause — the baud rate does not match the bus; under high load (>60-70%), arbitration delay and frame loss occur; Countermeasure — confirm the baud rate before connecting (500 kbit/s is most common, use canbusload to check the load rate), exclude high-load periods in periodicity analysis, and use hardware timestamps when precise timing is needed - seed-key security access denied: Symptom — UDS reads memory/writes calibration and returns 0x7F 27 33 (SecurityAccessDenied); Cause — 0x27 requires unlocking first: the server sends a seed (0x27 01/03), the client returns a key (0x27 02/04), and the algorithm is vendor-private (XOR/CRC/AES are common); Countermeasure — when a legitimate diagnostic tool/device is available, first capture one normal unlock sequence, and for algorithm recovery go through [[re-crypto-id]] / [[re-crypto-decrypt]]; do this only on your own test equipment, do not brute-force blindly
- Firmware verification/encryption layer: Symptom — the extracted firmware decodes to garbage in [[re-fw-extract]], or does not work when flashed back; Cause — ECU firmware has signature/CRC verification, bootloader signature verification, or full encryption; Countermeasure — during extraction, transmit the complete session via 0x34/0x36 and verify it; during analysis, first distinguish the encryption/signature layer before unpacking, and if it cannot be unpacked, switch to [[re-crypto-id]] / [[re-crypto-decrypt]]; operate only on authorized test benches/devices
- Treating an AUTOSAR runnable as dead code: Symptom — a business function has no caller at all, so it is judged to be leftover/useless code; Cause — the runnable is called by an RTEEvent via generated RTE glue inside some OS Task,the call relationship is in the configuration rather than in the source code; Countermeasure — find the
Rte_*wrapper and RTEEvent mapping, and confirm which OS Task it is mapped to ([[autosar-classic]]) - Treating the "old value" of implicit access as a consistency problem: Symptom — the producer changes the data during runtime, and the consumer runnable keeps reading the old value throughout its execution, raising suspicion of cache or memory corruption; Cause — implicit access takes a snapshot and writes back at runnable boundaries; Countermeasure — distinguish
Rte_Read_*(explicit) fromRte_IRead_*(implicit), and determine the communication form from the configuration ([[autosar-classic]]) - Treating
E_OS_ACCESSas a parameter error: Symptom —ActivateTaska service of this kind returns an access error, raising suspicion of a wrong task ID or OS corruption; Cause — the ownership/protection state of the OS-Application: access was not granted at configuration time, or the object belongs to another inaccessible application; Countermeasure — check the OS-Application that owns the object, the application state, the trust level, and the current call context ([[autosar-classic]])