├── DashSharp ├── FodyWeavers.xml ├── Models │ ├── DashListenerResponse.cs │ └── DashResponse.cs ├── packages.config ├── Exceptions │ └── PcapMissingException.cs ├── Properties │ └── AssemblyInfo.cs ├── Network │ └── DashNetwork.cs └── DashSharp.csproj ├── DashExample ├── App.config ├── Properties │ └── AssemblyInfo.cs ├── Program.cs └── DashExample.csproj ├── DashSharp.sln ├── README.md └── .gitignore /DashSharp/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /DashExample/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /DashSharp/Models/DashListenerResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DashSharp.Models 8 | { 9 | public class DashListenerResponse : EventArgs 10 | { 11 | public bool Started { get; set; } 12 | public string Message { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /DashSharp/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /DashSharp/Models/DashResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net.NetworkInformation; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DashSharp.Models 9 | { 10 | public class DashResponse : EventArgs 11 | { 12 | public string DashMac { get; set; } 13 | public int DashId { get; set; } 14 | public string Device { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /DashSharp/Exceptions/PcapMissingException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace DashSharp.Exceptions 4 | { 5 | public class PcapMissingException : Exception 6 | { 7 | public PcapMissingException() 8 | { 9 | } 10 | 11 | public PcapMissingException(string message) 12 | : base(message) 13 | { 14 | } 15 | 16 | public PcapMissingException(string format, params object[] args) 17 | : base(string.Format(format, args)) 18 | { 19 | } 20 | 21 | public PcapMissingException(string message, Exception innerException) 22 | : base(message, innerException) 23 | { 24 | } 25 | 26 | public PcapMissingException(string format, Exception innerException, params object[] args) 27 | : base(string.Format(format, args), innerException) 28 | { 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /DashSharp.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DashSharp", "DashSharp\DashSharp.csproj", "{0F2C32A0-ABB8-4734-9C34-3C059C42835F}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DashExample", "DashExample\DashExample.csproj", "{A6F544CB-B685-4897-A067-F23246D059BF}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {0F2C32A0-ABB8-4734-9C34-3C059C42835F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {0F2C32A0-ABB8-4734-9C34-3C059C42835F}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {0F2C32A0-ABB8-4734-9C34-3C059C42835F}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {0F2C32A0-ABB8-4734-9C34-3C059C42835F}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {A6F544CB-B685-4897-A067-F23246D059BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {A6F544CB-B685-4897-A067-F23246D059BF}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {A6F544CB-B685-4897-A067-F23246D059BF}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {A6F544CB-B685-4897-A067-F23246D059BF}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /DashSharp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("DashSharp")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DashSharp")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("0f2c32a0-abb8-4734-9c34-3c059c42835f")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /DashExample/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("DashExample")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DashExample")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a6f544cb-b685-4897-a067-f23246d059bf")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /DashExample/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using DashSharp; 7 | using DashSharp.Exceptions; 8 | using DashSharp.Models; 9 | 10 | namespace DashExample 11 | { 12 | class Program 13 | { 14 | 15 | private static void Main(string[] args) 16 | { 17 | Console.Title = "DashSharp - Amazon Dash Button"; 18 | Console.WriteLine("Dash Buttons have two MAC addresses, their wakeup and their pair. The last one you receive is the pair address. "); 19 | var network = new DashNetwork(); 20 | network.ListenerStarted += network_ListenerStarted; 21 | network.DashButtonProbed += network_DashProbed; 22 | try 23 | { 24 | network.StartListening(); 25 | } 26 | catch (PcapMissingException) 27 | { 28 | Console.WriteLine("No Pcap is missing, please install it."); 29 | } 30 | Console.Read(); 31 | } 32 | 33 | private static void network_DashProbed(object sender, EventArgs e) 34 | { 35 | var probe = (DashResponse)e; 36 | Console.WriteLine("Amazon Dash Connected: " + probe.DashMac + " seen on " + probe.Device); 37 | 38 | } 39 | 40 | private static void network_ListenerStarted(object sender, EventArgs e) 41 | { 42 | Console.WriteLine(((DashListenerResponse)e).Message); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DashSharp 2 | A C# Library to handle your amazon dash probing to execute custom actions. 3 | 4 | ### How does it work? 5 | 6 | When an Amazon Dash Button wakes up after being pushed, it introduces itself to the network via a small probe. By simply capturing this probe and raising some events, we can turn our dash button into our own internet of things device. 7 | 8 | ### How to set it up. 9 | 10 | Follow the setup steps provided by Amazon, once you reach step 3 (selecting an item you want the dash to purchase), exit the app and uninstall it (it will bomb you with notifications otherwise) 11 | 12 | Once the Dash Button has been connected to your wifi, any computer on your network can see it when it wakes up. By using this library you can write an application to handle it. 13 | 14 | 15 | ### Hello World 16 | 17 | Using the library is easy 18 | 19 | ```csharp 20 | private static void Main(string[] args) 21 | { 22 | Console.Title = "DashSharp - Amazon Dash Button"; 23 | var network = new DashNetwork(); 24 | network.ListenerStarted += network_ListenerStarted; 25 | network.DashButtonProbed += network_DashProbed; 26 | try 27 | { 28 | network.StartListening(); 29 | } 30 | catch (PcapMissingException) 31 | { 32 | Console.WriteLine("Pcap is missing, please install it."); 33 | } 34 | Console.Read(); 35 | } 36 | ``` 37 | 38 | ### Multiple physical addresses 39 | 40 | Dash Buttons have two physical addresses, one for when they are waking up/pressed and the other for their sync attempt/shutting down. This library monitors for them, you have to handle the logic. 41 | 42 | ### Requirements 43 | 44 | You'll neeed [WinPcap](https://www.winpcap.org/) on Windows and Pcap on Linux or OSX. 45 | 46 | ### Running code on your dash 47 | 48 | An interesting write up can be found [here](http://www.networkworld.com/article/2994131/internet-of-things/inside-the-amazon-dash-button-hack-and-how-to-make-it-useful.html) 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs) 2 | [Bb]in/ 3 | [Oo]bj/ 4 | 5 | # mstest test results 6 | TestResults 7 | 8 | ## Ignore Visual Studio temporary files, build results, and 9 | ## files generated by popular Visual Studio add-ons. 10 | 11 | # User-specific files 12 | *.suo 13 | *.user 14 | *.sln.docstates 15 | *.userprefs 16 | 17 | # Build results 18 | [Dd]ebug/ 19 | [Rr]elease/ 20 | x64/ 21 | *_i.c 22 | *_p.c 23 | *.ilk 24 | *.meta 25 | *.obj 26 | *.pch 27 | *.pdb 28 | *.pgc 29 | *.pgd 30 | *.rsp 31 | *.sbr 32 | *.tlb 33 | *.tli 34 | *.tlh 35 | *.tmp 36 | *.log 37 | *.vspscc 38 | *.vssscc 39 | .builds 40 | 41 | # Visual C++ cache files 42 | ipch/ 43 | *.aps 44 | *.ncb 45 | *.opensdf 46 | *.sdf 47 | 48 | # Visual Studio profiler 49 | *.psess 50 | *.vsp 51 | *.vspx 52 | 53 | # Guidance Automation Toolkit 54 | *.gpState 55 | 56 | # ReSharper is a .NET coding add-in 57 | _ReSharper* 58 | 59 | # NCrunch 60 | *.ncrunch* 61 | .*crunch*.local.xml 62 | 63 | # Installshield output folder 64 | [Ee]xpress 65 | 66 | # DocProject is a documentation generator add-in 67 | DocProject/buildhelp/ 68 | DocProject/Help/*.HxT 69 | DocProject/Help/*.HxC 70 | DocProject/Help/*.hhc 71 | DocProject/Help/*.hhk 72 | DocProject/Help/*.hhp 73 | DocProject/Help/Html2 74 | DocProject/Help/html 75 | 76 | # Click-Once directory 77 | publish 78 | 79 | # Publish Web Output 80 | *.Publish.xml 81 | 82 | # NuGet Packages Directory 83 | packages 84 | 85 | # Windows Azure Build Output 86 | csx 87 | *.build.csdef 88 | 89 | # Windows Store app package directory 90 | AppPackages/ 91 | 92 | # Others 93 | [Bb]in 94 | [Oo]bj 95 | sql 96 | TestResults 97 | [Tt]est[Rr]esult* 98 | *.Cache 99 | ClientBin 100 | [Ss]tyle[Cc]op.* 101 | ~$* 102 | *.dbmdl 103 | Generated_Code #added for RIA/Silverlight projects 104 | 105 | # Backup & report files from converting an old project file to a newer 106 | # Visual Studio version. Backup files are not needed, because we have git ;-) 107 | _UpgradeReport_Files/ 108 | Backup*/ 109 | UpgradeLog*.XML 110 | 111 | Installer/*setup.exe 112 | -------------------------------------------------------------------------------- /DashSharp/Network/DashNetwork.cs: -------------------------------------------------------------------------------- 1 | #region 2 | 3 | using System; 4 | using DashSharp.Exceptions; 5 | using DashSharp.Models; 6 | using PacketDotNet; 7 | using SharpPcap; 8 | 9 | #endregion 10 | 11 | namespace DashSharp 12 | { 13 | public class DashNetwork 14 | { 15 | private const int ReadTimeoutMilliseconds = 1000; 16 | public event EventHandler ListenerStarted; 17 | public event EventHandler DashButtonProbed; 18 | 19 | 20 | public void StartListening() 21 | { 22 | // Retrieve the device list 23 | try 24 | { 25 | var devices = CaptureDeviceList.Instance; 26 | if (devices.Count < 1) 27 | { 28 | throw new PcapMissingException("No interfaces found! Make sure WinPcap is installed."); 29 | } 30 | foreach (var device in devices) 31 | { 32 | if (device == null) continue; 33 | device.OnPacketArrival += delegate(object sender, CaptureEventArgs e) 34 | { 35 | var packet = Packet.ParsePacket(e.Packet.LinkLayerType, e.Packet.Data); 36 | var eth = (EthernetPacket) packet; 37 | var dashMac = eth.SourceHwAddress.ToString(); 38 | if (dashMac.Equals(device.MacAddress.ToString())) 39 | { 40 | //ignore packets from our own device 41 | return; 42 | } 43 | var dashId = dashMac.GetHashCode(); 44 | 45 | DashButtonProbed?.Invoke(this, 46 | new DashResponse 47 | { 48 | DashMac = dashMac, 49 | DashId = dashId, 50 | Device = device.MacAddress.ToString() 51 | }); 52 | }; 53 | device.Open(DeviceMode.Promiscuous, ReadTimeoutMilliseconds); 54 | // tcpdump filter to capture only ARP Packets 55 | device.Filter = "arp"; 56 | Action action = device.Capture; 57 | action.BeginInvoke(ar => action.EndInvoke(ar), null); 58 | ListenerStarted?.Invoke(this, 59 | new DashListenerResponse 60 | { 61 | Started = true, 62 | Message = $"Started listenr on {device.MacAddress}" 63 | }); 64 | } 65 | } 66 | catch (Exception) 67 | { 68 | throw new PcapMissingException("No interfaces found! Make sure WinPcap is installed."); 69 | } 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /DashExample/DashExample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {A6F544CB-B685-4897-A067-F23246D059BF} 8 | Exe 9 | Properties 10 | DashExample 11 | DashExample 12 | v4.5.2 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | ..\DashSharp\bin\Debug\DashSharp.dll 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 63 | -------------------------------------------------------------------------------- /DashSharp/DashSharp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {0F2C32A0-ABB8-4734-9C34-3C059C42835F} 8 | Library 9 | Properties 10 | DashSharp 11 | DashSharp 12 | v4.5.2 13 | 512 14 | 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | AnyCPU 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | AnyCPU 35 | 36 | 37 | 38 | ..\packages\PacketDotNet.0.13.0\lib\net\PacketDotNet.dll 39 | True 40 | 41 | 42 | ..\packages\SharpPcap.4.2.0\lib\net\SharpPcap.dll 43 | True 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | (); 86 | var attribute = config.Attribute("ExcludeAssemblies"); 87 | if (attribute != null) 88 | foreach (var item in attribute.Value.Split('|').Select(x => x.Trim()).Where(x => x != string.Empty)) 89 | excludedAssemblies.Add(item); 90 | var element = config.Element("ExcludeAssemblies"); 91 | if (element != null) 92 | foreach (var item in element.Value.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).Where(x => x != string.Empty)) 93 | excludedAssemblies.Add(item); 94 | 95 | var filesToCleanup = Files.Select(f => f.ItemSpec).Where(f => !excludedAssemblies.Contains(Path.GetFileNameWithoutExtension(f), StringComparer.InvariantCultureIgnoreCase)); 96 | 97 | foreach (var item in filesToCleanup) 98 | File.Delete(item); 99 | ]]> 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 109 | 110 | 111 | 112 | 119 | --------------------------------------------------------------------------------