ポケモンGO PLUSのプレビュー(リバースエンジニアリングによる調査)

ポケモンGoアプリケーションを調査しているときに、ポケモンGO PLUSというデバイスが今後リリースされる情報を偶然見つけました。ポケモンGO PLUSは、基本的に、ポケモンのIoT (モノのインターネット)です。リストバンドで装着するデバイスで、たとえば、モンスターボールを投げてポケモンを捕まえるためのボタンや、RGBでLEDを点灯させたり、近くにポケモンがいることを通知したりするバイブレーション機能が実装されています。

このデバイスはまだリリースされておらず、ソフトウェアも現在開発中であり、以下のようにバージョン0.29.xは「BETA4」になっています。

バージョン0.31.0の内容は大きく異なっており、ネイティブライブラリのlibpgpplugin.soでは多くのコードが変更されています。これは、PGP / GPGプラグインではありません。PGPは、Pokémon Go Plus(ポケモンGO PLUS)の略でしょう。

BLE(Bluetooth Low Energy)デバイス

まず、このデバイスは低消費電力通信向けBLT(Bluetooth Low Energy)で通信することがすぐにわかります(ワイヤレス活動量計のFitbit Flexやハイテク歯ブラシBeamなどの多くのIoTデバイスでBLTが使用されています)。

現在、4つのBLEサービスが計画されています。

  • ファームウェアアップデートサービス。このサービスは使用も実装もされていません。
  • デバイスコントロールサービス。現在のファームウェアバージョンを読み取り、ボタン押下を通知し、LEDとバイブレーションを通知します。LEDとバイブレーションは、同じパターン特性で操作されます。その仕組みを以下で詳しく見ていきましょう。
  • いわゆる「証明書」サービス(ただし、これは実際には認証サービスとして表示されます)。このサービスは完全に実装されていませんが、逆アセンブルした結果、認証では使い捨てのランダム値が呼び出され、AES-CTRモードで暗号化されているようです。今後のバージョンで、この認証について確認します。
  • バッテリーサービス。これは標準的なBLEサービスであり、標準的な値が使用されています。デバイスのバッテリー残量を確認できます。

アーキテクチャ

基本的に、バージョン0.31.0では、クライアントサービスはcom.nianticlabs.pokemongoplus.service.ToClientの命令を受け取ります。この命令の「extra」アクション(例、「batteryLevel」、「encounterId」、「pokestop」)によって、ClientBridgeクラスから適切なメソッドが呼び出されます。この場合は、それぞれ、sendBatteryLevel()、sendEncounterId()、およびsendPokestopId()が呼び出されます。これらのメソッドは、次に、libpgpplugin.soに実装されているネイティブ関数を呼び出します。

つまり、重要な操作の多くは、このネイティブライブラリで行われます。以下には、public native void sendEncounterId(long arg1)に相当するJNIスタブがあります。

このコードは、「J」というタイプのネイティブハンドルを取得します。Jは、JNIで「long」を意味します。残念ながら、ここまでの私の調査では、このデバイスとの通信はまだ実装されていないようです。

このため、ポケモンGO PLUSの動作の仕組みに関するヒントを得るためには、前のバージョン(v0.29.x)を確認する必要があります。

パターンのリバースエンジニアリング

実際、バージョン0.29.xでは、ポケモンGO PLUSデバイスに送信するいくつかのテストメッセージが表示されます。たとえば、デバイスを赤で点滅させるために送信するバイト値があり、ポケモンを捕まえたときのデバイス操作を指定するバイト値があります。

これらのパターンの形式は以下のようにコーディングされています。

次のヘッダーが存在します。

  • byte 1には、50分の1ミリ秒の遅延が含まれます。
  • byte 2と3は0であり、予約されている値でしょう。
  • byte 4には、メッセージの優先度(ビット5から7)が含まれており、次にビット0から5の3バイトの数のパターンが続きます。

