From 9ee43b6b673be3aed3adca1741ac0607bfefd06b Mon Sep 17 00:00:00 2001 From: evilsocket Date: Sat, 24 Feb 2018 17:04:16 +0100 Subject: [PATCH] new: improved control over events.stream verbosity ( ref #70 ) --- modules/events_ignore_list.go | 113 ++++++++++++++++++++++++++++++++++ modules/events_stream.go | 55 ++++++++++++----- modules/events_view.go | 53 ++++++++-------- 3 files changed, 179 insertions(+), 42 deletions(-) create mode 100644 modules/events_ignore_list.go diff --git a/modules/events_ignore_list.go b/modules/events_ignore_list.go new file mode 100644 index 00000000..cc0153a7 --- /dev/null +++ b/modules/events_ignore_list.go @@ -0,0 +1,113 @@ +package modules + +import ( + "errors" + "fmt" + "strings" + "sync" + + "github.com/bettercap/bettercap/core" + "github.com/bettercap/bettercap/session" +) + +var ( + ErrEmptyExpression = errors.New("Expression can not be empty.") +) + +type IgnoreFilter string + +func (f IgnoreFilter) Matches(s string) bool { + return string(f) == s || strings.HasPrefix(s, string(f)) +} + +type IgnoreList struct { + sync.RWMutex + filters []IgnoreFilter +} + +func NewIgnoreList() *IgnoreList { + return &IgnoreList{ + filters: make([]IgnoreFilter, 0), + } +} + +func (l *IgnoreList) checkExpression(expr string) (string, error) { + expr = core.Trim(expr) + if expr == "" { + return "", ErrEmptyExpression + } + + return expr, nil +} + +func (l *IgnoreList) Add(expr string) (err error) { + if expr, err = l.checkExpression(expr); err != nil { + return err + } + + l.Lock() + defer l.Unlock() + + // first check for duplicates + for _, filter := range l.filters { + if filter.Matches(expr) { + return fmt.Errorf("Filter '%s' already matches the expression '%s'.", filter, expr) + } + } + + // all good + l.filters = append(l.filters, IgnoreFilter(expr)) + + return nil +} + +func (l *IgnoreList) Remove(expr string) (err error) { + if expr, err = l.checkExpression(expr); err != nil { + return err + } + + l.Lock() + defer l.Unlock() + + // build a new list with everything that does not match + toRemove := IgnoreFilter(expr) + newList := make([]IgnoreFilter, 0) + for _, filter := range l.filters { + if toRemove.Matches(string(filter)) == false { + newList = append(newList, filter) + } + } + + if len(newList) == len(l.filters) { + return fmt.Errorf("Expression '%s' did not match any filter.", expr) + } + + // swap + l.filters = newList + + return nil +} + +func (l *IgnoreList) Ignored(e session.Event) bool { + l.RLock() + defer l.RUnlock() + + for _, filter := range l.filters { + if filter.Matches(e.Tag) { + return true + } + } + + return false +} + +func (l *IgnoreList) Empty() bool { + l.RLock() + defer l.RUnlock() + + return len(l.filters) == 0 +} + +func (l *IgnoreList) Filters() []IgnoreFilter { + return l.filters +} diff --git a/modules/events_stream.go b/modules/events_stream.go index 7512f425..d8dbfe69 100644 --- a/modules/events_stream.go +++ b/modules/events_stream.go @@ -1,30 +1,27 @@ package modules import ( + "fmt" "strconv" "github.com/bettercap/bettercap/core" + "github.com/bettercap/bettercap/log" "github.com/bettercap/bettercap/session" ) type EventsStream struct { session.SessionModule - filter string - quit chan bool + ignoreList *IgnoreList + quit chan bool } func NewEventsStream(s *session.Session) *EventsStream { stream := &EventsStream{ SessionModule: session.NewSessionModule("events.stream", s), - filter: "", quit: make(chan bool), + ignoreList: NewIgnoreList(), } - stream.AddParam(session.NewStringParameter("events.stream.filter", - "", - "", - "If filled, filter events by this prefix type.")) - stream.AddHandler(session.NewModuleHandler("events.stream on", "", "Start events stream.", func(args []string) error { @@ -48,6 +45,34 @@ func NewEventsStream(s *session.Session) *EventsStream { return stream.Show(limit) })) + stream.AddHandler(session.NewModuleHandler("events.ignore FILTER", "events.ignore ([^\\s]+)", + "Events with an identifier matching this filter will not be shown (use multiple times to add more filters).", + func(args []string) error { + return stream.ignoreList.Add(args[0]) + })) + + stream.AddHandler(session.NewModuleHandler("events.include FILTER", "events.include ([^\\s]+)", + "Used to remove filters passed with the events.ignore command.", + func(args []string) error { + return stream.ignoreList.Remove(args[0]) + })) + + stream.AddHandler(session.NewModuleHandler("events.filters", "", + "Print the list of filters used to ignore events.", + func(args []string) error { + if stream.ignoreList.Empty() { + fmt.Printf("Ignore filters list is empty.\n") + } else { + stream.ignoreList.RLock() + defer stream.ignoreList.RUnlock() + + for _, filter := range stream.ignoreList.Filters() { + fmt.Printf(" '%s'\n", string(filter)) + } + } + return nil + })) + stream.AddHandler(session.NewModuleHandler("events.clear", "", "Clear events stream.", func(args []string) error { @@ -71,24 +96,20 @@ func (s EventsStream) Author() string { } func (s *EventsStream) Configure() error { - var err error - if err, s.filter = s.StringParam("events.stream.filter"); err != nil { - return err - } return nil } func (s *EventsStream) Start() error { - if err := s.Configure(); err != nil { - return err - } - return s.SetRunning(true, func() { for { var e session.Event select { case e = <-s.Session.Events.NewEvents: - s.View(e, true) + if s.ignoreList.Ignored(e) == false { + s.View(e, true) + } else { + log.Debug("Skipping ignored event %v", e) + } break case <-s.quit: diff --git a/modules/events_view.go b/modules/events_view.go index 4145fda6..a120eb6d 100644 --- a/modules/events_view.go +++ b/modules/events_view.go @@ -11,11 +11,12 @@ import ( "github.com/bettercap/bettercap/session" ) -const eventTimeFormat = "2006-01-02 15:04:05" +const eventTimeFormat = "15:04:05" func (s EventsStream) viewLogEvent(e session.Event) { - fmt.Printf("[%s] [%s] %s\n", + fmt.Printf("[%s] [%s] [%s] %s\n", e.Time.Format(eventTimeFormat), + core.Green(e.Tag), e.Label(), e.Data.(session.LogMessage).Message) } @@ -28,14 +29,16 @@ func (s EventsStream) viewApEvent(e session.Event) { } if e.Tag == "wifi.ap.new" { - fmt.Printf("[%s] WiFi access point %s detected as %s%s.\n", + fmt.Printf("[%s] [%s] WiFi access point %s detected as %s%s.\n", e.Time.Format(eventTimeFormat), + core.Green(e.Tag), core.Bold(ap.ESSID()), core.Green(ap.BSSID()), vend) } else if e.Tag == "wifi.ap.lost" { - fmt.Printf("[%s] WiFi access point %s (%s) lost.\n", + fmt.Printf("[%s] [%s] WiFi access point %s (%s) lost.\n", e.Time.Format(eventTimeFormat), + core.Green(e.Tag), core.Red(ap.ESSID()), ap.BSSID()) } else { @@ -62,14 +65,16 @@ func (s EventsStream) viewEndpointEvent(e session.Event) { } if e.Tag == "endpoint.new" { - fmt.Printf("[%s] Endpoint %s detected as %s%s.\n", + fmt.Printf("[%s] [%s] Endpoint %s detected as %s%s.\n", e.Time.Format(eventTimeFormat), + core.Green(e.Tag), core.Bold(t.IpAddress), core.Green(t.HwAddress), vend) } else if e.Tag == "endpoint.lost" { - fmt.Printf("[%s] Endpoint %s%s lost.\n", + fmt.Printf("[%s] [%s] Endpoint %s%s lost.\n", e.Time.Format(eventTimeFormat), + core.Green(e.Tag), core.Red(t.IpAddress), name) } else { @@ -133,25 +138,23 @@ func (s EventsStream) viewSynScanEvent(e session.Event) { } func (s *EventsStream) View(e session.Event, refresh bool) { - if s.filter == "" || strings.Contains(e.Tag, s.filter) { - if e.Tag == "sys.log" { - s.viewLogEvent(e) - } else if strings.HasPrefix(e.Tag, "endpoint.") { - s.viewEndpointEvent(e) - } else if strings.HasPrefix(e.Tag, "wifi.ap.") { - s.viewApEvent(e) - } else if strings.HasPrefix(e.Tag, "mod.") { - s.viewModuleEvent(e) - } else if strings.HasPrefix(e.Tag, "net.sniff.") { - s.viewSnifferEvent(e) - } else if strings.HasPrefix(e.Tag, "syn.scan") { - s.viewSynScanEvent(e) - } else { - fmt.Printf("[%s] [%s] %v\n", e.Time.Format(eventTimeFormat), core.Green(e.Tag), e) - } + if e.Tag == "sys.log" { + s.viewLogEvent(e) + } else if strings.HasPrefix(e.Tag, "endpoint.") { + s.viewEndpointEvent(e) + } else if strings.HasPrefix(e.Tag, "wifi.ap.") { + s.viewApEvent(e) + } else if strings.HasPrefix(e.Tag, "mod.") { + s.viewModuleEvent(e) + } else if strings.HasPrefix(e.Tag, "net.sniff.") { + s.viewSnifferEvent(e) + } else if strings.HasPrefix(e.Tag, "syn.scan") { + s.viewSynScanEvent(e) + } else { + fmt.Printf("[%s] [%s] %v\n", e.Time.Format(eventTimeFormat), core.Green(e.Tag), e) + } - if refresh { - s.Session.Refresh() - } + if refresh { + s.Session.Refresh() } }