misc: small fix or general refactoring i did not bother commenting

This commit is contained in:
Simone Margaritelli 2024-09-21 17:38:52 +02:00
parent 2966153adf
commit 26c532316a
21 changed files with 355 additions and 75 deletions

View file

@ -134,8 +134,8 @@ func (mod *EventsStream) Render(output io.Writer, e session.Event) {
mod.viewUpdateEvent(output, e) mod.viewUpdateEvent(output, e)
} else if e.Tag == "gateway.change" { } else if e.Tag == "gateway.change" {
mod.viewGatewayEvent(output, e) mod.viewGatewayEvent(output, e)
} else if e.Tag == "mdns.service" { } else if strings.HasPrefix(e.Tag, "zeroconf.") {
mod.viewMDNSEvent(output, e) mod.viewZeroConfEvent(output, e)
} else if e.Tag != "tick" && e.Tag != "session.started" && e.Tag != "session.stopped" { } else if e.Tag != "tick" && e.Tag != "session.started" && e.Tag != "session.stopped" {
fmt.Fprintf(output, "[%s] [%s] %v\n", e.Time.Format(mod.timeFormat), tui.Green(e.Tag), e) fmt.Fprintf(output, "[%s] [%s] %v\n", e.Time.Format(mod.timeFormat), tui.Green(e.Tag), e)
} }

View file

@ -1,23 +0,0 @@
package events_stream
import (
"fmt"
"io"
"github.com/bettercap/bettercap/v2/modules/zerogod"
"github.com/bettercap/bettercap/v2/session"
"github.com/evilsocket/islazy/tui"
)
func (mod *EventsStream) viewMDNSEvent(output io.Writer, e session.Event) {
event := e.Data.(zerogod.ServiceDiscoveryEvent)
fmt.Fprintf(output, "[%s] [%s] service %s detected for %s (%s):%d with %d records\n",
e.Time.Format(mod.timeFormat),
tui.Green(e.Tag),
tui.Bold(event.Service.ServiceInstanceName()),
event.Service.AddrIPv4,
tui.Dim(event.Service.HostName),
event.Service.Port,
len(event.Service.Text),
)
}

View file

@ -0,0 +1,62 @@
package events_stream
import (
"fmt"
"io"
"strings"
"github.com/bettercap/bettercap/v2/modules/zerogod"
"github.com/bettercap/bettercap/v2/session"
"github.com/evilsocket/islazy/tui"
)
func (mod *EventsStream) viewZeroConfEvent(output io.Writer, e session.Event) {
if e.Tag == "zeroconf.service" {
event := e.Data.(zerogod.ServiceDiscoveryEvent)
fmt.Fprintf(output, "[%s] [%s] service %s detected for %s (%s):%d with %d records\n",
e.Time.Format(mod.timeFormat),
tui.Green(e.Tag),
tui.Bold(event.Service.ServiceInstanceName()),
event.Service.AddrIPv4,
tui.Dim(event.Service.HostName),
event.Service.Port,
len(event.Service.Text),
)
} else if e.Tag == "zeroconf.browsing" {
event := e.Data.(zerogod.BrowsingEvent)
source := event.Source
if event.Endpoint != nil {
source = event.Endpoint.ShortString()
}
services := make([]string, 0)
for _, q := range event.Query.Questions {
services = append(services, tui.Yellow(string(q.Name)))
}
/*
instances := make([]string, 0)
answers := append(event.Query.Answers, event.Query.Additionals...)
for _, answer := range answers {
if answer.Class == layers.DNSClassIN && answer.Type == layers.DNSTypePTR {
instances = append(instances, tui.Green(string(answer.PTR)))
} else {
instances = append(instances, tui.Green(answer.String()))
}
}
advPart := ""
if len(instances) > 0 {
advPart = fmt.Sprintf(" and advertising %s", strings.Join(instances, ", "))
}
*/
fmt.Fprintf(output, "[%s] [%s] %s is browsing for services %s\n",
e.Time.Format(mod.timeFormat),
tui.Green(e.Tag),
source,
strings.Join(services, ", "),
)
} else {
fmt.Fprintf(output, "[%s] [%s] %v\n", e.Time.Format(mod.timeFormat), tui.Green(e.Tag), e)
}
}

