はじめに
おうちハック Advent Calendar 2015の5日目の記事です。
こんにちは。CTOのkamocです。 前回の記事(ルンバがうちに、やってきた。)では最新モデルのルンバ980をハックしていく方向性について書きました。 今回はアプリとiRobot API間の通信をハックして行きます。
今回のゴール
今回は図の★の部分。アプリとiRobot API間の通信をハックして行きます。
今回の記事では、ルンバに「掃除しろ」と命令したらルンバが掃除を開始する Slack BOT を開発します。
iRobot アプリの掃除開始命令を解析し、Slack BOT から同命令を叩いてルンバに掃除させます。
通信内容を観察してみる
それでは早速 iRobot アプリと iRobot API の通信を解析してみましょう。 通信の解析には Charles というツールを使用しました。
iPhone のパケットキャプチャのやり方はこちらを参考にしました。
iPhoneのパケットキャプチャ - Qiita
Mac(本投稿ではOS X 10.9〜で説明)でのiPhoneのパケットキャプチャについて投稿します。 色々なやり方があると思いますが、自分は ・HTTPリクエストとレスポンス内容を確認する場合はCharles。 ・ネットワーク関連のエラー解析を行う場合はWireShark を使っております。 上記2つについて手順や自分が思う良いところ(個人的な見解ですが。。)などついて記載します。 HTTPプロキシとしてPC上で動作し、iPhoneからのリクエストとレスポンスをモニタリングします。 参考: http://www.charlesproxy.com/ 1.下記Webページの"Download a free trial"からCharlesをダウンロード/インストール。 http://www.charlesproxy.com/download/ 2.MacをWifiに接続。 3.Charlesのメインメニュー"Proxy"→"Proxy Settings..."を開いて下記を設定。 ・Proxies タブでPortを8888 にセット。 ・SSL タブで"Enable SSL Proxying"をチェック。 ・Locationsに*を追加。 1.設定→Wi-FiでMac側と同じWifiに接続。 2.接続したWifiの( i )ボタンをタップ。 3.下側にスクロールして、HTTPプロキシ「手動」を選択後、下記をセット。 ・サーバ:MacのIPアドレス(Mac側で設定→ネットワークで確認) ・ポート:8888 設定後、Charles上でiPhone側のHTTPパケットが見える。 4.上記HTTPプロキシ設定をした状態で、下記リンクからCharlesのSSL証明書をダウンロード&インストール。 http://charlesproxy.com/getssl ↓ 設定後、Charles上でiPhone側のHTTPSパケットが見える。 HTTPのリクエスト/レスポンス内容が確認しやすい。 HTTPSのリクエスト/レスポンス内容も確認できる(自分は特にこれが素晴らしいと思っています)。 3G,LTEなどの電話回線でのキャプチャが出来ない。Wifi でのみキャプチャ可能(HTTPプロキシなので)。 HTTP/HTTPS以外がキャプチャできない。 ネットワークエラー発生時に原因がよくわからないがある("504 Gateway timeout"発生時に"Broken Pipe"になってることがあった)。 無料版(トライアル版)はアプリ起動後30分で終了する。正式版は有料($50)。 iPhone側のネットワークデバイスを仮想インターフェイスとしてMac側にマウントしてパケットキャプチャする方法。 参考: http://qiita.com/ionis_h/items/661a9a9d41cb1574e357 http://qiita.com/isaoshimizu/items/da3e74d5a8e9b1d6b6a4 1.下記からWireSharkをダウンロード/インストール。 XQuartz(WireSharkで使用)も必要になるのでこれもダウンロード/インストール。 http://www.wireshark.org/download.html https://xquartz.macosforge.org/landing/ 2.MacにiPhoneをUSB接続。 3.ターミナルで下記コマンドを実行(iPhone側のネットワークをMACにアタッチ、キャプチャ開始)。 $rvictl -s iPhoneのudid(オーガナイザに表示されるiPhoneのidentifer) $tcpdump -i rvi0 -w [ダンプファイル名] 4.iPhoneで適当に通信を伴う操作(アプリでwebページを開くなど)をする。 5.ターミナルで下記コマンドを実行(キャプチャ終了)。 $rvictl -x iPhoneのudid(オーガナイザに表示されるiPhoneのidentifer) →これでターミナルのカレントフォルダにダンプファイルが作成される。 6.WireSharkを起動。 ※たまにWireSharkが起動しないときがありますが、Macへ再ログインすると解消する場合があります。 7.WireShark上でメインメニュー"File"→"Open..."を選択。 8.tcpdumpで作成したダンプファイルを選択。 ...
qiita.com
Charles を起動して iPhone のプロキシ設定を済ませた状態で、iRobotアプリを立ち上げるとこんな感じになります。
いろいろ通信してますね〜。 http://www.irobot.com と https://irobot.axeda.com のどちらかが iRobot API でしょう。この後詳しく見ていきます。 https://e.crashlytics.com はアプリのクラッシュレポートや利用状況を記録しているやつですね。いつもお世話になっています。 http://192.168.10.4 はルンバとの直接通信ですね。ルンバのIPアドレスは前回の記事で書いたとおり、iRobotアプリから確認することができます。
http://www.irobot.com との通信内容
Charles で通信内容覗いてみました。レスポンスのJSONの一例はこちら。
{
"termsUrl": "http:\/\/www.irobot.com\/roombaterms",
"privacyUrl": "",
"tosUrl": "",
"eulaUrl": "",
"version": "1.0"
}termsUrlの値の URL をブラウザで開いてみると、Legal Informationが表示されますね。 これは iRobot アプリの このアプリについて > 利用規約および個人情報保護方針 を選択した時に表示されるページです。
どうやらこのドメインとの通信では、アプリ内のWebView等で表示するコンテンツの情報を取得しているようですね。
https://irobot.axeda.com との通信内容
というわけで、こちらのドメインがルンバのAPIである可能性が濃厚になってきました。 通信を覗いてみましょう。
同ドメインについては以下のURLに対してのみ通信を行っています。 https://irobot.axeda.com/services/v1/rest/Scripto/execute/AspenApiRequest
一番上の通信のリクエストパラメータを見てみます。
blid=xxxxxxxxxx&robotpwd=xxxxxxxxxxx&method=getStatus
※ blid と robotpwd のパスワードは値をマスクしています。本記事では以降 blid を {{ ROOMBA_ID }}, robotpwd を {{ ROOMBA_PW }} と表記します。
どうやら、APIのURLは共通で、“method”パラメータの値で挙動を定義しているようですね。 レスポンスはこちらです。
おぉ!いろいろと取れましたねぇ。 このAPIを定期的に呼び出せば、ルンバの現在の状態を知ることができそうですね。
次に、掃除開始命令を探してみましょう。 Charles さんに接続した状態で、iRobot アプリから掃除開始命令を出します。
はい。いましたねー。
iRobot APIの紹介
解析して明らかになった iRobot API をいくつか紹介します。
API の URL はすべて以下のURL。
https://irobot.axeda.com/services/v1/rest/Scripto/execute/AspenApiRequest
掃除開始
リクエストパラメータを以下のように設定
blid: "{{ ROOMBA_ID }}"
robotpwd: "{{ ROOOMBA_PW }}"
method: "multipleFieldSet"
value: { "remoteCommand" : "start" }ステータス確認
リクエストパラメータを以下のように設定
blid: "{{ ROOMBA_ID }}"
robotpwd: "{{ ROOOMBA_PW }}"
method: "getStatus"行動履歴確認
リクエストパラメータを以下のように設定
blid: "{{ ROOMBA_ID }}"
robotpwd: "{{ ROOOMBA_PW }}"
method: "missionHistory"APIの調査が終わったところで、curlコマンドを使ってAPIを叩き、実際にルンバが動くかどうか試してみましょう。
curl コマンドを使った検証
試しに掃除開始APIを curl コマンドで叩いてみましょう。
curl https://irobot.axeda.com/services/v1/rest/Scripto/execute/AspenApiRequest -X POST -d "blid={{ROOMBA_ID}}&robotpwd={{ROOMBA_PW}}&method=multipleFieldSet&value=%7b%22remoteCommand%22%20%3a%20%22start%22%7d"
{"status":"OK","method":"multipleFieldSet"}%valueのパラメータは JSON 文字列をURLエンコードしています。
コンソールのEnterキーをターン!と叩きます。
・・・(2,3秒間があく)
ルンバ「ててーててー♪ ぴー ぴー ぴー ぴー」==◎
ルンバが走り出しました!!
ここまできたら後は Slack BOT とつなぐだけですね。
Slack bot の作成
Slack bot の作成は以下のサイトを参考にしました。
Slack で Hubot を使えるようにする - Qiita
Slack がコミュニケーションの中心になっていくなかで、Slack からできることを増やそうということで、Hubot( https://hubot.github.com/) を導入してみることにした。 Hubot を動かす環境として、お手軽な Heroku( https://www.heroku.com/) を利用する。 まず、Hubot を導入し、Slack 用の bot を作成する。Hubot の導入には npm( https://www.npmjs.org/) が必要なので、事前にインストールしておく。 続いて、bot 用のディレクトリを作成し、その中で bot を作成する。 これまでは、hubot --create を使っていたが、非推奨になっており、Yeoman( http://yeoman.io/) を使う方式に変わったようだ。そのため、generator-hubot のインストールが必要となっている。 yo hubot するとウィザードが始まるので、必要な情報を入力していく。入力した情報は、package.json に反映されるので、後から修正することも可能。 Bot adapter として slack を必ず指定すること。後から、個別にインストールする手間が省ける。 ここまでで bot の作成は完了したので、Heroku へデプロイするための準備を始める。まず git リポジトリを作成する。 続けて Heroku 上にアプリケーションを作成する。Heroku の操作のために Heroku Toolbelt(
qiita.com
Coffeeスクリプトはこんな感じです。
Slack bot のソースコード一式はGitHubにあげてあります。
{{ROOMBA_ID}} と {{ROOMBA_PW}} だけご自身のルンバの値に書き換えてください。
GitHub - kamomc/RoombaSlackBot: ルンバ980に掃除開始命令を送るSlackBOT
roomba980 is a chat bot built on the Hubot framework. It was initially generated by generator-hubot, and configured to be deployed on Heroku to get you up and running as quick as possible. This README is intended to help get you started.
github.com
社内 Slack で運用してみた
弊社 Slack にて世界中どこからでも、何時でも、kamoc宅のルンバを起動できるという状態にしてみました。
弊社社員に可愛がってもらっている様子がこちらです。
夜11:39に福島県からのリクエストで静岡県のルンバが掃除しております。
これはもう事件ですね。
セキュリティーの重要性について改めて考えさせられました。
現在1週間程運用しておりますが、深夜の掃除で目が覚めるといった自体は起きておりません。
SlackBOTをホストしているHerokuさんがスリープ状態になってしまい、呼びかけに反応しないという問題が発生するため、設定の調整が必要です。
それでは、今日はこの辺で。
ルンバかわいいよ、ルンバ。