いろんな技術にふれたい

いろんな技術に触れたい

日頃色々触れた技術を自分なりにまとめておきたいと思ってます。難しいものほどブログ書く時間がかかるのが問題・・・

RTL-SDR(nano 3)とURH(Universal Radio Hacker)を使ってみた

こちらはセキュリティキャンプアドベントカレンダー9日目(12/9)の記事になります.

adventar.org

私はセキュリティキャンプ全国大会2016の卒業生で.今年の全国大会チューター、その他地方大会のチュータなどしてました.

先月,PacSecにてTrend Microさん主催のRF CTFという世界初のCTFに参加してきました.

www.pacsec.jp

PacSecセキュリティカンファレンス」は、世界先端の情報セキュリティ専門家による最新の研究発表の講義と国際交流できる環境を兼ね備えた場を用意し、日本での先進的なセキュリティ人材育成への技術教育の場を提供する国際カンファレンスです。

また,PacSecでのメインのCTFはZero day Initiative主催のPWN2OWNです.

Zero Day Initiative | Home

来年以降も様々なイベントでRF CTFを主催したいと考えているそうです.

今回はその際にいただいたnano 3というSDRの利用方法のメモなどを残して置きたいと思います.セキュリティは関係ないかも?

また、私は現在SDRについては勉強中の身なのですがさいきんやっといろいろできるようになりました。そこでUniversal Radio hackerという便利なツールを見つけたので、ついでに紹介しようと思います。

SDR(Software Defined Radio)

皆さんご存知、ソフトウェア(定義)無線です(?)

ソフトウェア無線(Software-defined radio)とは、電子回路ハードウェア)に変更を加えることなく、制御ソフトウェアを変更することによって、無線通信方式を切り替えることが可能な無線通信、又はその技術。一般的には、広い周波数範囲において多くの変調方式が可能となるよう、ソフトウェアが、なるべく汎用性の高いプログラム可能なハードウェアを制御するものとして考えられている。

ソフトウェア無線 - Wikipedia

簡単に言うと、従来はマシンスペックが足りずできなかった処理をソフトウェアレベルで行うことで、ソフトウェアでより柔軟に無線を扱えるようになったものです。詳細はぐぐってください。

その歴史は1970年代の軍事利用目的の開始までさかのぼります。一般的な利用は1990年代の携帯電話網の送受信(トランシーバ)目的で開発されたことのようです。

また、日本語のSDRのページより英語版のほうが内容が充実しています(というか未翻訳状態)。

Software-defined radio - Wikipedia

現在、SDRの利用の目的は大きく分けて軍事利用アマチュア無線/個人利用と言われています。GNURadioについても取り上げられています。

More recently, the GNU Radio using primarily the Universal Software Radio Peripheral (USRP) uses a USB 2.0 interface, an FPGA, and a high-speed set of analog-to-digital and digital-to-analog converters, combined with reconfigurable free software. Its sampling and synthesis bandwidth is a thousand times that of PC sound cards, which enables wideband operation.

無料で利用でき、FPGAの設定をいろいろいじって利用できるため現在は多くの人に使われています。この前私が試したLoRaWANのデコードもGNURadioを使いました。電波のソースにSDRサーバを指定できたりと、様々な利用が可能になっています。

nano 3を試す!

いただいたnano 3はこんな感じの非常に小さくかわいいコンパクトなモジュールです。現在はこれに小さなヒートシンクをつけて使っています。

IMG_4993

IMG_5279

IMG_5036

こんな感じで,非常にシンプルなSDRとなっています.なお,”HOT⚠️"です.

検索すると,以下のNooElecのサイトがヒットします.

www.nooelec.com

The ultimate SDR bundle for USB On-The-Go applications.

Includes NESDR Nano 3 in an anodized aluminum enclosure, nano-sized antenna, 4 USB OTG adapters. heatsink and an articulating adapter for SMA antennas.

すぐにいろいろな端末で使えるのが利点だそうです.

Amazonでも取扱いしています.

RTL-SDRとは

RTL-SDR is a very cheap software defined radio that uses a DVB-T TV tunerdongle based on the RTL2832U chipset. ... Essentially, this means that a cheap $20 TV tuner USB dongle with the RTL2832U chip can be used as a computer based radio scanner.

https://www.rtl-sdr.com

だそうです.安価で利用できるSDRのことを指しており,TVチューナーなども含まれるそう.

US$32.95!安い!

気になるスペック等はこちら

USB Interface IC RTL2832U
Tuner IC R820T2
Frequency Range (approximate) 25MHz - 1750MHz
TCXO clock Yes
Antenna Connector Type MCX
Antenna Included? Yes
Remote Included? No
Additional Accessories Includes anodized aluminum enclosure, heatsink, articulating adapter for SMA antennas, nano-sized antenna and 4 USB OTG adapters.

HackRF ONEといった高価かつ高機能なSDRとの大きな違いはサンプリングレート,つまり1秒間あたりの信号サンプル数,時間分解能です.HackRF ONEでは20Mbps (up to 20 million samples per second)ですが,RTL-SDRでは約3Mbpsです.

また,公式サイトにてnano 3を利用するためのいくつかのソフトウェアが提供されています.

product_download

ここでは以下のOSに向けてソフトウェアやインストール手順が紹介されています.

Android端末とあるように,nano 3はモバイル端末でもSDRが利用しやすくなっており,一般的なツールと互換性があるようです.手元にあるAndroid端末はUSBホスト機能がなかったので試せなくて残念でした.

入手時のパッケージにもUSB typeAをマイクロUSBに変換するケーブルやアダプタが同梱されています.残念ながらiPhoneでは使えなさそうです.

また,パッケージには小さなヒートシンクも同梱されており,HOTへの対策はきちんとされています.

今回は一般的な用途で、このコンパクトなSDRがどれだけ使えるのか試したかったため、色々調査してみました。

結論から述べると,特に問題なく使えることが分かりました.

nano 3で電波のモニタ

それでは実際に利用する方法や様子をまとめておきます。

まず,MacOS上でlsusbしてデバイス情報を確認してみます.

 〉lsusb
...
Bus 020 Device 018: ID 0bda:2838 Realtek Semiconductor Corp. NESDR Nano 3  Serial: ***
...

やはり電波をとりあえず見るにはGqrxというツールが一番利用が楽ですし便利です.nano 3の公式サイトではその利用方法については書かれていませんでした,

http://gqrx.dk

Macではそのまま認識され、Gqrxを開くとそのまま利用することができます。Configはこんな感じになります.Input rateを1200000に設定します.

FMラジオはだいたい80MHz~100MHzです.とりあえず確認して,なにか音が聞こえるか試してみました.

TOKYO FMは周波数80.0MHzで、東京タワーから、檜原中継局(2015年12月開局)は西多摩郡檜原村から周波数86.6MHzで放送しています。

https://www.tfm.co.jp/listen/sp/

ノイズが多いですが,なにか聞こえます.

今回試す環境ではVirtualboxを利用しているので,「Devices→USB→NooElec NESDR Nano 3」で追加します.しかしLinux上で動かすには,そのままでは利用できませんでした.

そこで, "/etc/modprobe.d/fbdev-blacklist.conf"に以下を追加します.

blacklist dvb_usb_rtl28xxu
blacklist rtl2832
blacklist rtl2830

設定後,再起動したら認識されました.

IMG_6330

こちらは飛行機の中で電波を観測している様子です.

LoRaWANのデコードをしてみる

