From 6e73c47dd793fd41fbc7bfb525fa8044dc14fc8a Mon Sep 17 00:00:00 2001 From: evilsocket Date: Sun, 17 Mar 2019 12:46:23 +0100 Subject: [PATCH 1/5] misc: added race detector build to Makefile --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a1d15bfb..0d791f1b 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,9 @@ all: deps build deps: godep golint gofmt gomegacheck @dep ensure +build_with_race_detector: resources + @go build -race -o $(TARGET) . + build: resources @go build -o $(TARGET) . @@ -56,4 +59,4 @@ gomegacheck: @go get honnef.co/go/tools/cmd/megacheck gofmt: - gofmt -s -w $(PACKAGES) \ No newline at end of file + gofmt -s -w $(PACKAGES) From 64a5ce2b5800e9658b479aeab16d5d4fe88178e6 Mon Sep 17 00:00:00 2001 From: evilsocket Date: Sun, 17 Mar 2019 13:12:31 +0100 Subject: [PATCH 2/5] fix: using sync.Map to avoid race conditions on the packets.Queue --- modules/net_recon/net_show.go | 8 ++--- modules/net_recon/net_show_sort.go | 42 +++++++----------------- modules/wifi/wifi_show.go | 3 -- packets/queue.go | 52 +++++++++++------------------- 4 files changed, 34 insertions(+), 71 deletions(-) diff --git a/modules/net_recon/net_show.go b/modules/net_recon/net_show.go index ff793fdb..630f76cf 100644 --- a/modules/net_recon/net_show.go +++ b/modules/net_recon/net_show.go @@ -61,8 +61,11 @@ func (mod *Discovery) getRow(e *network.Endpoint, withMeta bool) [][]string { var traffic *packets.Traffic var found bool - if traffic, found = mod.Session.Queue.Traffic[e.IpAddress]; !found { + var v interface{} + if v, found = mod.Session.Queue.Traffic.Load(e.IpAddress); !found { traffic = &packets.Traffic{} + } else { + traffic = v.(*packets.Traffic) } seen := e.LastSeen.Format("15:04:05") @@ -203,9 +206,6 @@ func (mod *Discovery) colNames(hasMeta bool) []string { } func (mod *Discovery) showStatusBar() { - mod.Session.Queue.Stats.RLock() - defer mod.Session.Queue.Stats.RUnlock() - parts := []string{ 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)), diff --git a/modules/net_recon/net_show_sort.go b/modules/net_recon/net_show_sort.go index 10ad08e5..2109543f 100644 --- a/modules/net_recon/net_show_sort.go +++ b/modules/net_recon/net_show_sort.go @@ -41,24 +41,19 @@ func (a BySeenSorter) Less(i, j int) bool { return a[i].LastSeen.Before(a[j].Las type BySentSorter []*network.Endpoint +func trafficOf(ip string) *packets.Traffic { + if v, found := session.I.Queue.Traffic.Load(ip); !found { + return &packets.Traffic{} + } else { + return v.(*packets.Traffic) + } +} + func (a BySentSorter) Len() int { return len(a) } func (a BySentSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a BySentSorter) Less(i, j int) bool { - session.I.Queue.Lock() - defer session.I.Queue.Unlock() - - var found bool = false - var aTraffic *packets.Traffic = nil - var bTraffic *packets.Traffic = nil - - if aTraffic, found = session.I.Queue.Traffic[a[i].IpAddress]; !found { - aTraffic = &packets.Traffic{} - } - - if bTraffic, found = session.I.Queue.Traffic[a[j].IpAddress]; !found { - bTraffic = &packets.Traffic{} - } - + aTraffic := trafficOf(a[i].IpAddress) + bTraffic := trafficOf(a[j].IpAddress) return bTraffic.Sent > aTraffic.Sent } @@ -67,20 +62,7 @@ type ByRcvdSorter []*network.Endpoint func (a ByRcvdSorter) Len() int { return len(a) } func (a ByRcvdSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a ByRcvdSorter) Less(i, j int) bool { - session.I.Queue.Lock() - defer session.I.Queue.Unlock() - - var found bool = false - var aTraffic *packets.Traffic = nil - var bTraffic *packets.Traffic = nil - - if aTraffic, found = session.I.Queue.Traffic[a[i].IpAddress]; !found { - aTraffic = &packets.Traffic{} - } - - if bTraffic, found = session.I.Queue.Traffic[a[j].IpAddress]; !found { - bTraffic = &packets.Traffic{} - } - + aTraffic := trafficOf(a[i].IpAddress) + bTraffic := trafficOf(a[j].IpAddress) return bTraffic.Received > aTraffic.Received } diff --git a/modules/wifi/wifi_show.go b/modules/wifi/wifi_show.go index 8e45403f..6517c6b2 100644 --- a/modules/wifi/wifi_show.go +++ b/modules/wifi/wifi_show.go @@ -296,9 +296,6 @@ func (mod *WiFiModule) colNames(nrows int) []string { } func (mod *WiFiModule) showStatusBar() { - mod.Session.Queue.Stats.RLock() - defer mod.Session.Queue.Stats.RUnlock() - parts := []string{ 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)), diff --git a/packets/queue.go b/packets/queue.go index 94aef1a1..a3a1b44e 100644 --- a/packets/queue.go +++ b/packets/queue.go @@ -4,6 +4,7 @@ import ( "fmt" "net" "sync" + "sync/atomic" "github.com/bettercap/bettercap/network" @@ -25,8 +26,6 @@ type Traffic struct { } type Stats struct { - sync.RWMutex - Sent uint64 Received uint64 PktReceived uint64 @@ -39,10 +38,9 @@ type Queue struct { sync.RWMutex Activities chan Activity `json:"-"` - - Stats Stats - Protos map[string]uint64 - Traffic map[string]*Traffic + Stats Stats + Protos sync.Map + Traffic sync.Map iface *network.Endpoint handle *pcap.Handle @@ -55,8 +53,8 @@ type Queue struct { func NewQueue(iface *network.Endpoint) (q *Queue, err error) { q = &Queue{ - Protos: make(map[string]uint64), - Traffic: make(map[string]*Traffic), + Protos: sync.Map{}, + Traffic: sync.Map{}, Activities: make(chan Activity), writes: &sync.WaitGroup{}, @@ -102,14 +100,12 @@ func (q *Queue) trackProtocols(pkt gopacket.Packet) { continue } - q.Lock() name := proto.String() - if _, found := q.Protos[name]; !found { - q.Protos[name] = 1 + if v, found := q.Protos.Load(name); !found { + q.Protos.Store(name, 1) } else { - q.Protos[name]++ + q.Protos.Store(name, v.(int)+1) } - q.Unlock() } } @@ -122,46 +118,34 @@ func (q *Queue) trackActivity(eth *layers.Ethernet, ip4 *layers.IPv4, address ne Source: isSent, } - q.Lock() - defer q.Unlock() - // initialize or update stats addr := address.String() - if _, found := q.Traffic[addr]; !found { + if v, found := q.Traffic.Load(addr); !found { if isSent { - q.Traffic[addr] = &Traffic{Sent: pktSize} + q.Traffic.Store(addr, &Traffic{Sent: pktSize}) } else { - q.Traffic[addr] = &Traffic{Received: pktSize} + q.Traffic.Store(addr, &Traffic{Received: pktSize}) } } else { if isSent { - q.Traffic[addr].Sent += pktSize + v.(*Traffic).Sent += pktSize } else { - q.Traffic[addr].Received += pktSize + v.(*Traffic).Received += pktSize } } } func (q *Queue) TrackPacket(size uint64) { - q.Stats.Lock() - defer q.Stats.Unlock() - - q.Stats.PktReceived++ - q.Stats.Received += size + atomic.AddUint64(&q.Stats.PktReceived, 1) + atomic.AddUint64(&q.Stats.Received, size) } func (q *Queue) TrackSent(size uint64) { - q.Stats.Lock() - defer q.Stats.Unlock() - - q.Stats.Sent += size + atomic.AddUint64(&q.Stats.Sent, size) } func (q *Queue) TrackError() { - q.Stats.Lock() - defer q.Stats.Unlock() - - q.Stats.Errors++ + atomic.AddUint64(&q.Stats.Errors, 1) } func (q *Queue) getPacketMeta(pkt gopacket.Packet) map[string]string { From d6e67468099ca228d1464b8033ba0c629e9a1557 Mon Sep 17 00:00:00 2001 From: evilsocket Date: Sun, 17 Mar 2019 13:36:59 +0100 Subject: [PATCH 3/5] fix: setting BLE device name once services are enumerated --- modules/ble/ble_show_services.go | 4 ++++ network/ble_device.go | 13 ++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/modules/ble/ble_show_services.go b/modules/ble/ble_show_services.go index bb1ffc86..ffff0cae 100644 --- a/modules/ble/ble_show_services.go +++ b/modules/ble/ble_show_services.go @@ -367,6 +367,10 @@ func (mod *BLERecon) showServices(p gatt.Peripheral, services []*gatt.Service) { data = parseRawData(raw) } + if ch.Name() == "Device Name" && data != "" && mod.currDevice.DeviceName == "" { + mod.currDevice.DeviceName = data + } + if multi == nil { char.Data = data rows = append(rows, []string{ diff --git a/network/ble_device.go b/network/ble_device.go index 1b363dd7..3cb115aa 100644 --- a/network/ble_device.go +++ b/network/ble_device.go @@ -28,6 +28,7 @@ type BLEService struct { type BLEDevice struct { LastSeen time.Time + DeviceName string Vendor string RSSI int Device gatt.Peripheral @@ -62,9 +63,15 @@ func NewBLEDevice(p gatt.Peripheral, a *gatt.Advertisement, rssi int) *BLEDevice } func (d *BLEDevice) Name() string { - name := d.Device.Name() - if name == "" && d.Advertisement != nil { - name = d.Advertisement.LocalName + // get the name if it's being set during services enumeration via 'Device Name' + name := d.DeviceName + if name == "" { + // get the name from the device + name := d.Device.Name() + if name == "" && d.Advertisement != nil { + // get the name from the advertisement data + name = d.Advertisement.LocalName + } } return name } From 255102c250152be0a43e16d45772054a9c00b419 Mon Sep 17 00:00:00 2001 From: evilsocket Date: Sun, 17 Mar 2019 14:01:30 +0100 Subject: [PATCH 4/5] fix: allow wifi modules to use network aliases for clients never seen on lan --- modules/wifi/wifi_recon.go | 2 +- modules/wifi/wifi_recon_handshakes.go | 2 +- network/lan.go | 2 +- network/wifi_ap.go | 11 ++++++++++- session/session_core_handlers.go | 8 ++------ 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/modules/wifi/wifi_recon.go b/modules/wifi/wifi_recon.go index 6e62d0d9..dab0360b 100644 --- a/modules/wifi/wifi_recon.go +++ b/modules/wifi/wifi_recon.go @@ -124,7 +124,7 @@ func (mod *WiFiModule) discoverClients(radiotap *layers.RadioTap, dot11 *layers. freq := int(radiotap.ChannelFrequency) rssi := radiotap.DBMAntennaSignal - if station, isNew := ap.AddClientIfNew(bssid, freq, rssi); isNew { + if station, isNew := ap.AddClientIfNew(bssid, freq, rssi, mod.Session.Lan.Aliases()); isNew { mod.Session.Events.Add("wifi.client.new", ClientEvent{ AP: ap, Client: station, diff --git a/modules/wifi/wifi_recon_handshakes.go b/modules/wifi/wifi_recon_handshakes.go index a8eb676e..7c5045a5 100644 --- a/modules/wifi/wifi_recon_handshakes.go +++ b/modules/wifi/wifi_recon_handshakes.go @@ -36,7 +36,7 @@ func (mod *WiFiModule) discoverHandshakes(radiotap *layers.RadioTap, dot11 *laye staIsUs := bytes.Equal(staMac, mod.iface.HW) station, found := ap.Get(staMac.String()) if !found { - station, _ = ap.AddClientIfNew(staMac.String(), ap.Frequency, ap.RSSI) + station, _ = ap.AddClientIfNew(staMac.String(), ap.Frequency, ap.RSSI, mod.Session.Lan.Aliases()) } rawPMKID := []byte(nil) diff --git a/network/lan.go b/network/lan.go index 953ef882..9363c0ba 100644 --- a/network/lan.go +++ b/network/lan.go @@ -68,8 +68,8 @@ func (lan *LAN) SetAliasFor(mac, alias string) bool { defer lan.Unlock() mac = NormalizeMac(mac) + lan.aliases.Set(mac, alias) if e, found := lan.hosts[mac]; found { - lan.aliases.Set(mac, alias) e.Alias = alias return true } diff --git a/network/wifi_ap.go b/network/wifi_ap.go index afaf9c14..ec864916 100644 --- a/network/wifi_ap.go +++ b/network/wifi_ap.go @@ -4,6 +4,8 @@ import ( "encoding/json" "sync" "time" + + "github.com/evilsocket/islazy/data" ) type AccessPoint struct { @@ -65,7 +67,7 @@ func (ap *AccessPoint) RemoveClient(mac string) { } } -func (ap *AccessPoint) AddClientIfNew(bssid string, frequency int, rssi int8) (*Station, bool) { +func (ap *AccessPoint) AddClientIfNew(bssid string, frequency int, rssi int8, aliases *data.UnsortedKV) (*Station, bool) { ap.Lock() defer ap.Unlock() @@ -77,10 +79,17 @@ func (ap *AccessPoint) AddClientIfNew(bssid string, frequency int, rssi int8) (* s.RSSI = rssi s.LastSeen = time.Now() + if aliases != nil { + s.Alias = aliases.GetOr(bssid, "") + } + return s, false } s := NewStation("", bssid, frequency, rssi) + if aliases != nil { + s.Alias = aliases.GetOr(bssid, "") + } ap.clients[bssid] = s return s, true diff --git a/session/session_core_handlers.go b/session/session_core_handlers.go index 90b0b3d4..1a8fa83e 100644 --- a/session/session_core_handlers.go +++ b/session/session_core_handlers.go @@ -274,12 +274,8 @@ func (s *Session) shHandler(args []string, sess *Session) error { func (s *Session) aliasHandler(args []string, sess *Session) error { mac := args[0] alias := str.Trim(args[1]) - - if s.Lan.SetAliasFor(mac, alias) { - return nil - } else { - return fmt.Errorf("Could not find endpoint %s", mac) - } + s.Lan.SetAliasFor(mac, alias) + return nil } func (s *Session) addHandler(h CommandHandler, c *readline.PrefixCompleter) { From b9c49824571274f4eec2b2c49f6fe6d4fec64a22 Mon Sep 17 00:00:00 2001 From: evilsocket Date: Sun, 17 Mar 2019 14:21:21 +0100 Subject: [PATCH 5/5] fix: fixed packets.Queue JSON serialization for api.rest module --- packets/queue.go | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/packets/queue.go b/packets/queue.go index a3a1b44e..9546f738 100644 --- a/packets/queue.go +++ b/packets/queue.go @@ -1,6 +1,7 @@ package packets import ( + "encoding/json" "fmt" "net" "sync" @@ -21,15 +22,15 @@ type Activity struct { } type Traffic struct { - Sent uint64 - Received uint64 + Sent uint64 `json:"sent"` + Received uint64 `json:"received"` } type Stats struct { - Sent uint64 - Received uint64 - PktReceived uint64 - Errors uint64 + Sent uint64 `json:"sent"` + Received uint64 `json:"received"` + PktReceived uint64 `json:"pkts_received"` + Errors uint64 `json:"errors"` } type PacketCallback func(pkt gopacket.Packet) @@ -37,7 +38,7 @@ type PacketCallback func(pkt gopacket.Packet) type Queue struct { sync.RWMutex - Activities chan Activity `json:"-"` + Activities chan Activity Stats Stats Protos sync.Map Traffic sync.Map @@ -51,6 +52,12 @@ type Queue struct { active bool } +type queueJSON struct { + Stats Stats `json:"stats"` + Protos map[string]int `json:"protos"` + Traffic map[string]*Traffic `json:"traffic"` +} + func NewQueue(iface *network.Endpoint) (q *Queue, err error) { q = &Queue{ Protos: sync.Map{}, @@ -76,6 +83,28 @@ func NewQueue(iface *network.Endpoint) (q *Queue, err error) { return } +func (q *Queue) MarshalJSON() ([]byte, error) { + q.Lock() + defer q.Unlock() + doc := queueJSON{ + Stats: q.Stats, + Protos: make(map[string]int), + Traffic: make(map[string]*Traffic), + } + + q.Protos.Range(func(k, v interface{}) bool { + doc.Protos[k.(string)] = v.(int) + return true + }) + + q.Traffic.Range(func(k, v interface{}) bool { + doc.Traffic[k.(string)] = v.(*Traffic) + return true + }) + + return json.Marshal(doc) +} + func (q *Queue) OnPacket(cb PacketCallback) { q.Lock() defer q.Unlock()