自己紹介

KOBA789氏(以下、KOBA789):よろしくお願いします。2回ぐらい前に開催されたKernel/VMでは電磁リレーについて話しましたが、今回は「Bluetooth Low Energyでメガネとおしゃべりする」というテーマです。スライドが46枚あるので、超高速でいきます。

まず自己紹介です。おかげさまで無職から脱出しました。今は、人工衛星を作る仕事をしています。わりとご存じの方も多いかもしれませんが、自作DBMS勢です。さっき言ったとおり、Kernel/VMでは電磁リレーの回路CADとシミュレータを自作した話をしました。

こういう感じで、YouTuber活動が好きでやっていたり、いなかったりする人間です。

BLEをしゃべるメガネを購入

もう1回、タイトルです。メガネとBluetooth Low Energyでおしゃべりするって何やねんと。メガネってBLEしゃべれるんですかという話があると思うんですけど。

世の中には不思議なメガネがあります。これは、BLEをしゃべるメガネなんですね。hikalium先生が「Twitter」で「My new gear……」的なツイートをしていて、「これいいな」と思って、数日後、私も買いました。

これはどういうものかというと、各種センサーがメガネに埋め込まれていて、加速度センサー、ジャイロセンサーで姿勢が取れます。あと、筋電のセンサーが鼻あてに付いていて、まばたきや眼球の動きなどが取れます。

公開されているプロトコルはWebSocketだった

ですが、BLEでしゃべれると聞いていたのに、公開されているプロトコルはWebSocketでした。「あれ? BLEって聞いていたんだけど、なんでWebSocketなんだ」と買ってから気づきました。

これは事前の調査が足りなさ過ぎただけなのですが、どういうことなのかと思って調べてみたところ、(スライドを示して)こちらにメガネがあって、メガネからはBLEでiPhoneにつながります。iPhoneの専用アプリがWebSocketをしゃべって、WebSocketのクライアントになるんですよね。そして別のホストにWebSocketでデータを流します。

ここのWebSocketは公開されていて、仕様が明らかになっているので簡単に使えますが、こちら側(Bluetooth Low Energy)はなんと非公開でした。なので、真ん中のiPhoneが邪魔だなと思っても、どうしてもここに置かなきゃいけないんですね。

「iPhone1つぐらいおとなしく使えばいいんじゃないの?」「WebSocketで十分でしょ。別にBLEしゃべる必要なくない?」「WebSocketのほうが、なんだったら安定しているよ」

それはそのとおり……それはそのとおりなんだけど、でもiOSアプリを使うのはだるいし、Mac1台でなんとかなってほしいと思って買ったの。

体の姿勢をトラッキングする装置は、たいていのドライバーがWindows向けでMacで使えないから、「BLEしゃべれるんだったら、Macだけでできるじゃん」と思って買ったのに、「おいおい、iOSの端末が間に必要なのかよ」「それじゃあ結局環境ごちゃごちゃのままだよ」と悲しくなってしまった。

あとは、解析しがいがあるので、おもしろいおもちゃを手に入れたなというのが今回のモチベーションです。

「PacketLogger」を使ってパケットをキャプチャ

というわけで、解析をすることになりました。何はともあれ、こういう時はパケットをキャプチャをキャプチャしたいのですが、さっき言ったとおり、公式のアプリはiOSの上で動いています。

iOSにはみんな大好き「Wireshark」がいないんですよね。困ったなとなったのですが、よくよく調べてみると、Apple純正の開発ツールがあって、「PacketLogger」というそのままの名前のものが開発者向けに配られているんですよ。

開発用のプロファイル、特権APIが叩けるようになるのかはわかりませんが、そういう怪しげな設定をAppleのサイトから入れて、丁寧な権限昇格ダイアログみたいなものをポチポチして、インストールすると、無事にUSBケーブル経由で、iOSで通信しているBluetoothのパケットをMacで読めるようになります。キャプチャして、リモートデバッグみたいなことができるようになります。

これがすごく便利で、とりあえずこれを使えばキャプチャできます。どんな感じで見えるかというと、(スライドを示して)こういうアプリがあって、これを開くといきなりスタートしているので、Wiresharkと同じです。バーってここにパケットが流れている。いいぞいいぞと。

きちんとパケットがキャプチャできたのでそれを観察するのですが、様子がなんかおかしいんですよ。BLEといったら、GATTでKey-Valueストアみたいな感じで、1個1個のCharacteristicに値が入っているから、それを読んだらいいでしょと思っていたのですが、Characteristicが事実上1個くらいしかなくて、「なんで?」となりました。