こちらで紹介していたgr-loraをnano 3でも利用してみました。特に問題はなく利用できるようです。

tokina.hatenadiary.jp

github.com

/gr-lora_n3/apps$ python lora_receive_realtime.py 
linux; GNU C++ version 5.3.1 20151219; Boost_105800; UHD_003.009.002-0-unknown

Using Volk machine: avx_64_mmx_orc
gr-osmosdr 0.1.4 (0.1.4) gnuradio 3.7.9
built-in source types: file osmosdr fcd rtl rtl_tcp uhd miri hackrf bladerf rfspace airspy redpitaya 
Using device #0 NooElec NESDR Nano 3 SN: ******
Found Rafael Micro R820T tuner
[R82XX] PLL not locked!
Exact sample rate is: 1000000.026491 Hz
[R82XX] PLL not locked!
Bits (nominal) per symbol:  5.5
Bins per symbol:    2048
Samples per symbol:     16384
Decimation:         8

研究でLoRaWANの実機も利用することが多々あるので,非常に便利になりました.

URH (Universal Radio Hacker)を使ってみる

先日,ちらっと「Universal Radio Hacker」なるツールがあることを耳にしましたので調べてみました.

無線の解析にめっちゃ便利だったのでもっと利用されるべきでは?

適当に検索してもURHについて日本語の情報はあまり見つかりませんでしたので,少しまとめておきます.

もちろんオープンソースです.

github.com

The Universal Radio Hacker (URH) is a software for investigating unknown wireless protocols. Features include

  • 一般的なSDRのハードウェアを利用可能
    • hardware interfaces for common Software Defined Radios
  • 信号を簡単に復調できる
    • easy demodulation of signals
  • データの解析支援
    • assigning participants to keep overview of your data
  • デコーディングのカスタマイズ
    • customizable decodings to crack even sophisticated encodings like CC1101 data whitening
  • プロトコルロジック解析のためのラベル付
    • assign labels to reveal the logic of the protocol
  • セキュリティの脆弱性を見つけるためのファジングコンポーネント
    • fuzzing component to find security leaks
  • システムにリプレイ攻撃するための変調をサポート
    • modulation support to inject the data back into the system
  • 攻撃の再現性のためのシミュレーション環境
    • simulation environment to perform stateful attacks

とあるように,URHは未知の無線プロトコルの解析ツールであり,様々なハードウェアを利用でき,復調が可能です.また,ファジングや電波の記録,再送も簡単になっており,シミュレーションも可能です.もちろんGUI上で操作が可能です.この前新しいバージョンが出たばっかりです.頻繁に更新されるので、興味のある人はGithubでWatchingしておいたほうがいいでしょう。私もまだ使い始めたばかりなので,まだわかってないことも多いです.

インストーラガイドでは以下での利用方法を公開しています.

私はSDRの環境はまとめてXubuntu 16.04 LTS上に構築しているので,今回もそちらに環境を用意しました.

Linux (今回はXubuntuですが,Ubuntuやその他のDebian系でもいけそう)の環境に応じたパッケージマネージャでのインストーラ経由のインストール方法について示されています.今回はpipを利用します.

> $ sudo apt-get update
> $ sudo apt-get install python3-numpy python3-psutil python3-zmq python3-pyqt5 g++ libpython3-dev python3-pip cython3
> $ sudo pip3 install urh

これでインストールできました.

もしかしたらグラフ関係でぶつかる人もいるかも知れません.私は以前にpythonのグラフ描画系のライブラリは一通り入れていたので,ゼロの環境から入れる人は気をつけてください.

アプリケーション一覧にて"urh"と検索するか,Terminal上でurhと入力するとURHを起動できます.

URHの基本的な機能

基本的に何ができるかは,以下の動画が参考になります.

www.youtube.com

  • リアルタイムスペクトラムのモニタリング,解析→Spectrum Analyzer
  • 電波の記録→Record Signal
  • 記録した電波の解析→メインの画面
  • プロトコルスニッフィング→Sniff Protocol
  • デコード→Decoding

これらのツールがセットになっています.

URHを起動するとこんなシンプルな画面が.タブのFile,もしくはEditから各種ツールを呼び出します.

URH_Top

URHは基本的にはモニタリングより,ログを取る→解析する,に適したツールです.細かいところ(例えばログを取得した状態の設定が解析に引き継がれるなど)に気がきいており,非常に好感が持てます.

それでは,各機能について簡単にまとめたいと思います.

スペクトラムのモニタリング(Spectrum Analyzer)

SpectrumAnalyzer

これはリアルタイムに実際の電波をモニタリングするツールです.赤く見えているのは最大時のスペクトラムです.

スペクトラムのモニタリングだけならGqrxのほうが便利でしょう.しかし,その他のツールと組み合わせて使うときは,一度このアナライザで周波数を確認したほうが良いでしょう.ここで周波数やサンプルレートなどを指定しておくと,例えばRecord Signalツールを利用するときに同様の設定で開かれます.

電波の記録(Record Signal)

RecordSignal

電波を記録できます(そのまま)

Startを押すと記録を開始します.ファイルサイズがリアルタイムに表示されているので便利です.Saveボタンで保存してないと破棄されるので注意してください.

記録したシグナルは.complex形式で保存され,どうやらこれはバイナリファイルらしい.

一応GHexで開いてみるとこんな感じです.

GHEx

記録したシグナルの解析

さっき記録したファイルを保存して,Record Signalの画面を閉じるとメインの画面(解析画面)が勝手に開きます.このときファイルサイズが大きいほど時間がかかるので待ちましょう.

メインの画面には以下のタブがあります.

  • Interpretation → シグナルを確認するメインの画面
  • Analysis → シグナルのデコードの解析
  • Generator → 波形データの生成
  • Simulator → 記録したシグナル,もしくはGenerateしたものからプロトコルを作成し,仮想のParticipantsを用意してシミュレーションシナリオの作成

また,試してないですが,保存しているシグナルから,Generatorを使って送信データを生成することもできるようです.LoRaのハッキングに使えそう?

あと,うまくデコードできた場合には,この仕組みを逆に,自由なInputで出力波形をGeneratorで作成できるっぽいです.

LoRaWANのデータを例に少し解析してみます.以下はSF=12のときのLoRaの電波を受信してみた様子です.

URH_interpretation

青い選択されている部分が1秒間のシグナルです.

URH_interpretation2

非常に拡大すると,最大分解能は500nsであることが分かります.

なお,画面したに01ビットが表示されていますが,これはとりあえず自動的にデコードされただけで特に意味があるわけではありません.これだと分かりづらいので,SF=7のときのシグナルを以下に示します.

URH_interpretation3

LoRaWANのSF=12のとき,送信時間は理論上約1318msですが,SF=7のときは約55msです(最適化なし).図におけるブロックのように見えるところは,LoRa変調であると推測されます.

プロトコルのスニッフィング(Sniff protocol)

SniffProcotol

どうやらリアルタイムで,対象の周波数の変調を試みるツールのようです.

今の所,私はあまりこれを有効活用したことはありません.

受信メッセージの解析,デコード

ASK/OOKの復号には以下の動画が参考になるでしょう.

www.youtube.com

RF CTFではOOKの問題がでました.GNURadioで保存した01のシグナルのバイナリファイルをロードしてみるとこんな感じになります.

Decode1

同じ01の列が連続している事がわかります.これはGNURadioで,既に01に変換されているため,Modulation:ASK(OOK),Error Tolerance:0,Bit Length:1にします.すると,画面したに01のそれっぽいビット列が現れるはずです.

