diff --git a/modules/arp_spoof.go b/modules/arp_spoof.go index 27d644ad..280352a4 100644 --- a/modules/arp_spoof.go +++ b/modules/arp_spoof.go @@ -1,10 +1,7 @@ package modules import ( - "fmt" "net" - "regexp" - "strings" "sync" "time" @@ -12,13 +9,8 @@ import ( "github.com/bettercap/bettercap/network" "github.com/bettercap/bettercap/packets" "github.com/bettercap/bettercap/session" - - "github.com/malfunkt/iprange" ) -// lulz this sounds like a hamburger -var macParser = regexp.MustCompile(`([a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2})`) - type ArpSpoofer struct { session.SessionModule addresses []net.IP @@ -140,47 +132,17 @@ func (p *ArpSpoofer) unSpoof() error { return nil } -func (p *ArpSpoofer) parseTargets(targets string) (err error) { - // first isolate MACs and parse them - for _, mac := range macParser.FindAllString(targets, -1) { - mac = network.NormalizeMac(mac) - log.Debug("Parsing MAC %s", mac) - hw, err := net.ParseMAC(mac) - if err != nil { - return fmt.Errorf("Error while parsing MAC '%s': %s", mac, err) - } - p.macs = append(p.macs, hw) - targets = strings.Replace(targets, mac, "", -1) - } - - targets = strings.Trim(targets, ", ") - - log.Debug("Parsing IP range %s", targets) - if len(p.macs) == 0 || targets != "" { - list, err := iprange.ParseList(targets) - if err != nil { - return fmt.Errorf("Error while parsing arp.spoof.targets variable '%s': %s.", targets, err) - } - - p.addresses = list.Expand() - } - - log.Debug(" addresses=%v", p.addresses) - log.Debug(" macs=%v", p.macs) - - return nil -} - func (p *ArpSpoofer) Configure() error { var err error var targets string if err, targets = p.StringParam("arp.spoof.targets"); err != nil { return err - } else if err = p.parseTargets(targets); err != nil { + } else if p.addresses, p.macs, err = network.ParseTargets(targets, p.Session.Lan.Aliases()); err != nil { return err } + log.Debug(" addresses=%v macs=%v", p.addresses, p.macs) if p.ban == true { log.Warning("Running in BAN mode, forwarding not enabled!") p.Session.Firewall.EnableForwarding(false) diff --git a/network/aliases.go b/network/aliases.go index 8d2cd28d..6e3dd797 100644 --- a/network/aliases.go +++ b/network/aliases.go @@ -83,3 +83,16 @@ func (a *Aliases) Set(mac, alias string) error { return a.saveUnlocked() } + +func (a *Aliases) Find(alias string) (mac string, found bool) { + a.Lock() + defer a.Unlock() + + for m, a := range a.data { + if alias == a { + return m, true + } + } + + return "", false +} diff --git a/network/lan.go b/network/lan.go index b33979f7..3199a4b6 100644 --- a/network/lan.go +++ b/network/lan.go @@ -94,6 +94,10 @@ func (lan *LAN) List() (list []*Endpoint) { return } +func (lan *LAN) Aliases() *Aliases { + return lan.aliases +} + func (lan *LAN) WasMissed(mac string) bool { if mac == lan.iface.HwAddress || mac == lan.gateway.HwAddress { return false diff --git a/network/net.go b/network/net.go index bc85ec82..fa8be2d7 100644 --- a/network/net.go +++ b/network/net.go @@ -8,6 +8,8 @@ import ( "strings" "github.com/bettercap/bettercap/core" + + "github.com/malfunkt/iprange" ) var ErrNoIfaces = errors.New("No active interfaces found.") @@ -22,8 +24,13 @@ const ( ) var ( - BroadcastHw = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} - IPv4Validator = regexp.MustCompile("^[0-9\\.]+/?\\d*$") + BroadcastHw = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + IPv4Validator = regexp.MustCompile(`^[0-9\.]+/?\d*$`) + IPv4RangeValidator = regexp.MustCompile(`^[0-9\.\-]+/?\d*$`) + MACValidator = regexp.MustCompile(`(?i)^[a-f0-9]{1,2}:[a-f0-9]{1,2}:[a-f0-9]{1,2}:[a-f0-9]{1,2}:[a-f0-9]{1,2}:[a-f0-9]{1,2}$`) + // lulz this sounds like a hamburger + macParser = regexp.MustCompile(`(?i)([a-f0-9]{1,2}:[a-f0-9]{1,2}:[a-f0-9]{1,2}:[a-f0-9]{1,2}:[a-f0-9]{1,2}:[a-f0-9]{1,2})`) + aliasParser = regexp.MustCompile(`(?i)([a-z_][a-z_0-9]+)`) ) func IsZeroMac(mac net.HardwareAddr) bool { @@ -60,6 +67,53 @@ func NormalizeMac(mac string) string { return strings.ToLower(strings.Join(parts, ":")) } +func ParseTargets(targets string, aliasMap *Aliases) (ips []net.IP, macs []net.HardwareAddr, err error) { + ips = make([]net.IP, 0) + macs = make([]net.HardwareAddr, 0) + + // first isolate MACs and parse them + for _, mac := range macParser.FindAllString(targets, -1) { + mac = NormalizeMac(mac) + hw, err := net.ParseMAC(mac) + if err != nil { + return nil, nil, fmt.Errorf("Error while parsing MAC '%s': %s", mac, err) + } + + macs = append(macs, hw) + targets = strings.Replace(targets, mac, "", -1) + } + targets = strings.Trim(targets, ", ") + + // check and resolve aliases + for _, alias := range aliasParser.FindAllString(targets, -1) { + if mac, found := aliasMap.Find(alias); found == true { + mac = NormalizeMac(mac) + hw, err := net.ParseMAC(mac) + if err != nil { + return nil, nil, fmt.Errorf("Error while parsing MAC '%s': %s", mac, err) + } + + macs = append(macs, hw) + targets = strings.Replace(targets, alias, "", -1) + } else { + return nil, nil, fmt.Errorf("Could not resolve alias %s", alias) + } + } + targets = strings.Trim(targets, ", ") + + // parse what's left + if targets != "" { + list, err := iprange.ParseList(targets) + if err != nil { + return nil, nil, fmt.Errorf("Error while parsing address list '%s': %s.", targets, err) + } + + ips = list.Expand() + } + + return +} + func buildEndpointFromInterface(iface net.Interface) (*Endpoint, error) { addrs, err := iface.Addrs() if err != nil {