第一次打開 CAN 分析工具時,你可能會看到一行像這樣的紀錄:
can0 180 [4] 12 C0 01 2A
短短一行裡,有介面名稱、Identifier、資料長度與四個 Data byte。
但真正在線路上傳送的 CAN Frame,前後還有同步、仲裁、錯誤檢查及確認接收所需的欄位。
如果只盯著 12 C0 01 2A,很容易把「看到資料」誤認成「已經知道資料代表什麼」。
看到 ACK 時,也可能誤以為指定 ECU 已經完成動作。
今天要做的事,就是把一筆 Classical CAN Data Frame 拆開,理解每個欄位能告訴我們什麼,以及它不能證明什麼。
讀完這篇文章,你應該能夠:
Classical CAN 定義了幾種不同用途的 Frame:
| Frame 類型 | 主要用途 | 是否承載 Data Field |
|---|---|---|
| Data Frame | 傳送應用資料 | 是,0~8 bytes |
| Remote Frame | 請求另一個節點傳送指定 Identifier 的 Data Frame | 否 |
| Error Frame | 節點偵測到錯誤時,通知其他節點目前傳輸有問題 | 否 |
| Overload Frame | 在特定條件下延後下一筆 Data 或 Remote Frame | 否 |
今天專注在最常見的 Data Frame。
Remote Frame、Error Frame 與錯誤狀態會在後續診斷及攻擊可用性時再回來討論。
本文所說的 0~8 bytes 與 15-bit CRC,指的是 Classical CAN。
CAN FD 的資料長度與 CRC 規則不同,不要直接套用。
先從整體順序看起:

