Amazon Dash Buttonの仕組みとハック

# Amazon Dash Buttonとは
Amazon Dash Buttonはボタンをポチッと押すだけであらかじめ設定しておいた商品を自動注文してくれるIoTデバイスです。
初期セットアップはスマホからアプリで簡単に行うことができます。
一度注文したらその商品が届くまでボタンを何度押しても無効となり、重複注文を防ぎます。
![スクリーンショット 2016-12-15 9.50.19.png](https://qiita-image-store.s3.amazonaws.com/0/105205/6c42b43b-8dda-0450-008d-6892a807c86d.png)

# Amazon Dash Buttonの仕組み
## 初期設定方法
１．Bluetoothでスマホと接続する
まずAmazon Dash ButtonをBluetooth経由でスマホと接続するための設定を行います。

<img width="375" alt="IMG_8682.png" src="https://qiita-image-store.s3.amazonaws.com/0/105205/b804881b-58c4-6871-d1aa-903dcd671528.png">
アプリがアップデートされてアカウントサービスの中にDash端末という項目ができているので
「新しい端末をセットアップ」を押します。
規約が表示されるので確認して次に進みます。

<img width="375" alt="IMG_8683.png" src="https://qiita-image-store.s3.amazonaws.com/0/105205/94b6e4ad-f239-377f-719b-ad447e6f06bb.png">
ボタンを6秒長押しすることでBluetoothと同期します。

２．Wi-Fiに接続する
<img width="375" alt="IMG_8684.png" src="https://qiita-image-store.s3.amazonaws.com/0/105205/ba04461e-8919-da2e-ed1e-59b81a654d15.png">
同期した後はAmazon Dash ButtonがキャッチできるWi-FiのSSID一覧が表示されるので接続したいSSIDを選択してパスワードを入力すればOKです。

３．注文する商品を選択する
<img width="375" alt="IMG_8685.png" src="https://qiita-image-store.s3.amazonaws.com/0/105205/f5362f94-3d59-f843-bffe-2c7abe361764.png">
最後に商品を選択して終了です。

## 「通常の」仕組み
初期設定が終わればボタンを押すだけで自動注文されるようになります。
ボタンが押されて商品が注文される仕組みについて説明します。
（他の記事を参考にしてたり自分の憶測が入っているのであまり信じないでください。）

Amazon Dash Buttonは常時電源オフとなっているはずです。
そうでないと電池がもちません。
なのでボタンが押されるとまず最初に電源がONになりそうです。
次に、あらかじめ設定しておいたWi-Fiに接続し、IPを付与してもらいます。
そのため**DHCPでIPを取得するために頑張ります**。
（Amazon Dash Buttonを利用するのにDHCPが利用できる環境は必須のようです。）
そしたらようやくインターネットに接続できるのでAmazonのサーバに商品注文リクエストを送ります。
コレが一連の動作です。
まとめると、
1. 電源ON
2. 設定しておいたWi-Fiに接続
3. DHCPでIP取得
4. 商品注文リクエスト

## 「ハックな事をする」仕組み
ボタンが押されるとピザを取ったりタクシー呼んだり車庫のシャッター開けたりするハックをしている人達が既にいますが、
決してAmazon Dash Buttonのケースをこじ開けて基盤を取り出してプログラム焼き込んで…なんてことはしていません。
これは上に記した通常の仕組みをそのまま残しつつ実現しています。

どのようにハックしているか。通常の動作の中で、
Amazon Dash Buttonが「DHCPでIPを付与してもらうために頑張る」というところがキーです。
DHCPでIPを取得する時はどのように動作するのか、調べてみましょう。
http://itpro.nikkeibp.co.jp/members/NNW/NETPOINT/20041116/152622/?rt=nocnt
DHCPでIPを取得するなかで、割り当てられたIPが他のマシンと重複してないかを確認するときにARP要求をブロードキャストします。

Amazon Dash Buttonをハックしている殆どの人は、この仕組を使っています。
Amazon Dash ButtonのMACアドレスからARP要求が飛んでくる事を監視するサーバをネットワーク内に置いておけば、
ボタンを押されたタイミングでそのサーバから何かしらのアクションを起こすことができます。
ただ問題なのは、Amazon Dash Buttonからするとネットワーク内にARP要求を監視しているサーバが存在しようが
関係ないので、ボタンが押されると通常通り商品注文リクエストを送ってしまいます。

そのためAmazon Dash Buttonをハックするときは必ずアプリの設定時に「ボタンが押されると届く商品の設定」を
途中で辞めなければいけません。
もし設定が入っているとピザを注文する度に歯磨き粉も届いてしまいます。

# 今回作ったもの

## IFTTT連携してSlack投稿
ボタンを押すとSlackに投稿されるようにしました。

### IFTTT連携
IFTTTとAmazon Dash Buttonを連携させるためにまずレシピを作ります。
![スクリーンショット 2016-12-15 2.06.51.png](https://qiita-image-store.s3.amazonaws.com/0/105205/e80f2f54-87de-ecc4-2ca1-a0f2e9cc81ff.png)
今回はMaker Eventを使いました。
Maker Eventは特定のURLに対してGETまたはPUSHリクエストを送るとトリガーが発動します。
今回はアクションにはSlackに文字を送るだけにしました。

### サーバ側実装
nodejsを使って同一ネットワーク内からの特定のMACアドレスのARPプローブを検知するとListenerが発火して色々できるnpmモジュールを使いました。
https://www.npmjs.com/package/dash-button

実装はこんな感じ

```
var DashButton = require("dash-button");
var request = require('request');

const PHY_ADDR = "XX:XX:XX:XX:XX:XX";
var button = new DashButton(PHY_ADDR);

var options = {
    url: 'https://maker.ifttt.com/trigger/{event}/with/key/{secret_key}',
    method: 'GET',
}
button.addListener(() => {
    request(options, function (error, response, body) {
        console.log("complete");
    })
});
```
これをPC上で実行しておきます。

ボタンを押すと
![スクリーンショット 2016-12-15 2.17.11.png](https://qiita-image-store.s3.amazonaws.com/0/105205/dfac6793-0778-28ae-5112-a1a4cb6606e8.png)
投稿されました！

## Mac大合唱

ちょっと趣向を変えて、ボタンを押すとARPがブロードキャストされるという性質を使ってなにか面白いことができないかと考えました。あまり面白くないですが…
同一ネットワークに繋がったMacがtcpdumpでAmazon Dash ButtonのMACアドレスを監視してARPがブロードキャストされたらsayコマンドで同時に喋らせるというやつです。

```
#!/bin/bash
tcpdump -i en0 -e | while read line
do
    if [[ $line = *XX:XX:XX:XX:XX:XX*ethertype\ ARP* ]]; then
        echo "button pressed"
        say "ボタンが押されました"
    fi
done
```

# まとめ
Amazon Dash Button自体に改造を施すというわけでもなく、非常にクリーンにハックできる仕組みになっているのがいい感じですね。
が、やはりAmazon側の意図した使われ方ではないはずなのでこのハックは個人の利用範囲に留めましょう。