Amazon Dash Buttons

Amazon has this amazing product called Dash. It’s a product line of WiFi buttons that connect to your wireless network and when you press the button Amazon orders the associated product for you. Ideally when you’re running low on washing detergent you would press the “Tide” Dash button and Amazon would ship you another bottle of Tide. The buttons are $5.00 on the website and you get 5 dollars off your first product so the button is essentially free. These buttons are pretty cool just the way Amazon intended them...but where’s the fun in using something the way you’re supposed to.

It quickly became apparent that these buttons could be used in home automation projects as a cheap and unique way to get user input into the system. I’m hacking my first button to be a reminder that I need to bring a new bottle of shampoo into the shower before I get in instead of after like usually happens.

The idea is that when I use the last of the shampoo I will press one of these Dash buttons that will be hanging in the shower. The button will talk to my automation system and pop up an alert on the touch panel in the bathroom. When I start my morning routine the flashing light on the touch panel will remind me to grab a fresh shampoo bottle as I step into the shower.

The hack works like this

Typically when you press the button on the Dash the device wakes up from a low power sleep mode, connects to the network, then reaches out to the Amazon servers with some kind of identifier that lets Amazon know you need to order something, and then it finally goes back to sleep. This all happens in about a one minute time span. What I’m doing here is taking advantage of the fact that the button needs to connect to the network when it wakes up. As it connects to the network it sends out an ARP probe and grabs a network address. All I need to do is setup a Raspberry Pi to sniff the network traffic for ARP packets from the specific MAC address of the Dash button. When I press the Dash button the device wakes up and sends the ARP probe; the Raspberry Pi sees the ARP probe compares it to the programming to make sure it matches the MAC address of the button I’m looking for and then sends a notification to the Crestron system which lights up a flashing light on the touch panel.

As long as you cancel the Amazon setup process when you configure the Dash button it can’t actually order anything. The button goes back to sleep and is ready to be pressed again in the future. Other people have gone so far as to block the traffic from going to Amazon with their router using custom config files. I chose not to go that far as this method works well.

Here’s how I accomplished the task

The first thing I did was setup the Dash button to work with amazon. I followed almost all of the steps. When the setup process asks you to pick a product to buy I simply backed out and exited the setup. Now the button can’t buy a product when it connects to Amazon’s servers. You may want to create a specific Amazon account to be used when doing this. I found that I did get a bunch of notification on my phone every time I pressed the button. It would tell me that I need to complete the setup of the Dash button. You can turn these notifications off in the App but I thought that I might want to actually use a Dash button for its intended purpose in the future and may want those notifications.

So I setup a new amazon account with a specific email address (using gmail’s cool “+” feature) which I can filter and delete in my inbox if needed.

Once I setup the Dash button I started to program the Pi.

The first thing to do is to start capturing ARP packets. I created two python programs. One that would display the MAC address of all ARP packets that are captured. This lets me find the MAC address of each Dash as I press the button. My second program only responds when it sees ARP packets from specific MAC addresses from the Dash buttons.

These two sites are not only the inspiration for this project but are also the write-ups I used to get packet capture installed and to get the basic script working.

https://medium.com/@edwardbenson/how-i-hacked-amazon-s-5-wifi-button-to-track-baby-data-794214b0bdd8#.i5gs59ce5

https://familab.org/2016/02/hacking-the-amazon-dash-button-to-make-a-simple-cheap-iot-place-anywhere-networked-button-3/

This gave me more information on how Scapy works. This helped helped me understand and decide where/how I was going to program my script to send the message to Crestron.

http://www.secdev.org/projects/scapy/doc/usage.html

I used this write-up to get the code for the socket connection that I used to connect to the Crestron server.

https://pymotw.com/2/socket/tcp.html

The next step was to starting my script as a service so that it will start every time the Pi boots even if I don’t log in and run the script. I found this thread and it got me going because I do it so infrequently that I forget how to do it every time. I added the link to my script at the end of /etc/rc.local

https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=46125

import socket
import sys

def sendArpData( dashbuttonID ):
    message = dashbuttonID
    server_address = ("192.168.1.140", 30005)
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # Connect the socket to the port where the server is listening
    #print >>sys.stderr, 'connecting to %s port %s' % server_address
    sock.connect(server_address)
    sock.sendall(message)
    sock.close()
    return;

from scapy.all import *
def arp_display(pkt):
  if pkt[ARP].op == 1: #who-has (request)
    if pkt[ARP].psrc == '0.0.0.0': # ARP Probe
      if pkt[ARP].hwsrc == 'a0:02:dc:42:30:86': # Gillette
        print "Gillette"
        sendArpData( "Gillette" )
      elif pkt[ARP].hwsrc == 'f0:27:2d:60:5f:98': # Dash2 - Gaterade
        sendArpData( "DashButton2" )
      elif pkt[ARP].hwsrc == 'a0:02:dc:de:13:89': # Dash3 - Gaterade
        sendArpData( "DashButton3" )
      elif pkt[ARP].hwsrc == 'a0:02:dc:99:d3:84': # Dash4 - Vitamin Water
        sendArpData( "||DashButton4||" )
      elif pkt[ARP].hwsrc == '74:75:48:0d:39:ac': # Dash5 - Vitamin Water
        sendArpData( "DashButton5" )
      else:
        #print "ARP Probe from unknown device: " + pkt[ARP].hwsrc
        return

#run sniffing function
print sniff(prn=arp_display, filter="arp", store=0, count=0)

#test actions
#sendArpData( "testdata" )
#print sniff(prn=arp_display, filter="arp", store=0, count=20)

UPDATES

The new Dash buttons may not send ARP probe. I have 8 Dash buttons. 4 of them are recognized and 4 are not. I did a search for other people having this problem and came across this post. The thread on github below has posts from 2015 and this is now 2016 when I got my 8 buttons. So clearly they’re still sending some buttons that ARP probe. I did notice the buttons that didn’t probe had a different flashing LED pattern when I set them up. I’m going to look into the serial number sequence next to see if I can figure out a pattern to which buttons work and which don’t. I’ll probably end up rewriting my program to look for the buttons in a different way.

https://github.com/hortinstein/node-dash-button/issues/26