Decode2

また,スペクトラムの強さで01を変えたい場合があります.例えば受信Gainが小さい状態で受信したシグナルは起伏が弱いです.この「0と1を判断するしきい値」を設定することもできます.Signal View:Demodulatedに設定します.ドラッグでこの閾値を変更できます.

Decode3

この状態で,EditタブからDecodingを開くと,様々な符号化方式でのDecodeが試せます.このDecodeに関してはあまり使い方が公開されていない+自分もわかっていないのでまだ勉強が必要です.

Decode4

選択できるのは,今の所NRZ,マンチェスターⅠ,マンチェスターⅡ,差動マンチェスター符号化っぽいです.例えば,ここでNRZ,Remove Redundancyが適切な場合,これを保存し,メイン画面のAnalysisなどで選択できるようになるようです.

最後に

今回はPacSec2018のRF CTFでもらったRTL-SDRであるnano 3 SDRについての使用してみたレビューと,ついでにURH(Universal Radio Hacker)についてまとめてみました.

まだまだURHについてはこれから使いこなしたいです.本当はAnalysisにもっと多くの機能やらなんやらあるようなのですが,まだ良くわかっていません..

最近,研究ではシミュレーションからLoRaWANの実機の計測を行うことが多くなってきたので,そのついでというのも少しありました(あっちはHackRF ONEの利用を予定しています).

と,アドベントカレンダー担当日の前日にこの記事を書いていると,センスウェイさんからLoRaWANスターターキットが届きました.これも試したいですね(というか記事を書くことがマストになっている).

また今後もこういったCTFはもちろん,社のレッドチームに入るべく,普通のCTFにもチャレンジしていこうと思い,「ネコチャンナノ!(NekochanNano!)」というCTFチームを何人かとともに立ち上げました.アイコンも自作しました!!

さて,次のアドベントカレンダーは12/12にtex2eさんによる「秘密分散技術(ホワイトハッカ飴の解説)」です.お楽しみに.

今年もあと僅かです!

Write Up - Car Hacking Challenge @ CODE BLUE 2018

今年も頑張ってWrite up書くぞ!

ということで,今年もCODE BLUEとAVTokyoを楽しんできました.といっても今年で2回目です.

codeblue.jp

今年チャレンジを提供してくださったのはイエラエセキュリティさんと,Karambaセキュリティさん,SOMPO CYBER SECURITYさんです.

ierae.co.jp

karambasecurity.com

Black HATで意気投合し,急遽チャレンジを行うことになったとか.

今回,私たちのチームは3位となり,表彰していただくことができました.

ちなみにチーム名は黒林檎さんをリスペクトして「りんごちゃん」でいきました.

ありがとうございます!(?)

Writeup

今回は環境を与えられ,特に説明などはなく競技が始まりました.

「自動車を制御できたらOK」

でした.運営の方に乗っ取り成功を証明すればOKです.

昨年とは違い,今年は「ネットワークレベルだけではない」チャレンジにしたかったとおっしゃっていたとおり,Challenge3からバイナリ解析問題になり,どのチームも解けていませんでした.

つまり,各チームは2日間合計のポイントは300で打ち止めとなってしまいました.

私も競技当日はできなかったバイナリ解析をあとからいろいろ試してみたので,それについても書きたいと思います(といってもまだまだ初心者ですが).

また,我々のチームはブレッドボードでCANを分岐させていたので,何度もCANバスを壊してしまい(バスオフ状態),「CANが壊れた札」を何度もあげていました.お手数をおかけしてごめんなさい.

また,私はあまり貢献できず,力不足を感じました・・・.

競技環境

競技環境は以下のような感じでした.

基本的に各テーブルにチームが配置され,テーブルにあるラジコンに対して攻撃をしかけます.

攻撃は前年同様CANレベルでしかできません.

またおそらく私達のチームだけブレッドボードをつかってCANを分岐させていたかもしれません.

今回,解析機としてはNVさんとそけとさんが持たれていたCANable(ほしい!)とMicroPecker,中華製の謎なアナライザ,そして用意された解析用RasPiが利用できました.

その他のテーブルではどうやらCANoeを持ってきていたチームもあった気がします.

Tutorial (50 pt.)

** tutorial
CAN you send messages to control the mini car?
Point:50

チュートリアルです.

送信にはcan-utilsのcansendを使えます.

github.com

みんな大好きcan-utils

実は私達りんごちゃんは,このチュートリアルがよくわかっておらず,チャレンジ2のあとでチュートリアルのポイントをもらいました.そのため3位になってしまいました.運営の人は何も言わず・・・

Challenge1 (100 pt.)

** challenge1
File : candump-level1.log
Point: 100

ログファイル一つ,なるほど.

ログファイルの中身はこんな感じ.

(1533125865.267025) slcan0 07B#00090001
(1533125865.572777) slcan0 07B#00090001
...
(1533125867.572873) slcan0 07B#00090700
(1533125867.878477) slcan0 07B#00090700
...

どうやらバスにはCANID:07Bだけが流れているようです.

これは簡単で,流れているメッセージを適当にSniffし,前進後進とかをなりすますだけです.上のログファイルは実際に流れている前進,後進,右折,左折の状態が含まれています.

流れているメッセージをリバエンして,Pythonスクリプトなり,MicroPeckerなりでなりすませばOK.

Challenge2 (150 pt.)

** challenge2
File: candump-level2.log
Point: 150

チャレンジを変更するにはコントローラをいじって現在挑んでいるチャレンジに設定します.

こちらもログファイル一つです.

ログファイルの中身はこんな感じ.

(1533126275.404112) slcan0 0AA#4800A0009F00
(1533126275.486353) slcan0 0AA#4900A0009F00
(1533126275.788527) slcan0 0AA#4A00A0009F00
(1533126276.090534) slcan0 0AA#4B00A0009F00
(1533126276.392959) slcan0 0AA#4C00A0009F00
(1533126276.474821) slcan0 0AA#4D00A0009F00
(1533126276.777152) slcan0 0AA#4E00A0009F00
(1533126277.079348) slcan0 0AA#4F00A0205400
(1533126277.381486) slcan0 0AA#5000A0705400
(1533126277.463680) slcan0 0AA#5100A0705400
...
(1533126296.551704) slcan0 0AA#9E00A0009F00
(1533126296.699943) slcan0 0AC#ABABABABABABABAB
(1533126296.854026) slcan0 0AA#9F00A0009F00
(1533126296.971713) slcan0 0AC#ABABABABABABABAB
(1533126297.156086) slcan0 0AA#A000A0009F00
(1533126297.180000) slcan0 0AC#ABABABABABABABAB
(1533126297.238066) slcan0 0AA#A100A0009F00
(1533126297.395621) slcan0 0AC#ABABABABABABABAB
(1533126297.540430) slcan0 0AA#A200A0009F00
(1533126297.572759) slcan0 0AC#ABABABABABABABAB
(1533126297.747856) slcan0 0AC#ABABABABABABABAB
(1533126297.842621) slcan0 0AA#A30080009F00
(1533126297.988772) slcan0 0AC#ABABABABABABABAB
(1533126298.144710) slcan0 0AA#A40080105400
(1533126298.188454) slcan0 0AC#ABABABABABABABAB
(1533126298.226842) slcan0 0AA#A50080105400
(1533126298.361315) slcan0 0AC#ABABABABABABABAB
(1533126298.529293) slcan0 0AA#A60080105400
(1533126298.831397) slcan0 0AA#A70080205400
...

