From fd586cf5121accc13bbc25570c0c5b71783623bf Mon Sep 17 00:00:00 2001 From: evilsocket Date: Tue, 13 Mar 2018 22:43:56 +0100 Subject: [PATCH] new: implemented update.check module (closes #172) --- core/options.go | 2 +- main.go | 1 + modules/events_view.go | 14 ++++++ modules/update.go | 96 ++++++++++++++++++++++++++++++++++++++++++ session/session.go | 1 - 5 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 modules/update.go diff --git a/core/options.go b/core/options.go index 261bf172..c26d9236 100644 --- a/core/options.go +++ b/core/options.go @@ -19,7 +19,7 @@ type Options struct { func ParseOptions() (Options, error) { o := Options{ InterfaceName: flag.String("iface", "", "Network interface to bind to, if empty the default interface will be auto selected."), - AutoStart: flag.String("autostart", "events.stream, net.recon", "Comma separated list of modules to auto start."), + AutoStart: flag.String("autostart", "events.stream, net.recon, update.check", "Comma separated list of modules to auto start."), Caplet: flag.String("caplet", "", "Read commands from this file and execute them in the interactive session."), Debug: flag.Bool("debug", false, "Print debug messages."), Silent: flag.Bool("silent", false, "Suppress all logs which are not errors."), diff --git a/main.go b/main.go index 9dc1e5a6..cf3cea8e 100644 --- a/main.go +++ b/main.go @@ -40,6 +40,7 @@ func main() { sess.Register(modules.NewEventsStream(sess)) sess.Register(modules.NewTicker(sess)) + sess.Register(modules.NewUpdateModule(sess)) sess.Register(modules.NewMacChanger(sess)) sess.Register(modules.NewProber(sess)) sess.Register(modules.NewDiscovery(sess)) diff --git a/modules/events_view.go b/modules/events_view.go index 4ac29e80..b70203e5 100644 --- a/modules/events_view.go +++ b/modules/events_view.go @@ -10,6 +10,8 @@ import ( "github.com/bettercap/bettercap/core" "github.com/bettercap/bettercap/network" "github.com/bettercap/bettercap/session" + + "github.com/google/go-github/github" ) const eventTimeFormat = "15:04:05" @@ -167,6 +169,16 @@ func (s *EventsStream) viewSynScanEvent(e session.Event) { core.Bold(se.Address)) } +func (s *EventsStream) viewUpdateEvent(e session.Event) { + update := e.Data.(*github.RepositoryRelease) + + fmt.Fprintf(s.output, "[%s] [%s] An update to version %s is available at %s\n", + e.Time.Format(eventTimeFormat), + core.Bold(core.Yellow(e.Tag)), + core.Bold(*update.TagName), + *update.HTMLURL) +} + func (s *EventsStream) View(e session.Event, refresh bool) { if e.Tag == "sys.log" { s.viewLogEvent(e) @@ -182,6 +194,8 @@ func (s *EventsStream) View(e session.Event, refresh bool) { s.viewSnifferEvent(e) } else if strings.HasPrefix(e.Tag, "syn.scan.") { s.viewSynScanEvent(e) + } else if e.Tag == "update.available" { + s.viewUpdateEvent(e) } else { fmt.Fprintf(s.output, "[%s] [%s] %v\n", e.Time.Format(eventTimeFormat), core.Green(e.Tag), e) } diff --git a/modules/update.go b/modules/update.go new file mode 100644 index 00000000..0b15232a --- /dev/null +++ b/modules/update.go @@ -0,0 +1,96 @@ +package modules + +import ( + "context" + "math" + "strconv" + "strings" + + "github.com/bettercap/bettercap/core" + "github.com/bettercap/bettercap/log" + "github.com/bettercap/bettercap/session" + + "github.com/google/go-github/github" +) + +type UpdateModule struct { + session.SessionModule + client *github.Client +} + +func NewUpdateModule(s *session.Session) *UpdateModule { + u := &UpdateModule{ + SessionModule: session.NewSessionModule("update", s), + client: github.NewClient(nil), + } + + u.AddHandler(session.NewModuleHandler("update.check on", "", + "Check latest available stable version and compare it with the one being used.", + func(args []string) error { + return u.Start() + })) + + return u +} + +func (u *UpdateModule) Name() string { + return "update" +} + +func (u *UpdateModule) Description() string { + return "A module to check for bettercap's updates." +} + +func (u *UpdateModule) Author() string { + return "Simone Margaritelli " +} + +func (u *UpdateModule) Configure() error { + return nil +} + +func (u *UpdateModule) Stop() error { + return nil +} + +func (u *UpdateModule) versionToNum(ver string) float64 { + if ver[0] == 'v' { + ver = ver[1:] + } + + n := 0.0 + parts := strings.Split(ver, ".") + nparts := len(parts) + + // reverse + for i := nparts/2 - 1; i >= 0; i-- { + opp := nparts - 1 - i + parts[i], parts[opp] = parts[opp], parts[i] + } + + for i, e := range parts { + ev, _ := strconv.Atoi(e) + n += float64(ev) * math.Pow10(i) + } + + return n +} + +func (u *UpdateModule) Start() error { + return u.SetRunning(true, func() { + defer u.SetRunning(false, nil) + + log.Info("Checking latest stable release ...") + + if releases, _, err := u.client.Repositories.ListReleases(context.Background(), "bettercap", "bettercap", nil); err == nil { + latest := releases[0] + if u.versionToNum(core.Version) < u.versionToNum(*latest.TagName) { + u.Session.Events.Add("update.available", latest) + } else { + log.Info("You are running %s which is the latest stable version.", core.Bold(core.Version)) + } + } else { + log.Error("Error while fetching latest release info from GitHub: %s", err) + } + }) +} diff --git a/session/session.go b/session/session.go index 01d3e6c4..d69375ee 100644 --- a/session/session.go +++ b/session/session.go @@ -254,7 +254,6 @@ func (s *Session) Close() { } s.Firewall.Restore() - s.Queue.Stop() if *s.Options.EnvFile != "" { envFile, _ := core.ExpandPath(*s.Options.EnvFile)