次に、この3バイトのパターンは次のようになります。

  • byte 1: 50分の1ミリ秒の遅延。
  • byte 2: ビット7-4は、LEDの緑色に対応し、ビット0-3は赤色に対応します。
  • byte 3: 「インターポレーション」が有効な場合、ビット4から6がバイブレーションレベルを示すことを、ビット7は意味します。最後に、ビット0から3は、青色のLEDに対応します。

では、getBlinkRed()というパターンを見ていきましょう。

  • ヘッダーは、「0 0 0 13」です。これは、遅延や優先度が設定されておらず、13個の3バイトのパターンがその後に続くことを意味します。
  • 最初のパターンは、「1, 15, 112」です。これは、短い遅延(1)があることを意味します。15は、バイナリでは00001111となり、緑でなく赤になります。112は0x70 = 01110000bであり、青色ではなく、インターポレーションがなく、バイブレーションが有効であることを示しています。つまり、基本的にこのLEDは点滅し、バイブレーションします。
  • 次のパターンは、「1, 0, 0」です。短い遅延があり、緑、青、または赤ではなく、バイブレーションもありません。つまり、LEDとバイブレーションがオフになっています。

その他のパターンは、赤色の点滅とバイブレーション、そして停止するプロセスを繰り返します。これは、デバイスを赤色に点滅させる効果があります。

では、getCaptureSucceededの動作を見ていきましょう。今度は手短に説明しますが、ビットごとに確認していきましょう。

ヘッダーは、24個の3バイトパターンがあることを示しています。実際には、4つのパターンが6回繰り返されています。

  • パターン1:「3, 8, 240」。短い遅延(3)、緑なし、幾分かの赤、青なし、インターポレーションとバイブレーション。
  • パターン2:「3, 240, 240」。 短い遅延(3)、緑全開、赤と青なし、インターポレーションとバイブレーション。
  • パターン3:「2, 0, 255」。 短い遅延(2)、緑と赤なし、青全開、インターポレーション、バイブレーション。
  • パターン4:「1, 0, 143」。 短い遅延(1)、緑と赤なし、青全開、インターポレーション、バイブレーションなし。

これは、燃えるような赤色が表示され、次に緑から青に点灯し、バイブレーションが作動することになるのでしょう。

「decode」(getDowserProximity1()、getPokemonCaught()、getReachedPokestop()、getSpawnedPokemon()...)にはその他にもいくつかのパターンがあります。また、getMorseGame1()のような面白い関数もあります。私のPythonスクリプトを使用してデコードできます

このリバースエンジニアリングの結果は、実際のポケモンGO PLUSデバイスがリリースされた後に、実際に再確認する必要があります。リリースされるまでの間に、仕様が変更される可能性があるためです。

結論

朗報ですが、Dalvikクラスや調査したネイティブライブラリに悪意のあるコードは見つかりませんでした。

次に、これらの情報が簡単に入手できることから、ハッカーはポケモンGO PLUSデバイスを自分で作成できることが考えられます。実際、マイコンボードArduinoを使用したそのような動きがすでに確認されています

また、これらのデバイスを別の目的で利用できるようにすることも可能です。たとえば、期待されるようにデバイスが使い捨てのランダムな値を生成する場合、ハードウェア乱数生成器として使用できます。Fitbit Flexでこれを実行したことがあります。また、自分でパターンをコーディングすることもできます。

最後になりますが、実装されるペアリングの仕組みがどれだけ優れているかにもよりますが、攻撃者や嫉妬深い競合他社が、ダミーパターンを送信してバイブレーションを繰り返してデバイスのバッテリーを消費させたり、ポケモンが近くにいることを伝える偽のアラームを送信したりすることができる場合があります。このようなパターンの改ざんは、ポケモンGO PLUSがなくても実際に行われていますので、ポケモンGOを楽しむときには十分に注意してください。

ポケモンGOに関するヒントをいただいたRaphael Le Brasに感謝の意を示します。

-- Crypto Girl

ポケモンGOアプリケーションに関する脅威分析レポートについては、ここをクリックしてください。