基本的にCANID:0AAが流れているようです.実際のバスと比較すると,どうやらCANID:0ACは何かしらの注入されたメッセージだと推測されます.これから,適当なメッセージを送信してもバスには影響がないことがわかります.

また,CANID:0AAの最初の1バイト目はカウンタの役割を果たしており,さらに,後ろのバイトは動作を示しているようです.

0AA : XX 00 ?0 ?0 ?? 00

?のいずれかのビットがいずれかの状態(前進など)を示しているようです.

そのため,スクリプトで,現在流れているCANID:0AAのメッセージの最初の1バイト目を見て,それに+1し,バスをリバエンして判明した?の状態をなりすまし,バスへCANID:0AAをより高頻度で送ればOKです.

Challenge3 (200 pt.)

** challenge3
File1: candump-level3.log
File2: ADC_s32k144-c3.zip
Point: 200

さてここからが問題です.

謎のZIPファイルと謎のログファイルがあります.結論から言うと,どのチームもこれ以降のチャレンジは解けていません.

ここで私たち(主にNVさんがやってくれ,私は後日確認してみました)がやったことについてまとめておきたいと思います.

まず何も説明がないため,このZIPがなんなのか,このZIPをどうするのか,そもそもログ解析を先にやるのか何もわかりません.

そこでまずログファイルと実際にバスに流れているメッセージを確認しました.

ログファイルの中身はこんな感じ,

(1533126102.822934) slcan0 0AC#529991C16E110643
(1533126103.127298) slcan0 0AC#23DA17C92B19416B
(1533126103.194215) slcan0 00A#FF2D6FF564010000
(1533126103.431857) slcan0 0AC#EEF44D14B1BFED22
(1533126103.514492) slcan0 0AC#E0EB1589F69E36E4
(1533126103.819137) slcan0 0AC#66DB30BE07ED45FE
(1533126104.123407) slcan0 0AC#79B98837D3A5CF95
(1533126104.194135) slcan0 00A#E7316FF564010000
(1533126104.428008) slcan0 0AC#07217A5B352ED3C7
...
(1533126131.011415) slcan0 0AC#ABABABABABABABAB
(1533126131.011433) slcan0 0CD#1F86ABF780DCDD3F 
(1533126131.011436) slcan0 0CD#6ACF56BB1ACABAF3
(1533126131.020957) slcan0 0AC#EFAADCE02750BB8D
(1533126131.194017) slcan0 00A#5F9B6FF564010000
(1533126131.325540) slcan0 0AC#A9BC18BE235C6669
(1533126131.408103) slcan0 0AC#38FB4F832439937C
(1533126131.643659) slcan0 0AC#ABABABABABABABAB 
(1533126131.643679) slcan0 0CD#1F86ABF780DCDD3F
(1533126131.643683) slcan0 0CD#6ACF56BB1ACABAF3
...

チャレンジ1と2とは異なり,どうやらCANID:00A, 0AC, 0CDの3種類あるようです.

さらに,0AC#ABABABABABABABABはバスを観測していても流れておらず,CANID:0CDも通常は流れていませんでした.

これから,どうやら0AC#ABABABABABABABABは攻撃メッセージあり,CANID:0CDは攻撃が失敗したときに流れるメッセージであることが推測できました.また,CANID:0CDのメッセージのペイロードはいずれも同じでした.

何もわからないため,とりあえずこのログをslcan0->can0にしてcanplayerで送信してもなにも起こりませんでした.

操作のログを記録しまくり,リプレイをすると一度だけ動きましたが再現性はなく・・・.

一日目はこれ以上わかりませんでした.

バス上のCANメッセージについて

バス上に流れているメッセージを確認したところ,CANID:00A 1メッセージに対して,CANID:0AC 4メッセージ流れているようです.

また,適当にCANID:0ACをなりすまそうとしても全くできないことから,どうやら暗号化された通信をしているようです.

以上を踏まえ,さらになりすましメッセージを送信して検証を重ね整理すると,だいたい以下であると推測しました.

  • ID:00Aをもとに暗号化したメッセージがID:0AC?
  • ID:00Aのフォーマットについて 00A: XX YY ZZ F5 64 01 00 00
    • XXは減少カウンタ/ランダム
    • YYは増加カウンタ/ランダム
    • ZZは数十秒程度で1増えるカウンタ
    • 4バイト目以降は固定
  • ID:0ACのペイロードはすべて暗号化されている
  • ID:0DCを連続で送信するとID:00AのXXとYYがカウンタの役割を果たす
    • エラーカウンタ?このときもラジコンカーは正常に走行する

これらから,単純に以下のようになり済ませる可能性を推測.

    1. ID:00AのZZが00~FFのいずれの場合のメッセージをすべてキャプチャしてなりすます.それを記録した辞書を作成し,現在のバスをSniffし,上書きする.
    2. 結論:かなり大変なため今回はこれを試さず
    1. ID:0DCを連続でそうしんしまくり,このときのID:00Aをなりすます.ID:0ACはID:00Aをもとに暗号化していると考えられるので,1.よりもパターンが少なく済む?
    2. 結論:適当なスクリプトを書いたがうまく行かず(あんまり検証する時間もなかった)

ZIPファイルの解読(パスワード解析)

一日目競技終了後NVさんがjohnを使ってZIPファイルを解読してくれました.

ご存知の方ば多いとは思いますが,johnというハッシュ推測ツールがあり,さらにパスワードリスト(辞書)にはrockyouというこれまた様々なパスワードを詰め込んだものがあります.

対象のZIPファイルのハッシュ値は以下でした.

$ > ./zip2john ../CarHack/ADC_s32k144-c3.zip
ADC_s32k144-c3.zip:$zip2$*0*3*0*42ba75f53e5c44709c693155e955c828*4f02*25d3*ZFILE*/home/teshiba/CarHack/ADC_s32k144-c3.zip*0*4d*b1a5363f4210c4f60ef1*$/zip2$:::::ADC_s32k144-c3.zip

こちらで解析を試みたところ,以下のようにパスワードが解読できます.

> $ ./zip2john ../CarHack/ADC_s32k144-c3.zip > hash.txt
> $ john --wordlist=rockyou.lst hash.txt
Loaded 1 password hash (ZIP, WinZip [PBKDF2-SHA1 4x SSE2])
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:00:02 0.21% (ETA: 03:20:55) 0g/s 8500p/s 8500c/s 8500C/s 
S3cur1ty         (ADC_s32k144-c3.zip)
1g 0:00:03:29 DONE (2018-11-02 03:08) 0.004784g/s 10053p/s 10053c/s 10053C/s TEAMOCRUZ..R679FUKU
Session completed

rockyouは100MBを超える辞書なのですが,私の仮想環境でも割とすぐに全探索できました.さて,以上の結果からパスワードは「S3cur1ty」であることがわかりました.これはSecurityのLeet変換であることが分かりました

Leet - Wikipedia

バイナリ

さて,本題のバイナリです.

引きずり出したバイナリの解析をいろいろ試してみました.

とりあえずobjdumpでヘッダを確認すると

> $ objdump -h ADC_s32k144-c3.elf

ADC_s32k144-c3.elf: file format ELF32-arm-little

