new: net.probe on uses both NBNS and MDNS queries to fetch endpoints metadata and hostnames

This commit is contained in:
evilsocket 2018-09-09 12:35:00 +03:00
commit e2cc4574c4
No known key found for this signature in database
GPG key ID: 1564D7F30393A456
8 changed files with 127 additions and 106 deletions

View file

@ -18,54 +18,41 @@ var (
)
func MDNSGetMeta(pkt gopacket.Packet) map[string]string {
meta := make(map[string]string)
if ludp := pkt.Layer(layers.LayerTypeUDP); ludp != nil {
if udp := ludp.(*layers.UDP); udp != nil && udp.SrcPort == MDNSPort && udp.DstPort == MDNSPort {
dns := layers.DNS{}
if err := dns.DecodeFromBytes(udp.Payload, gopacket.NilDecodeFeedback); err == nil {
answers := append(dns.Answers, dns.Additionals...)
answers = append(answers, dns.Authorities...)
for _, answer := range answers {
switch answer.Type {
case layers.DNSTypePTR:
case layers.DNSTypeA:
case layers.DNSTypeAAAA:
meta["mdns:hostname"] = string(answer.Name)
case layers.DNSTypeTXT:
meta := make(map[string]string)
for _, raw := range answer.TXTs {
if value := string(raw); strings.Contains(value, "=") {
parts := strings.SplitN(value, "=", 2)
meta[core.Trim(parts[0])] = core.Trim(parts[1])
}
}
if len(meta) > 0 {
return meta
}
}
}
}
}
}
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 {
dns := layers.DNS{}
if err := dns.DecodeFromBytes(udp.Payload, gopacket.NilDecodeFeedback); err == nil {
answers := append(dns.Answers, dns.Additionals...)
answers = append(answers, dns.Authorities...)
for _, answer := range answers {
switch answer.Type {
case layers.DNSTypePTR:
case layers.DNSTypeA:
case layers.DNSTypeAAAA:
return string(answer.Name)
}
}
}
}
}
return ""
}
func NewMDNSProbe(from net.IP, from_hw net.HardwareAddr) (error, []byte) {
eth := layers.Ethernet{
SrcMAC: from_hw,

36
packets/nbns.go Normal file
View file

@ -0,0 +1,36 @@
package packets
import (
"github.com/bettercap/bettercap/core"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
)
const (
NBNSPort = 137
NBNSMinRespSize = 73
)
var (
// NBNS hostname resolution request buffer.
NBNSRequest = []byte{
0x82, 0x28, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x20, 0x43, 0x4B, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x0,
0x0, 0x21, 0x0, 0x1,
}
)
func NBNSGetMeta(pkt gopacket.Packet) map[string]string {
if ludp := pkt.Layer(layers.LayerTypeUDP); ludp != nil {
if udp := ludp.(*layers.UDP); udp != nil && udp.SrcPort == NBNSPort && len(udp.Payload) >= NBNSMinRespSize {
return map[string]string{
"nbns:hostname": core.Trim(string(udp.Payload[57:72])),
}
}
}
return nil
}

View file

@ -13,11 +13,10 @@ import (
)
type Activity struct {
IP net.IP
MAC net.HardwareAddr
Hostname string
Meta map[string]string
Source bool
IP net.IP
MAC net.HardwareAddr
Meta map[string]string
Source bool
}
type Traffic struct {
@ -114,14 +113,13 @@ func (q *Queue) trackProtocols(pkt gopacket.Packet) {
}
}
func (q *Queue) trackActivity(eth *layers.Ethernet, ip4 *layers.IPv4, address net.IP, hostname string, meta map[string]string, pktSize uint64, isSent bool) {
func (q *Queue) trackActivity(eth *layers.Ethernet, ip4 *layers.IPv4, address net.IP, 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,
IP: address,
MAC: eth.SrcMAC,
Meta: meta,
Source: isSent,
}
q.Lock()
@ -166,6 +164,36 @@ func (q *Queue) TrackError() {
q.Stats.Errors++
}
func (q *Queue) getPacketMeta(pkt gopacket.Packet) map[string]string {
meta := make(map[string]string)
mdns := MDNSGetMeta(pkt)
nbns := NBNSGetMeta(pkt)
if mdns != nil {
for k, v := range mdns {
meta[k] = v
}
}
if nbns != nil {
for k, v := range nbns {
meta[k] = v
}
}
/*
// 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)
if hostname != "" {
meta["mdns:hostname"] = hostname
}
*/
return meta
}
func (q *Queue) worker() {
for pkt := range q.srcChannel {
if !q.active {
@ -194,19 +222,16 @@ 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
hostname := MDNSGetHostname(pkt)
// check if we can get some meta info from mDNS TXT records
meta := MDNSGetMeta(pkt)
meta := q.getPacketMeta(pkt)
q.trackActivity(eth, ip4, ip4.SrcIP, hostname, meta, pktSize, true)
q.trackActivity(eth, ip4, ip4.SrcIP, 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, "", nil, pktSize, false)
q.trackActivity(eth, ip4, ip4.DstIP, nil, pktSize, false)
}
}
}