diff --git a/modules/wifi_hopping.go b/modules/wifi_hopping.go index aa742d8c..6e0fddff 100644 --- a/modules/wifi_hopping.go +++ b/modules/wifi_hopping.go @@ -33,10 +33,11 @@ func (w *WiFiModule) channelHopper() { // more channels, therefore we need to increase the time // we hop on each one otherwise me lose information if len(w.frequencies) > 14 { - delay = 500 * time.Millisecond + delay = delay * 2 } - for _, frequency := range w.frequencies { + frequencies := w.frequencies + for _, frequency := range frequencies { channel := network.Dot11Freq2Chan(frequency) // stick to the access point channel as long as it's selected // or as long as we're deauthing on it diff --git a/modules/wifi_recon.go b/modules/wifi_recon.go index 8e32c073..0faf47c6 100644 --- a/modules/wifi_recon.go +++ b/modules/wifi_recon.go @@ -3,6 +3,8 @@ package modules import ( "fmt" "net" + "strconv" + "strings" "sync" "time" @@ -87,6 +89,10 @@ func NewWiFiModule(s *session.Session) *WiFiModule { func(args []string) error { w.ap = nil w.stickChan = 0 + var err error + if w.frequencies, err = network.GetSupportedFrequencies(w.Session.Interface.Name()); err != nil { + return err + } return nil })) @@ -106,9 +112,34 @@ func NewWiFiModule(s *session.Session) *WiFiModule { return w.Show("rssi") })) - w.AddParam(session.NewIntParameter("wifi.recon.channel", - "", - "WiFi channel or empty for channel hopping.")) + w.AddHandler(session.NewModuleHandler("wifi.recon.channel", `wifi\.recon\.channel[\s]+([0-9]+(?:[, ]+[0-9]+)*|clear)`, + "WiFi channels (comma separated) or empty for channel hopping.", + func(args []string) error { + newfrequencies := w.frequencies[:0] + + if len(args) > 0 && args[0] != "clear" { + channels := strings.Split(args[0], ",") + for _, c := range channels { + trimmed := strings.Trim(c, " ") + channel, err := strconv.Atoi(trimmed) + if err != nil { + return err + } + newfrequencies = append(newfrequencies, network.Dot11Chan2Freq(channel)) + } + } else { + // No channels setted, retrieve frequencies supported by the card + if frequencies, err := network.GetSupportedFrequencies(w.Session.Interface.Name()); err != nil { + return err + } else { + newfrequencies = frequencies + } + } + + w.frequencies = newfrequencies + + return nil + })) w.AddParam(session.NewStringParameter("wifi.source.file", "", @@ -117,7 +148,7 @@ func NewWiFiModule(s *session.Session) *WiFiModule { w.AddParam(session.NewIntParameter("wifi.hop.period", "250", - "If channel hopping is enabled (empty wifi.recon.channel), this is the time in millseconds the algorithm will hop on every channel (it'll be doubled if both 2.4 and 5.0 bands are available).")) + "If channel hopping is enabled (empty wifi.recon.channel), this is the time in milliseconds the algorithm will hop on every channel (it'll be doubled if both 2.4 and 5.0 bands are available).")) w.AddParam(session.NewBoolParameter("wifi.skip-broken", "true", @@ -177,13 +208,12 @@ func (w *WiFiModule) Configure() error { w.hopPeriod = time.Duration(hopPeriod) * time.Millisecond if w.source == "" { - if err, w.channel = w.IntParam("wifi.recon.channel"); err == nil { - if err = network.SetInterfaceChannel(w.Session.Interface.Name(), w.channel); err != nil { + // No channels setted, retrieve frequencies supported by the card + if len(w.frequencies) == 0 { + if w.frequencies, err = network.GetSupportedFrequencies(w.Session.Interface.Name()); err != nil { return err } - log.Info("WiFi recon active on channel %d.", w.channel) - } else { - w.channel = 0 + // we need to start somewhere, this is just to check if // this OS supports switching channel programmatically. if err = network.SetInterfaceChannel(w.Session.Interface.Name(), 1); err != nil { @@ -191,12 +221,6 @@ func (w *WiFiModule) 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 @@ -207,8 +231,15 @@ func (w *WiFiModule) discoverAccessPoints(radiotap *layers.RadioTap, dot11 *laye if ok, ssid := packets.Dot11ParseIDSSID(packet); ok == true { from := dot11.Address3 if network.IsZeroMac(from) == false && network.IsBroadcastMac(from) == false { + var frequency int bssid := from.String() - frequency := int(radiotap.ChannelFrequency) + + 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) } } diff --git a/modules/wifi_show.go b/modules/wifi_show.go index 3272b75c..827e4b92 100644 --- a/modules/wifi_show.go +++ b/modules/wifi_show.go @@ -17,7 +17,8 @@ func (w *WiFiModule) isApSelected() bool { return w.ap != nil } -func (w *WiFiModule) getRow(station *network.Station) []string { +func (w *WiFiModule) getRow(station *network.Station) ([]string, bool) { + include := false sinceStarted := time.Since(w.Session.StartedAt) sinceFirstSeen := time.Since(station.FirstSeen) @@ -61,6 +62,17 @@ func (w *WiFiModule) getRow(station *network.Station) []string { recvd = humanize.Bytes(station.Received) } + if w.source == "" { + for _, frequencies := range w.frequencies { + if frequencies == station.Frequency { + include = true + break + } + } + } else { + include = true + } + if w.isApSelected() { return []string{ fmt.Sprintf("%d dBm", station.RSSI), @@ -70,7 +82,7 @@ func (w *WiFiModule) getRow(station *network.Station) []string { sent, recvd, seen, - } + }, include } else { // this is ugly, but necessary in order to have this // method handle both access point and clients @@ -93,7 +105,7 @@ func (w *WiFiModule) getRow(station *network.Station) []string { sent, recvd, seen, - } + }, include } } @@ -123,7 +135,9 @@ func (w *WiFiModule) Show(by string) error { rows := make([][]string, 0) for _, s := range stations { - rows = append(rows, w.getRow(s)) + if row, include := w.getRow(s); include == true { + rows = append(rows, row) + } } nrows := len(rows) diff --git a/network/wifi.go b/network/wifi.go index d3b22314..6a87615c 100644 --- a/network/wifi.go +++ b/network/wifi.go @@ -18,6 +18,18 @@ func Dot11Freq2Chan(freq int) int { return 0 } +func Dot11Chan2Freq(channel int) int { + if channel <= 13 { + return ((channel - 1) * 5) + 2412 + } else if channel == 14 { + return 2484 + } else if channel <= 173 { + return ((channel - 7) * 5) + 5035 + } + + return 0 +} + type APNewCallback func(ap *AccessPoint) type APLostCallback func(ap *AccessPoint) diff --git a/packets/dot11.go b/packets/dot11.go index 919b9108..ae27126b 100644 --- a/packets/dot11.go +++ b/packets/dot11.go @@ -126,3 +126,20 @@ func Dot11IsDataFor(dot11 *layers.Dot11, station net.HardwareAddr) bool { // packet going to this specific BSSID? return bytes.Compare(dot11.Address1, station) == 0 } + +func Dot11ParseDSSet(packet gopacket.Packet) (bool, int) { + channel := 0 + found := false + for _, layer := range packet.Layers() { + info, ok := layer.(*layers.Dot11InformationElement) + if ok == true { + if info.ID == layers.Dot11InformationElementIDDSSet { + channel, _ = Dot11InformationElementIDDSSetDecode(info.Info) + found = true + break + } + } + } + + return found, channel +} diff --git a/packets/dot11_types.go b/packets/dot11_types.go index bd85d2e1..6df708af 100644 --- a/packets/dot11_types.go +++ b/packets/dot11_types.go @@ -211,3 +211,11 @@ func Dot11InformationElementRSNInfoDecode(buf []byte) (rsn RSNInfo, err error) { return } + +func Dot11InformationElementIDDSSetDecode(buf []byte) (channel int, err error) { + if err = canParse("DSSet.channel", buf, 1); err == nil { + channel = int(buf[0]) + } + + return +}