mirror of
https://github.com/bettercap/bettercap
synced 2025-08-19 04:59:25 -07:00
new: the arp.spoof.targets variable now supports MAC addresses as well (closes #87)
This commit is contained in:
parent
bb0bb46915
commit
3926f52f2d
2 changed files with 96 additions and 17 deletions
|
@ -3,19 +3,26 @@ package modules
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bettercap/bettercap/log"
|
"github.com/bettercap/bettercap/log"
|
||||||
|
"github.com/bettercap/bettercap/network"
|
||||||
"github.com/bettercap/bettercap/packets"
|
"github.com/bettercap/bettercap/packets"
|
||||||
"github.com/bettercap/bettercap/session"
|
"github.com/bettercap/bettercap/session"
|
||||||
|
|
||||||
"github.com/malfunkt/iprange"
|
"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 {
|
type ArpSpoofer struct {
|
||||||
session.SessionModule
|
session.SessionModule
|
||||||
done chan bool
|
done chan bool
|
||||||
addresses []net.IP
|
addresses []net.IP
|
||||||
|
macs []net.HardwareAddr
|
||||||
ban bool
|
ban bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +31,7 @@ func NewArpSpoofer(s *session.Session) *ArpSpoofer {
|
||||||
SessionModule: session.NewSessionModule("arp.spoof", s),
|
SessionModule: session.NewSessionModule("arp.spoof", s),
|
||||||
done: make(chan bool),
|
done: make(chan bool),
|
||||||
addresses: make([]net.IP, 0),
|
addresses: make([]net.IP, 0),
|
||||||
|
macs: make([]net.HardwareAddr, 0),
|
||||||
ban: false,
|
ban: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,10 +72,10 @@ func (p ArpSpoofer) Author() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ArpSpoofer) sendArp(saddr net.IP, smac net.HardwareAddr, check_running bool, probe bool) {
|
func (p *ArpSpoofer) sendArp(saddr net.IP, smac net.HardwareAddr, check_running bool, probe bool) {
|
||||||
|
targets := make(map[string]net.HardwareAddr, 0)
|
||||||
|
|
||||||
for _, ip := range p.addresses {
|
for _, ip := range p.addresses {
|
||||||
if check_running && p.Running() == false {
|
if p.Session.Skip(ip) == true {
|
||||||
return
|
|
||||||
} else if p.Session.Skip(ip) == true {
|
|
||||||
log.Debug("Skipping address %s from ARP spoofing.", ip)
|
log.Debug("Skipping address %s from ARP spoofing.", ip)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -79,10 +87,33 @@ func (p *ArpSpoofer) sendArp(saddr net.IP, smac net.HardwareAddr, check_running
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if err, pkt := packets.NewARPReply(saddr, smac, ip, hw); err != nil {
|
targets[ip.String()] = hw
|
||||||
log.Error("Error while creating ARP spoof packet for %s: %s", ip.String(), err)
|
}
|
||||||
|
|
||||||
|
for _, hw := range p.macs {
|
||||||
|
ip, err := network.ArpInverseLookup(p.Session.Interface.Name(), hw.String(), false)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Error while looking up ip address for %s: %s", hw.String(), err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Session.Skip(net.ParseIP(ip)) == true {
|
||||||
|
log.Debug("Skipping address %s from ARP spoofing.", ip)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
targets[ip] = hw
|
||||||
|
}
|
||||||
|
|
||||||
|
for ip, mac := range targets {
|
||||||
|
if check_running && p.Running() == false {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err, pkt := packets.NewARPReply(saddr, smac, net.ParseIP(ip), mac); err != nil {
|
||||||
|
log.Error("Error while creating ARP spoof packet for %s: %s", ip, err)
|
||||||
} else {
|
} else {
|
||||||
log.Debug("Sending %d bytes of ARP packet to %s:%s.", len(pkt), ip.String(), hw.String())
|
log.Debug("Sending %d bytes of ARP packet to %s:%s.", len(pkt), ip, mac.String())
|
||||||
p.Session.Queue.Send(pkt)
|
p.Session.Queue.Send(pkt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,27 +123,53 @@ func (p *ArpSpoofer) unSpoof() error {
|
||||||
from := p.Session.Gateway.IP
|
from := p.Session.Gateway.IP
|
||||||
from_hw := p.Session.Gateway.HW
|
from_hw := p.Session.Gateway.HW
|
||||||
|
|
||||||
log.Info("Restoring ARP cache of %d targets.", len(p.addresses))
|
log.Info("Restoring ARP cache of %d targets.", len(p.addresses)+len(p.macs))
|
||||||
|
|
||||||
p.sendArp(from, from_hw, false, false)
|
p.sendArp(from, from_hw, false, false)
|
||||||
|
|
||||||
return nil
|
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.TrimLeft(targets, ", ")
|
||||||
|
targets = strings.TrimRight(targets, ", ")
|
||||||
|
|
||||||
|
log.Debug("Parsing IP range %s", targets)
|
||||||
|
list, err := iprange.Parse(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 {
|
func (p *ArpSpoofer) Configure() error {
|
||||||
var err error
|
var err error
|
||||||
var targets string
|
var targets string
|
||||||
|
|
||||||
if err, targets = p.StringParam("arp.spoof.targets"); err != nil {
|
if err, targets = p.StringParam("arp.spoof.targets"); err != nil {
|
||||||
return err
|
return err
|
||||||
|
} else if err = p.parseTargets(targets); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
list, err := iprange.Parse(targets)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error while parsing arp.spoof.targets variable '%s': %s.", targets, err)
|
|
||||||
}
|
|
||||||
p.addresses = list.Expand()
|
|
||||||
|
|
||||||
if p.ban == true {
|
if p.ban == true {
|
||||||
log.Warning("Running in BAN mode, forwarding not enabled!")
|
log.Warning("Running in BAN mode, forwarding not enabled!")
|
||||||
p.Session.Firewall.EnableForwarding(false)
|
p.Session.Firewall.EnableForwarding(false)
|
||||||
|
@ -133,7 +190,7 @@ func (p *ArpSpoofer) Start() error {
|
||||||
from := p.Session.Gateway.IP
|
from := p.Session.Gateway.IP
|
||||||
from_hw := p.Session.Interface.HW
|
from_hw := p.Session.Interface.HW
|
||||||
|
|
||||||
log.Info("ARP spoofer started, probing %d targets.", len(p.addresses))
|
log.Info("ARP spoofer started, probing %d targets.", len(p.addresses)+len(p.macs))
|
||||||
|
|
||||||
for p.Running() {
|
for p.Running() {
|
||||||
p.sendArp(from, from_hw, true, false)
|
p.sendArp(from, from_hw, true, false)
|
||||||
|
|
|
@ -12,7 +12,7 @@ type ArpTable map[string]string
|
||||||
|
|
||||||
var (
|
var (
|
||||||
arpWasParsed = false
|
arpWasParsed = false
|
||||||
arpLock = &sync.Mutex{}
|
arpLock = &sync.RWMutex{}
|
||||||
arpTable = make(ArpTable)
|
arpTable = make(ArpTable)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -64,6 +64,9 @@ func ArpLookup(iface string, address string, refresh bool) (string, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arpLock.RLock()
|
||||||
|
defer arpLock.RUnlock()
|
||||||
|
|
||||||
// Lookup the hardware address of this ip.
|
// Lookup the hardware address of this ip.
|
||||||
if mac, found := arpTable[address]; found == true {
|
if mac, found := arpTable[address]; found == true {
|
||||||
return mac, nil
|
return mac, nil
|
||||||
|
@ -72,8 +75,27 @@ func ArpLookup(iface string, address string, refresh bool) (string, error) {
|
||||||
return "", fmt.Errorf("Could not find mac for %s", address)
|
return "", fmt.Errorf("Could not find mac for %s", address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ArpInverseLookup(iface string, mac string, refresh bool) (string, error) {
|
||||||
|
if ArpParsed() == false || refresh == true {
|
||||||
|
if _, err := ArpUpdate(iface); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arpLock.RLock()
|
||||||
|
defer arpLock.RUnlock()
|
||||||
|
|
||||||
|
for ip, hw := range arpTable {
|
||||||
|
if hw == mac {
|
||||||
|
return ip, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("Could not find IP for %s", mac)
|
||||||
|
}
|
||||||
|
|
||||||
func ArpParsed() bool {
|
func ArpParsed() bool {
|
||||||
arpLock.Lock()
|
arpLock.RLock()
|
||||||
defer arpLock.Unlock()
|
defer arpLock.RUnlock()
|
||||||
return arpWasParsed
|
return arpWasParsed
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue