Thursday, 23 February 2017
Amazon Dash Button Hacking
If you are in the US or UK (Amazon hates Canada) and you have an Amazon Prime account you can buy these Dash buttons for $5 each (I've heard they go on sale for even cheaper too) and if you buy one that has a product you actually want they will credit your account $5 on your first order.
If you know someone in the USA or have a reshipping address you should be able to get one anywhere in the world though.
First thing to know is there are two generations of this button...
The old generation had no site survey and the internal web server would allow you to setup the button via a laptop or phone, the new button requires the Amazon Shopping App until someone figures out the setup process. I believe they also changed some SSL stuff.
If you want to see the tear-downs and detailed write ups on these buttons visit Matthew Petroff's sites below.
I will be talking about the second revision as this is the one I have.
By holding the button down for 6 seconds it will go into setup mode... It will broadcast a WiFi network "Amazon ConfigureMe" and it will also be discoverable via Bluetooth.
If you connect to the WiFi it will give you an IP in the 192.168.0.1/24 subnet and the button will be 192.168.0.1. You can go to it's webpage to view model, firmware and battery status.
There is not currently a manual setup procedure.
It uses a single AAA battery but the case is sealed so you will need to cut it open to change the battery.
To setup the WiFi network:
1) Download and install the Amazon Shopping App.
2) Select the menu and select "Settings" with your countries Flag
3) Select Country & Language
4) Set your country to United States or United Kingdom (supported areas)
5) Hit Done
6) Hit the menu button and select "My Account"
7) Scroll down (it's a couple screens down) You should see Dash Devices
8) Choose Setup New Device
9) Follow instructions to enter your WiFi settings
10) When it gets to the point where it says select your product you can exit out of the process so your button won't order anything
At this point your Dash should have got an address from DHCP so check your leases, you can then decide if you want it online or not... If you don't block it at the router* If it has internet access it may get firmware updates and other nasty things from Amazon so there may be good reason not to let it online.
* If you have a higher end router that lets you do DNAT, you should DNAT the device to a HTTPS server somewhere on the internet, it will realize the cert doesn't match and go back to sleep within seconds... If it's packets are just dropped or it's sent to a closed port it will spend about 20 seconds trying to make DNS, DHCP and HTTPS requests before giving up killing the battery faster.
The unit stays in a deep sleep until the button is pushed... It takes about 3 seconds between the time you push the button for the device to wake up, connect to WiFi and send several (for some reason) DHCP requests. This device would not be ideal for realtime requests (like a light switch) where you expect instant gratification.
Here are the approximate times for press detection based on the detection method:
DNAT to a remote web server: ~10 seconds
ARP for gateway: ~8 seconds
DHCP broadcast: ~3 seconds
Keep in mind none of these methods care what the button has to say, it just detects the fact that it's coming online, it really only does one thing anway so there's no need to get into the nitty gritty of it's protocol... Either it's there (been pushed within the last few seconds) or it's not.
DNAT can be setup on a high end router based on the MAC or IP address of the device in question. You then just need a script that can accept a connection on a port and then do whatever action you want when that button is pressed. This is the slowest and would require a different port/server for each button you own.
ARP has been used by a lot of button hackers online... There is a simple scapy script that will detect the buttons ARP request. You get the MAC of the button in this request so you only need the one script which can uniquely identify each button and run commands based on that. This is pretty quick but not the fastest way as the button sends 3-4 DHCP requests before looking for the gateway.
DHCP sniffing is the fastest way you can trigger an event off the button. I have written a simple python script that takes stdin from tcpdump and looks for the MAC of the buttons and then runs a command when it sees the first one. The request is noted within 3 seconds of hitting the button... This is as fast as you will be able to get with this tech as it takes a while to wake up and connect to WiFi.
All these methods will generate mutliple requests per press so you should ignore anything but the first press within about 5-10 seconds. This will stop it from sending multiple commands.
I have this simple script running on my Rasberry Pi:
# Watches DHCP requests via TCPdump and looks for Amazon buttons
# Will call automation server via HTTPs to call actions.
# Run with the following command:
# nohup tcpdump port 67 or port 68 -e -n -l | python button.py &
# nohup keeps it running after you log out
# port 67 or 68 is to filter for DHCP traffic
# -e Prints the link-level header on each dump line
# -n Doesn't attempt to resolve DNS names
# -l Make stdout line buffered for piping it to this script
# python button.py ME!
# & Run in the background
# Allows button to be pressed right after script starts
timeout = time.time()-15
# Downside is using the same timeout for all buttons is that only 1 press of any button can happen in a 10 second period.
# You can add a timeout for each button if you feel the need.
# Read data from tcpdump via stdin
name = sys.stdin.readline()
# One block for each button. Change the ac:63 mac to your buttons MAC
# ff:ff:ff etc is broadcast, leave this part alone.
if name.find('ac:63:be:xx:xx:xx > ff:ff:ff:ff:ff:ff') != -1:
# Button 1
# Enforce minimum 10 second delay between pushes so this doesn't activate more than once
if time.time() > timeout+10:
# In my case make a web request to my automation server
req = urllibequest('https://www.myserver.com/buttons/button1.py')
response = urllib2.urlopen(req)
# Update the last pressed time
timeout = time.time()
Put the above script in a file called button.py, update the MAC address to match your button (and copy the if block multiple times if you want more than 1 button) and finally alter the web request to either your server, or you can have the script run your code directly for quicker response.
Then start it up with the following command:
nohup tcpdump port 67 or port 68 -e -n -l | python button.py &
It's either going to have to run as root or you will need to give a non-root user access to tcpdump. Since the script is so simple I don't think there's really any possibility to exploit it as it stands. If anyone sees a problem please let me know in the comments.
The sticky stuff on the back is basically useless. Mine fell off the wall after 15 minutes. I used some mounting tape to hold it up. It also comes with a removable hook you can hang it from.
If you want to spend a LOT more money there are other buttons out there that will probably preform much better. I am also looking at getting a CHIP (like the Pi Zero but with WiFi) and wiring in a bunch of buttons to that for a future project...
It seems most of the hacker community has moved on from these things, so getting any more info on writing new firmware, or adding new features or setting up without the app is unlikely to come.
- Cheap and maybe even free (if you live in the USA or UK and already have Prime)
- Easy to setup via the Amazon App
- MINIMUM of 3 seconds between push and detection so not great for real time applications
- Single use, you can't detect multiple presses within a wake cycle long presses or anything else
- You will have to wreck it to change the battery, it's sealed shut. However It does take a regular AAA if you get in.
- Battery may die quickly if you press it a couple times a day...
- Can also order you cat food while turning your lights on and off :P
- Sticky stuff on the back is useless