diff --git a/modules/wifi_recon.go b/modules/wifi_recon.go index f9b3383b..7a10d6e7 100644 --- a/modules/wifi_recon.go +++ b/modules/wifi_recon.go @@ -28,9 +28,10 @@ var maxStationTTL = 5 * time.Minute type WiFiRecon struct { session.SessionModule - handle *pcap.Handle - channel int - apBSSID net.HardwareAddr + handle *pcap.Handle + channel int + frequencies []int + apBSSID net.HardwareAddr } func NewWiFiRecon(s *session.Session) *WiFiRecon { @@ -157,7 +158,7 @@ func (w *WiFiRecon) getRow(station *network.Station) []string { fmt.Sprintf("%d dBm", station.RSSI), bssid, station.Vendor, - strconv.Itoa(station.Channel), + strconv.Itoa(mhz2chan(station.Frequency)), sent, recvd, seen, @@ -169,7 +170,7 @@ func (w *WiFiRecon) getRow(station *network.Station) []string { ssid, station.Vendor, encryption, - strconv.Itoa(station.Channel), + strconv.Itoa(mhz2chan(station.Frequency)), sent, recvd, seen, @@ -179,8 +180,12 @@ func (w *WiFiRecon) getRow(station *network.Station) []string { func mhz2chan(freq int) int { // ambo! - if freq <= 2484 { + if freq <= 2472 { return ((freq - 2412) / 5) + 1 + } else if freq == 2484 { + return 14 + } else if freq >= 5035 && freq <= 5865 { + return ((freq - 5035) / 5) + 7 } return 0 } @@ -267,6 +272,12 @@ func (w *WiFiRecon) Configure() error { log.Info("WiFi recon active with channel hopping.") } + if frequencies, err := network.GetSupportedFrequencies(w.Session.Interface.Name()); err != nil { + return err + } else { + w.frequencies = frequencies + } + return nil } @@ -325,8 +336,8 @@ func (w *WiFiRecon) discoverAccessPoints(radiotap *layers.RadioTap, dot11 *layer // search for Dot11InformationElementIDSSID if ok, ssid := packets.Dot11ParseIDSSID(packet); ok == true { bssid := dot11.Address3.String() - channel := mhz2chan(int(radiotap.ChannelFrequency)) - w.Session.WiFi.AddIfNew(ssid, bssid, true, channel, radiotap.DBMAntennaSignal) + frequency := int(radiotap.ChannelFrequency) + w.Session.WiFi.AddIfNew(ssid, bssid, true, frequency, radiotap.DBMAntennaSignal) } } @@ -334,8 +345,8 @@ func (w *WiFiRecon) discoverClients(radiotap *layers.RadioTap, dot11 *layers.Dot // packet going to this specific BSSID? if packets.Dot11IsDataFor(dot11, ap) == true { src := dot11.Address2 - channel := mhz2chan(int(radiotap.ChannelFrequency)) - w.Session.WiFi.AddIfNew("", src.String(), false, channel, radiotap.DBMAntennaSignal) + frequency := int(radiotap.ChannelFrequency) + w.Session.WiFi.AddIfNew("", src.String(), false, frequency, radiotap.DBMAntennaSignal) } } @@ -366,7 +377,8 @@ func (w *WiFiRecon) updateStats(dot11 *layers.Dot11, packet gopacket.Packet) { func (w *WiFiRecon) channelHopper() { log.Info("Channel hopper started.") for w.Running() == true { - for channel := 1; channel < 15; channel++ { + for _, frequency := range w.frequencies { + channel := mhz2chan(frequency) if err := network.SetInterfaceChannel(w.Session.Interface.Name(), channel); err != nil { log.Warning("Error while hopping to channel %d: %s", channel, err) } diff --git a/modules/wifi_recon_sort.go b/modules/wifi_recon_sort.go index b5c75ca1..9ef6d1b1 100644 --- a/modules/wifi_recon_sort.go +++ b/modules/wifi_recon_sort.go @@ -20,10 +20,10 @@ type ByChannelSorter []*network.Station func (a ByChannelSorter) Len() int { return len(a) } func (a ByChannelSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a ByChannelSorter) Less(i, j int) bool { - if a[i].Channel == a[j].Channel { + if a[i].Frequency == a[j].Frequency { return a[i].HwAddress < a[j].HwAddress } - return a[i].Channel < a[j].Channel + return a[i].Frequency < a[j].Frequency } type ByEssidSorter []*network.Station diff --git a/network/net_darwin.go b/network/net_darwin.go index bac2a40f..1b6b42a8 100644 --- a/network/net_darwin.go +++ b/network/net_darwin.go @@ -41,3 +41,9 @@ func SetInterfaceChannel(iface string, channel int) error { } return nil } + +//! TODO Get the list of the available frequencies supported by the network card +func GetSupportedFrequencies(iface string) ([]int, error) { + freqs := []int{2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484} + return freqs, nil +} diff --git a/network/net_linux.go b/network/net_linux.go index b6207930..508b4aae 100644 --- a/network/net_linux.go +++ b/network/net_linux.go @@ -1,9 +1,12 @@ package network import ( + "bufio" "fmt" "net" "regexp" + "strconv" + "strings" "github.com/evilsocket/bettercap-ng/core" ) @@ -13,6 +16,7 @@ var IPv4RouteParser = regexp.MustCompile("^(default|[0-9\\.]+)\\svia\\s([0-9\\.] var IPv4RouteTokens = 4 var IPv4RouteCmd = "ip" var IPv4RouteCmdOpts = []string{"route"} +var WiFiFreqParser = regexp.MustCompile("^\\s+Channel.([0-9]+)\\s+:\\s+([0-9\\.]+)\\s+GHz.*$") func IPv4RouteIsGateway(ifname string, tokens []string, f func(gateway string) (*Endpoint, error)) (*Endpoint, error) { ifname2 := tokens[3] @@ -39,3 +43,23 @@ func SetInterfaceChannel(iface string, channel int) error { } return nil } + +func GetSupportedFrequencies(iface string) ([]int, error) { + freqs := make([]int, 0) + out, err := core.Exec("iwlist", []string{iface, "freq"}) + if err != nil { + return freqs, err + } else if out != "" { + scanner := bufio.NewScanner(strings.NewReader(out)) + for scanner.Scan() { + line := scanner.Text() + matches := WiFiFreqParser.FindStringSubmatch(line) + if matches != nil && len(matches) == 3 { + if freq, err := strconv.ParseFloat(matches[2], 64); err == nil { + freqs = append(freqs, int(freq*1000)) + } + } + } + } + return freqs, nil +} diff --git a/network/net_windows.go b/network/net_windows.go index dfb8ec15..5fe544c8 100644 --- a/network/net_windows.go +++ b/network/net_windows.go @@ -62,3 +62,8 @@ func getInterfaceName(iface net.Interface) string { func SetInterfaceChannel(iface string, channel int) error { return fmt.Errorf("Windows does not support WiFi channel hopping.") } + +func GetSupportedFrequencies(iface string) ([]int, error) { + freqs := make([]int, 0) + return freqs, fmt.Errorf("Windows does not support WiFi channel hopping.") +} diff --git a/network/wifi.go b/network/wifi.go index bc2ab654..08852e6d 100644 --- a/network/wifi.go +++ b/network/wifi.go @@ -8,6 +8,8 @@ import ( type StationNewCallback func(s *Station) type StationLostCallback func(s *Station) +var Channels5Ghz = [...]int{36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 132, 134, 136, 138, 140, 142, 144, 149, 151, 153, 155, 157, 159, 161, 165, 169, 173} + type WiFi struct { sync.Mutex Interface *Endpoint @@ -49,7 +51,7 @@ func (w *WiFi) Remove(mac string) { } } -func (w *WiFi) AddIfNew(ssid, mac string, isAp bool, channel int, rssi int8) *Station { +func (w *WiFi) AddIfNew(ssid, mac string, isAp bool, frequency int, rssi int8) *Station { w.Lock() defer w.Unlock() @@ -60,7 +62,7 @@ func (w *WiFi) AddIfNew(ssid, mac string, isAp bool, channel int, rssi int8) *St return station } - newStation := NewStation(ssid, mac, isAp, channel, rssi) + newStation := NewStation(ssid, mac, isAp, frequency, rssi) w.Stations[mac] = newStation if w.newCb != nil { diff --git a/network/wifi_station.go b/network/wifi_station.go index 5edbfc1b..9a755905 100644 --- a/network/wifi_station.go +++ b/network/wifi_station.go @@ -3,19 +3,19 @@ package network type Station struct { *Endpoint IsAP bool - Channel int + Frequency int RSSI int8 Sent uint64 Received uint64 Encryption string } -func NewStation(essid, bssid string, isAp bool, channel int, rssi int8) *Station { +func NewStation(essid, bssid string, isAp bool, frequency int, rssi int8) *Station { return &Station{ - Endpoint: NewEndpointNoResolve(MonitorModeAddress, bssid, essid, 0), - IsAP: isAp, - Channel: channel, - RSSI: rssi, + Endpoint: NewEndpointNoResolve(MonitorModeAddress, bssid, essid, 0), + IsAP: isAp, + Frequency: frequency, + RSSI: rssi, } }