Sections:
Idx Name          Size      Address          Type
  0               00000000 0000000000000000 
  1 .interrupts   00000400 0000000000000000 DATA 
  2 .flash_config 00000010 0000000000000400 DATA 
  3 .text         00001744 0000000000000410 TEXT DATA 
  4 .interrupts_ram 00000400 000000001fff8000 BSS
  5 .data         00000000 000000001fff8400 DATA 
  6 .code         00000000 000000001fff8400 DATA 
  7 .bss          000002a0 0000000020000000 BSS
  8 .heap         00000400 00000000200002a0 BSS
  9 .stack        00000400 00000000200006a0 BSS
 10 .ARM.attributes 00000031 0000000000000000 
 11 .comment      00000070 0000000000000000 
 12 .debug_info   0000044c 0000000000000000 
 13 .debug_abbrev 000001fd 0000000000000000 
 14 .debug_loc    000002f1 0000000000000000 
 15 .debug_aranges 00000080 0000000000000000 
 16 .debug_line   00000257 0000000000000000 
 17 .debug_str    0000024e 0000000000000000 
 18 .debug_frame  000000a0 0000000000000000 
 19 .shstrtab     000000da 0000000000000000 
 20 .symtab       00001590 0000000000000000 
 21 .strtab       00001180 0000000000000000 

このあとradare2やobjdumpをいろいろ試してみました.

以下にCAN受信部分の逆アセンブルした結果(i386)を示します.

0000176d <can_receive_msg>:
    176d:   b4 17                   mov    $0x17,%ah
    176f:   4d                      dec    %ebp
    1770:   d5 f8                   aad    $0xf8
    1772:   c0                      (bad)  
    1773:   30 d5                   xor    %dl,%ch              ; //compare?
    1775:   f8                      clc    
    1776:   c4 30                   les    (%eax),%esi
    1778:   d5 f8                   aad    $0xf8
    177a:   c0 60 c3 f3             shlb   $0xf3,-0x3d(%eax)
    177e:   8a 43 c6                mov    -0x3a(%ebx),%al
    1781:   f3 03 46 03             repz add 0x3(%esi),%eax
    1785:   60                      pusha  
    1786:   46                      inc    %esi             ; while(True){
    1787:   71 be                   jno    1747 <can_transmit_msg+0x9e>   ;//transmit?
    1789:   b1 05                   mov    $0x5,%cl
    178b:   30 00                   xor    %al,(%eax)               ;
    178d:   22 4f f0                and    -0x10(%edi),%cl
    1790:   ff 31                   pushl  (%ecx)
    1792:   12 f0                   adc    %al,%dh
    1794:   03 03                   add    (%ebx),%eax
    1796:   01 f1                   add    %esi,%ecx
    1798:   01 04 08                add    %eax,(%eax,%ecx,1)
    179b:   bf 21 46 01 f1          mov    $0xf1014621,%edi
    17a0:   32 04 c3                xor    (%ebx,%eax,8),%al
    17a3:   f1                      icebp  
    17a4:   03 03                   add    (%ebx),%eax
    17a6:   55                      push   %ebp
    17a7:   f8                      clc    
    17a8:   24 40                   and    $0x40,%al
    17aa:   db 00                   fildl  (%eax)
    17ac:   01 32                   add    %esi,(%edx)
    17ae:   24 fa                   and    $0xfa,%al
    17b0:   03 f3                   add    %ebx,%esi
    17b2:   b2 42                   mov    $0x42,%dl
    17b4:   00 f8                   add    %bh,%al
    17b6:   01 3f                   add    %edi,(%edi)
    17b8:   eb d1                   jmp    178b <can_receive_msg+0x1e>        ;
    17ba:   04 4b                   add    $0x4b,%al
    17bc:   10 22                   adc    %ah,(%edx)
    17be:   d3 f8                   sar    %cl,%eax
    17c0:   80 10 99                adcb   $0x99,(%eax)
    17c3:   68 1a 63 00 20          push   $0x2000631a
    17c8:   70 bc                   jo     1786 <can_receive_msg+0x19>    ; }//while loop
    17ca:   70 47                   jo     1813 <ADC_init+0x42>

送信部分

000016a9 <can_transmit_msg>:
    16a9:   b5 2b                   mov    $0x2b,%ch
    16ab:   4f                      dec    %edi
    16ac:   3b 6b 23                cmp    0x23(%ebx),%ebp
    16af:   f0 01 03                lock add %eax,(%ebx)
    16b2:   3b 63 43                cmp    0x43(%ebx),%esp
    16b5:   79 03                   jns    16ba <can_transmit_msg+0x11>
    16b7:   b3 46                   mov    $0x46,%bl
    16b9:   1d 4f f0 ff 35          sbb    $0x35fff04f,%eax
    16be:   00 21                   add    %ah,(%ecx)
    16c0:   11 f0                   adc    %esi,%eax
    16c2:   03 03                   add    (%ebx),%eax
    16c4:   05 f1 23 02 04          add    $0x40223f1,%eax
    16c9:   bf 01 35 47 f8          mov    $0xf8473501,%edi
    16ce:   22 30                   and    (%eax),%dh
    16d0:   c3                      ret    
    16d1:   f1                      icebp  
    16d2:   03 04 ab                add    (%ebx,%ebp,4),%eax
    16d5:   00 03                   add    %al,(%ebx)
    16d7:   f1                      icebp  
    16d8:   40                      inc    %eax
    16d9:   23 03                   and    (%ebx),%eax
    16db:   f5                      cmc    
    16dc:   00 33                   add    %dh,(%ebx)
    16de:   16                      push   %ss
    16df:   f8                      clc    
    16e0:   01 2f                   add    %ebp,(%edi)
    16e2:   d3 f8                   sar    %cl,%eax
    16e4:   88 e0                   mov    %ah,%al
    16e6:   e4 00                   in     $0x0,%al
    16e8:   a2 40 4e ea 02          mov    %al,0x2ea4e40
    16ed:   02 c3                   add    %bl,%al
    16ef:   f8                      clc    
    16f0:   88 20                   mov    %ah,(%eax)
    16f2:   43                      inc    %ebx
    16f3:   79 01                   jns    16f6 <can_transmit_msg+0x4d>
    16f5:   31 8b 42 e2 dc 17       xor    %ecx,0x17dce242(%ebx)
    16fb:   4a                      dec    %edx
    16fc:   1b 04 43                sbb    (%ebx,%eax,2),%eax
    16ff:   f0 44                   lock inc %esp
    1701:   63 c2                   arpl   %ax,%dx
    1703:   f8                      clc    
    1704:   80 30 03                xorb   $0x3,(%eax)
    1707:   68 9b 04 23 f0          push   $0xf023049b
    170c:   60                      pusha  
    170d:   43                      inc    %ebx
    170e:   c2 f8 84                ret    $0x84f8
    1711:   30 d2                   xor    %dl,%dl
    1713:   f8                      clc    
    1714:   80 30 c3                xorb   $0xc3,(%eax)
    1717:   f3 03 63 08             repz add 0x8(%ebx),%esp
    171b:   2b 0e                   sub    (%esi),%ecx
    171d:   d0 10                   rclb   (%eax)
    171f:   46                      inc    %esi
    1720:   05 21 d0 f8 80          add    $0x80f8d021,%eax
    1725:   20 4f f4                and    %cl,-0xc(%edi)
    1728:   7a 73                   jp     179d <can_receive_msg+0x30>
    172a:   c2 f3 03                ret    $0x3f3
    172d:   62 00                   bound  %eax,(%eax)
    172f:   bf 01 3b fc d1          mov    $0xd1fc3b01,%edi
    1734:   01 39                   add    %edi,(%ecx)
    1736:   03 d0                   add    %eax,%edx
    1738:   08 2a                   or     %ch,(%edx)
    173a:   f2 d1 00                repnz roll (%eax)
    173d:   20 f0                   and    %dh,%al
    173f:   bd 05 4a d2 f8          mov    $0xf8d24a05,%ebp
    1744:   80 30 23                xorb   $0x23,(%eax)
    1747:   f0 70 63                lock jo 17ad <can_receive_msg+0x40>
    174a:   43                      inc    %ebx
    174b:   f0 10 63 c2             lock adc %ah,-0x3e(%ebx)
    174f:   f8                      clc    
    1750:   80 30 4f                xorb   $0x4f,(%eax)
    1753:   f0 ff 30                lock pushl (%eax)
    1756:   f0                      lock
    1757:   bd                      .byte 0xbd