圖 1:Classical CAN Data Frame 的主要欄位,Intermission 屬於 Frame 之間的間隔,不是 Data Frame 本身
| 欄位 | 主要內容 | 要回答的問題 |
|---|---|---|
| SOF | Start of Frame,1 個 dominant bit | 一筆 Frame 從哪裡開始? |
| Arbitration Field | Identifier 與參與仲裁的控制位元 | 這是什麼訊息?誰先使用 Bus? |
| Control Field | 格式相關位元與 4-bit DLC | 後面有多少 Data byte? |
| Data Field | 0~8 bytes 的應用資料 | 實際承載哪些數值? |
| CRC Field | 15-bit CRC sequence 與 CRC delimiter | 傳輸途中是否出現可偵測的錯誤? |
| ACK Field | ACK slot 與 ACK delimiter | 是否至少有另一個節點正確收到 Frame? |
| EOF | End of Frame,7 個 recessive bit | 這筆 Frame 在哪裡結束? |
Data Frame 結束後,至少還有 3 個 recessive bit 的 Intermission,將它和下一筆 Data 或 Remote Frame 分開。
接下來逐一打開最重要的欄位。
SOF 是 Start of Frame 的縮寫。
當 Bus 處於 idle 狀態時,傳送端用一個 dominant bit 開始新的 Frame,也讓其他節點在這個起點完成同步。
SOF 本身不承載車速或控制命令,但接收端若連 Frame 的起點都判斷錯誤,後面的 Identifier、DLC 與 Data 就不可能被正確解析。
Identifier 可以協助接收節點判斷訊息種類,也會參與 Bus 仲裁。
它仍然不是傳送端或接收端 ECU 的地址。
Classical CAN 支援兩種 Identifier 長度:
| 格式 | Identifier 長度 | 可表示的數值範圍 | 常見十六進位寫法 |
|---|---|---|---|
| Standard/Base Frame Format | 11 bits | 0x000~0x7FF |
0x180 |
| Extended Frame Format | 29 bits | 0x00000000~0x1FFFFFFF |
0x18DAF110 |
29-bit Extended ID 不是在 11-bit ID 後面隨意附上一段資料。
在 Frame 中,它由 11-bit Base Identifier 與 18-bit Identifier Extension 組成,中間還有 SRR 與 IDE 等控制位元。
IDE 是 Identifier Extension 的縮寫,用來區分 Standard 與 Extended 格式:
這裡先記住結果即可。
Day 05 會把每一個 dominant/recessive bit 排開,完整解釋為什麼較小的 ID 通常具有較高優先權。
一個數值落在 0x000~0x7FF,不代表它在線路上必然使用 Standard 格式。
Extended Frame 的 29-bit Identifier 也可以是較小的數值,只是實際工具通常會另外保存或顯示 Extended Frame Format 旗標。
因此分析紀錄時,要同時確認:
不要只靠十六進位字串的長短猜測 Frame 格式。
RTR 是 Remote Transmission Request 的縮寫。
在 Classical CAN 中,它用來區分 Data Frame 與 Remote Frame。
| RTR 狀態 | Frame 類型 | Data Field |
|---|---|---|
| dominant | Data Frame | 可以有 0~8 bytes |
| recessive | Remote Frame | 沒有 Data Field |
若 Data Frame 和 Remote Frame 使用相同 Identifier 並同時競爭,Data Frame 的 dominant RTR 會勝過 Remote Frame 的 recessive RTR。
這也提醒我們,仲裁不只看畫面上顯示的 Identifier 數字,還會延伸到 Arbitration Field 中的相關位元。
DLC 是 Data Length Code 的縮寫,可以理解為資料長度代碼。
它由 4 個 bit 組成,告訴接收端後面的 Data Field 有多長。
在本文使用的 Classical CAN 一般範例中,DLC 0 到 8 和 Data byte 數量一對一對應:
| DLC | Data Field 長度 | 範例 |
|---|---|---|
| 0 | 0 bytes | 沒有 Data byte 的 Data Frame |
| 1 | 1 byte | 7F |
| 4 | 4 bytes | 12 C0 01 2A |
| 8 | 8 bytes | 11 22 33 44 55 66 77 88 |
DLC 是「長度資訊」,不是 Data 本身,也不會解釋每個 byte 的意義。
還有一個容易踩到的細節:Classical CAN 在線路上的 raw DLC 可能出現 9 到 15,但實際 payload 仍以 8 bytes 為上限。
部分作業系統介面或分析工具會直接顯示正規化後的 payload length。
閱讀工具輸出時,先確認欄位寫的是 raw DLC 還是實際 byte 數,尤其不要把 CAN FD 的 DLC 對照表直接套進 Classical CAN。
Data Field 是應用程式真正放資料的位置,Classical CAN 最多承載 8 bytes。
假設我們看到:
Identifier:0x180
DLC:4
Data:12 C0 01 2A
單靠 CAN 協定,我們只能確定這裡有四個 byte:
| Byte 位置 | 十六進位值 | 十進位值 |
|---|---|---|
| Byte 0 | 0x12 |
18 |
| Byte 1 | 0xC0 |
192 |
| Byte 2 | 0x01 |
1 |
| Byte 3 | 0x2A |
42 |
我們還不知道它是車速、溫度、方向燈狀態,還是完全不同的訊息。
CAN Data Field 本身不會定義:
這些語意要由車輛或系統的通訊規格定義,實務上也可能整理在 DBC 等資料庫檔案裡。
相同 Identifier 與 Data,在不同車款、網路區段或軟體版本中不必然有相同意思。
為了練習,我們替 0x180 定義一份完全虛構的應用層規格:
| Byte | 教學用定義 | 解碼方式 |
|---|---|---|
| 0~1 | 車速 | 16-bit unsigned big-endian,raw value × 0.01 km/h |
| 2 | 方向燈狀態 | 0x00 關閉、0x01 左、0x02 右 |
| 3 | Rolling counter | 每次傳送加 1,溢位後回到 0 |
現在才可以解讀 12 C0 01 2A:
0x12C0 = 4800
4800 × 0.01 km/h = 48.00 km/h
0x01 = 左方向燈
0x2A = counter 42
這個結果成立的原因,不是 CAN 規定 0x12C0 代表 48 km/h,而是我們先取得了一份訊號定義。
0x180與上述編碼只用於教學,不代表任何特定車款的真實訊息定義。
CRC 是 Cyclic Redundancy Check 的縮寫,中文常稱循環冗餘檢查。
傳送端會根據 SOF 到 Data Field 的相關 bit 計算 CRC sequence,接收端也會依照收到的內容重新計算並比對。
Classical CAN 的 CRC Field 包含:
如果計算結果不一致,接收端可以判定傳輸發生 CRC error,接著透過 CAN 的錯誤處理機制讓這筆傳輸失敗並等待重送。
但 CRC 不是密碼學上的 Message Authentication Code,也沒有祕密金鑰。
能夠送出 CAN Frame 的節點,可以對自己建立的 Identifier 與 Data 計算出正確 CRC。
因此 CRC 能協助偵測線路雜訊與部分傳輸錯誤,卻不能證明:
這就是「錯誤偵測」和「來源驗證」不能混為一談的地方。
ACK 是 Acknowledge 的縮寫。
ACK Field 由 ACK slot 與 ACK delimiter 組成。
在 ACK slot,傳送端先送出 recessive bit。
正確收到 Frame 的接收節點則送出 dominant bit,覆蓋 Bus 上的 recessive 狀態。
傳送端看到 dominant,便知道至少有另一個節點在通訊層正確收到這筆 Frame。
即使接收節點的 Acceptance Filter 最後不接受這個 Identifier,只要它在通訊層正確收到 Frame,仍可能參與 ACK。
所以 ACK 只能證明到這一層:
至少有另一個節點正確收到 Frame
≠
某個指定 ECU 已接收並採用 Data
≠
車門、燈光或煞車已完成動作
如果傳送端沒有看到 ACK,就會判定 ACK error。
不過造成 ACK error 的原因可能是其他節點未連線、bit rate 不一致、實體線路異常,或節點處於只監聽模式等情況,不能只憑這一項現象直接下結論。
EOF 是 End of Frame 的縮寫,由 7 個 recessive bit 組成。
它讓節點確認 Data Frame 或 Remote Frame 已經結束。
EOF 後面的 Intermission 至少有 3 個 recessive bit,為下一筆 Data 或 Remote Frame 留出最小間隔。
Intermission 屬於 Inter-frame Space,不是 Data Frame 本體的一部分。
把這個邊界分清楚,閱讀示波器波形或規格圖時才不會把 Frame 長度多算三個 bit。
除了 Data Field 長度可以改變,Classical CAN 還會使用 bit stuffing 維持同步並協助偵測錯誤。
從 SOF 到 CRC sequence 的區段中,只要連續出現五個相同邏輯值的 bit,傳送端就插入一個相反值的 stuff bit。
接收端驗證後再將它移除。
因此兩筆具有相同 DLC 的 Frame,也可能因 Identifier 與 Data 的 bit pattern 不同,而在線路上占用不同的實際 bit 數。
Stuff bit 不是應用資料,也不會增加 DLC。
回到開頭的紀錄:
can0 180 [4] 12 C0 01 2A
許多 CAN Controller 與作業系統介面會替應用程式處理 Frame 前後的低層通訊細節。
應用程式通常取得的是已經通過控制器處理的 Frame 資訊,而不是每一個線路 bit。
以上面的簡化格式為例:
| 顯示內容 | 可以怎麼讀 |
|---|---|
can0 |
接收這筆紀錄的本機 CAN 介面 |
180 |
Identifier 為 0x180 |
[4] |
顯示四個 Data byte,實際工具可能標成 length 或 DLC |
12 C0 01 2A |
Data Field 的四個 byte |
沒有出現在這一行,不代表 CRC 與 ACK 不存在。
若要觀察線路上的完整 bit sequence,通常需要支援相應解析能力的 CAN 分析儀或示波器,而不是只看一般應用層紀錄。
Linux SocketCAN 的 Classical CAN 使用者空間結構,主要提供 can_id、payload length 與最多 8 bytes 的 data。
較低層錯誤則可由驅動程式另外產生 Error Message Frame 回報。
拆完 Frame 後,可以把每個欄位的可靠性邊界整理成一張表:
| 看見的現象 | 可以合理判斷 | 不能直接推論 |
|---|---|---|
Identifier 是 0x180 |
Frame 使用這個訊息標籤與仲裁值 | 一定由某個指定 ECU 發送 |
| DLC/length 是 4 | Data Field 有四個 byte | 四個 byte 的語意與編碼方式 |
| CRC 正確 | Frame 通過 CAN 傳輸錯誤檢查 | 訊息具有密碼學完整性與真實性 |
| Bus 上出現 ACK | 至少有另一個節點正確收到 Frame | 指定 ECU 已執行對應功能 |
| Data 重複出現 | 同一組 byte 再次被觀察到 | 一定是正常週期訊息,而非 replay |
這些限制也解釋了為什麼單看 Classical CAN 基礎欄位,無法完成來源驗證與防重放。
實際防護還要依架構加入 Gateway 過濾、分區、訊息新鮮度檢查,或更高層的驗證機制。
不過,也不能反過來說「CAN 沒有加密,所以任何車都能被控制」。
要形成真實攻擊路徑,仍須確認攻擊者能否接觸該網路區段、取得傳送能力、理解訊息語意,並繞過其他架構與應用層控制。
下面兩筆紀錄沿用本文的虛構 0x180 規格,時間戳記先省略:
can0 180 [4] 12 C0 01 2A
can0 180 [4] 12 C0 01 2B
請先回答:
先停在這裡,不要急著往下滑!
請先自己標出 Identifier、DLC/length 與每個 byte,再往下對照答案。
| 問題 | 作者的答案 |
|---|---|
| Identifier | 兩筆都是 0x180,Frame 格式仍應由工具的 Standard/Extended 旗標確認 |
| Data Field 長度 | 兩筆都是 4 bytes |
| 發生變化的 byte | Byte 3 從 0x2A 變成 0x2B |
| 車速 | Byte 0~1 都是 0x12C0,依虛構規格解碼為 48.00 km/h |
| 方向燈 | Byte 2 都是 0x01,依虛構規格解碼為左方向燈 |
| Rolling counter | 依虛構規格從 42 增加到 43 |
我們可以說兩筆紀錄符合這份教學規格的連續 counter,也可以說 Data 所表示的車速與方向燈狀態沒有改變。
但我們不能只靠這兩行證明傳送端身分,也不能證明實體燈具已亮起。
要驗證前者,需要額外的架構或安全機制。
要驗證後者,則需要應用層狀態回報或獨立感測結果。
這份答案使用完全虛構的訊息定義,不代表任何特定車款採用相同編碼。
安全與法律提醒: 後續擷取或傳送 CAN 訊息時,請只使用模擬環境、測試台或明確取得授權的設備。
不要在道路車輛或他人的設備上進行未授權測試。
今天我們知道 Identifier 位於 Arbitration Field,也知道 Standard/Extended 格式會在仲裁過程中產生差異。
Day 05 將把兩筆同時傳送的 Identifier 排成 bit sequence,看看 dominant 0 如何覆蓋 recessive 1,並真正理解為什麼 ID 數值越小,優先權通常越高。