いろんな技術にふれたい

いろんな技術に触れたい

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

センスウェイさんのLoRaWANスターターキットを試してみた

Getting start the Senseway LoRaWAN Starter Kit

こんにちは.最近修論をどうにかやっつけたtokina(himitu)です.来週修論発表です(どうでもいい).今回はセンスウェイさんにLoRaWANスターターキットを頂いたので,その紹介をします!1月に間に合いました!!

長いので記事を分けました.センサ値取得〜可視化とか具体的な実装の話は次の記事を見てください

tokina.hatenadiary.jp

HIRATA Kenjiさん(@field_k),ありがとうございます!

www.senseway.net

私はLoRa/LoRaWANの研究をしており,理解しきれていない部分もあり,いまでも勉強中の身です.最近OpenwaveさんのDragino LoRaモジュールをいじったりしていました.

ではまず,入手した経緯から.

きっかけ

昨年「IoTつくるよ!」というIoTのプチ博覧会のようなイベントにてアールエスコンポーネンツさんのお仕事を手伝いました.

IoTMaking

www.tsukuruyo.net

アールエスコンポーネンツ(RS Components)社は電子部品の販売代理店で,Raspberry Piの正規代理店でもあります.もしかしたらロゴをみたことがあるかもしれません.

jp.rs-online.com

実は私はアールエスコンポーネンツのブランドである「DesignSpark」にて記事を書いたり翻訳したりしています.

そんなこんなで,IoTつくるよ!にてお手伝いさせていただいていたのですが,アールエスコンポーネンツさんのブースの近くにセンスェイさんがいました(なおとなりはDoroneのOS開発をされているDoCoJAのブースでした).

このとき数週間前からLoRaWANのサービスを提供しているというセンスェイさんについてはTwitterで目にしていました.

twitter.com

IoTつくるよ!にセンスェイさんがいるのは当日,開始時間になってから知りました.

これがきっかけとなり,スターターキットをいただくことになりました.それが昨年末のことです(あれから研究をずっとやっていました).

IoTMaking_Senseway

LoRaWANスターターキット

LoRaとLoRaWANの違いについては無限回述べているので今回は簡単に.

LoRaはSemtech社が開発している無線の変調方式で,LoRaWANはSemtech社含むLoRa Allianceが公開するLoRa無線を利用した全体のシステムを表しています(昔はMAC層以上のプロトコルを指していたこともある?).

センスウェイさんが提供しているLoRaWANサービスはSenseWay Mission Connectと呼ばれているIoT通信プラットフォームです,

https://www.senseway.net より

LoRaWANデバイスのデータを収集,デバイスを管理する総合的なプラットフォームです.

スターターキットには以下のものが含まれていました.なお,スターターキットの購入案内ページはこちらです.

store.senseway.net

  • Arduino Uno互換機
  • LoRa (WAN)通信モジュール
    • LoRaアンテナ(800MHz ~ 1GHz向け?)
    • USB-Bケーブル
  • LoRaWAN屋内用ゲートウェイ
    • アンテナ
    • Mini USBケーブル
    • USB変換アダプタ
    • LANケーブル
  • 温度センサ(ADT7410)

StarterKit

実際のLoRaノード(デバイス)はこちら.アンテナがごつい!

LoRaNode

試してみた

実際に試してみたので,簡単に何ができそうかまとめてみます.

一応参考にした資料は有償であるキットに含まれているので,具体的な手順については言及しないことにします.

Senseway Mission Connect

センスウェイさんが提供するLoRaWANサービスの名称が「Senseway Mission Connect」です.

ここでデバイスの登録などができます.

MissionConnect

まず,このデバイス管理のところへキットに入っているLoRaノードのDevEUIを追加します.Dev EUIはLoRaWANにおいてデバイスを識別するためのIDで,他のサービスでもこれは必要になってきます.

また,今回はPINコードも必要でした.これをなくすとまずいですね.

これで入手したデバイスのActivationはできたようです.

LoRaWANゲートウェイの用意

ここまでで入手したデバイスと,LoRaWANゲートウェイ上の仮想のデバイスのリンクができたので,今度は実際のゲートウェイの準備をします.

案内されたマニュアルにはゲートウェイについては触れられていなかったので,適用に調べてこちらがヒット.

service.senseway.net

今回,私の環境ではWiFiでWANへと接続します.なお,本体にはUSB電源から電源を供給可能です.適当にそこらへんに落ちていたMini USBケーブルでつないで少し放置すると自動的に初期化が終わり,SSID:AP-XXXXXという無線LANを吹きます.なお,ここはきちんと暗号化されているので比較的安心です.

あとは上のセンスウェイさんのマニュアル通り.

なお,今回WiFiを選びましたが,もちろん使用用途によっては携帯回線とかもあると思います.ゲートウェイの設定画面では3G/4G LTEも選択可能でした.

※ここで特に受信したLoRaノードのメッセージの送信先となるLoRaWANサーバは選べないようです.多分ファームウェアレベルで書き込まれているっぽい?

うまく接続すると,webコンソールのStatus>Overviewで確認できます.DHCPでアドレスを割り当てる場合はここから確認すればいいはず.ゲートウェイ自体もAPになりますが,そっちは192.168.55.0/24で割り当てられます.

SSH接続を試みてみたところ,username/Passwordを聞かれますが,認証情報は公開されていません.Nmapすると80,22番ポートが空いていました(??).

ノードのプログラミング

仕様とライブラリ -KashiwaGeeks

LoRaノードはArduino Uno互換ボードとモジュールで構成されているので,Arduino Unoでプログラミングします.(今回試した私の環境ではArduino 1.8.8です)