また,おそらく解読すべきであろう関数は"challenge_three_unique"という関数でした.

※長いのでGistに投げました.

また,IDAを利用して逆コンパイルもやりました(そこまでして解けないのか?と怒られそう)

このバイナリにはこれらの関数が含まれていました.

// Function declarations

void __noreturn Reset_Handler();
int __fastcall Speck_Encrypt_32(int result, int a2, unsigned __int16 *a3, unsigned __int16 *a4);
int __fastcall Speck_Encrypt_48(int a1, int *a2, _DWORD *a3, int a4);
int __fastcall Speck_Encrypt_64(int result, int a2, int *a3, int *a4);
int __fastcall Speck_Encrypt_96(int a1, int a2, int a3, int a4);
int __fastcall Speck_Encrypt_128(__int64 a1, __int64 *a2, __int64 *a3);
int __fastcall Speck_Decrypt_32(char a1, int a2, unsigned __int16 *a3, _WORD *a4);
int __fastcall Speck_Decrypt_48(char a1, int a2, _DWORD *a3, int a4);
int __fastcall Speck_Decrypt_64(char a1, int a2, int *a3, int *a4);
int __fastcall Speck_Decrypt_96(char a1, int a2, int a3, int a4);
int __fastcall Speck_Decrypt_128(char a1, int a2, __int64 *a3, __int64 *a4);
signed int __fastcall Speck_Init(int a1, unsigned int a2, int a3, char *a4);
int __fastcall Speck_Encrypt(int a1, int a2, int a3);
int __fastcall prepare_joystick_msg(int a1, _BYTE *a2);
int __cdecl main(int argc, const char **argv, const char **envp);
int SOSC_init_8MHz();
int SPLL_init_160MHz();
void NormalRUNmode_80MHz();
void rtc_init();
__int64 get_time_tick();
__int64 get_time_seconds();
signed int __fastcall challenge_three_unique(_DWORD *a1, int a2);
signed int current_challenge_number();
int can_init();
signed int __fastcall can_transmit_msg(int a1);
int can_has_msg();
int __fastcall can_receive_msg(int a1);
int ADC_init();
int __fastcall convertAdcChan(char a1);
int adc_complete();
int read_adc_chx();
signed int SystemInit();
int *init_data_bss();
int_t __fastcall memcmp(const void *src1, const void *src2, size_t n);
void *__fastcall memcpy(void *dst, const void *src, size_t n);
void *__fastcall memset(void *dst, int_t val, size_t n);
void __fastcall _fill_mem(void *dst, int_t val, uint32_t n);

ここでchallenge_three_unique関数はこんな感じ.

※これもGistに投げました

ここで最も怪しい部分は

if ( v11 != 8 || Speck_Encrypt((int)&spk_8_byte_level_three, (int)&v36, (int)&v41) )

のSpeck_Encrypt関数を読んでいる部分です.

int __fastcall Speck_Encrypt(int a1, int a2, int a3)
{
  (*(void (__fastcall **)(_DWORD, int, int, int))(a1 + 4))(*(unsigned __int8 *)(a1 + 15), a1 + 48, a2, a3);
  return 0;
}

ちょっとこの関数がなにをしているのかわからないのですが,変数spk_8_byte_level_threeが暗号鍵であり,Speck_Encrypt関数は必要な暗号化関数を呼び出しているのでしょうか.

変数定義は

_UNKNOWN spk_8_byte_level_three; // weak

となっています._UNKNOWNなのでわからないということでしょうか.これは以下の初期化をしそうな関数で先に初期化されてそうな感じです.

Speck_Init((int)&spk_8_byte_level_three, 4u, 0, (char *)&v41);

さらに,この関数の引数は

signed int __fastcall Speck_Init(int a1, unsigned int a2, int a3, char *a4)

こんな感じなので,おそらくspk_8_byte_level_threeのメモリアドレスに直接何かしらの値をいれて初期化をしているのかと思いました.なので怪しいのはここら辺なのではないかと想うのですが,これ以上はわかりませんでした.

 ...
  dst = 0LL;
 ...
 if ( v15 )
  {
    v16 = a4;
    v17 = (__int64 *)&dst;
    do
    {
      v18 = v17;
      ++v17;
      memcpy(v18, v16, v8 >> 3);
      v16 += v14;
    }
    while ( v17 != (__int64 *)(&dst + v15) );
    memcpy((void *)(v9 + 48), &dst, v8 >> 3);//先にv9 = a1;としている
  }
  else
  {
    memcpy((void *)(a1 + 48), &dst, v8 >> 3);
  }
 ...

Speckによる暗号化について

競技中には実際に暗号化を解いてなりすましを行うプログラムの作成までいきませんでした.

しかし,Speckという暗号化が行われていることはわかっていましたので,このSpeckについても競技時間内に簡単に調べていました.

Speckとは?なんかSimonってのもあるらしい.

github.com

いろいろ調査していくと上記Githubが.

さらにSpeck自体の論文もみつかりました.

https://eprint.iacr.org/2013/404.pdf

こちらの論文に実装例についても書かれています.(ptが暗号対象のメッセージ,ctが暗号化されたメッセージ,kが鍵となっています)

#define LCS _lrotl  //left circular shift
#define RCS _lrotr  //right circular shift
#define u64 unsigned long long
#define R(x,y,k) (x=RCS(x,8), x+=y, x^=k, y=LCS(y,3), y^=x)

void Speck128Encrypt(u64 pt[], u64 ct[], u64 k[])
 {
  u64 i;
   ct[0]=pt[0]; ct[1]=pt[1];
   for(i=0; i<32; i++) R(ct[1], ct[0], k[i]);
 }

もし競技中に解析までうまくい行けば,

  • 暗号鍵を発見する
  • Speckの暗号化を試す(解析でおそらく128bit->128bit暗号だろうと推測)
  • 現在流れているメッセージ(CANID:00A?)を鍵としてCANID:0ACを作成?するスクリプトを作成

という感じでしょうか.

Challenge4 (300 pt.)

** challenge4
File1: candump-level4.log
File2: ADC_s32k144 -c4.zip
Point: 300

チャレンジ3同様ZIPファイルがありますね.

もちろんチャレンジ3が解けていないので.4も解けていないのですが,後日わかったことを残しておきます.

まず,ZIPのパスワードについてはわかりませんでしたので,こそっと教えてもらいました.

中にはやはりバイナリファイルが一つ.

ちなみにハッシュ値はこれでした.

> $ ./zip2john ../CarHack/ADC_s32k144-c4.zip
ADC_s32k144-c4.zip:$zip2$*0*3*0*22165c2abb12e7fd2a99f43ed1a91057*fa09*24d9*ZFILE*/home/teshiba/CarHack/ADC_s32k144-c4.zip*0*4e*2a44cf1768a739b3501f*$/zip2$:::::ADC_s32k144-c4.zip

