diff --git a/modules/wifi/wifi.go b/modules/wifi/wifi.go index 465d6e61..bdd513d5 100644 --- a/modules/wifi/wifi.go +++ b/modules/wifi/wifi.go @@ -26,6 +26,7 @@ import ( type WiFiModule struct { session.SessionModule + iface *network.Endpoint handle *pcap.Handle source string region string @@ -59,6 +60,7 @@ type WiFiModule struct { func NewWiFiModule(s *session.Session) *WiFiModule { mod := &WiFiModule{ SessionModule: session.NewSessionModule("wifi", s), + iface: s.Interface, minRSSI: -200, channel: 0, stickChan: 0, @@ -79,6 +81,11 @@ func NewWiFiModule(s *session.Session) *WiFiModule { chanLock: &sync.Mutex{}, } + mod.AddParam(session.NewStringParameter("wifi.interface", + "", + "", + "If filled, will use this interface name instead of the one provided by the -iface argument or detected automatically.")) + mod.AddHandler(session.NewModuleHandler("wifi.recon on", "", "Start 802.11 wireless base stations discovery and channel hopping.", func(args []string) error { @@ -117,7 +124,7 @@ func NewWiFiModule(s *session.Session) *WiFiModule { func(args []string) (err error) { mod.ap = nil mod.stickChan = 0 - mod.frequencies, err = network.GetSupportedFrequencies(mod.Session.Interface.Name()) + mod.frequencies, err = network.GetSupportedFrequencies(mod.iface.Name()) mod.hopChanges <- true return err })) @@ -273,7 +280,7 @@ func NewWiFiModule(s *session.Session) *WiFiModule { if len(freqs) == 0 { mod.Debug("resetting hopping channels") - if freqs, err = network.GetSupportedFrequencies(mod.Session.Interface.Name()); err != nil { + if freqs, err = network.GetSupportedFrequencies(mod.iface.Name()); err != nil { return err } } @@ -324,6 +331,7 @@ const ( ) func (mod *WiFiModule) Configure() error { + var ifName string var hopPeriod int var err error @@ -345,7 +353,17 @@ func (mod *WiFiModule) Configure() error { } } - ifName := mod.Session.Interface.Name() + if err, ifName = mod.StringParam("wifi.interface"); err != nil { + return err + } else if ifName == "" { + mod.iface = mod.Session.Interface + ifName = mod.iface.Name() + } else if mod.iface, err = network.FindInterface(ifName); err != nil { + return fmt.Errorf("could not find interface %s: %v", ifName, err) + } + + mod.Info("using interface %s (%s)", ifName, mod.iface.HwAddress) + if mod.source != "" { if mod.handle, err = pcap.OpenOffline(mod.source); err != nil { return fmt.Errorf("error while opening file %s: %s", mod.source, err) @@ -355,7 +373,7 @@ func (mod *WiFiModule) Configure() error { if err := network.SetWiFiRegion(mod.region); err != nil { return err } else { - mod.Info("WiFi region set to '%s'", mod.region) + mod.Debug("WiFi region set to '%s'", mod.region) } } @@ -363,7 +381,7 @@ func (mod *WiFiModule) Configure() error { if err := network.SetInterfaceTxPower(ifName, mod.txPower); err != nil { mod.Warning("could not set interface %s txpower to %d, 'Set Tx Power' requests not supported", ifName, mod.txPower) } else { - mod.Info("interface %s txpower set to %d", ifName, mod.txPower) + mod.Debug("interface %s txpower set to %d", ifName, mod.txPower) } } @@ -388,7 +406,7 @@ func (mod *WiFiModule) Configure() error { return fmt.Errorf("error while setting timeout: %s", err) } else if mod.handle, err = ihandle.Activate(); err != nil { if retry == 0 && err.Error() == ErrIfaceNotUp { - mod.Warning("interface %s is down, bringing it up ...", ifName) + mod.Debug("interface %s is down, bringing it up ...", ifName) if err := network.ActivateInterface(ifName); err != nil { return err } @@ -433,7 +451,7 @@ func (mod *WiFiModule) Configure() error { func (mod *WiFiModule) updateInfo(dot11 *layers.Dot11, packet gopacket.Packet) { // avoid parsing info from frames we're sending staMac := ops.Ternary(dot11.Flags.FromDS(), dot11.Address1, dot11.Address2).(net.HardwareAddr) - if !bytes.Equal(staMac, mod.Session.Interface.HW) { + if !bytes.Equal(staMac, mod.iface.HW) { if ok, enc, cipher, auth := packets.Dot11ParseEncryption(packet, dot11); ok { // Sometimes we get incomplete info about encryption, which // makes stations with encryption enabled switch to OPEN. @@ -499,7 +517,9 @@ func (mod *WiFiModule) Start() error { continue } - mod.Session.Queue.TrackPacket(uint64(len(packet.Data()))) + if mod.iface == mod.Session.Interface { + mod.Session.Queue.TrackPacket(uint64(len(packet.Data()))) + } // perform initial dot11 parsing and layers validation if ok, radiotap, dot11 := packets.Dot11Parse(packet); ok { diff --git a/modules/wifi/wifi_assoc.go b/modules/wifi/wifi_assoc.go index 975fd91a..a2fb66c9 100644 --- a/modules/wifi/wifi_assoc.go +++ b/modules/wifi/wifi_assoc.go @@ -11,13 +11,13 @@ import ( ) func (mod *WiFiModule) sendAssocPacket(ap *network.AccessPoint) { - if err, pkt := packets.NewDot11Auth(mod.Session.Interface.HW, ap.HW, 1); err != nil { + if err, pkt := packets.NewDot11Auth(mod.iface.HW, ap.HW, 1); err != nil { mod.Error("cloud not create auth packet: %s", err) } else { mod.injectPacket(pkt) } - if err, pkt := packets.NewDot11AssociationRequest(mod.Session.Interface.HW, ap.HW, ap.ESSID(), 1); err != nil { + if err, pkt := packets.NewDot11AssociationRequest(mod.iface.HW, ap.HW, ap.ESSID(), 1); err != nil { mod.Error("cloud not create association request packet: %s", err) } else { mod.injectPacket(pkt) diff --git a/modules/wifi/wifi_hopping.go b/modules/wifi/wifi_hopping.go index 80a2c0c2..79fea79e 100644 --- a/modules/wifi/wifi_hopping.go +++ b/modules/wifi/wifi_hopping.go @@ -13,7 +13,7 @@ func (mod *WiFiModule) onChannel(channel int, cb func()) { prev := mod.stickChan mod.stickChan = channel - if err := network.SetInterfaceChannel(mod.Session.Interface.Name(), channel); err != nil { + if err := network.SetInterfaceChannel(mod.iface.Name(), channel); err != nil { mod.Warning("error while hopping to channel %d: %s", channel, err) } else { mod.Debug("hopped on channel %d", channel) @@ -53,7 +53,7 @@ func (mod *WiFiModule) channelHopper() { mod.Debug("hopping on channel %d", channel) mod.chanLock.Lock() - if err := network.SetInterfaceChannel(mod.Session.Interface.Name(), channel); err != nil { + if err := network.SetInterfaceChannel(mod.iface.Name(), channel); err != nil { mod.Warning("error while hopping to channel %d: %s", channel, err) } mod.chanLock.Unlock() diff --git a/modules/wifi/wifi_recon_handshakes.go b/modules/wifi/wifi_recon_handshakes.go index bbc84ce3..d7701be9 100644 --- a/modules/wifi/wifi_recon_handshakes.go +++ b/modules/wifi/wifi_recon_handshakes.go @@ -33,7 +33,7 @@ func (mod *WiFiModule) discoverHandshakes(radiotap *layers.RadioTap, dot11 *laye // (Reference about PMKID https://hashcat.net/forum/thread-7717.html) // In this case, we need to add ourselves as a client station of the AP // in order to have a consistent association of AP, client and handshakes. - staIsUs := bytes.Equal(staMac, mod.Session.Interface.HW) + staIsUs := bytes.Equal(staMac, mod.iface.HW) station, found := ap.Get(staMac.String()) if !found { station, _ = ap.AddClientIfNew(staMac.String(), ap.Frequency, ap.RSSI) diff --git a/modules/wifi/wifi_show.go b/modules/wifi/wifi_show.go index 7a44bb26..8e45403f 100644 --- a/modules/wifi/wifi_show.go +++ b/modules/wifi/wifi_show.go @@ -300,7 +300,7 @@ func (mod *WiFiModule) showStatusBar() { defer mod.Session.Queue.Stats.RUnlock() parts := []string{ - fmt.Sprintf("%s (ch. %d)", mod.Session.Interface.Name(), network.GetInterfaceChannel(mod.Session.Interface.Name())), + fmt.Sprintf("%s (ch. %d)", mod.iface.Name(), network.GetInterfaceChannel(mod.iface.Name())), fmt.Sprintf("%s %s", tui.Red("↑"), humanize.Bytes(mod.Session.Queue.Stats.Sent)), fmt.Sprintf("%s %s", tui.Green("↓"), humanize.Bytes(mod.Session.Queue.Stats.Received)), fmt.Sprintf("%d pkts", mod.Session.Queue.Stats.PktReceived),