LoRaWAN Shieldについてのマニュアルはこちら.

service.senseway.net

マニュアルにはありませんでしたが,確認してみたところ,シリアルポートとはボーレート57600で通信してるっぽいです(プログラムのConsoleBegin()がSerial.begin()に相当するみたい).

Windowsで試したのですが,ドライバの関係か,最初は認識されませんでした.なお,書き込み時のボードにはArduino/Genuino Unoを選択します.

Arduinoとモジュールとの通信はD11/D12ピンをUARTシリアルで行っているようなので,基本的にArduinoのSoftware Serialから行うことができます(D11 UART_TX,D12 UART_RX).

しかしこれだと1からプログラミングすることになってしまうので,用意されているライブラリを使います.これには「KashiwaGeeks」というツールが利用できるそうです.山口知昭さんという有名な方が開発したそうです.

github.com

LoRaWAN Application framework for Arduino. This framwork consists of Application,LoRaWAN devices and Payload Classes. These classes provide following functions:

  1. Power saving with various sleep modes.
  2. Wake up by watchdog timer.
  3. Interrupt handling for INT0 and INT1.
  4. Task execution control.
  5. LoRaWAN devices control.
  6. Allow payload to be created bit by bit.

ITメディアでも取り上げられています.

blogs.itmedia.co.jp

 KashiwaGeeksを導入すると、
 1)スリープ機能による省電力化 
 2)タイマーによるウェイクアップ機能
 3)INT0、INT1割り込み機能
 4)タスク実行管理機能
が提供されます。

多分Kiwitechのデバイスが主な対象なようです.ソラコムさんのデバイスでも利用できるみたいです.

これにより,ピン配置が正しければ問題なくLoRaモジュールを使うことができるようになります.

なお,ADB922S.cppで以下のように定義されていますね.

#define LoRa_Rx_PIN               11
#define LoRa_Tx_PIN               12
#define LoRa_WAKEUP_PIN            7

また,ノードのActivationの方式としてABPとOTAAという2種類があるのですが,センスウェイさんのLoRaWANサーバではOTAAのみ利用可能だそうです(最初ちょっと面倒ですが,こっちのほうがセキュアですね).違いはぐぐってください.

KashiwaGeeksの特徴(メモ)

KashiwaGeeksをいじってて思ったこととしては,間欠動作を便利にプログラミングできるように作られているんだなということです.

全体のプログラムのイメージを簡単なフロー図にまとめてみました.

KashiwaGeeksImg

定期動作を原則とし,用意したタスクを定期実行するようです.このとき,動作時間が重ならないように気をつける必要があります.多分重なると処理に遅延が発生する原因とかになると思います.

プログラムの長さは少し冗長気味にはなりますが,わかりやすくなっています.

テスト

いくつかのサンプル例が用意されているので,普通に「End-node_sample」のスケッチ例から試してみました.

ソースコードはこれです.Arduino IDEでこれを書き込めば終了です.

KashiwaGeeks/examples/End-node_Sample at master · ty4tw/KashiwaGeeks · GitHub

書き込み成功しているようなので,Arduino IDE上からツール>シリアルモニタを開き,ボーレード57600(bps)で見てみます.

**** End-node_Sample *****
try to join... accepted.

_/_/_/ KashiwaGeeks 0.10.3 _/_/_/


  Task1 invoked

Temperature:  1020 degrees C
%RH: 2020 %
Pressure: 5005 Pa

Send  =>lorawan tx ucnf 12 03fc07e40000138d<=

Recv  =>lorawan tx ucnf 12 03fc07e40000138d

>> Ok

>> tx_ok

> <=

 SUCCESS
LoRa sleep.

temperature: 1020 Degreesが気になりますが(このサンプルではセンサ値をダミーとして送信しているみたいです),とりあえずOTAAでActivationとネットワークへのJOINを行い,成功していることがわかります.次にLoRaを送信して,Ackかなにかが返ってきており,最後にスリープモードに入っていることが確認できますね.

ここでもしやと思い,webのSenseWay Mission Connectを見てみると,Uplinkのカウンタが増えています.ということは,とりあえずこれでLoRaWANサーバにデータの送信が成功していることがわかります.

Message

私はこれでできるとは思っていなかったので驚きました.なぜなら普通はArduinoのプログラム中にDev EUIを書き込まないとLoRaWANサーバがノードを認識できない(はず)からです.なのにこうしてUplinkのカウンタが増えているこということは,ユーザが変更できない領域にDev EUIが書き込まれていることを指しているということになります.

つまり,正規のDev EUIを書き込まれたノードじゃないと(センスウェイさんのLoRaWANサーバでは)使えないということです(ベンダーロックインなのでそれはそう).

ひとまずこれでLoRaデバイス→LoRaゲートウェイ→LoRaWANサーバの通信がテストできました.

ですがこれだとセンサ値とか送れてないのでセンサノードとしてはなんの意味もなしていないです.

長いので次の記事でセンサを試したことをまとめたいと思います.

とりあえず感想

ここまでの感想としては

  • 利用,テストが簡単
  • GatewayのUsername/Passwordを教えてほしい
  • KashiwaGeeks使ったほうがいいかも
  • Dev EUI周辺がどうなっているのか全くわからない!

個人的に,LoRa無線を簡単に使うためのRadioHeadライブラリや,LoRaWANプロトコルに対応するためのLMiCライブラリ(IBMのやつ)が使えるのか気になります.書き込みだけはできるっぽい?

それでは具体的な実装とか,実際にプログラム〜可視化を行っているのはこちらです↓

tokina.hatenadiary.jp

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!