パスワードはあるキーワードをLeet変換したものでした.Challenge3のLeet変換がヒントでしたが,実際にはこれはノーヒントだったのでなかなかハードです.

バイナリ

こちらも少しバイナリを覗いてみました.

objdump -hの結果

> $ objdump -h ADC_s32k144-c4.elf 

ADC_s32k144-c4.elf: file format ELF32-arm-little

Sections:
Idx Name          Size      Address          Type
  0               00000000 0000000000000000 
  1 .interrupts   00000400 0000000000000000 DATA 
  2 .flash_config 00000010 0000000000000400 DATA 
  3 .text         0000163c 0000000000000410 TEXT DATA 
  4 .interrupts_ram 00000400 000000001fff8000 BSS
  5 .data         00000000 000000001fff8400 DATA 
  6 .code         00000000 000000001fff8400 DATA 
  7 .bss          00000514 0000000020000000 BSS
  8 .heap         00000404 0000000020000514 BSS
  9 .stack        00000400 0000000020000918 BSS
 10 .ARM.attributes 00000031 0000000000000000 
 11 .comment      00000070 0000000000000000 
 12 .debug_info   0000044c 0000000000000000 
 13 .debug_abbrev 000001fd 0000000000000000 
 14 .debug_loc    000002f1 0000000000000000 
 15 .debug_aranges 00000080 0000000000000000 
 16 .debug_line   00000257 0000000000000000 
 17 .debug_str    0000024e 0000000000000000 
 18 .debug_frame  000000a0 0000000000000000 
 19 .shstrtab     000000da 0000000000000000 
 20 .symtab       000015a0 0000000000000000 
 21 .strtab       00001186 0000000000000000 

また,逆コンパイルして確認した関数はこちら.

// Function declarations

void __noreturn Reset_Handler();
int __fastcall Speck_Encrypt_32(int result, int a2, unsigned __int16 *a3, unsigned __int16 *a4);
int __fastcall Speck_Encrypt_48(int a1, int *a2, _DWORD *a3, int a4);
int __fastcall Speck_Encrypt_64(int result, int a2, int *a3, int *a4);
int __fastcall Speck_Encrypt_96(int a1, int a2, int a3, int a4);
int __fastcall Speck_Encrypt_128(__int64 a1, __int64 *a2, __int64 *a3);
int __fastcall Speck_Decrypt_32(char a1, int a2, unsigned __int16 *a3, _WORD *a4);
int __fastcall Speck_Decrypt_48(char a1, int a2, _DWORD *a3, int a4);
int __fastcall Speck_Decrypt_64(char a1, int a2, int *a3, int *a4);
int __fastcall Speck_Decrypt_96(char a1, int a2, int a3, int a4);
int __fastcall Speck_Decrypt_128(char a1, int a2, __int64 *a3, __int64 *a4);
signed int __fastcall Speck_Init(int a1, unsigned int a2, int a3, char *a4);
int __fastcall Speck_Encrypt(int a1, int a2, int a3);
int __fastcall prepare_joystick_msg(int a1, _BYTE *a2);
int __cdecl main(int argc, const char **argv, const char **envp);
int SOSC_init_8MHz();
int SPLL_init_160MHz();
void NormalRUNmode_80MHz();
void rtc_init();
__int64 get_time_tick();
__int64 get_time_seconds();
signed int __fastcall challenge_four_unique(_DWORD *a1, int a2);
signed int current_challenge_number();
int can_init();
signed int __fastcall can_transmit_msg(int a1);
int can_has_msg();
int __fastcall can_receive_msg(int a1);
int ADC_init();
int __fastcall convertAdcChan(char a1);
int adc_complete();
int read_adc_chx();
signed int SystemInit();
int *init_data_bss();
int_t __fastcall memcmp(const void *src1, const void *src2, size_t n);
void *__fastcall memcpy(void *dst, const void *src, size_t n);
void *__fastcall memset(void *dst, int_t val, size_t n);
void __fastcall _fill_mem(void *dst, int_t val, uint32_t n);

これはChallenge3とほぼ同じ関数です.唯一異なるのがunique関数みたいです.challenge_four_unique関数はこちら(Gist)

Challenge5 (400 pt.)

** challenge5
File: candump-level5.log
Point: 400

最後はログファイル一つだけなようです.

中身はこんな感じでした.

...
(1533129089.360862) slcan0 0AA#341FB94624EA
(1533129089.590563) slcan0 0AA#ABABABABABAB
(1533129089.590588) slcan0 001#3FAA00A1BDAE
(1533129089.590593) slcan0 001#1CAA326503AA
(1533129089.665513) slcan0 0AA#E02CA5C4916E
(1533129089.970509) slcan0 0AA#3E05BB6265FE
(1533129090.053125) slcan0 0AA#324FD26F81EA
(1533129090.357986) slcan0 0AA#A892177DA890
(1533129090.662907) slcan0 0AA#FD493958D08A
(1533129090.967815) slcan0 0AA#DA26998053CD
(1533129091.050468) slcan0 0AA#EBD4DD184981
(1533129091.238912) slcan0 0AA#ABABABABABAB
(1533129091.238945) slcan0 001#3FAA00A1BDAE
(1533129091.238948) slcan0 001#1CAA6A30AA6D
(1533129091.355445) slcan0 0AA#0DE00D067D20
(1533129091.660199) slcan0 0AA#5BED4529D410
...

よく見るとCANID:0AAに混ざってCANID:001がところどころ混ざっているようです. 

感想とか

今回は昨年と違い,かなり本格的な自動車ハックという感じでした.賞品として,今回ドローンをいただけましたが,今回のチャレンジ環境をまるごと持って帰ってもいいとおっしゃっており,個人的に欲しかったです.それだけでも出る価値はありました.

実際に解析の経験が非常に求められていたのではないでしょうか.私も来年から会社にてそういった業務にも取り組む可能性があるので,今回はできるだけしっかり調べてみました.次回に活かせればいいですが,,

もし,この記事おかしい!とか,具体的にコメントしたい!とか,もはや答え教えてくれる!とかありましたら,以下でプルリクもしくはコメントなどでくれても大丈夫です.

github.com

また,今回私はCODE BLUEではこのチャレンジだけではなく,翻訳スタッフをさせていただいたり,講演を聞いたり,その他のCTFに参加したりできました.DeloitteのCTFではTsubasaくんが2位だったらしい!

さらに今まで関わってきた多くの方にも会うことができ,非常に実りある経験となりました.来年も参加できるように勉強を続けていきたいです!最後の学生生活残りもやるぞ~

Thank you CODE BLUE!

