bettercap/modules/net_probe/net_probe.go

167 lines
3.7 KiB
Go

package net_probe
import (
"sync"
"time"
"github.com/bettercap/bettercap/v2/network"
"github.com/bettercap/bettercap/v2/session"
"github.com/malfunkt/iprange"
)
type Probes struct {
NBNS bool
MDNS bool
UPNP bool
WSD bool
}
type Prober struct {
session.SessionModule
throttle int
probes Probes
waitGroup *sync.WaitGroup
}
func NewProber(s *session.Session) *Prober {
mod := &Prober{
SessionModule: session.NewSessionModule("net.probe", s),
waitGroup: &sync.WaitGroup{},
}
mod.SessionModule.Requires("net.recon")
mod.AddParam(session.NewBoolParameter("net.probe.nbns",
"true",
"Enable NetBIOS name service discovery probes."))
mod.AddParam(session.NewBoolParameter("net.probe.mdns",
"true",
"Enable mDNS discovery probes."))
mod.AddParam(session.NewBoolParameter("net.probe.upnp",
"true",
"Enable UPNP discovery probes."))
mod.AddParam(session.NewBoolParameter("net.probe.wsd",
"true",
"Enable WSD discovery probes."))
mod.AddParam(session.NewIntParameter("net.probe.throttle",
"10",
"If greater than 0, probe packets will be throttled by this value in milliseconds."))
mod.AddHandler(session.NewModuleHandler("net.probe on", "",
"Start network hosts probing in background.",
func(args []string) error {
return mod.Start()
}))
mod.AddHandler(session.NewModuleHandler("net.probe off", "",
"Stop network hosts probing in background.",
func(args []string) error {
return mod.Stop()
}))
return mod
}
func (mod Prober) Name() string {
return "net.probe"
}
func (mod Prober) Description() string {
return "Keep probing for new hosts on the network by sending dummy UDP packets to every possible IP on the subnet."
}
func (mod Prober) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>"
}
func (mod *Prober) Configure() error {
var err error
if err, mod.throttle = mod.IntParam("net.probe.throttle"); err != nil {
return err
} else if err, mod.probes.NBNS = mod.BoolParam("net.probe.nbns"); err != nil {
return err
} else if err, mod.probes.MDNS = mod.BoolParam("net.probe.mdns"); err != nil {
return err
} else if err, mod.probes.UPNP = mod.BoolParam("net.probe.upnp"); err != nil {
return err
} else if err, mod.probes.WSD = mod.BoolParam("net.probe.wsd"); err != nil {
return err
} else {
mod.Debug("Throttling packets of %d ms.", mod.throttle)
}
return nil
}
func (mod *Prober) Start() error {
if err := mod.Configure(); err != nil {
return err
}
return mod.SetRunning(true, func() {
mod.waitGroup.Add(1)
defer mod.waitGroup.Done()
if mod.Session.Interface.IpAddress == network.MonitorModeAddress {
mod.Info("Interface is in monitor mode, skipping net.probe")
return
}
cidr := mod.Session.Interface.CIDR()
list, err := iprange.Parse(cidr)
if err != nil {
mod.Fatal("%s", err)
}
if mod.probes.MDNS {
mod.Session.Run("zerogod.discovery on")
}
fromIP := mod.Session.Interface.IP
fromHW := mod.Session.Interface.HW
addresses := list.Expand()
throttle := time.Duration(mod.throttle) * time.Millisecond
mod.Info("probing %d addresses on %s", len(addresses), cidr)
for mod.Running() {
if mod.probes.UPNP {
mod.sendProbeUPNP(fromIP, fromHW)
}
if mod.probes.WSD {
mod.sendProbeWSD(fromIP, fromHW)
}
for _, ip := range addresses {
if !mod.Running() {
return
} else if mod.Session.Skip(ip) {
mod.Debug("skipping address %s from probing.", ip)
continue
} else if mod.probes.NBNS {
mod.sendProbeNBNS(fromIP, fromHW, ip)
}
time.Sleep(throttle)
}
time.Sleep(5 * time.Second)
}
})
}
func (mod *Prober) Stop() error {
return mod.SetRunning(false, func() {
if mod.probes.MDNS {
mod.Session.Run("zerogod.discovery off")
}
mod.waitGroup.Wait()
})
}