1メッセージが20Byteなのですが、バーッとダンプしたものを眺めてみると、(スライドを示して)ここ、シーケンス番号みたいに見える。連続的に変化してそうなやつなんだけど、これ、なんか単調増加じゃないなとか。

こちら側の、メガネをぶんぶん振り回した時に変わるところが、たぶん加速度センサーなんだけど、5Byteしかない。「えっ、これ3軸だよな? 5って何?」みたいな感じになりました。

Node.jsとRustでキャプチャの取得を実装

「よし、解析の時間だ」と解析の時間がやってまいりました。やっていくぞ。まず解析の方針です。さっき見たとおり、一筋縄ではいかなそう。なんらかのXORがされていそうですが、コンピューター自体がそんなにリッチじゃないのでたぶんザコい。

私たちには、公式アプリが吐くWebSocketのデータというゴールデンマスターがある。これと突き合わせれば、きっとリバースエンジニアリングできると信じてやっていく。

まず、キャプチャするやつを作るところからです。WebSocketのほうは、Node.jsでこのくらい書いたら終わりなので、これでよし。

次はBLEですが、さっきのアプリでキャプチャができるんですよね。キャプチャはできるのですが、パケットのダンプの形式がbtsnoopという、もしかしたらその業界の人たちには馴染み深いのかもしれませんが、私は聞いたことがなかった形式でした。

中身を見てみたらバイナリだったので「うげっ」となったのですが、仕様を調べてみたところ意外とシンプルで、頭から順番に次のレコードの長さはこれだよと書いてありました。それを長さ分、パカッとバイト列を切り取って、また次のやつを読むというのを順繰りに繰り返していけば全部読めるというかたちだったので、適当にRustで実装しました。

これは、昨日の夜(※発表当時)に作業配信をやりながら実装していたのですが、すぐできました。左側がWebSocketから得られたJSON、右側はBLEから得られたCSVです。

ツールを使ってデータを可視化

これをなんとか可視化したいんですね。目力を活用して、グッと睨んで、「これはもしかして、あの値とXORされているのではないか」とやるには可視化が重要です。

可視化が重要ですが、KOBA789はなんとPythonが書けないというか、宗教上の理由でPythonを書けないんですね。「Matplotlib」とかが使えないんですよ。

なのでどうするかというと、私はSQLが大好きなのでSQLのエコシステムに乗っかることにしました。

SQLのエコシステムには、こういう可視化ツール(Bdash)があって、SQLを書いて、パラパラと表が出てきたら、それをいきなり表にしてくれるやつがあります。「こういうのでいいんだよ、こういうので」みたいな感じですよね。

まばたきのパラメーターを使って位相を合わせる

せっかくなので、これにデータを突っ込んで、グラフを描いて眺めてあげます。すると、こんな感じになります。ここで、位相は合ってるのかという疑問が出てきます。

パケットキャプチャのスタートがずれているので、たぶん位相が合っていないんですよ。なので位相を合わせるために、まばたきのパラメーターを使います。これはワンショットなので使いやすいです。

位相が合ったら、グッと睨んでいくと。すると、こういうグラフが出てきます。これを@xrekkusuという人に見せると、@xrekkusuがグッと睨んで、「これはね、126とXORしたあとにプラス1しているんだよ」みたいなことを言ってくるので、そのとおりにやります。

SQLを使って加速度のビット数を調査

次に加速度のビット数を調べる必要があります。5Byteの中に3軸を詰め込んでいるので、なんらかでしょうということで、内訳を調べています。ここでもSQLが大活躍します。

相関するところが1になるSQLを書いて総当りしていくと、「ここの列に入っとるやんけ」ということがバレます。

関係がある列を絞り込めたら、あとはブルートフォースでXORとかそういう計算をします。数学が詳しい人はきちんと連立方程式が解けるんだと思いますが、私は解けなかったのでブルートフォースです。

加速度センサーの値を手にいれました、めでたしめでたし。BLEでおしゃべりできるようになったので、BLEで通信するアプリを書きます。「BlueZ」、あるいはAppleの「Core Bluetooth」、これも普通ですが、私は「Web Bluetooth」を使いました。

デモ

Web Bluetoothは、WebブラウザーでBLEがしゃべれるというもので、デモをします。デモはきちんと成功するように作ってきたんだ。いくぞ。

ここに四角いのが出ていると思うのですが、今私の頭の角度と一緒に動いているのがわかりますか? ブラウザーの中にJSでBLEを実装して、メガネとおしゃべりしています。やったね!