LoRaWANとセキュリティとあとは細かい話 [IoTSecJP Tokyo #4 振り返り]

How Can I Hack LoRaWAN?

先日,「LoRaWANとセキュリティとあとは細かい話」というタイトルでIoTSecJPにてお話させて頂きました.今回は13時30分から18時半と長丁場でしたね.皆様お疲れ様でした.

初めてブログでLoRaWANのお話をする気がします.正直,まだまだこの分野(特にSDRとか)は私はまだ素人の段階なので少々キョドってしまった気がします..

本記事ではお話させていただいたスライドの補足から,SDRを利用したハックなどについてもう少しメモを残しておきたいと思います.

さて,早速ですが私が発表したスライドはこちらです.

※当初公開時の資料を更新しています

ruffnex.net

補足

細かいところなどを自分でもう一度調べながら補足します.間違いなどありましたらご指摘ください.

まず,LoRaWAN™は仕様がオープンされていますが,オープンソースではありません

これは公開版のスライドが間違っていました,ここで謝罪します.ごめんなさい.(発表した資料は修正してありました).

ですが,実際に利用されているノードやゲートウェイにはオープンソースハードウェアなものも多いです.

また,詳しく述べなかったのですがLoRaとLoRaWANは別ものです.

LoRaというのは物理変調規格のことで,このチップについては非公開となっています.

LoRaWANは無線技術のことを指しています.

LoRa Alliance™ and The Things Network(TTN)

LoRaWANの基本的な仕様はLoRa Alliance™が策定しています.

LoRaアライアンスの公式サイトはこちらになります.

lora-alliance.org

また,仕様書やホワイトペーパーなども提供しています.最新の仕様書v1.1(specification v1.1)はこちらになります.PDFが提供されています.できればこれを翻訳してみたいのですがどんどん更新されるためなかなか・・・,

lora-alliance.org

仕様自体の詳細以外にも,Back-End InterfacesとRegional Parameterについても公開されています.

また,The Things NetworkというLoRaWAN向けのクラウドサービスがあります.実質公式といっても過言ではないほどよく使われており,海外でのプロトタイプ記事などではTTNと略されることが多いです.日本語のページも用意されています.

www.thethingsnetwork.org

また,公開&非公開も含めて登録されているLoRaGatewayをMapで確認することもできます

www.thethingsnetwork.org

Member White Paper: End to End Secure LoRaWAN™

lora-alliance.org

こんなものが今年の8月にリリースされているのに今更気づきました.

やはり新しい技術だけあって毎回調べ直さないとどんどん新しいものがでてきますね.

こちらの資料はノードとGW間のセキュリティについてまとめています.こちらではKey Management System(KMS)やHardware multiple levels of isolation(実行環境の独立化)について書かれています.

ホワイトペーパーがこうして出されているのは,決まった仕様がない今,セキュリティについて言及されていることから,少しでも急いで出したいという気持ちがあるのでしょう.

たぶん正式に年内には仕様が出るのではないでしょうか.

ARIB STD-T108について

こちらの方の資料が非常によくまとまっているので,ARIBについて知りたい方はこちらをご参照ください.しかし,最新版のARIB STD-T108ではないのでご注意ください.

www.slideshare.net

登壇が終わり,Twitterを開くと

luminさんとNVさん,ありがとうございます.

私がARIB STD-T108を入手したのは今年の2月(割と最新版@20180122が出てすぐ)だったのですが,どうやら英語の最新版が無料で公開されているとのことです.知らなかった・・・.一体いつの間に!!

ほら,ここに”無料ダウンロード”とあります!なんで英語版が無料なのかさっぱりわかりません.足元見てるんでしょうか.

www.arib.or.jp

実はARIB関係は指導教員である教授が強いので,その関係で入手しやすかったです.

SDR(software defined radio) Hacking for LoRaWAN

私「ん~,とりあえずGqrxでLoRaWANの電波みれたけどこれじゃ面白くないなあ.」

教授「なに,これでLoRaWANのデータみれないの?」

(とりあえず調べる私)

私「完璧に理解した」

gr-loraというLoRaWANをデコードしてくれるツールがあるらしいことがわかり,いろいろ調べて今回の登壇内容のデモ&資料が出来上がりました.

詳しくはわからないのですが,gr-loraというツールには古いものと新しいもの (forkされた?)があります.

2年前からあまり更新されていないものがこちら.

github.com

私が今回試したのはこちらです.

github.com

環境の用意からの詳細についてはまた別の記事にしたいと思います.(近い内に書くぞ)

周波数のトレース?について

LoRaWANの運用では,実際には複数のチャンネルを行き来するのですが,それらを解析(トレース?)できるのか?」との質問をいただきました.

正直よくわからなかったのですが,LoRaWANでは複数チャネルを利用することについては知っていました.

そもそもClassBビーコンや連送は別の周波数だからです.それらについて知るためには結局Gqrxなどを利用して複数の周波数をモニタリングするしかないのかなあと思いました.

このときは気づかなかったのですが,今になって

「gr-loraを用いたDecodeを行う際に指定する周波数をどうやって知るのか?」

という意図だとわかりました.ちょっとこれについては私も今後試してみたいと思っています.

今回はノードの実装プログラムが手元にあり,使用する周波数がわかっていたので,これが不明な状態であることを前提としたスニッフィングについて検討してみます.

SDR Hacking for XX

SDRは電波を出すものなら何でもいけます.今回御社に貸与頂いたHackRF ONEは1MHz~6GHzまで対応しているので,キーフォブ,LoRaWAN,Sigfox,WiFiなどなんでも(もちろん法律の範囲内で)いけます.私もこれから勉強していこうと思うのですが,手元にあった書籍で参考になりそうなものを紹介しておきます.これ以外にもありましたらぜひ教えていただきたいです.

  • IoT Hackers Handbook: An Ultiimate guide to Hacking the Internet of Things and Learning IoT Security (Aditya Gupta)

SDRの基本的な使い方からGNU Radioを利用したDecodeまでの基本が学べます.もし手に入る方がいればぜひこちらを読んでみると良いでしょう.私は以前こちらの本を心優しい方に購入していただきました.とても感謝しています.

IoT Hackers Handbook: An Ultimate Guide to Hacking the Internet of Things and Learning IoT Security

IoT Hackers Handbook: An Ultimate Guide to Hacking the Internet of Things and Learning IoT Security

  • カーハッカーズ・ハンドブック (Craig Smith, 井上 博之)

もちろん,自動車セキュリティ分野でもSDRは活躍(?)します.例のカーハッカーズハンドブックではTPMS(タイヤのモニタリングシステム)やキーフォブのハッキングについても紹介されています.今度これについても試してみたいと思います.

カーハッカーズ・ハンドブック ―車載システムの仕組み・分析・セキュリティ

カーハッカーズ・ハンドブック ―車載システムの仕組み・分析・セキュリティ

  • ハッカーの学校 IoTハッキングの教科書 (黒林檎, 村島 正浩)

また,先日発売されました黒林檎(@r00tapple)さんの「ハッカーの学校 IoTハッキングの教科書」においてもSDRについて紹介されています.ここではSDRを利用したReplay攻撃の方法について見ることができます.SDRについてはちょっとしか書かれていないのですが,IoTハッキングとはなにかを知ることができるのでおすすめです.

ハッカーの学校 IoTハッキングの教科書

ハッカーの学校 IoTハッキングの教科書

最後に

「法律には気をつけて」

今回IoTSecJPではこの言葉がよく言われていました.今回,Decodeには受信しか行っていないのですが,やはりPassiveに攻撃したい場合は送信するしかないですね.そのためにはやはりMy電波室が必要になってくるのでしょうか.

また,今後こうした法律に触れる可能性がある分野をやっていくにあたって,「日本ハッカー協会」が役に立つかも?とluminさんに伺い,ハッカーのはしくれである私も登録させてもらいました.

一般社団法人日本ハッカー協会

もっとSDR勉強します!初学者ながら,お話を聞いていただいた方はありがとうございました!

おまけ

白百合さん(@WhiteLily6u6)さんが同日にまとめを書いてくれていますので,ぜひ興味のある方はご一読ください.

whitelily6u6.hateblo.jp