new: improved control over events.stream verbosity ( ref #70 )

This commit is contained in:
evilsocket 2018-02-24 17:04:16 +01:00
parent e6170263a2
commit 9ee43b6b67
3 changed files with 179 additions and 42 deletions

View file

@ -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
}

View file

@ -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:

View file

@ -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()
}
}