diff --git a/modules/net_recon_show.go b/modules/net_recon_show.go index 23f2b938..f9eeb694 100644 --- a/modules/net_recon_show.go +++ b/modules/net_recon_show.go @@ -89,10 +89,11 @@ func (d *Discovery) getRow(e *network.Endpoint, withMeta bool) []string { if withMeta { metas := []string{} e.Meta.Each(func(name string, value interface{}) { - metas = append(metas, fmt.Sprintf("%s: %s", name, value.(string))) + metas = append(metas, fmt.Sprintf("%s=%s", core.Bold(name), core.Yellow(value.(string)))) }) - row = append(row, strings.Join(metas, "\n")) + sort.Strings(metas) + row = append(row, strings.Join(metas, ", ")) } return row diff --git a/packets/mdns.go b/packets/mdns.go index d84d8382..bb50885b 100644 --- a/packets/mdns.go +++ b/packets/mdns.go @@ -1,6 +1,10 @@ package packets import ( + "strings" + + "github.com/bettercap/bettercap/core" + "github.com/google/gopacket" "github.com/google/gopacket/layers" @@ -9,6 +13,33 @@ import ( const MDNSPort = 5353 +func MDNSGetMeta(pkt gopacket.Packet) map[string]string { + if ludp := pkt.Layer(layers.LayerTypeUDP); ludp != nil { + if udp := ludp.(*layers.UDP); udp != nil && udp.SrcPort == MDNSPort && udp.DstPort == MDNSPort { + var msg dns.Msg + if err := msg.Unpack(udp.Payload); err == nil && msg.Opcode == dns.OpcodeQuery && len(msg.Answer) > 0 { + for _, answer := range append(msg.Answer, msg.Extra...) { + switch answer.(type) { + case *dns.TXT: + meta := make(map[string]string) + txt := answer.(*dns.TXT) + for _, value := range txt.Txt { + if strings.Contains(value, "=") { + parts := strings.SplitN(value, "=", 2) + meta[core.Trim(parts[0])] = core.Trim(parts[1]) + } + } + if len(meta) > 0 { + return meta + } + } + } + } + } + } + return nil +} + func MDNSGetHostname(pkt gopacket.Packet) string { if ludp := pkt.Layer(layers.LayerTypeUDP); ludp != nil { if udp := ludp.(*layers.UDP); udp != nil && udp.SrcPort == MDNSPort && udp.DstPort == MDNSPort { diff --git a/packets/queue.go b/packets/queue.go index 0e6fcabf..1a617ba9 100644 --- a/packets/queue.go +++ b/packets/queue.go @@ -16,6 +16,7 @@ type Activity struct { IP net.IP MAC net.HardwareAddr Hostname string + Meta map[string]string Source bool } @@ -113,12 +114,13 @@ func (q *Queue) trackProtocols(pkt gopacket.Packet) { } } -func (q *Queue) trackActivity(eth *layers.Ethernet, ip4 *layers.IPv4, address net.IP, hostname string, pktSize uint64, isSent bool) { +func (q *Queue) trackActivity(eth *layers.Ethernet, ip4 *layers.IPv4, address net.IP, hostname string, meta map[string]string, pktSize uint64, isSent bool) { // push to activity channel q.Activities <- Activity{ IP: address, MAC: eth.SrcMAC, Hostname: hostname, + Meta: meta, Source: isSent, } @@ -192,17 +194,19 @@ func (q *Queue) worker() { isFromMe := q.iface.IP.Equal(ip4.SrcIP) isFromLAN := q.iface.Net.Contains(ip4.SrcIP) if !isFromMe && isFromLAN { - // check if the packet is a useful MDNS query response + // check if the packet is a useful mDNS query response hostname := MDNSGetHostname(pkt) + // check if we can get some meta info from mDNS TXT records + meta := MDNSGetMeta(pkt) - q.trackActivity(eth, ip4, ip4.SrcIP, hostname, pktSize, true) + q.trackActivity(eth, ip4, ip4.SrcIP, hostname, meta, pktSize, true) } // something going to someone on the LAN isToMe := q.iface.IP.Equal(ip4.DstIP) isToLAN := q.iface.Net.Contains(ip4.DstIP) if !isToMe && isToLAN { - q.trackActivity(eth, ip4, ip4.DstIP, "", pktSize, false) + q.trackActivity(eth, ip4, ip4.DstIP, "", nil, pktSize, false) } } } diff --git a/session/session_setup.go b/session/session_setup.go index b2488191..ab001d17 100644 --- a/session/session_setup.go +++ b/session/session_setup.go @@ -94,8 +94,15 @@ func (s *Session) startNetMon() { existing, _ = s.Lan.Get(mac) } - if existing != nil && existing.Hostname == "" && event.Hostname != "" { - existing.Hostname = event.Hostname + if existing != nil { + if existing.Hostname == "" && event.Hostname != "" { + existing.Hostname = event.Hostname + } + if event.Meta != nil { + for k, v := range event.Meta { + existing.Meta.Set(k, v) + } + } } } }