mirror of
https://github.com/bettercap/bettercap.git
synced 2025-03-12 04:36:03 -07:00
124 lines
3.0 KiB
Go
124 lines
3.0 KiB
Go
package modules
|
|
|
|
import (
|
|
"bytes"
|
|
"net"
|
|
"time"
|
|
|
|
"github.com/bettercap/bettercap/log"
|
|
"github.com/bettercap/bettercap/network"
|
|
"github.com/bettercap/bettercap/packets"
|
|
|
|
"github.com/google/gopacket"
|
|
"github.com/google/gopacket/layers"
|
|
)
|
|
|
|
var maxStationTTL = 5 * time.Minute
|
|
|
|
type WiFiProbe struct {
|
|
FromAddr net.HardwareAddr
|
|
FromVendor string
|
|
FromAlias string
|
|
SSID string
|
|
RSSI int8
|
|
}
|
|
|
|
func (w *WiFiModule) stationPruner() {
|
|
w.reads.Add(1)
|
|
defer w.reads.Done()
|
|
|
|
log.Debug("WiFi stations pruner started.")
|
|
for w.Running() {
|
|
// loop every AP
|
|
for _, ap := range w.Session.WiFi.List() {
|
|
sinceLastSeen := time.Since(ap.LastSeen)
|
|
if sinceLastSeen > maxStationTTL {
|
|
log.Debug("Station %s not seen in %s, removing.", ap.BSSID(), sinceLastSeen)
|
|
w.Session.WiFi.Remove(ap.BSSID())
|
|
continue
|
|
}
|
|
// loop every AP client
|
|
for _, c := range ap.Clients() {
|
|
sinceLastSeen := time.Since(c.LastSeen)
|
|
if sinceLastSeen > maxStationTTL {
|
|
log.Debug("Client %s of station %s not seen in %s, removing.", c.String(), ap.BSSID(), sinceLastSeen)
|
|
ap.RemoveClient(c.BSSID())
|
|
}
|
|
}
|
|
}
|
|
time.Sleep(1 * time.Second)
|
|
}
|
|
}
|
|
|
|
func (w *WiFiModule) discoverAccessPoints(radiotap *layers.RadioTap, dot11 *layers.Dot11, packet gopacket.Packet) {
|
|
// search for Dot11InformationElementIDSSID
|
|
if ok, ssid := packets.Dot11ParseIDSSID(packet); ok {
|
|
from := dot11.Address3
|
|
|
|
// skip stuff we're sending
|
|
if w.apRunning && bytes.Equal(from, w.apConfig.BSSID) {
|
|
return
|
|
}
|
|
|
|
if !network.IsZeroMac(from) && !network.IsBroadcastMac(from) {
|
|
var frequency int
|
|
bssid := from.String()
|
|
|
|
if found, channel := packets.Dot11ParseDSSet(packet); found {
|
|
frequency = network.Dot11Chan2Freq(channel)
|
|
} else {
|
|
frequency = int(radiotap.ChannelFrequency)
|
|
}
|
|
|
|
w.Session.WiFi.AddIfNew(ssid, bssid, frequency, radiotap.DBMAntennaSignal)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (w *WiFiModule) discoverProbes(radiotap *layers.RadioTap, dot11 *layers.Dot11, packet gopacket.Packet) {
|
|
if dot11.Type != layers.Dot11TypeMgmtProbeReq {
|
|
return
|
|
}
|
|
|
|
reqLayer := packet.Layer(layers.LayerTypeDot11MgmtProbeReq)
|
|
if reqLayer == nil {
|
|
return
|
|
}
|
|
|
|
req, ok := reqLayer.(*layers.Dot11MgmtProbeReq)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
tot := len(req.Contents)
|
|
if tot < 3 {
|
|
return
|
|
}
|
|
|
|
avail := uint32(tot - 2)
|
|
if avail < 2 {
|
|
return
|
|
}
|
|
size := uint32(req.Contents[1])
|
|
if size == 0 || size > avail {
|
|
return
|
|
}
|
|
|
|
w.Session.Events.Add("wifi.client.probe", WiFiProbe{
|
|
FromAddr: dot11.Address2,
|
|
FromVendor: network.ManufLookup(dot11.Address2.String()),
|
|
FromAlias: w.Session.Lan.GetAlias(dot11.Address2.String()),
|
|
SSID: string(req.Contents[2 : 2+size]),
|
|
RSSI: radiotap.DBMAntennaSignal,
|
|
})
|
|
}
|
|
|
|
func (w *WiFiModule) discoverClients(radiotap *layers.RadioTap, dot11 *layers.Dot11, packet gopacket.Packet) {
|
|
w.Session.WiFi.EachAccessPoint(func(bssid string, ap *network.AccessPoint) {
|
|
// packet going to this specific BSSID?
|
|
if packets.Dot11IsDataFor(dot11, ap.HW) {
|
|
ap.AddClient(dot11.Address2.String(), int(radiotap.ChannelFrequency), radiotap.DBMAntennaSignal)
|
|
}
|
|
})
|
|
}
|