Skip to content

Instantly share code, notes, and snippets.

@mikeflynn
Last active October 5, 2015 06:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikeflynn/74c582aa05802eb01966 to your computer and use it in GitHub Desktop.
Save mikeflynn/74c582aa05802eb01966 to your computer and use it in GitHub Desktop.
The network sniffing functionality for the Amazon Dash Button hack.
func SnifferStart() {
// Get a list of all interfaces.
ifaces, err := net.Interfaces()
if err != nil {
panic(err)
}
var wg sync.WaitGroup
for _, iface := range ifaces {
wg.Add(1)
// Start up a scan on each interface.
go func(iface net.Interface) {
defer wg.Done()
if err := scan(&iface); err != nil {
log.Printf("interface %v: %v", iface.Name, err)
}
}(iface)
}
wg.Wait()
}
func scan(iface *net.Interface) error {
// We just look for IPv4 addresses, so try to find if the interface has one.
var addr *net.IPNet
if addrs, err := iface.Addrs(); err != nil {
return err
} else {
for _, a := range addrs {
if ipnet, ok := a.(*net.IPNet); ok {
if ip4 := ipnet.IP.To4(); ip4 != nil {
addr = &net.IPNet{
IP: ip4,
Mask: ipnet.Mask[len(ipnet.Mask)-4:],
}
break
}
}
}
}
// Sanity-check that the interface has a good address.
if addr == nil {
return fmt.Errorf("no good IP network found")
} else if addr.IP[0] == 127 {
return fmt.Errorf("skipping localhost")
} else if addr.Mask[0] != 0xff || addr.Mask[1] != 0xff {
return fmt.Errorf("mask means network is too large")
}
log.Printf("Using network range %v for interface %v", addr, iface.Name)
// Open up a pcap handle for packet reads/writes.
handle, err := pcap.OpenLive(iface.Name, 65536, true, pcap.BlockForever)
if err != nil {
return err
}
defer handle.Close()
stop := make(chan struct{})
readARP(handle, iface, stop)
defer close(stop)
return err
}
func readARP(handle *pcap.Handle, iface *net.Interface, stop chan struct{}) {
src := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet)
in := src.Packets()
for {
var packet gopacket.Packet
select {
case <-stop:
return
case packet = <-in:
arpLayer := packet.Layer(layers.LayerTypeARP)
if arpLayer == nil {
continue
}
arp := arpLayer.(*layers.ARP)
if !net.IP(arp.SourceProtAddress).Equal(net.ParseIP("0.0.0.0")) {
continue
}
found := false
for mac, fn := range DashMacs {
if net.HardwareAddr(arp.SourceHwAddress).String() == mac {
log.Printf("Click sniffed for %v", mac)
fn()
found = true
}
}
if !found {
log.Printf("FOUND UNKNOWN MAC: %v", net.HardwareAddr(arp.SourceHwAddress))
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment