new: net.show.filter, net.show.limit, net.show.sort and net.show.sort_by parameters to control net.show

This commit is contained in:
evilsocket 2019-01-23 20:03:01 +01:00
commit 28f8586abb
No known key found for this signature in database
GPG key ID: 1564D7F30393A456
4 changed files with 178 additions and 29 deletions

View file

@ -10,6 +10,7 @@ import (
type Discovery struct {
session.SessionModule
selector *ViewSelector
}
func NewDiscovery(s *session.Session) *Discovery {
@ -36,33 +37,17 @@ func NewDiscovery(s *session.Session) *Discovery {
d.AddHandler(session.NewModuleHandler("net.show", "",
"Show cache hosts list (default sorting by ip).",
func(args []string) error {
return d.Show("address", "")
}))
d.AddHandler(session.NewModuleHandler("net.show by seen", "",
"Show cache hosts list (sort by last seen).",
func(args []string) error {
return d.Show("seen", "")
}))
d.AddHandler(session.NewModuleHandler("net.show by sent", "",
"Show cache hosts list (sort by sent packets).",
func(args []string) error {
return d.Show("sent", "")
}))
d.AddHandler(session.NewModuleHandler("net.show by rcvd", "",
"Show cache hosts list (sort by received packets).",
func(args []string) error {
return d.Show("rcvd", "")
return d.Show("")
}))
d.AddHandler(session.NewModuleHandler("net.show ADDRESS1, ADDRESS2", `net.show (.+)`,
"Show information about a specific list of addresses (by IP or MAC).",
func(args []string) error {
return d.Show("address", args[0])
return d.Show(args[0])
}))
d.selector = ViewSelectorFor(&d.SessionModule, "net.show", []string{"ip", "mac", "seen", "sent", "rcvd"}, "")
return d
}

View file

@ -110,16 +110,44 @@ func (d *Discovery) getRow(e *network.Endpoint, withMeta bool) [][]string {
return rows
}
func (d *Discovery) Show(by string, expr string) (err error) {
var targets []*network.Endpoint
if expr != "" {
if targets, err = network.ParseEndpoints(expr, d.Session.Lan); err != nil {
return err
func (d *Discovery) doFilter(target *network.Endpoint) bool {
if d.selector.Expression == nil {
return true
}
return d.selector.Expression.MatchString(target.IpAddress) ||
d.selector.Expression.MatchString(target.Ip6Address) ||
d.selector.Expression.MatchString(target.HwAddress) ||
d.selector.Expression.MatchString(target.Hostname) ||
d.selector.Expression.MatchString(target.Alias) ||
d.selector.Expression.MatchString(target.Vendor)
}
func (d *Discovery) doSelection(arg string) (err error, targets []*network.Endpoint) {
if err = d.selector.Update(); err != nil {
return
}
if arg != "" {
if targets, err = network.ParseEndpoints(arg, d.Session.Lan); err != nil {
return
}
} else {
targets = d.Session.Lan.List()
}
switch by {
filtered := []*network.Endpoint{}
for _, target := range targets {
if d.doFilter(target) {
filtered = append(filtered, target)
}
}
targets = filtered
switch d.selector.SortBy {
case "ip":
sort.Sort(ByIpSorter(targets))
case "mac":
sort.Sort(ByMacSorter(targets))
case "seen":
sort.Sort(BySeenSorter(targets))
case "sent":
@ -130,6 +158,33 @@ func (d *Discovery) Show(by string, expr string) (err error) {
sort.Sort(ByAddressSorter(targets))
}
// default is asc
if d.selector.Sort == "desc" {
// from https://github.com/golang/go/wiki/SliceTricks
for i := len(targets)/2 - 1; i >= 0; i-- {
opp := len(targets) - 1 - i
targets[i], targets[opp] = targets[opp], targets[i]
}
}
if d.selector.Limit > 0 {
limit := d.selector.Limit
max := len(targets)
if limit > max {
limit = max
}
targets = targets[0:limit]
}
return
}
func (d *Discovery) Show(arg string) (err error) {
var targets []*network.Endpoint
if err, targets = d.doSelection(arg); err != nil {
return
}
pad := 1
if d.Session.Interface.HwAddress == d.Session.Gateway.HwAddress {
pad = 0

View file

@ -17,11 +17,27 @@ func (a ByAddressSorter) Less(i, j int) bool {
return a[i].IpAddressUint32 < a[j].IpAddressUint32
}
type ByIpSorter []*network.Endpoint
func (a ByIpSorter) Len() int { return len(a) }
func (a ByIpSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByIpSorter) Less(i, j int) bool {
return a[i].IpAddressUint32 < a[j].IpAddressUint32
}
type ByMacSorter []*network.Endpoint
func (a ByMacSorter) Len() int { return len(a) }
func (a ByMacSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByMacSorter) Less(i, j int) bool {
return a[i].HwAddress < a[j].HwAddress
}
type BySeenSorter []*network.Endpoint
func (a BySeenSorter) Len() int { return len(a) }
func (a BySeenSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a BySeenSorter) Less(i, j int) bool { return a[i].LastSeen.After(a[j].LastSeen) }
func (a BySeenSorter) Less(i, j int) bool { return a[i].LastSeen.Before(a[j].LastSeen) }
type BySentSorter []*network.Endpoint
@ -43,7 +59,7 @@ func (a BySentSorter) Less(i, j int) bool {
bTraffic = &packets.Traffic{}
}
return bTraffic.Sent < aTraffic.Sent
return bTraffic.Sent > aTraffic.Sent
}
type ByRcvdSorter []*network.Endpoint
@ -66,5 +82,5 @@ func (a ByRcvdSorter) Less(i, j int) bool {
bTraffic = &packets.Traffic{}
}
return bTraffic.Received < aTraffic.Received
return bTraffic.Received > aTraffic.Received
}

93
modules/view_selector.go Normal file
View file

@ -0,0 +1,93 @@
package modules
import (
"fmt"
"regexp"
"strings"
"github.com/bettercap/bettercap/session"
)
type ViewSelector struct {
owner *session.SessionModule
Filter string
filterName string
filterPrev string
Expression *regexp.Regexp
SortBy string
sortBys map[string]bool
sortByName string
Sort string
sortName string
Limit int
limitName string
}
func ViewSelectorFor(m *session.SessionModule, prefix string, sortBys []string, defSortBy string) *ViewSelector {
s := &ViewSelector{
owner: m,
filterName: prefix + ".filter",
filterPrev: "",
sortByName: prefix + ".sort_by",
sortBys: make(map[string]bool),
sortName: prefix + ".sort",
limitName: prefix + ".limit",
SortBy: defSortBy,
Sort: "asc",
Limit: 0,
Filter: "",
Expression: nil,
}
for _, sb := range sortBys {
s.sortBys[sb] = true
}
m.AddParam(session.NewStringParameter(s.filterName, "", "", "Defines a regular expression filter for "+prefix))
m.AddParam(session.NewStringParameter(s.sortByName, defSortBy, "", "Defines sorting field for "+prefix+", available: "+strings.Join(sortBys, ", ")))
m.AddParam(session.NewStringParameter(s.sortName, "asc", "", "Defines sorting direction for "+prefix))
m.AddParam(session.NewIntParameter(s.limitName, "0", "Defines limit for "+prefix))
return s
}
func (s *ViewSelector) Update() (err error) {
if err, s.Filter = s.owner.StringParam(s.filterName); err != nil {
return
}
if s.Filter != "" {
if s.Filter != s.filterPrev {
if s.Expression, err = regexp.Compile(s.Filter); err != nil {
return
}
}
} else {
s.Expression = nil
}
s.filterPrev = s.Filter
if err, s.SortBy = s.owner.StringParam(s.sortByName); err != nil {
return
} else if s.SortBy != "" {
if _, found := s.sortBys[s.SortBy]; !found {
return fmt.Errorf("'%s' is not valid for %s", s.SortBy, s.sortByName)
}
}
if err, s.Sort = s.owner.StringParam(s.sortName); err != nil {
return
} else if s.Sort != "asc" && s.Sort != "desc" {
return fmt.Errorf("'%s' is not valid for %s", s.Sort, s.sortName)
}
if err, s.Limit = s.owner.IntParam(s.limitName); err != nil {
return
}
return
}