- 低価格のBluetooth LE LED照明をHome Assistantに統合しようとするリバースエンジニアリングの過程で、10Mのアドレス指定可能LEDストリングの隠しエフェクト値を試していたところ、コントローラーが動作しなくなった
- AndroidのBluetooth HCI snoopとWireshark/tsharkで、アプリが照明に書き込むBLEパケットをキャプチャし、
btatt.opcode.method==0x12の書き込み要求から制御バイトを追跡した
- iDeal LEDアプリのパケットは単純なon/off値には見えず、APKのデコンパイルと既存の解析記事を経て、
libAES.so内の固定AESキーで復号した
- 復号されたon/offパケットは固定ヘッダーと5番目のバイトの
1/0の違いとして整理でき、色・明るさ・エフェクト機能を繰り返し実行してバイトパターンを記録した
- RGBについて、アプリが使う5ビット範囲の
0x1Fを超える8ビット値を送ると、より明るい色が出せたが、エフェクト番号12を送った瞬間に照明が消え、Bluetooth広告も消えた
低価格BLE照明をホームオートメーションに統合する出発点
- Bluetooth LEで通信し、専用アプリがある機器はホームオートメーションシステムに統合できるという前提で、複数の低価格LEDストリップをリバースエンジニアリングした
- 以前には、£2.38のBluetooth LE制御5M非アドレス指定LEDストリップを数時間でHome Assistantに接続しており、関連コードはbj_ledで公開されている
- LEDnetWFコントローラーのBLEリバースエンジニアリング作業もlednetwf_bleにある
- 今回の対象は机の上にあった10Mアドレス指定可能LEDストリングで、"iDeal LED"アプリで制御される
- アプリは機能が多く、比較的よく動作する
- LEDはWS2812または類似製品の可能性がある
- 製品はAliExpressで購入した照明である
アプリが送るBLEバイトのキャプチャ
- 自作ソフトウェアで機器を制御するには、まずアプリがBluetoothで機器に送るバイト列を確認する必要がある
- 一般的な照明プロトコルは、ヘッダー、on/offや色変更のような命令バイト、チェックサムの可能性があるフッターで構成されることがある
- Androidでは次の手順でキャプチャした
- 開発者モードを有効にする
- 照明アプリをインストールする
- 開発者設定で
Bluetooth HCI snoopを有効にする
- アプリで照明のオン・オフなどの操作を行う
adb pull sdcard/btsnoop_hci.log .でログをコンピューターにコピーする
- Wiresharkでログを開くと、照明に送信されたバイトを確認できる
- フィルター例は
bluetooth.dst == ff:ff:ff:ff:ff:ff && btatt.opcode.method==0x12
- MACアドレスは実際の照明のMACに置き換える必要がある
btatt.opcode.method==0x12はAndroid端末から照明への書き込み操作が発生したことを意味する
- tsharkを使えば、パケット値をターミナルから直接取り出せる
tshark -r <filename> -T fields -e btatt.valueはLEDコントローラーに書き込まれたペイロードを出力する
単純なリプレイでは不十分だったiDeal LEDプロトコル
- 一部の照明では、on/off動作にほぼそのまま読めるパターンが見られる
- 例として
69 96 02 01 01と69 96 02 01 00が繰り返される形がある
- 最後のバイトが
1と0に変わり、オンとオフを表す
- 今回のiDeal LED照明では、はるかに長いバイト列が繰り返され、on/offに対応する2種類のパケットは識別できるものの、値はノイズのように見えた
- 単にオン・オフしたいだけなら、キャプチャしたバイト列をそのまま再送するリプレイで十分な場合がある
gatttoolでBLE機器に接続し、バイトを送信できる
- 送信先ハンドルはWiresharkで確認する必要がある
- より多くの制御を行うにはパケット構造を理解する必要があり、Androidアプリ自体を解析する段階へ進んだ
APKのデコンパイルとAESキーの発見
- APKをダウンロードし、 jadxで開いてアプリコードを確認した
- ソース内にAESへの参照が見つかり、プロトコルが暗号化されている可能性が出てきた
- 暗号化データについて、次の条件を仮定した
- 同じ操作の暗号文が毎回変わらないため、一貫したキーがある可能性がある
- 低消費電力MCUで高速に復号する必要があるため、短いキーが有利である
- キーは機器ごとに固有ではなく、固定キーである可能性がある
- アプリには
libAES.soというコンパイル済みのAESライブラリが入っており、jadxだけでは解析できなかった
- 別の人が
ida freeでAESライブラリをデコンパイルし、埋め込みキーを見つけた解析記事を見つけ、そのキーを試した
Crypto.CipherのAES ECBモードで復号すると、on/offパケットが意味のある形に変わった
- 復号後の値は
05 54 55 52 4E 01 ...と05 54 55 52 4E 00 ...のように現れた
- 固定ヘッダーの後ろにある5番目のバイトが
1または0に変わり、on/offを表す
- 残りは0で埋められている
- この段階から、アプリが送るパケットを復号し、自作コードで同じ制御を再現できるようになった
機能ごとのバイトパターンの記録
- アプリの全機能を1つずつ実行し、送信バイトを記録する方法でプロトコルの範囲を広げた
- 各操作は複数回繰り返し、セクションの区切りのために照明をオフ・オンするパターンを挟んだ
- 色をred、green、blueの順に何度も変更する
- 明るさを100%、50%、10%、50%、100%に変更する
- 各まとまりの間にoff/onを入れて、キャプチャログで境界を見つけやすくする
- この方法で、操作に応じてどのバイトが変わるかを確認し、記録した操作とキャプチャしたパケットを対応付けられた
コントローラーを文鎮化したエフェクト番号12
- 色変更を調べる中で、アプリがred、green、blue値に
0x1Fより大きい値を送っていないことを確認した
0x1Fは5ビット範囲である
- 8ビット値を直接送ると、より明るい色が動作した
- アプリが使う10個のエフェクト以外に追加エフェクトがあるか確認するため、
range(20)ループを回してエフェクト番号を順番に送った
- 1から10までは正常に進んだ
- 11では隠しモードのように見える動作を見つけた
- 12に進んだ瞬間、照明が消えた
- その後、照明は再び点かなくなった
- Bluetooth広告をしなくなった
- 接続もできなくなった
- 電源投入時にボタンを押し続けても復旧しなかった
- 一晩中電源を抜いておいても戻らなかった
- バッファオーバーフローでファームウェアが破損した可能性を推測したが、原因は確定していない
- LED自体は標準的なアドレス指定可能LEDなので、別のマイクロコントローラーに接続してストリングを再利用できる
残った成果物と注意点
- 失敗にもかかわらず、プロトコルの大部分を文書化し、Home Assistantカスタムコンポーネントを含むGitHubプロジェクトを作成した
- コンポーネントは動作するが、同様の方法による実験は照明コントローラーを故障させる可能性があるため、各自の責任で進める必要がある
1件のコメント
Hacker News の意見
FTA の「固定ヘッダー」というよりは、長さバイト(「コマンドは5バイト」)、コマンド
TURN、引数 0/1 があり、残りを16バイトまで 0 で埋めた形式に見える54 55 52 4Eは大文字アルファベットのTURNとしてすぐ目に入る数字は
0x30、大文字は0x41、小文字は0x61から始まることを知っていると、16進ダンプで英数字のパターンを見つけやすい短い文字列にはこうした知識が役立つが、パケットやメモリダンプを見るときは標準的な hexdump 形式がいちばんよい
0x54 55 52 4Eは実際にT U R Nだuintである可能性が高い電源供給の問題かもしれない。WS281x 系は非常に明るく点灯でき、複数をまとめるとものすごく電流を食う
100個のストリップに 12V 3A の電源なら、全体を最大輝度の白でかろうじて点けられる程度で、しかも非常にまぶしい
なので、まず切れたヒューズを見ると思う。ファームウェアが最大輝度 255 のうち 31 までしか使っていないのも手がかりになる
0x1fに制限されているのを見て、自分も最初はそう思った。運がよければ電源にヒューズがあり、ヒューズだけが飛んだのかもしれない復旧できなくても、標準的な WS281x LED ストリングは Raspberry Pi に接続できるし、自分のオープンソースのアドレス指定可能 LED コントローラーも使える :) https://github.com/mbevand/ledthemfight
内蔵エフェクトがあり、DIY 向けに非常にモジュール化して作ってあるので、Python 2行で簡単なカスタム LED エフェクトモジュールを作れる。デモはこちら: https://youtu.be/qpd2rILsnM4
12V、赤、緑、青の4本の線がある個別アドレス指定ではなく、ストリップ全体が同じ色に点くアナログ RGB ストリップのようだ
https://www.aliexpress.com/item/1005005485885067.html
LED 照明を何かいじってみたい人は、WLED をぜひ見るべき。内蔵エフェクトが多く、Web GUI があり、とても安い ESP32 や ESP8266 をコントローラーとして使い、音への反応もできる。今、室内のクリスマス照明で WLED を動かしているが、かなりいい感じだ
消費電力を制限するきれいな方法だ
良い記事。手持ちの照明をリバースエンジニアリングしようとして、暗号化されていると分かったことを思い出した
ひとつは amaran 60d、残りは SmallRig RM75 のバッテリー LED ライトが数個で、2つのアプリを別々に操作せず、1本のスクリプトですべてオン・オフしたかった
アプリとプロトコルのリバースエンジニアリングにかなり時間を費やし、どちらのライトも同じネゴシエーション手順を使っているが、別々のライブラリで実装しているように見えた
接続時に行う Diffie-Hellman 鍵交換を真似しようとしたが、結局あきらめた。記憶ではその後にさらに1〜2段階あり、最初の鍵を送ったあと、またランダムに見える数値(別の鍵?)を送るのだが、それが何を求めているのか分からなかった
この記事を見て、単にハードコードされた鍵を入れて動くか確認してみるべきだと思った
Elgato Stream Deck や Home Assistant 向けのオープンソース連携ができれば、大きな成功例になると思う。机でトーキングヘッド動画を撮る YouTube 系の人たちには、スマホアプリで照明を制御するよりずっとよいはず
BLE 接続のクリスマス照明を自動化しようとして、電子ごみを作ってしまった。あなたにもできる
iPhone はよく分からないが、Android ではバックグラウンドに置いておけば、スマホのすっきりした GUI で BLE アクティビティを捕まえられる。毎日使っている
特定の照明コマンドを受け取ると文鎮化していたキーボード MCUを思い出す
OpenRGB は最終的に、そのハードウェアでそのモジュールが自動実行されないよう無効化しなければならなかった。時にはメーカー製ソフトウェアも同じバグを引き起こしていた
残念ながら、通常はシステム内プログラミングモードに入るには USB HID レポートを送る必要があったが、影響を受けたデバイスはもはや列挙さえされなかった
実際にファームウェア破損なのか、それとも別の未定義動作によってハードウェアが壊れたのかは別問題だ
「無線で平文を送ったら安全じゃないだろう」
「心配ない、AES 暗号化を入れた」
ペアリング方式がそうなっているからだ。アプリが
255.255.255.255にパケットを無差別にブロードキャストし、対象デバイス(電球、コンセントなど)はプロミスキャスモードで待機するパケット内容は WPA2 などで保護されるが、パケット長は保護されないため、設定ハンドシェイクの次の文字の ASCII バイト値を各パケット長に設定した非常に小さなパケットを大量に送る。おそらく何度も繰り返して送るのだろう
そのためペアリングに2分かかり、カウンターが0に達する前にいつも突然止まる
去年、自宅の暖炉のBLEコントローラーをリバースエンジニアリングしていたとき、本当に心配していたのがこれだった
特に「Set password」コマンドは生のバイト入力を受け取るのに、OEMアプリは長さ制限のある数字データしか送っていなかったため
幸い、少し電源が切れると、それ以前に起きたことを全部忘れてしまうようだった
なので同じブランドのBLEコントローラーの大半は、デフォルトパスワードの
0000のまま残っているようだ。停電が一度起きれば結局その状態に戻る。本当に暇なら、BLEウォードライビングのネタとしてはかなり良さそう自分もリバースエンジニアリングの成果をHome Assistant連携にしており(https://github.com/kaechele/napoleon-efire)、システムとプロトコルのドキュメントも作成した(https://bonaparte.readthedocs.io/en/latest/index.html)
車のルーフラックに付ける柔軟で頑丈なライトを探している
バッテリー駆動で屋外・全天候向けで、バッテリーボックスを結束バンドで表面に簡単に固定できるとよい
できれば「ミニ」フォームファクターの
T5で、RGBかつプログラム可能で、クリスマスには赤/緑、ハロウィンには紫/オレンジなど季節ごとに使いたいこの条件に合う製品を知っている人がいるか気になる。最初の3条件はWalmartやHome Depotで手に入るが、最後の条件を満たすものを見つけるのが難しかった
検索してもノイズばかり出てくる
[1] https://cdn.christmaslightsetc.com/images/CategoryDetail/788...
例えば12V LEDストリップのうちIP67防水(シリコンチューブ内に入ったタイプ)は簡単に入手できるし [0]、クリスマスライトのようなストリングよりLED数がずっと多いので効果もより強いはず
ただしArduino、ESP32、ESP8266のようなマイクロコントローラーを買ってプログラムし、車のバッテリーからどう電源を取るかを自分で解決する必要がある [1]
電子部品は車内に入れて、トランクの外へは配線だけ出せば、既存のトランクシールで防水を期待できるかもしれない
[0] https://www.aliexpress.com/item/1005004289391906.html
[1] https://www.aliexpress.com/item/1005005977505151.html
延長ケーブルに再はんだ付けしたり、チェーン状につないだりするのも簡単
https://www.aliexpress.com/item/4000105913323.html
読んだ限りでは、こうした製品や似た5Vライトが屋外のクリスマスライトショーで標準のように使われているらしい
#projectsと#showcaseチャンネルを見るとよい。車両にRGB LED照明を取り付けたプロジェクトが多いただし、この方面は簡単にハマってしまうので注意
招待リンク: https://discord.gg/eVhhh2Wh
壊れたクリスマスライトを分解した様子を見られるだろうか?
中にどんなチップが入っているか分かれば、フラッシュメモリがあるか、ダンプしやすいかの手がかりになる