new: parsing RSSI ( ref #53 )

This commit is contained in:
evilsocket 2018-02-17 04:10:37 +01:00
commit 0ad426024f
6 changed files with 98 additions and 30 deletions

View file

@ -44,17 +44,18 @@ func (w *WiFi) Remove(mac string) {
} }
} }
func (w *WiFi) AddIfNew(ssid, mac string, isAp bool, channel int) *WiFiStation { func (w *WiFi) AddIfNew(ssid, mac string, isAp bool, channel int, rssi int8) *WiFiStation {
w.Lock() w.Lock()
defer w.Unlock() defer w.Unlock()
mac = network.NormalizeMac(mac) mac = network.NormalizeMac(mac)
if station, found := w.Stations[mac]; found { if station, found := w.Stations[mac]; found {
w.Stations[mac].LastSeen = time.Now() station.LastSeen = time.Now()
station.RSSI = rssi
return station return station
} }
newStation := NewWiFiStation(ssid, mac, isAp, channel) newStation := NewWiFiStation(ssid, mac, isAp, channel, rssi)
w.Stations[mac] = newStation w.Stations[mac] = newStation
w.Session.Events.Add("wifi.station.new", newStation) w.Session.Events.Add("wifi.station.new", newStation)

View file

@ -100,7 +100,7 @@ func NewWiFiRecon(s *session.Session) *WiFiRecon {
w.AddHandler(session.NewModuleHandler("wifi.show", "", w.AddHandler(session.NewModuleHandler("wifi.show", "",
"Show current wireless stations list (default sorting by essid).", "Show current wireless stations list (default sorting by essid).",
func(args []string) error { func(args []string) error {
return w.Show("channel") return w.Show("rssi")
})) }))
w.AddParam(session.NewIntParameter("wifi.recon.channel", w.AddParam(session.NewIntParameter("wifi.recon.channel",
@ -142,6 +142,8 @@ func (w *WiFiRecon) getRow(station *WiFiStation) []string {
seen = core.Dim(seen) seen = core.Dim(seen)
} }
encryption := w.stats.EncryptionOf(station.HW)
sent := "" sent := ""
bytes := w.stats.SentFrom(station.HW) bytes := w.stats.SentFrom(station.HW)
if bytes > 0 { if bytes > 0 {
@ -155,9 +157,11 @@ func (w *WiFiRecon) getRow(station *WiFiStation) []string {
} }
row := []string{ row := []string{
fmt.Sprintf("%d dBm", station.RSSI),
bssid, bssid,
station.ESSID(), station.ESSID(),
station.Vendor, station.Vendor,
encryption,
strconv.Itoa(station.Channel), strconv.Itoa(station.Channel),
sent, sent,
recvd, recvd,
@ -165,6 +169,7 @@ func (w *WiFiRecon) getRow(station *WiFiStation) []string {
} }
if w.isApSelected() { if w.isApSelected() {
row = []string{ row = []string{
fmt.Sprintf("%d dBm", station.RSSI),
bssid, bssid,
station.Vendor, station.Vendor,
strconv.Itoa(station.Channel), strconv.Itoa(station.Channel),
@ -209,11 +214,13 @@ func (w *WiFiRecon) Show(by string) error {
stations := w.wifi.List() stations := w.wifi.List()
if by == "seen" { if by == "seen" {
sort.Sort(BywifiSeenSorter(stations)) sort.Sort(ByWiFiSeenSorter(stations))
} else if by == "essid" { } else if by == "essid" {
sort.Sort(ByEssidSorter(stations)) sort.Sort(ByEssidSorter(stations))
} else { } else if by == "channel" {
sort.Sort(ByChannelSorter(stations)) sort.Sort(ByChannelSorter(stations))
} else {
sort.Sort(ByRSSISorter(stations))
} }
rows := make([][]string, 0) rows := make([][]string, 0)
@ -221,10 +228,10 @@ func (w *WiFiRecon) Show(by string) error {
rows = append(rows, w.getRow(s)) rows = append(rows, w.getRow(s))
} }
columns := []string{"BSSID", "SSID", "Vendor", "Channel", "Sent", "Recvd", "Last Seen"} columns := []string{"RSSI", "BSSID", "SSID", "Vendor", "Encryption", "Channel", "Sent", "Recvd", "Last Seen"}
if w.isApSelected() { if w.isApSelected() {
// these are clients // these are clients
columns = []string{"MAC", "Vendor", "Channel", "Sent", "Received", "Last Seen"} columns = []string{"RSSI", "MAC", "Vendor", "Channel", "Sent", "Received", "Last Seen"}
fmt.Printf("\n%s clients:\n", w.accessPoint.String()) fmt.Printf("\n%s clients:\n", w.accessPoint.String())
} }
@ -263,7 +270,6 @@ func (w *WiFiRecon) Configure() error {
return err return err
} }
log.Info("WiFi recon active with channel hopping.") log.Info("WiFi recon active with channel hopping.")
} }
w.wifi = NewWiFi(w.Session, w.Session.Interface) w.wifi = NewWiFi(w.Session, w.Session.Interface)
@ -337,7 +343,7 @@ func (w *WiFiRecon) discoverAccessPoints(radiotap *layers.RadioTap, dot11 *layer
if ok, ssid := packets.Dot11ParseIDSSID(packet); ok == true { if ok, ssid := packets.Dot11ParseIDSSID(packet); ok == true {
bssid := dot11.Address3.String() bssid := dot11.Address3.String()
channel := mhz2chan(int(radiotap.ChannelFrequency)) channel := mhz2chan(int(radiotap.ChannelFrequency))
w.wifi.AddIfNew(ssid, bssid, true, channel) w.wifi.AddIfNew(ssid, bssid, true, channel, radiotap.DBMAntennaSignal)
} }
} }
@ -346,16 +352,13 @@ func (w *WiFiRecon) discoverClients(radiotap *layers.RadioTap, dot11 *layers.Dot
if packets.Dot11IsDataFor(dot11, ap) == true { if packets.Dot11IsDataFor(dot11, ap) == true {
src := dot11.Address2 src := dot11.Address2
channel := mhz2chan(int(radiotap.ChannelFrequency)) channel := mhz2chan(int(radiotap.ChannelFrequency))
w.wifi.AddIfNew("", src.String(), false, channel) w.wifi.AddIfNew("", src.String(), false, channel, radiotap.DBMAntennaSignal)
} }
} }
func (w *WiFiRecon) updateStats(dot11 *layers.Dot11, packet gopacket.Packet) { func (w *WiFiRecon) updateStats(dot11 *layers.Dot11, packet gopacket.Packet) {
// only collect stats from data frames // collect stats from data frames
if dot11.Type.MainType() != layers.Dot11TypeData { if dot11.Type.MainType() == layers.Dot11TypeData {
return
}
bytes := uint64(len(packet.Data())) bytes := uint64(len(packet.Data()))
dst := dot11.Address1 dst := dot11.Address1
@ -363,6 +366,13 @@ func (w *WiFiRecon) updateStats(dot11 *layers.Dot11, packet gopacket.Packet) {
w.stats.CollectReceived(dst, bytes) w.stats.CollectReceived(dst, bytes)
w.stats.CollectSent(src, bytes) w.stats.CollectSent(src, bytes)
}
if ok, enc := packets.Dot11ParseEncryption(packet, dot11); ok == true {
for _, e := range enc {
w.stats.CollectEncryption(dot11.Address3, e)
}
}
} }
func (w *WiFiRecon) Start() error { func (w *WiFiRecon) Start() error {

View file

@ -1,5 +1,16 @@
package modules package modules
type ByRSSISorter []*WiFiStation
func (a ByRSSISorter) Len() int { return len(a) }
func (a ByRSSISorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByRSSISorter) Less(i, j int) bool {
if a[i].RSSI == a[j].RSSI {
return a[i].HwAddress < a[j].HwAddress
}
return a[i].RSSI > a[j].RSSI
}
type ByChannelSorter []*WiFiStation type ByChannelSorter []*WiFiStation
func (a ByChannelSorter) Len() int { return len(a) } func (a ByChannelSorter) Len() int { return len(a) }
@ -22,10 +33,10 @@ func (a ByEssidSorter) Less(i, j int) bool {
return a[i].ESSID() < a[j].ESSID() return a[i].ESSID() < a[j].ESSID()
} }
type BywifiSeenSorter []*WiFiStation type ByWiFiSeenSorter []*WiFiStation
func (a BywifiSeenSorter) Len() int { return len(a) } func (a ByWiFiSeenSorter) Len() int { return len(a) }
func (a BywifiSeenSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a ByWiFiSeenSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a BywifiSeenSorter) Less(i, j int) bool { func (a ByWiFiSeenSorter) Less(i, j int) bool {
return a[i].LastSeen.After(a[j].LastSeen) return a[i].LastSeen.After(a[j].LastSeen)
} }

View file

@ -8,13 +8,15 @@ type WiFiStation struct {
*network.Endpoint *network.Endpoint
IsAP bool IsAP bool
Channel int Channel int
RSSI int8
} }
func NewWiFiStation(essid, bssid string, isAp bool, channel int) *WiFiStation { func NewWiFiStation(essid, bssid string, isAp bool, channel int, rssi int8) *WiFiStation {
return &WiFiStation{ return &WiFiStation{
Endpoint: network.NewEndpointNoResolve(network.MonitorModeAddress, bssid, essid, 0), Endpoint: network.NewEndpointNoResolve(network.MonitorModeAddress, bssid, essid, 0),
IsAP: isAp, IsAP: isAp,
Channel: channel, Channel: channel,
RSSI: rssi,
} }
} }

View file

@ -2,12 +2,22 @@ package modules
import ( import (
"net" "net"
"strings"
"sync" "sync"
) )
type WiFiStationStats struct { type WiFiStationStats struct {
Sent uint64 Sent uint64
Received uint64 Received uint64
Encryption map[string]bool
}
func NewWiFiStationStats(sent uint64, recvd uint64) *WiFiStationStats {
return &WiFiStationStats{
Sent: sent,
Received: recvd,
Encryption: make(map[string]bool),
}
} }
type WiFiStats struct { type WiFiStats struct {
@ -29,7 +39,7 @@ func (s *WiFiStats) CollectSent(station net.HardwareAddr, bytes uint64) {
if sstats, found := s.stats[bssid]; found == true { if sstats, found := s.stats[bssid]; found == true {
sstats.Sent += bytes sstats.Sent += bytes
} else { } else {
s.stats[bssid] = &WiFiStationStats{Sent: bytes} s.stats[bssid] = NewWiFiStationStats(bytes, 0)
} }
} }
@ -41,7 +51,21 @@ func (s *WiFiStats) CollectReceived(station net.HardwareAddr, bytes uint64) {
if sstats, found := s.stats[bssid]; found == true { if sstats, found := s.stats[bssid]; found == true {
sstats.Received += bytes sstats.Received += bytes
} else { } else {
s.stats[bssid] = &WiFiStationStats{Received: bytes} s.stats[bssid] = NewWiFiStationStats(0, bytes)
}
}
func (s *WiFiStats) CollectEncryption(station net.HardwareAddr, enc string) {
s.Lock()
defer s.Unlock()
bssid := station.String()
if sstats, found := s.stats[bssid]; found == true {
sstats.Encryption[enc] = true
} else {
stats := NewWiFiStationStats(0, 0)
stats.Encryption[enc] = true
s.stats[bssid] = stats
} }
} }
@ -66,3 +90,18 @@ func (s *WiFiStats) SentTo(station net.HardwareAddr) uint64 {
} }
return 0 return 0
} }
func (s *WiFiStats) EncryptionOf(station net.HardwareAddr) string {
s.Lock()
defer s.Unlock()
bssid := station.String()
if sstats, found := s.stats[bssid]; found == true {
unique := make([]string, 0)
for key := range sstats.Encryption {
unique = append(unique, key)
}
return strings.Join(unique, ", ")
}
return ""
}

View file

@ -66,6 +66,11 @@ func Dot11ParseIDSSID(packet gopacket.Packet) (bool, string) {
} }
} }
func Dot11ParseEncryption(packet gopacket.Packet, dot11 *layers.Dot11) (bool, []string) {
// TODO :(
return false, nil
}
func Dot11IsDataFor(dot11 *layers.Dot11, station net.HardwareAddr) bool { func Dot11IsDataFor(dot11 *layers.Dot11, station net.HardwareAddr) bool {
// only check data packets of connected stations // only check data packets of connected stations
if dot11.Type.MainType() != layers.Dot11TypeData { if dot11.Type.MainType() != layers.Dot11TypeData {