wifi module: fix on beacon parsing and multiple channel selection

This commit is contained in:
Matrix86 2018-03-12 16:06:51 +01:00
parent 582e1ae81e
commit 4726c2fc9d
4 changed files with 105 additions and 22 deletions

View file

@ -3,6 +3,8 @@ package modules
import ( import (
"fmt" "fmt"
"net" "net"
"strconv"
"strings"
"sync" "sync"
"time" "time"
@ -87,6 +89,10 @@ func NewWiFiModule(s *session.Session) *WiFiModule {
func(args []string) error { func(args []string) error {
w.ap = nil w.ap = nil
w.stickChan = 0 w.stickChan = 0
var err error
if w.frequencies, err = network.GetSupportedFrequencies(w.Session.Interface.Name()); err != nil {
return err
}
return nil return nil
})) }))
@ -106,9 +112,34 @@ func NewWiFiModule(s *session.Session) *WiFiModule {
return w.Show("rssi") return w.Show("rssi")
})) }))
w.AddParam(session.NewIntParameter("wifi.recon.channel", w.AddHandler(session.NewModuleHandler("wifi.recon.channel", `wifi\.recon\.channel[\s]*([0-9]+(?:[, ]+[0-9]+)*)?`,
"", "WiFi channels (comma separated) or empty for channel hopping.",
"WiFi channel or empty for channel hopping.")) func(args []string) error {
newfrequencies := w.frequencies[:0]
if len(args) > 0 && args[0] != "" {
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, chan2mhz(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", w.AddParam(session.NewStringParameter("wifi.source.file",
"", "",
@ -117,7 +148,7 @@ func NewWiFiModule(s *session.Session) *WiFiModule {
w.AddParam(session.NewIntParameter("wifi.hop.period", w.AddParam(session.NewIntParameter("wifi.hop.period",
"250", "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", w.AddParam(session.NewBoolParameter("wifi.skip-broken",
"true", "true",
@ -150,6 +181,18 @@ func mhz2chan(freq int) int {
return 0 return 0
} }
func chan2mhz(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
}
func (w *WiFiModule) Configure() error { func (w *WiFiModule) Configure() error {
var hopPeriod int var hopPeriod int
var err error var err error
@ -189,13 +232,12 @@ func (w *WiFiModule) Configure() error {
w.hopPeriod = time.Duration(hopPeriod) * time.Millisecond w.hopPeriod = time.Duration(hopPeriod) * time.Millisecond
if w.source == "" { if w.source == "" {
if err, w.channel = w.IntParam("wifi.recon.channel"); err == nil { // No channels setted, retrieve frequencies supported by the card
if err = network.SetInterfaceChannel(w.Session.Interface.Name(), w.channel); err != nil { if len(w.frequencies) == 0 {
if w.frequencies, err = network.GetSupportedFrequencies(w.Session.Interface.Name()); err != nil {
return err 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 // we need to start somewhere, this is just to check if
// this OS supports switching channel programmatically. // this OS supports switching channel programmatically.
if err = network.SetInterfaceChannel(w.Session.Interface.Name(), 1); err != nil { if err = network.SetInterfaceChannel(w.Session.Interface.Name(), 1); err != nil {
@ -203,12 +245,6 @@ func (w *WiFiModule) Configure() error {
} }
log.Info("WiFi recon active with channel hopping.") 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 return nil
@ -251,8 +287,15 @@ func (w *WiFiModule) discoverAccessPoints(radiotap *layers.RadioTap, dot11 *laye
// search for Dot11InformationElementIDSSID // search for Dot11InformationElementIDSSID
if ok, ssid := packets.Dot11ParseIDSSID(packet); ok == true { if ok, ssid := packets.Dot11ParseIDSSID(packet); ok == true {
if isZeroBSSID(dot11.Address3) == false && isBroadcastBSSID(dot11.Address3) == false { if isZeroBSSID(dot11.Address3) == false && isBroadcastBSSID(dot11.Address3) == false {
var frequency int
bssid := dot11.Address3.String() bssid := dot11.Address3.String()
frequency := int(radiotap.ChannelFrequency)
if found, channel := packets.Dot11ParseDSSet(packet); found {
frequency = chan2mhz(channel)
} else {
frequency = int(radiotap.ChannelFrequency)
}
w.Session.WiFi.AddIfNew(ssid, bssid, frequency, radiotap.DBMAntennaSignal) w.Session.WiFi.AddIfNew(ssid, bssid, frequency, radiotap.DBMAntennaSignal)
} }
} }
@ -342,10 +385,11 @@ func (w *WiFiModule) channelHopper() {
// more channels, therefore we need to increase the time // more channels, therefore we need to increase the time
// we hop on each one otherwise me lose information // we hop on each one otherwise me lose information
if len(w.frequencies) > 14 { if len(w.frequencies) > 14 {
delay = 500 * time.Millisecond delay = delay * 2 * time.Millisecond
} }
for _, frequency := range w.frequencies { frequencies := w.frequencies
for _, frequency := range frequencies {
channel := mhz2chan(frequency) channel := mhz2chan(frequency)
// stick to the access point channel as long as it's selected // stick to the access point channel as long as it's selected
// or as long as we're deauthing on it // or as long as we're deauthing on it

View file

@ -17,7 +17,8 @@ func (w *WiFiModule) isApSelected() bool {
return w.ap != nil 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) sinceStarted := time.Since(w.Session.StartedAt)
sinceFirstSeen := time.Since(station.FirstSeen) sinceFirstSeen := time.Since(station.FirstSeen)
@ -61,6 +62,17 @@ func (w *WiFiModule) getRow(station *network.Station) []string {
recvd = humanize.Bytes(station.Received) 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() { if w.isApSelected() {
return []string{ return []string{
fmt.Sprintf("%d dBm", station.RSSI), fmt.Sprintf("%d dBm", station.RSSI),
@ -70,7 +82,7 @@ func (w *WiFiModule) getRow(station *network.Station) []string {
sent, sent,
recvd, recvd,
seen, seen,
} }, include
} else { } else {
// this is ugly, but necessary in order to have this // this is ugly, but necessary in order to have this
// method handle both access point and clients // method handle both access point and clients
@ -93,7 +105,7 @@ func (w *WiFiModule) getRow(station *network.Station) []string {
sent, sent,
recvd, recvd,
seen, seen,
} }, include
} }
} }
@ -123,7 +135,9 @@ func (w *WiFiModule) Show(by string) error {
rows := make([][]string, 0) rows := make([][]string, 0)
for _, s := range stations { 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) nrows := len(rows)

View file

@ -126,3 +126,20 @@ func Dot11IsDataFor(dot11 *layers.Dot11, station net.HardwareAddr) bool {
// packet going to this specific BSSID? // packet going to this specific BSSID?
return bytes.Compare(dot11.Address1, station) == 0 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
}

View file

@ -211,3 +211,11 @@ func Dot11InformationElementRSNInfoDecode(buf []byte) (rsn RSNInfo, err error) {
return return
} }
func Dot11InformationElementIDDSSetDecode(buf []byte) (channel int, err error) {
if err = canParse("DSSet.channel", buf, 1); err == nil {
channel = int(buf[0])
}
return
}