View file

@ -3,10 +3,14 @@ package zerogod
import ( import (
"github.com/bettercap/bettercap/v2/session" "github.com/bettercap/bettercap/v2/session"
"github.com/bettercap/bettercap/v2/tls" "github.com/bettercap/bettercap/v2/tls"
"github.com/google/gopacket"
"github.com/google/gopacket/pcap"
) )
type ZeroGod struct { type ZeroGod struct {
session.SessionModule session.SessionModule
sniffer *pcap.Handle
snifferCh chan gopacket.Packet
browser *Browser browser *Browser
advertiser *Advertiser advertiser *Advertiser
} }
@ -14,8 +18,6 @@ type ZeroGod struct {
func NewZeroGod(s *session.Session) *ZeroGod { func NewZeroGod(s *session.Session) *ZeroGod {
mod := &ZeroGod{ mod := &ZeroGod{
SessionModule: session.NewSessionModule("zerogod", s), SessionModule: session.NewSessionModule("zerogod", s),
browser: nil,
advertiser: nil,
} }
mod.SessionModule.Requires("net.recon") mod.SessionModule.Requires("net.recon")
@ -115,12 +117,6 @@ func (mod *ZeroGod) Configure() (err error) {
return session.ErrAlreadyStarted(mod.Name()) return session.ErrAlreadyStarted(mod.Name())
} }
if mod.browser != nil {
mod.browser.Stop(false)
}
mod.browser = NewBrowser()
return return
} }
@ -130,7 +126,7 @@ func (mod *ZeroGod) Start() (err error) {
} }
// start the root discovery // start the root discovery
if err = mod.startResolver(DNSSD_DISCOVERY_SERVICE); err != nil { if err = mod.startDiscovery(DNSSD_DISCOVERY_SERVICE); err != nil {
return err return err
} }
@ -144,14 +140,6 @@ func (mod *ZeroGod) Start() (err error) {
func (mod *ZeroGod) Stop() error { func (mod *ZeroGod) Stop() error {
return mod.SetRunning(false, func() { return mod.SetRunning(false, func() {
mod.stopAdvertiser() mod.stopAdvertiser()
if mod.browser != nil { mod.stopDiscovery()
mod.Debug("stopping discovery")
mod.browser.Stop(true)
mod.Debug("stopped")
mod.browser = nil
}
}) })
} }

View file

@ -7,6 +7,7 @@ import (
"net" "net"
"strings" "strings"
"github.com/evilsocket/islazy/ops"
"github.com/evilsocket/islazy/tui" "github.com/evilsocket/islazy/tui"
) )
@ -30,10 +31,12 @@ var TCP_HANDLERS = map[string]Handler{
type Acceptor struct { type Acceptor struct {
mod *ZeroGod mod *ZeroGod
srvHost string srvHost string
proto string
port uint16 port uint16
service string service string
tlsConfig *tls.Config tlsConfig *tls.Config
listener net.Listener tcpListener net.Listener
udpListener *net.UDPConn
running bool running bool
context context.Context context context.Context
ctxCancel context.CancelFunc ctxCancel context.CancelFunc
@ -53,9 +56,12 @@ type HandlerContext struct {
func NewAcceptor(mod *ZeroGod, service string, srvHost string, port uint16, tlsConfig *tls.Config, ippAttributes map[string]string) *Acceptor { func NewAcceptor(mod *ZeroGod, service string, srvHost string, port uint16, tlsConfig *tls.Config, ippAttributes map[string]string) *Acceptor {
context, ctcCancel := context.WithCancel(context.Background()) context, ctcCancel := context.WithCancel(context.Background())
proto := ops.Ternary(strings.Contains(service, "_tcp"), "tcp", "udp").(string)
acceptor := Acceptor{ acceptor := Acceptor{
mod: mod, mod: mod,
port: port, port: port,
proto: proto,
service: service, service: service,
context: context, context: context,
ctxCancel: ctcCancel, ctxCancel: ctcCancel,
@ -72,36 +78,34 @@ func NewAcceptor(mod *ZeroGod, service string, srvHost string, port uint16, tlsC
} }
if acceptor.handler.Handle == nil { if acceptor.handler.Handle == nil {
mod.Warning("no protocol handler found for service %s, using generic dump handler", tui.Yellow(service)) mod.Warning("no protocol handler found for service %s, using generic %s dump handler", tui.Yellow(service), proto)
acceptor.handler.Handle = handleGenericTCP acceptor.handler.Handle = handleGenericTCP
} else { } else {
mod.Info("found %s protocol handler", tui.Green(service)) mod.Info("found %s %s protocol handler", proto, tui.Green(service))
} }
return &acceptor return &acceptor
} }
func (a *Acceptor) Start() (err error) { func (a *Acceptor) startTCP() (err error) {
var lc net.ListenConfig var lc net.ListenConfig
if a.tcpListener, err = lc.Listen(a.context, "tcp", fmt.Sprintf("0.0.0.0:%d", a.port)); err != nil {
if a.listener, err = lc.Listen(a.context, "tcp", fmt.Sprintf("0.0.0.0:%d", a.port)); err != nil {
return err return err
} }
if a.tlsConfig != nil { if a.tlsConfig != nil {
a.listener = tls.NewListener(a.listener, a.tlsConfig) a.tcpListener = tls.NewListener(a.tcpListener, a.tlsConfig)
} }
a.running = true a.running = true
go func() { go func() {
a.mod.Debug("tcp listener for port %d (%s) started", a.port, tui.Green(a.service)) a.mod.Debug("%s listener for port %d (%s) started", a.proto, a.port, tui.Green(a.service))
for a.running { for a.running {
if conn, err := a.listener.Accept(); err != nil { if conn, err := a.tcpListener.Accept(); err != nil {
if a.running { if a.running {
a.mod.Error("%v", err) a.mod.Error("%v", err)
} }
} else { } else {
a.mod.Debug("accepted connection for service %s (port %d): %v", tui.Green(a.service), a.port, conn.RemoteAddr()) a.mod.Debug("accepted %s connection for service %s (port %d): %v", a.proto, tui.Green(a.service), a.port, conn.RemoteAddr())
go a.handler.Handle(&HandlerContext{ go a.handler.Handle(&HandlerContext{
service: a.service, service: a.service,
mod: a.mod, mod: a.mod,
@ -113,17 +117,60 @@ func (a *Acceptor) Start() (err error) {
}) })
} }
} }
a.mod.Debug("tcp listener for port %d (%s) stopped", a.port, tui.Green(a.service)) a.mod.Debug("%s listener for port %d (%s) stopped", a.proto, a.port, tui.Green(a.service))
}() }()
return nil return nil
} }
func (a *Acceptor) Stop() { func (a *Acceptor) startUDP() (err error) {
a.mod.Debug("stopping tcp listener for port %d", a.port) if udpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("0.0.0.0:%d", a.port)); err != nil {
a.running = false return err
a.ctxCancel() } else if a.udpListener, err = net.ListenUDP("udp", udpAddr); err != nil {
<-a.context.Done() return err
a.listener.Close() } else {
a.mod.Debug("tcp listener for port %d stopped", a.port) a.running = true
go func() {
var buffer [4096]byte
a.mod.Info("%s listener for port %d (%s) started", a.proto, a.port, tui.Green(a.service))
for a.running {
if n, addr, err := a.udpListener.ReadFromUDP(buffer[0:]); err != nil {
a.mod.Warning("error reading udp packet: %v", err)
} else if n <= 0 {
a.mod.Info("empty read")
} else {
a.mod.Info("%v:\n%s", addr, Dump(buffer[0:n]))
}
}
a.mod.Info("%s listener for port %d (%s) stopped", a.proto, a.port, tui.Green(a.service))
}()
}
return nil
}
func (a *Acceptor) Start() (err error) {
if a.proto == "tcp" {
return a.startTCP()
} else {
return a.startUDP()
}
}
func (a *Acceptor) Stop() {
a.mod.Debug("stopping %s listener for port %d", a.proto, a.port)
a.running = false
if a.proto == "tcp" {
a.ctxCancel()
<-a.context.Done()
a.tcpListener.Close()
} else {
a.udpListener.Close()
}
a.mod.Debug("%s listener for port %d stopped", a.proto, a.port)
} }

View file

@ -5,6 +5,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"math/rand"
"net"
"os" "os"
"strings" "strings"
"time" "time"
@ -20,6 +22,27 @@ type Advertiser struct {
Acceptors []*Acceptor Acceptors []*Acceptor
} }
func isPortAvailable(port int) bool {
address := fmt.Sprintf("127.0.0.1:%d", port)
if conn, err := net.DialTimeout("tcp", address, 10*time.Millisecond); err != nil {
return true
} else if conn == nil {
return true
} else {
conn.Close()
return false
}
}
func isPortRequested(svc *ServiceData, services []*ServiceData) bool {
for _, other := range services {
if svc != other && svc.Port == other.Port {
return true
}
}
return false
}
func (mod *ZeroGod) loadTLSConfig() (*tls.Config, error) { func (mod *ZeroGod) loadTLSConfig() (*tls.Config, error) {
var certFile string var certFile string
var keyFile string var keyFile string
@ -104,6 +127,21 @@ func (mod *ZeroGod) startAdvertiser(fileName string) error {
Acceptors: make([]*Acceptor, 0), Acceptors: make([]*Acceptor, 0),
} }
// fix ports
for _, svc := range advertiser.Services {
// if no external responder has been specified, check if port is available
if svc.Responder == "" {
for svc.Port == 0 || !isPortAvailable(svc.Port) || isPortRequested(svc, services) {
newPort := (rand.Intn(65535-1024) + 1024)
mod.Warning("port %d for service %s is not avaialble, trying %d ...",
svc.Port,
svc.FullName(),
newPort)
svc.Port = newPort
}
}
}
// paralleize initialization // paralleize initialization
svcChan := make(chan error, numServices) svcChan := make(chan error, numServices)
for _, svc := range advertiser.Services { for _, svc := range advertiser.Services {

View file

@ -4,7 +4,7 @@ import (
"context" "context"
"sort" "sort"
"github.com/bettercap/bettercap/v2/zeroconf" "github.com/bettercap/bettercap/v2/modules/zerogod/zeroconf"
"github.com/evilsocket/islazy/tui" "github.com/evilsocket/islazy/tui"
) )

View file

@ -1,19 +1,31 @@
package zerogod package zerogod
import ( import (
"net"
"strings" "strings"
"time"
"github.com/bettercap/bettercap/v2/modules/zerogod/zeroconf"
"github.com/bettercap/bettercap/v2/network" "github.com/bettercap/bettercap/v2/network"
"github.com/bettercap/bettercap/v2/session" "github.com/bettercap/bettercap/v2/session"
"github.com/bettercap/bettercap/v2/zeroconf"
"github.com/evilsocket/islazy/tui" "github.com/evilsocket/islazy/tui"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
) )
// a service has been discovered
type ServiceDiscoveryEvent struct { type ServiceDiscoveryEvent struct {
Service zeroconf.ServiceEntry `json:"service"` Service zeroconf.ServiceEntry `json:"service"`
Endpoint *network.Endpoint `json:"endpoint"` Endpoint *network.Endpoint `json:"endpoint"`
} }
// an endpoint is browsing for specific services
type BrowsingEvent struct {
Source string `json:"source"`
Query layers.DNS `json:"service"`
Endpoint *network.Endpoint `json:"endpoint"`
}
func (mod *ZeroGod) onServiceDiscovered(svc *zeroconf.ServiceEntry) { func (mod *ZeroGod) onServiceDiscovered(svc *zeroconf.ServiceEntry) {
mod.Debug("%++v", *svc) mod.Debug("%++v", *svc)
@ -21,8 +33,15 @@ func (mod *ZeroGod) onServiceDiscovered(svc *zeroconf.ServiceEntry) {
svcName := strings.Replace(svc.Instance, ".local", "", 1) svcName := strings.Replace(svc.Instance, ".local", "", 1)
if !mod.browser.HasResolverFor(svcName) { if !mod.browser.HasResolverFor(svcName) {
mod.Debug("discovered service %s", tui.Green(svcName)) mod.Debug("discovered service %s", tui.Green(svcName))
if err := mod.startResolver(svcName); err != nil { if ch, err := mod.browser.StartBrowsing(svcName, "local.", mod); err != nil {
mod.Error("%v", err) mod.Error("%v", err)
} else {
// start listening on this channel
go func() {
for entry := range ch {
mod.onServiceDiscovered(entry)
}
}()
} }
} }
return return
@ -58,17 +77,116 @@ func (mod *ZeroGod) onServiceDiscovered(svc *zeroconf.ServiceEntry) {
mod.Debug("got mdns entry for unknown ip: %++v", *svc) mod.Debug("got mdns entry for unknown ip: %++v", *svc)
} }
session.I.Events.Add("mdns.service", event) session.I.Events.Add("zeroconf.service", event)
session.I.Refresh() session.I.Refresh()
} }
func (mod *ZeroGod) startResolver(service string) error { func (mod *ZeroGod) onPacket(pkt gopacket.Packet) {
mod.Debug("%++v", pkt)
netLayer := pkt.NetworkLayer()
if netLayer == nil {
mod.Warning("not network layer in packet %+v", pkt)
return
}
var srcIP net.IP
// var dstIP net.IP
switch netLayer.LayerType() {
case layers.LayerTypeIPv4:
ip := netLayer.(*layers.IPv4)
srcIP = ip.SrcIP
// dstIP = ip.DstIP
case layers.LayerTypeIPv6:
ip := netLayer.(*layers.IPv6)
srcIP = ip.SrcIP
// dstIP = ip.DstIP
default:
mod.Warning("unexpected network layer type %v in packet %+v", netLayer.LayerType(), pkt)
return
}
// not interested in packet generated by us
if srcIP.Equal(mod.Session.Interface.IP) || srcIP.Equal(mod.Session.Interface.IPv6) {
mod.Debug("skipping local packet")
return
}
udp := pkt.Layer(layers.LayerTypeUDP)
if udp == nil {
mod.Warning("not udp layer in packet %+v", pkt)
return
}
dns := layers.DNS{}
if err := dns.DecodeFromBytes(udp.LayerPayload(), gopacket.NilDecodeFeedback); err != nil {
mod.Warning("could not decode DNS (%v) in packet %+v", err, pkt)
return
}
// since the browser is already checking for these, we are only interested in queries
numQs := len(dns.Questions)
if numQs == 0 {
mod.Debug("skipping answers only packet")
return
}
event := BrowsingEvent{
Source: srcIP.String(),
Query: dns,
Endpoint: mod.Session.Lan.GetByIp(srcIP.String()),
}
if event.Endpoint == nil {
// TODO: if nil, this is probably an IPv6 only record, try to somehow check which known IPv4 it is
// TODO: make configurable?
mod.Debug("got mdns packet from unknown ip %s: %++v", srcIP, dns)
return
}
session.I.Events.Add("zeroconf.browsing", event)
session.I.Refresh()
}
func (mod *ZeroGod) startDiscovery(service string) (err error) {
mod.Debug("starting resolver for service %s", tui.Yellow(service)) mod.Debug("starting resolver for service %s", tui.Yellow(service))
// create passive sniffer
if mod.sniffer != nil {
mod.sniffer.Close()
}
readTimeout := 500 * time.Millisecond
if mod.sniffer, err = network.CaptureWithTimeout(mod.Session.Interface.Name(), readTimeout); err != nil {
return err
} else if err = mod.sniffer.SetBPFFilter("udp and port 5353"); err != nil {
return err
}
// prepare source and start listening for packets
src := gopacket.NewPacketSource(mod.sniffer, mod.sniffer.LinkType())
mod.snifferCh = src.Packets()
// start listening for new packets
go func() {
mod.Debug("sniffer started")
for pkt := range mod.snifferCh {
if !mod.Running() {
mod.Debug("end pkt loop (pkt=%v)", pkt)
break
}
mod.onPacket(pkt)
}
mod.Debug("sniffer stopped")
}()
// create service browser
if mod.browser != nil {
mod.browser.Stop(false)
}
mod.browser = NewBrowser()
// start active browsing
if ch, err := mod.browser.StartBrowsing(service, "local.", mod); err != nil { if ch, err := mod.browser.StartBrowsing(service, "local.", mod); err != nil {
return err return err
} else { } else {
// start listening // start listening for new services
go func() { go func() {
for entry := range ch { for entry := range ch {
mod.onServiceDiscovered(entry) mod.onServiceDiscovered(entry)
@ -78,3 +196,21 @@ func (mod *ZeroGod) startResolver(service string) error {
return nil return nil
} }
func (mod *ZeroGod) stopDiscovery() {
if mod.browser != nil {
mod.Debug("stopping discovery")
mod.browser.Stop(true)
mod.browser = nil
mod.Debug("discovery stopped")
}
if mod.sniffer != nil {
mod.Debug("stopping sniffer")
mod.snifferCh <- nil
mod.sniffer.Close()
mod.sniffer = nil
mod.snifferCh = nil
mod.Debug("sniffer stopped")
}
}

View file

@ -5,8 +5,8 @@ import (
"strings" "strings"
"github.com/bettercap/bettercap/v2/modules/syn_scan" "github.com/bettercap/bettercap/v2/modules/syn_scan"
"github.com/bettercap/bettercap/v2/modules/zerogod/zeroconf"
"github.com/bettercap/bettercap/v2/network" "github.com/bettercap/bettercap/v2/network"
"github.com/bettercap/bettercap/v2/zeroconf"
"github.com/evilsocket/islazy/str" "github.com/evilsocket/islazy/str"
) )

View file

@ -50,6 +50,7 @@ func ippClientHandler(ctx *HandlerContext) {
read, err := ctx.client.Read(buf) read, err := ctx.client.Read(buf)
if err != nil { if err != nil {
if err == io.EOF { if err == io.EOF {
ctx.mod.Debug("EOF, client %s disconnected", clientIP)
return return
} }
ctx.mod.Warning("error while reading from %v: %v", clientIP, err) ctx.mod.Warning("error while reading from %v: %v", clientIP, err)
@ -67,12 +68,12 @@ func ippClientHandler(ctx *HandlerContext) {
reader := bufio.NewReader(bytes.NewReader(raw_req)) reader := bufio.NewReader(bytes.NewReader(raw_req))
http_req, err := http.ReadRequest(reader) http_req, err := http.ReadRequest(reader)
if err != nil { if err != nil {
ctx.mod.Error("error while parsing http request from %v: %v", clientIP, err) ctx.mod.Error("error while parsing http request from %v: %v\n%s", clientIP, err, Dump(raw_req))
return return
} }
clientUA := http_req.UserAgent() clientUA := http_req.UserAgent()
ctx.mod.Debug("%v -> %s", clientIP, tui.Green(clientUA)) ctx.mod.Info("%v -> %s", clientIP, tui.Green(clientUA))
ipp_body, err := ippReadRequestBody(ctx, http_req) ipp_body, err := ippReadRequestBody(ctx, http_req)
if err != nil { if err != nil {
@ -92,8 +93,14 @@ func ippClientHandler(ctx *HandlerContext) {
ipp_op_name = name ipp_op_name = name
} }
ctx.mod.Info("%s <- %s (%s) %s", reqUsername := tui.Dim("<unknown>")
if value, found := ipp_req.OperationAttributes["requesting-user-name"]; found {
reqUsername = tui.Blue(value.(string))
}
ctx.mod.Info("%s <- %s@%s (%s) %s",
tui.Yellow(ctx.service), tui.Yellow(ctx.service),
reqUsername,
clientIP, clientIP,
tui.Green(clientUA), tui.Green(clientUA),
tui.Bold(ipp_op_name)) tui.Bold(ipp_op_name))

View file

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"github.com/bettercap/bettercap/v2/zeroconf" "github.com/bettercap/bettercap/v2/modules/zerogod/zeroconf"
"github.com/evilsocket/islazy/str" "github.com/evilsocket/islazy/str"
yaml "gopkg.in/yaml.v3" yaml "gopkg.in/yaml.v3"
) )

View file

@ -5,7 +5,7 @@ import (
"net" "net"
"strings" "strings"
"github.com/bettercap/bettercap/v2/zeroconf" "github.com/bettercap/bettercap/v2/modules/zerogod/zeroconf"
"github.com/evilsocket/islazy/tui" "github.com/evilsocket/islazy/tui"
) )

View file

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/evilsocket/islazy/ops"
"github.com/evilsocket/islazy/str" "github.com/evilsocket/islazy/str"
"github.com/evilsocket/islazy/tui" "github.com/evilsocket/islazy/tui"
) )
@ -20,7 +21,10 @@ func (mod *ZeroGod) show(filter string, withData bool) error {
for _, entry := range entries { for _, entry := range entries {
if endpoint := mod.Session.Lan.GetByIp(entry.Address); endpoint != nil { if endpoint := mod.Session.Lan.GetByIp(entry.Address); endpoint != nil {
fmt.Fprintf(mod.Session.Events.Stdout, "* %s (%s)\n", tui.Bold(endpoint.IpAddress), tui.Dim(endpoint.Vendor)) fmt.Fprintf(mod.Session.Events.Stdout, "* %s (%s)%s\n",
tui.Bold(endpoint.IpAddress),
tui.Dim(endpoint.Vendor),
ops.Ternary(endpoint.Hostname == "", "", " "+tui.Bold(endpoint.Hostname)))
} else { } else {
fmt.Fprintf(mod.Session.Events.Stdout, "* %s\n", tui.Bold(entry.Address)) fmt.Fprintf(mod.Session.Events.Stdout, "* %s\n", tui.Bold(entry.Address))
} }

View file

@ -161,6 +161,27 @@ func (t *Endpoint) String() string {
return fmt.Sprintf("%s%s (%s) - %s", ipPart, t.HwAddress, t.Vendor, tui.Bold(name)) return fmt.Sprintf("%s%s (%s) - %s", ipPart, t.HwAddress, t.Vendor, tui.Bold(name))
} }
func (t *Endpoint) ShortString() string {
parts := []string{
t.IpAddress,
}
if t.Vendor != "" {
parts = append(parts, tui.Dim(fmt.Sprintf("(%s)", t.Vendor)))
}
name := t.Hostname
if t.Alias != "" {
name = t.Alias
}
if name != "" {
parts = append(parts, tui.Bold(name))
}
return strings.Join(parts, " ")
}
func (t *Endpoint) OnMeta(meta map[string]string) { func (t *Endpoint) OnMeta(meta map[string]string) {
host := "" host := ""
for k, v := range meta { for k, v := range meta {