しゅーと (@shutingrz)
しゅーと (@shutingrz)
Security researcher
Jul 22, 2019 5 min read

ドア開錠を行うCAN通信を特定する

thumbnail for this post

今回も引き続きシミュレーション環境のICSimでCAN通信の勉強。

前回 はどのCANメッセージがドアをあけるものなのかわからないながらも、通信そのままリプレイさせることでドアの開錠を成功させた。

今回は、どのCANメッセージがドアをあける通信なのか特定を試みる。


環境

Ubuntu 18.04 Desktop


CAN通信をモニターしてフィルタするソフトウェアはいくつか存在する。

が、色々試していくうちに現時点においてはSavvyCANがOSSの中で最高のCANモニターだと思ったのでSavvyCANを使ってドア解錠のメッセージを特定していく。

※カーハッカーズハンドブックではSavvyCANは巻末付録で紹介されているが、内容が古く「SocketCANには対応していない」旨のコメントがある。
 現在はSocketCANに対応しているし何ならNetwork経由でもモニタできるようになっているっぽいのでイチオシ。

SavvyCAN のインストール

Qt5のインストール

$ wget https://download.qt.io/official_releases/qt/5.12/5.12.4/qt-opensource-linux-x64-5.12.4.run
$ chmod a+x ./qt-opensource-linux-x64-5.12.4.run 
$ sudo ./qt-opensource-linux-x64-5.12.4.run 

qtライブラリのインストール

qtserialbusは Ubuntu 18.04 では aptの公式リポジトリに含まれないので自分でビルドする。

$ sudo apt install qtdeclarative5-dev qttools5-dev g++
$ git clone https://github.com/qt/qtserialbus
$ cd qtserialbus
$ /opt/Qt5.12.4/5.12.4/gcc_64/bin/qmake .
$ make
$ sudo make install

SavvyCANのビルド

$ git clone https://github.com/collin80/SavvyCAN
$ cd SavvyCAN
$ /opt/Qt5.12.4/5.12.4/gcc_64/bin/qmake CONFIG+=debug
$ make

起動

./SavvyCAN

vcan0に接続

Connection Settings -> Add New Device Connection で新規接続。

  • Connection Type: QT SerialBus Devices
  • SerialBus Device Type: socketcan
  • Port: vcan0

add_device

ICSimを起動しておくと、接続後に大量のCANデータが流れることを確認できる。

SavvyCANを使ってドア開錠通信を特定

まず前提として、CAN通信の話。

リアルタイムに情報が必要となるエンジン・ステアリング・車軸センサー周りのECUは、常に自らの情報を定期的にCANバスを垂れ流しているものだという。
その結果、CANバスには常に情報が溢れているとのこと。

ただ今回はドアの開錠を行う操作を見つけ出す。
これは「トリガー」を発生させることになるので、CANメッセージの中でそのCAN IDは非常に少ない(トリガーごとに1個あるいは数個)ことが予想される。

つまりドア開錠操作を発生させたときに初めて出現するCAN IDを見つけ出す。

SavvyCANではデータが流れる順に表示される標準モード以外に、「Overwrite Mode」という、各CAN IDごとの最新データが表示されるモードが存在する。

表示には統計情報としてCntカラムがあり、そしてクリックでソートできるので、ドア開錠を発生させたときに初めてカラムが追加されCntが非常に少ないようなCAN IDがドア開錠メッセージであることが推測できる。

CANバスをキャプチャしそれっぽいものを探す

ということでやってみた。手順は以下。

  1. SavvyCANをOverWrite Modeにしておく。
  2. キャプチャを開始する。
  3. Cntでソートし、一番少ないCntのところを注視しておく。
  4. ICSimのコントローラーで左フロントドアを開錠する。
  5. 開錠操作後に初めて追加されてCntが非常に少ないCAN IDを探す。

動画でどうぞ。

detect_doorlock

すぐにわかる。ドア開錠メッセージのCAN IDは0x19Bっぽい。データは「00 00 0E 00 00 00」。

ドアが開錠するか試す

実際に試してみる。

SavvyCANのPlayback機能を使って通信を送ることもできるが、今回送るメッセージは1つだけなのでcansendの方がわかりやすい。

$ cansend vcan0 19B#00.00.0E.00.00.00

動画でどうぞ(スマホは見づらいかも)

send_doorlock

見事に開いた!SavvyCANいいっすね^~

全てのドア開錠通信を調べる

ICSimは全てで4つのドアがある。全てのパターンを試したところ、全てCAN IDは 0x19Bだった。

データは以下の対応だった。

ドアの状態 操作 データ3バイト目 2進数
全て閉じている 左フロントドア開錠 0E 0000 1110
上列操作後の状態 右フロントドア開錠 0C 0000 1100
上列操作後の状態 左リアドア開錠 08 0000 1000
上列操作後の状態 右リアドア開錠(->全て開いた) 00 0000 0000

表の2進数を見れば一目瞭然。ドアの状態はドアごとにビットで管理されてるようだ。
ちなみにドアを順次閉じていき、全て閉めたところのCANメッセージは 0F (0000 1111)だった。

特定のドアを開けたい場合は、そのドアに対応したビットを0にして、 CAN IDが 0x19B なメッセージを送れば良さそう。

まとめ

SavvyCANを使ってICSimのCAN通信からドアを開錠するCAN IDを探して再現することができた。

ただこれがドアを開け閉めさせるトリガーとなる通信なのか、それともコントローラ内部でドアを開け閉めしたあと、今のドア状態をみんなに伝えますという意味の通信なのか、どちらかよくわからない。

もし後者ならば、仮に攻撃者が詐称したとしても運転席のメーターパネルが「ドア開いてますよ」とピーピーなるだけで肝心のドアロックは開かないのでは🤔
(実車はどうなってるのか・・・試したいけど車がない😭)

それと、今回はICSimがコントローラーによる操作のときだけ該当通信を発生させていたおかげでCntが極小となり統計解析で見つけやすかったが、全体のドアの状態を送る形式なら原理上定期的にCANメッセージを発生させていてもいいはずなので、もしそうだったら見つけるのは大変だったかも。
(実車はどうなってるのか・・・試したいけど車がない😭)

SavvyCANについて

実際に色々使ってみるとわかりますが、SavvyCANは高機能であるものの、色んなグラフを見るとき特定のデータでnull pointerにアクセスしてクラッシュすることが割とよくあります。

ただ原因はわりと単純だったりするし、しかも開発者のcollin氏もすぐに直してくれるので、バグに気付いたらぜひGithubにPRやissueを投げてもらえると非常に助かります。

自分も使って初日で2箇所もクラッシュにハマりましたが、原因を特定してIssueを投げたりPRを送ったりしたら1日もせずに修正を取り込んでくれました。

参考


次回は何をしよう・・・車が欲しい・・・・。