mirror of
https://github.com/bettercap/bettercap
synced 2025-08-19 13:09:49 -07:00
new: new c2 module, first draft
This commit is contained in:
parent
35dbb8a368
commit
583a54c194
23 changed files with 579 additions and 163 deletions
2
go.mod
2
go.mod
|
@ -3,6 +3,7 @@ module github.com/bettercap/bettercap
|
|||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
|
||||
github.com/adrianmo/go-nmea v1.3.0
|
||||
github.com/antchfx/jsonquery v1.1.4
|
||||
github.com/antchfx/xpath v1.1.10 // indirect
|
||||
|
@ -38,6 +39,7 @@ require (
|
|||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/robertkrimen/otto v0.0.0-20200922221731-ef014fd054ac
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07
|
||||
github.com/thoj/go-ircevent v0.0.0-20190807115034-8e7ce4b5a1eb
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a // indirect
|
||||
golang.org/x/net v0.0.0-20200925080053-05aa5d4ee321
|
||||
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d // indirect
|
||||
|
|
4
go.sum
4
go.sum
|
@ -1,5 +1,7 @@
|
|||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
|
||||
github.com/adrianmo/go-nmea v1.1.0 h1:0NILSj14nj6LvVQHo/afHbyPgGz5qvp5PM6jmMyAQzY=
|
||||
github.com/adrianmo/go-nmea v1.1.0/go.mod h1:HHPxPAm2kmev+61qmkZh7xgZF/7qHtSpsWppip2Ipv8=
|
||||
github.com/adrianmo/go-nmea v1.3.0 h1:BFrLRj/oIh+DYujIKpuQievq7X3NDHYq57kNgsfr2GY=
|
||||
|
@ -151,6 +153,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
|||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 h1:UyzmZLoiDWMRywV4DUYb9Fbt8uiOSooupjTq10vpvnU=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
github.com/thoj/go-ircevent v0.0.0-20190807115034-8e7ce4b5a1eb h1:EavwSqheIJl3nb91HhkL73DwnT2Fk8W3yM7T7TuLZvA=
|
||||
github.com/thoj/go-ircevent v0.0.0-20190807115034-8e7ce4b5a1eb/go.mod h1:I0ZT9x8wStY6VOxtNOrLpnDURFs7HS0z1e1vhuKUEVc=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
package ble
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
|
@ -146,7 +145,7 @@ func (mod *BLERecon) Show() error {
|
|||
}
|
||||
|
||||
if len(rows) > 0 {
|
||||
tui.Table(os.Stdout, mod.colNames(hasName), rows)
|
||||
tui.Table(mod.Session.Events.Stdout, mod.colNames(hasName), rows)
|
||||
mod.Session.Refresh()
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ package ble
|
|||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -406,7 +405,7 @@ func (mod *BLERecon) showServices(p gatt.Peripheral, services []*gatt.Service) {
|
|||
if wantsToWrite && !foundToWrite {
|
||||
mod.Error("writable characteristics %s not found.", mod.writeUUID)
|
||||
} else {
|
||||
tui.Table(os.Stdout, columns, rows)
|
||||
tui.Table(mod.Session.Events.Stdout, columns, rows)
|
||||
mod.Session.Refresh()
|
||||
}
|
||||
}
|
||||
|
|
354
modules/c2/c2.go
Normal file
354
modules/c2/c2.go
Normal file
|
@ -0,0 +1,354 @@
|
|||
package c2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"github.com/acarl005/stripansi"
|
||||
"github.com/bettercap/bettercap/modules/events_stream"
|
||||
"github.com/bettercap/bettercap/session"
|
||||
"github.com/evilsocket/islazy/log"
|
||||
"github.com/evilsocket/islazy/str"
|
||||
irc "github.com/thoj/go-ircevent"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type settings struct {
|
||||
server string
|
||||
ssl bool
|
||||
nick string
|
||||
user string
|
||||
password string
|
||||
operator string
|
||||
controlChannel string
|
||||
eventsChannel string
|
||||
outputChannel string
|
||||
}
|
||||
|
||||
type C2 struct {
|
||||
session.SessionModule
|
||||
|
||||
settings settings
|
||||
stream *events_stream.EventsStream
|
||||
templates map[string]*template.Template
|
||||
channels map[string]string
|
||||
client *irc.Connection
|
||||
eventBus session.EventBus
|
||||
quit chan bool
|
||||
}
|
||||
|
||||
type eventContext struct {
|
||||
Session *session.Session
|
||||
Event session.Event
|
||||
}
|
||||
|
||||
func NewC2(s *session.Session) *C2 {
|
||||
mod := &C2{
|
||||
SessionModule: session.NewSessionModule("c2", s),
|
||||
stream: events_stream.NewEventsStream(s),
|
||||
templates: make(map[string]*template.Template),
|
||||
channels: make(map[string]string),
|
||||
quit: make(chan bool),
|
||||
settings: settings{
|
||||
server: "localhost:6697",
|
||||
ssl: true,
|
||||
nick: "bettercap",
|
||||
user: "bettercap",
|
||||
password: "password",
|
||||
operator: "admin",
|
||||
eventsChannel: "#events",
|
||||
outputChannel: "#events",
|
||||
controlChannel: "#events",
|
||||
},
|
||||
}
|
||||
|
||||
mod.AddParam(session.NewStringParameter("c2.server",
|
||||
mod.settings.server,
|
||||
"",
|
||||
"IRC server address and port."))
|
||||
|
||||
mod.AddParam(session.NewBoolParameter("c2.server.tls",
|
||||
"true",
|
||||
"Enable or disable TLS."))
|
||||
|
||||
mod.AddParam(session.NewStringParameter("c2.operator",
|
||||
mod.settings.operator,
|
||||
"",
|
||||
"IRC nickname of the user allowed to run commands."))
|
||||
|
||||
mod.AddParam(session.NewStringParameter("c2.nick",
|
||||
mod.settings.nick,
|
||||
"",
|
||||
"IRC nickname."))
|
||||
|
||||
mod.AddParam(session.NewStringParameter("c2.username",
|
||||
mod.settings.user,
|
||||
"",
|
||||
"IRC username."))
|
||||
|
||||
mod.AddParam(session.NewStringParameter("c2.password",
|
||||
mod.settings.password,
|
||||
"",
|
||||
"IRC server password."))
|
||||
|
||||
mod.AddParam(session.NewStringParameter("c2.channel.output",
|
||||
mod.settings.outputChannel,
|
||||
"",
|
||||
"IRC channel to send commands output to."))
|
||||
|
||||
mod.AddParam(session.NewStringParameter("c2.channel.events",
|
||||
mod.settings.eventsChannel,
|
||||
"",
|
||||
"IRC channel to send events to."))
|
||||
|
||||
mod.AddParam(session.NewStringParameter("c2.channel.control",
|
||||
mod.settings.controlChannel,
|
||||
"",
|
||||
"IRC channel to receive commands from."))
|
||||
|
||||
mod.AddHandler(session.NewModuleHandler("c2 on", "",
|
||||
"Start the C2 module.",
|
||||
func(args []string) error {
|
||||
return mod.Start()
|
||||
}))
|
||||
|
||||
mod.AddHandler(session.NewModuleHandler("c2 off", "",
|
||||
"Stop the C2 module.",
|
||||
func(args []string) error {
|
||||
return mod.Stop()
|
||||
}))
|
||||
|
||||
mod.AddHandler(session.NewModuleHandler("c2.channel.set EVENT_TYPE CHANNEL",
|
||||
"c2.channel.set ([^\\s]+) (.+)",
|
||||
"Set a specific channel to report events of this type.",
|
||||
func(args []string) error {
|
||||
eventType := args[0]
|
||||
channel := args[1]
|
||||
|
||||
mod.Debug("setting channel for event %s: %v", eventType, channel)
|
||||
mod.channels[eventType] = channel
|
||||
return nil
|
||||
}))
|
||||
|
||||
mod.AddHandler(session.NewModuleHandler("c2.channel.clear EVENT_TYPE",
|
||||
"c2.channel.clear ([^\\s]+)",
|
||||
"Clear the channel to use for a specific event type.",
|
||||
func(args []string) error {
|
||||
eventType := args[0]
|
||||
if _, found := mod.channels[args[0]]; found {
|
||||
delete(mod.channels, eventType)
|
||||
mod.Debug("cleared channel for %s", eventType)
|
||||
} else {
|
||||
return fmt.Errorf("channel for event %s not set", args[0])
|
||||
}
|
||||
return nil
|
||||
}))
|
||||
|
||||
mod.AddHandler(session.NewModuleHandler("c2.template.set EVENT_TYPE TEMPLATE",
|
||||
"c2.template.set ([^\\s]+) (.+)",
|
||||
"Set the reporting template to use for a specific event type.",
|
||||
func(args []string) error {
|
||||
eventType := args[0]
|
||||
eventTemplate := args[1]
|
||||
|
||||
parsed, err := template.New(eventType).Parse(eventTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mod.Debug("setting template for event %s: %v", eventType, parsed)
|
||||
mod.templates[eventType] = parsed
|
||||
return nil
|
||||
}))
|
||||
|
||||
mod.AddHandler(session.NewModuleHandler("c2.template.clear EVENT_TYPE",
|
||||
"c2.template.clear ([^\\s]+)",
|
||||
"Clear the reporting template to use for a specific event type.",
|
||||
func(args []string) error {
|
||||
eventType := args[0]
|
||||
if _, found := mod.templates[args[0]]; found {
|
||||
delete(mod.templates, eventType)
|
||||
mod.Debug("cleared template for %s", eventType)
|
||||
} else {
|
||||
return fmt.Errorf("template for event %s not set", args[0])
|
||||
}
|
||||
return nil
|
||||
}))
|
||||
|
||||
mod.Session.Events.OnPrint(mod.onPrint)
|
||||
|
||||
return mod
|
||||
}
|
||||
|
||||
func (mod *C2) Name() string {
|
||||
return "c2"
|
||||
}
|
||||
|
||||
func (mod *C2) Description() string {
|
||||
return "A CnC module that connects to an IRC server for reporting and commands."
|
||||
}
|
||||
|
||||
func (mod *C2) Author() string {
|
||||
return "Simone Margaritelli <evilsocket@gmail.com>"
|
||||
}
|
||||
|
||||
func (mod *C2) Configure() (err error) {
|
||||
if mod.Running() {
|
||||
return session.ErrAlreadyStarted(mod.Name())
|
||||
}
|
||||
|
||||
if err, mod.settings.server = mod.StringParam("c2.server"); err != nil {
|
||||
return err
|
||||
} else if err, mod.settings.ssl = mod.BoolParam("c2.server.tls"); err != nil {
|
||||
return err
|
||||
} else if err, mod.settings.nick = mod.StringParam("c2.nick"); err != nil {
|
||||
return err
|
||||
} else if err, mod.settings.user = mod.StringParam("c2.username"); err != nil {
|
||||
return err
|
||||
} else if err, mod.settings.password = mod.StringParam("c2.password"); err != nil {
|
||||
return err
|
||||
} else if err, mod.settings.operator = mod.StringParam("c2.operator"); err != nil {
|
||||
return err
|
||||
} else if err, mod.settings.eventsChannel = mod.StringParam("c2.channel.events"); err != nil {
|
||||
return err
|
||||
} else if err, mod.settings.controlChannel = mod.StringParam("c2.channel.control"); err != nil {
|
||||
return err
|
||||
} else if err, mod.settings.outputChannel = mod.StringParam("c2.channel.output"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mod.eventBus = mod.Session.Events.Listen()
|
||||
|
||||
mod.client = irc.IRC(mod.settings.nick, mod.settings.user)
|
||||
|
||||
if log.Level == log.DEBUG {
|
||||
mod.client.VerboseCallbackHandler = true
|
||||
mod.client.Debug = true
|
||||
}
|
||||
mod.client.Password = mod.settings.password
|
||||
mod.client.UseTLS = mod.settings.ssl
|
||||
mod.client.TLSConfig = &tls.Config{
|
||||
InsecureSkipVerify: true, // TODO: pass this by parameter?
|
||||
}
|
||||
|
||||
mod.client.AddCallback("PRIVMSG", func(event *irc.Event) {
|
||||
channel := event.Arguments[0]
|
||||
message := event.Message()
|
||||
from := event.Nick
|
||||
|
||||
if from != mod.settings.operator {
|
||||
mod.client.Privmsg(event.Nick, "nope")
|
||||
return
|
||||
}
|
||||
|
||||
if channel != mod.settings.controlChannel && channel != mod.settings.nick {
|
||||
mod.Debug("from:%s on:%s - '%s'", from, channel, message)
|
||||
return
|
||||
}
|
||||
|
||||
mod.Debug("from:%s on:%s - '%s'", from, channel, message)
|
||||
|
||||
parts := strings.SplitN(message, " ", 2)
|
||||
cmd := parts[0]
|
||||
args := ""
|
||||
if len(parts) > 1 {
|
||||
args = parts[1]
|
||||
}
|
||||
|
||||
if cmd == "join" {
|
||||
mod.client.Join(args)
|
||||
} else if cmd == "part" {
|
||||
mod.client.Part(args)
|
||||
} else if cmd == "nick" {
|
||||
mod.client.Nick(args)
|
||||
} else if err = mod.Session.Run(message); err == nil {
|
||||
// mod.client.Privmsg(event.Nick, "ok")
|
||||
} else {
|
||||
mod.client.Privmsgf(event.Nick, "error: %v", stripansi.Strip(err.Error()))
|
||||
}
|
||||
})
|
||||
|
||||
mod.client.AddCallback("001", func(e *irc.Event) {
|
||||
mod.Debug("got 101")
|
||||
mod.client.Join(mod.settings.controlChannel)
|
||||
mod.client.Join(mod.settings.outputChannel)
|
||||
mod.client.Join(mod.settings.eventsChannel)
|
||||
})
|
||||
|
||||
return mod.client.Connect(mod.settings.server)
|
||||
}
|
||||
|
||||
func (mod *C2) onPrint(format string, args...interface{}) {
|
||||
if !mod.Running() {
|
||||
return
|
||||
}
|
||||
|
||||
msg := stripansi.Strip(str.Trim(fmt.Sprintf(format, args...)))
|
||||
|
||||
for _, line := range strings.Split(msg, "\n") {
|
||||
mod.client.Privmsg(mod.settings.outputChannel, line)
|
||||
}
|
||||
}
|
||||
|
||||
func (mod *C2) onEvent(e session.Event) {
|
||||
if mod.Session.EventsIgnoreList.Ignored(e) {
|
||||
return
|
||||
}
|
||||
|
||||
// default channel or event specific channel?
|
||||
channel := mod.settings.eventsChannel
|
||||
if custom, found := mod.channels[e.Tag]; found {
|
||||
channel = custom
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
if tpl, found := mod.templates[e.Tag]; found {
|
||||
// use a custom template to render this event
|
||||
if err := tpl.Execute(&out, eventContext{
|
||||
Session: mod.Session,
|
||||
Event: e,
|
||||
}); err != nil {
|
||||
fmt.Fprintf(&out, "%v", err)
|
||||
}
|
||||
} else {
|
||||
// use the default view to render this event
|
||||
mod.stream.Render(&out, e)
|
||||
}
|
||||
|
||||
// make sure colors and in general bash escape sequences are removed
|
||||
msg := stripansi.Strip(str.Trim(string(out.Bytes())))
|
||||
|
||||
mod.client.Privmsg(channel, msg)
|
||||
}
|
||||
|
||||
func (mod *C2) Start() error {
|
||||
if err := mod.Configure(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return mod.SetRunning(true, func() {
|
||||
mod.Info("started")
|
||||
|
||||
for mod.Running() {
|
||||
var e session.Event
|
||||
select {
|
||||
case e = <-mod.eventBus:
|
||||
mod.onEvent(e)
|
||||
|
||||
case <-mod.quit:
|
||||
mod.Debug("got quit")
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (mod *C2) Stop() error {
|
||||
return mod.SetRunning(false, func() {
|
||||
mod.quit <- true
|
||||
mod.Session.Events.Unlisten(mod.eventBus)
|
||||
mod.client.Quit()
|
||||
mod.client.Disconnect()
|
||||
})
|
||||
}
|
|
@ -91,7 +91,7 @@ func (mod *CapletsModule) Show() error {
|
|||
})
|
||||
}
|
||||
|
||||
tui.Table(os.Stdout, colNames, rows)
|
||||
tui.Table(mod.Session.Events.Stdout, colNames, rows)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -106,8 +106,8 @@ func (mod *CapletsModule) Paths() error {
|
|||
rows = append(rows, []string{path})
|
||||
}
|
||||
|
||||
tui.Table(os.Stdout, colNames, rows)
|
||||
fmt.Printf("(paths can be customized by defining the %s environment variable)\n", tui.Bold(caplets.EnvVarName))
|
||||
tui.Table(mod.Session.Events.Stdout, colNames, rows)
|
||||
mod.Printf("(paths can be customized by defining the %s environment variable)\n", tui.Bold(caplets.EnvVarName))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
61
modules/events_stream/events_rotation.go
Normal file
61
modules/events_stream/events_rotation.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
package events_stream
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/evilsocket/islazy/zip"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (mod *EventsStream) doRotation() {
|
||||
if mod.output == os.Stdout {
|
||||
return
|
||||
} else if !mod.rotation.Enabled {
|
||||
return
|
||||
}
|
||||
|
||||
output, isFile := mod.output.(*os.File)
|
||||
if !isFile {
|
||||
return
|
||||
}
|
||||
|
||||
mod.rotation.Lock()
|
||||
defer mod.rotation.Unlock()
|
||||
|
||||
doRotate := false
|
||||
if info, err := output.Stat(); err == nil {
|
||||
if mod.rotation.How == "size" {
|
||||
doRotate = float64(info.Size()) >= float64(mod.rotation.Period*1024*1024)
|
||||
} else if mod.rotation.How == "time" {
|
||||
doRotate = info.ModTime().Unix()%int64(mod.rotation.Period) == 0
|
||||
}
|
||||
}
|
||||
|
||||
if doRotate {
|
||||
var err error
|
||||
|
||||
name := fmt.Sprintf("%s-%s", mod.outputName, time.Now().Format(mod.rotation.Format))
|
||||
|
||||
if err := output.Close(); err != nil {
|
||||
mod.Printf("could not close log for rotation: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := os.Rename(mod.outputName, name); err != nil {
|
||||
mod.Printf("could not rename %s to %s: %s\n", mod.outputName, name, err)
|
||||
} else if mod.rotation.Compress {
|
||||
zipName := fmt.Sprintf("%s.zip", name)
|
||||
if err = zip.Files(zipName, []string{name}); err != nil {
|
||||
mod.Printf("error creating %s: %s", zipName, err)
|
||||
} else if err = os.Remove(name); err != nil {
|
||||
mod.Printf("error deleting %s: %s", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
mod.output, err = os.OpenFile(mod.outputName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
mod.Printf("could not open %s: %s", mod.outputName, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package events_stream
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
@ -27,7 +28,7 @@ type EventsStream struct {
|
|||
session.SessionModule
|
||||
timeFormat string
|
||||
outputName string
|
||||
output *os.File
|
||||
output io.Writer
|
||||
rotation rotation
|
||||
triggerList *TriggerList
|
||||
waitFor string
|
||||
|
@ -149,13 +150,13 @@ func NewEventsStream(s *session.Session) *EventsStream {
|
|||
"Print the list of filters used to ignore events.",
|
||||
func(args []string) error {
|
||||
if mod.Session.EventsIgnoreList.Empty() {
|
||||
fmt.Printf("Ignore filters list is empty.\n")
|
||||
mod.Printf("Ignore filters list is empty.\n")
|
||||
} else {
|
||||
mod.Session.EventsIgnoreList.RLock()
|
||||
defer mod.Session.EventsIgnoreList.RUnlock()
|
||||
|
||||
for _, filter := range mod.Session.EventsIgnoreList.Filters() {
|
||||
fmt.Printf(" '%s'\n", string(filter))
|
||||
mod.Printf(" '%s'\n", string(filter))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -322,7 +323,7 @@ func (mod *EventsStream) Show(limit int) error {
|
|||
}
|
||||
|
||||
if numSelected := len(selected); numSelected > 0 {
|
||||
fmt.Println()
|
||||
mod.Printf("\n")
|
||||
for i := range selected {
|
||||
mod.View(selected[numSelected-1-i], false)
|
||||
}
|
||||
|
@ -360,7 +361,9 @@ func (mod *EventsStream) Stop() error {
|
|||
return mod.SetRunning(false, func() {
|
||||
mod.quit <- true
|
||||
if mod.output != os.Stdout {
|
||||
mod.output.Close()
|
||||
if fp, ok := mod.output.(*os.File); ok {
|
||||
fp.Close()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package events_stream
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/bettercap/bettercap/session"
|
||||
|
||||
"github.com/evilsocket/islazy/tui"
|
||||
|
@ -41,7 +39,7 @@ func (mod *EventsStream) showTriggers() error {
|
|||
})
|
||||
|
||||
if len(rows) > 0 {
|
||||
tui.Table(os.Stdout, colNames, rows)
|
||||
tui.Table(mod.Session.Events.Stdout, colNames, rows)
|
||||
mod.Session.Refresh()
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,11 @@ package events_stream
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bettercap/bettercap/network"
|
||||
"github.com/bettercap/bettercap/session"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/bettercap/bettercap/modules/net_sniff"
|
||||
"github.com/bettercap/bettercap/modules/syn_scan"
|
||||
|
@ -15,18 +14,17 @@ import (
|
|||
"github.com/google/go-github/github"
|
||||
|
||||
"github.com/evilsocket/islazy/tui"
|
||||
"github.com/evilsocket/islazy/zip"
|
||||
)
|
||||
|
||||
func (mod *EventsStream) viewLogEvent(e session.Event) {
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] [%s] %s\n",
|
||||
func (mod *EventsStream) viewLogEvent(output io.Writer, e session.Event) {
|
||||
fmt.Fprintf(output, "[%s] [%s] [%s] %s\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
e.Label(),
|
||||
e.Data.(session.LogMessage).Message)
|
||||
}
|
||||
|
||||
func (mod *EventsStream) viewEndpointEvent(e session.Event) {
|
||||
func (mod *EventsStream) viewEndpointEvent(output io.Writer, e session.Event) {
|
||||
t := e.Data.(*network.Endpoint)
|
||||
vend := ""
|
||||
name := ""
|
||||
|
@ -42,7 +40,7 @@ func (mod *EventsStream) viewEndpointEvent(e session.Event) {
|
|||
}
|
||||
|
||||
if e.Tag == "endpoint.new" {
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] endpoint %s%s detected as %s%s.\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] endpoint %s%s detected as %s%s.\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
tui.Bold(t.IpAddress),
|
||||
|
@ -50,7 +48,7 @@ func (mod *EventsStream) viewEndpointEvent(e session.Event) {
|
|||
tui.Green(t.HwAddress),
|
||||
tui.Dim(vend))
|
||||
} else if e.Tag == "endpoint.lost" {
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] endpoint %s%s %s%s lost.\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] endpoint %s%s %s%s lost.\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
tui.Red(t.IpAddress),
|
||||
|
@ -58,127 +56,84 @@ func (mod *EventsStream) viewEndpointEvent(e session.Event) {
|
|||
tui.Green(t.HwAddress),
|
||||
tui.Dim(vend))
|
||||
} else {
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] %s\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] %s\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
t.String())
|
||||
}
|
||||
}
|
||||
|
||||
func (mod *EventsStream) viewModuleEvent(e session.Event) {
|
||||
func (mod *EventsStream) viewModuleEvent(output io.Writer, e session.Event) {
|
||||
if *mod.Session.Options.Debug {
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] %s\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] %s\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
e.Data)
|
||||
}
|
||||
}
|
||||
|
||||
func (mod *EventsStream) viewSnifferEvent(e session.Event) {
|
||||
func (mod *EventsStream) viewSnifferEvent(output io.Writer, e session.Event) {
|
||||
if strings.HasPrefix(e.Tag, "net.sniff.http.") {
|
||||
mod.viewHttpEvent(e)
|
||||
mod.viewHttpEvent(output, e)
|
||||
} else {
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] %s\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] %s\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
e.Data.(net_sniff.SnifferEvent).Message)
|
||||
}
|
||||
}
|
||||
|
||||
func (mod *EventsStream) viewSynScanEvent(e session.Event) {
|
||||
func (mod *EventsStream) viewSynScanEvent(output io.Writer, e session.Event) {
|
||||
se := e.Data.(syn_scan.SynScanEvent)
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] found open port %d for %s\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] found open port %d for %s\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
se.Port,
|
||||
tui.Bold(se.Address))
|
||||
}
|
||||
|
||||
func (mod *EventsStream) viewUpdateEvent(e session.Event) {
|
||||
func (mod *EventsStream) viewUpdateEvent(output io.Writer, e session.Event) {
|
||||
update := e.Data.(*github.RepositoryRelease)
|
||||
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] an update to version %s is available at %s\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] an update to version %s is available at %s\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Bold(tui.Yellow(e.Tag)),
|
||||
tui.Bold(*update.TagName),
|
||||
*update.HTMLURL)
|
||||
}
|
||||
|
||||
func (mod *EventsStream) doRotation() {
|
||||
if mod.output == os.Stdout {
|
||||
return
|
||||
} else if !mod.rotation.Enabled {
|
||||
return
|
||||
}
|
||||
|
||||
mod.rotation.Lock()
|
||||
defer mod.rotation.Unlock()
|
||||
|
||||
doRotate := false
|
||||
if info, err := mod.output.Stat(); err == nil {
|
||||
if mod.rotation.How == "size" {
|
||||
doRotate = float64(info.Size()) >= float64(mod.rotation.Period*1024*1024)
|
||||
} else if mod.rotation.How == "time" {
|
||||
doRotate = info.ModTime().Unix()%int64(mod.rotation.Period) == 0
|
||||
}
|
||||
}
|
||||
|
||||
if doRotate {
|
||||
var err error
|
||||
|
||||
name := fmt.Sprintf("%s-%s", mod.outputName, time.Now().Format(mod.rotation.Format))
|
||||
|
||||
if err := mod.output.Close(); err != nil {
|
||||
fmt.Printf("could not close log for rotation: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := os.Rename(mod.outputName, name); err != nil {
|
||||
fmt.Printf("could not rename %s to %s: %s\n", mod.outputName, name, err)
|
||||
} else if mod.rotation.Compress {
|
||||
zipName := fmt.Sprintf("%s.zip", name)
|
||||
if err = zip.Files(zipName, []string{name}); err != nil {
|
||||
fmt.Printf("error creating %s: %s", zipName, err)
|
||||
} else if err = os.Remove(name); err != nil {
|
||||
fmt.Printf("error deleting %s: %s", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
mod.output, err = os.OpenFile(mod.outputName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
fmt.Printf("could not open %s: %s", mod.outputName, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (mod *EventsStream) View(e session.Event, refresh bool) {
|
||||
func (mod *EventsStream) Render(output io.Writer, e session.Event) {
|
||||
var err error
|
||||
if err, mod.timeFormat = mod.StringParam("events.stream.time.format"); err != nil {
|
||||
fmt.Fprintf(mod.output, "%v", err)
|
||||
fmt.Fprintf(output, "%v", err)
|
||||
mod.timeFormat = "15:04:05"
|
||||
}
|
||||
|
||||
if e.Tag == "sys.log" {
|
||||
mod.viewLogEvent(e)
|
||||
mod.viewLogEvent(output, e)
|
||||
} else if strings.HasPrefix(e.Tag, "endpoint.") {
|
||||
mod.viewEndpointEvent(e)
|
||||
mod.viewEndpointEvent(output, e)
|
||||
} else if strings.HasPrefix(e.Tag, "wifi.") {
|
||||
mod.viewWiFiEvent(e)
|
||||
mod.viewWiFiEvent(output, e)
|
||||
} else if strings.HasPrefix(e.Tag, "ble.") {
|
||||
mod.viewBLEEvent(e)
|
||||
mod.viewBLEEvent(output, e)
|
||||
} else if strings.HasPrefix(e.Tag, "hid.") {
|
||||
mod.viewHIDEvent(e)
|
||||
mod.viewHIDEvent(output, e)
|
||||
} else if strings.HasPrefix(e.Tag, "mod.") {
|
||||
mod.viewModuleEvent(e)
|
||||
mod.viewModuleEvent(output, e)
|
||||
} else if strings.HasPrefix(e.Tag, "net.sniff.") {
|
||||
mod.viewSnifferEvent(e)
|
||||
mod.viewSnifferEvent(output, e)
|
||||
} else if e.Tag == "syn.scan" {
|
||||
mod.viewSynScanEvent(e)
|
||||
mod.viewSynScanEvent(output, e)
|
||||
} else if e.Tag == "update.available" {
|
||||
mod.viewUpdateEvent(e)
|
||||
mod.viewUpdateEvent(output, e)
|
||||
} else {
|
||||
fmt.Fprintf(mod.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)
|
||||
}
|
||||
}
|
||||
|
||||
func (mod *EventsStream) View(e session.Event, refresh bool) {
|
||||
mod.Render(mod.output, e)
|
||||
|
||||
if refresh && mod.output == os.Stdout {
|
||||
mod.Session.Refresh()
|
||||
|
|
|
@ -4,6 +4,7 @@ package events_stream
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/bettercap/bettercap/network"
|
||||
"github.com/bettercap/bettercap/session"
|
||||
|
@ -11,7 +12,7 @@ import (
|
|||
"github.com/evilsocket/islazy/tui"
|
||||
)
|
||||
|
||||
func (mod *EventsStream) viewBLEEvent(e session.Event) {
|
||||
func (mod *EventsStream) viewBLEEvent(output io.Writer, e session.Event) {
|
||||
if e.Tag == "ble.device.new" {
|
||||
dev := e.Data.(*network.BLEDevice)
|
||||
name := dev.Device.Name()
|
||||
|
@ -23,7 +24,7 @@ func (mod *EventsStream) viewBLEEvent(e session.Event) {
|
|||
vend = fmt.Sprintf(" (%s)", tui.Yellow(vend))
|
||||
}
|
||||
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] new BLE device%s detected as %s%s %s.\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] new BLE device%s detected as %s%s %s.\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
name,
|
||||
|
@ -41,15 +42,11 @@ func (mod *EventsStream) viewBLEEvent(e session.Event) {
|
|||
vend = fmt.Sprintf(" (%s)", tui.Yellow(vend))
|
||||
}
|
||||
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] BLE device%s %s%s lost.\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] BLE device%s %s%s lost.\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
name,
|
||||
dev.Device.ID(),
|
||||
vend)
|
||||
} /* else {
|
||||
fmt.Fprintf(s.output,"[%s] [%s]\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag))
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,6 @@ import (
|
|||
"github.com/bettercap/bettercap/session"
|
||||
)
|
||||
|
||||
func (mod *EventsStream) viewBLEEvent(e session.Event) {
|
||||
func (mod *EventsStream) viewBLEEvent(output io.Writer, e session.Event) {
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package events_stream
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/bettercap/bettercap/network"
|
||||
"github.com/bettercap/bettercap/session"
|
||||
|
@ -9,16 +10,16 @@ import (
|
|||
"github.com/evilsocket/islazy/tui"
|
||||
)
|
||||
|
||||
func (mod *EventsStream) viewHIDEvent(e session.Event) {
|
||||
func (mod *EventsStream) viewHIDEvent(output io.Writer, e session.Event) {
|
||||
dev := e.Data.(*network.HIDDevice)
|
||||
if e.Tag == "hid.device.new" {
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] new HID device %s detected on channel %s.\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] new HID device %s detected on channel %s.\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
tui.Bold(dev.Address),
|
||||
dev.Channels())
|
||||
} else if e.Tag == "hid.device.lost" {
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] HID device %s lost.\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] HID device %s lost.\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
tui.Red(dev.Address))
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
@ -128,11 +129,11 @@ func (mod *EventsStream) dumpRaw(body []byte) string {
|
|||
return "\n" + hex.Dump(body) + "\n"
|
||||
}
|
||||
|
||||
func (mod *EventsStream) viewHttpRequest(e session.Event) {
|
||||
func (mod *EventsStream) viewHttpRequest(output io.Writer, e session.Event) {
|
||||
se := e.Data.(net_sniff.SnifferEvent)
|
||||
req := se.Data.(net_sniff.HTTPRequest)
|
||||
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] %s\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] %s\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
se.Message)
|
||||
|
@ -166,15 +167,15 @@ func (mod *EventsStream) viewHttpRequest(e session.Event) {
|
|||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(mod.output, "\n%s\n", dump)
|
||||
fmt.Fprintf(output, "\n%s\n", dump)
|
||||
}
|
||||
}
|
||||
|
||||
func (mod *EventsStream) viewHttpResponse(e session.Event) {
|
||||
func (mod *EventsStream) viewHttpResponse(output io.Writer, e session.Event) {
|
||||
se := e.Data.(net_sniff.SnifferEvent)
|
||||
res := se.Data.(net_sniff.HTTPResponse)
|
||||
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] %s\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] %s\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
se.Message)
|
||||
|
@ -198,14 +199,14 @@ func (mod *EventsStream) viewHttpResponse(e session.Event) {
|
|||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(mod.output, "\n%s\n", dump)
|
||||
fmt.Fprintf(output, "\n%s\n", dump)
|
||||
}
|
||||
}
|
||||
|
||||
func (mod *EventsStream) viewHttpEvent(e session.Event) {
|
||||
func (mod *EventsStream) viewHttpEvent(output io.Writer, e session.Event) {
|
||||
if e.Tag == "net.sniff.http.request" {
|
||||
mod.viewHttpRequest(e)
|
||||
mod.viewHttpRequest(output, e)
|
||||
} else if e.Tag == "net.sniff.http.response" {
|
||||
mod.viewHttpResponse(e)
|
||||
mod.viewHttpResponse(output, e)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package events_stream
|
|||
import (
|
||||
"fmt"
|
||||
"github.com/bettercap/bettercap/modules/wifi"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/bettercap/bettercap/network"
|
||||
|
@ -11,7 +12,7 @@ import (
|
|||
"github.com/evilsocket/islazy/tui"
|
||||
)
|
||||
|
||||
func (mod *EventsStream) viewWiFiApEvent(e session.Event) {
|
||||
func (mod *EventsStream) viewWiFiApEvent(output io.Writer, e session.Event) {
|
||||
ap := e.Data.(*network.AccessPoint)
|
||||
vend := ""
|
||||
if ap.Vendor != "" {
|
||||
|
@ -23,7 +24,7 @@ func (mod *EventsStream) viewWiFiApEvent(e session.Event) {
|
|||
}
|
||||
|
||||
if e.Tag == "wifi.ap.new" {
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] wifi access point %s%s detected as %s%s.\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] wifi access point %s%s detected as %s%s.\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
tui.Bold(ap.ESSID()),
|
||||
|
@ -31,20 +32,20 @@ func (mod *EventsStream) viewWiFiApEvent(e session.Event) {
|
|||
tui.Green(ap.BSSID()),
|
||||
tui.Dim(vend))
|
||||
} else if e.Tag == "wifi.ap.lost" {
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] wifi access point %s (%s) lost.\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] wifi access point %s (%s) lost.\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
tui.Red(ap.ESSID()),
|
||||
ap.BSSID())
|
||||
} else {
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] %s\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] %s\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
ap.String())
|
||||
}
|
||||
}
|
||||
|
||||
func (mod *EventsStream) viewWiFiClientProbeEvent(e session.Event) {
|
||||
func (mod *EventsStream) viewWiFiClientProbeEvent(output io.Writer, e session.Event) {
|
||||
probe := e.Data.(wifi.ProbeEvent)
|
||||
desc := ""
|
||||
if probe.FromAlias != "" {
|
||||
|
@ -57,7 +58,7 @@ func (mod *EventsStream) viewWiFiClientProbeEvent(e session.Event) {
|
|||
rssi = fmt.Sprintf(" (%d dBm)", probe.RSSI)
|
||||
}
|
||||
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] station %s%s is probing for SSID %s%s\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] station %s%s is probing for SSID %s%s\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
probe.FromAddr,
|
||||
|
@ -66,7 +67,7 @@ func (mod *EventsStream) viewWiFiClientProbeEvent(e session.Event) {
|
|||
tui.Yellow(rssi))
|
||||
}
|
||||
|
||||
func (mod *EventsStream) viewWiFiHandshakeEvent(e session.Event) {
|
||||
func (mod *EventsStream) viewWiFiHandshakeEvent(output io.Writer, e session.Event) {
|
||||
hand := e.Data.(wifi.HandshakeEvent)
|
||||
|
||||
from := hand.Station
|
||||
|
@ -86,7 +87,7 @@ func (mod *EventsStream) viewWiFiHandshakeEvent(e session.Event) {
|
|||
what += " (half)"
|
||||
}
|
||||
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] captured %s -> %s %s to %s\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] captured %s -> %s %s to %s\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
from,
|
||||
|
@ -95,20 +96,20 @@ func (mod *EventsStream) viewWiFiHandshakeEvent(e session.Event) {
|
|||
hand.File)
|
||||
}
|
||||
|
||||
func (mod *EventsStream) viewWiFiClientEvent(e session.Event) {
|
||||
func (mod *EventsStream) viewWiFiClientEvent(output io.Writer, e session.Event) {
|
||||
ce := e.Data.(wifi.ClientEvent)
|
||||
|
||||
ce.Client.Alias = mod.Session.Lan.GetAlias(ce.Client.BSSID())
|
||||
|
||||
if e.Tag == "wifi.client.new" {
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] new station %s detected for %s (%s)\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] new station %s detected for %s (%s)\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
ce.Client.String(),
|
||||
tui.Bold(ce.AP.ESSID()),
|
||||
tui.Dim(ce.AP.BSSID()))
|
||||
} else if e.Tag == "wifi.client.lost" {
|
||||
fmt.Fprintf(mod.output, "[%s] [%s] station %s disconnected from %s (%s)\n",
|
||||
fmt.Fprintf(output, "[%s] [%s] station %s disconnected from %s (%s)\n",
|
||||
e.Time.Format(mod.timeFormat),
|
||||
tui.Green(e.Tag),
|
||||
ce.Client.String(),
|
||||
|
@ -117,16 +118,16 @@ func (mod *EventsStream) viewWiFiClientEvent(e session.Event) {
|
|||
}
|
||||
}
|
||||
|
||||
func (mod *EventsStream) viewWiFiEvent(e session.Event) {
|
||||
func (mod *EventsStream) viewWiFiEvent(output io.Writer, e session.Event) {
|
||||
if strings.HasPrefix(e.Tag, "wifi.ap.") {
|
||||
mod.viewWiFiApEvent(e)
|
||||
mod.viewWiFiApEvent(output, e)
|
||||
} else if e.Tag == "wifi.client.probe" {
|
||||
mod.viewWiFiClientProbeEvent(e)
|
||||
mod.viewWiFiClientProbeEvent(output, e)
|
||||
} else if e.Tag == "wifi.client.handshake" {
|
||||
mod.viewWiFiHandshakeEvent(e)
|
||||
mod.viewWiFiHandshakeEvent(output, e)
|
||||
} else if e.Tag == "wifi.client.new" || e.Tag == "wifi.client.lost" {
|
||||
mod.viewWiFiClientEvent(e)
|
||||
mod.viewWiFiClientEvent(output, e)
|
||||
} else {
|
||||
fmt.Fprintf(mod.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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ func (mod *GPS) readLine() (line string, err error) {
|
|||
}
|
||||
|
||||
func (mod *GPS) Show() error {
|
||||
fmt.Printf("latitude:%f longitude:%f quality:%s satellites:%d altitude:%f\n",
|
||||
mod.Printf("latitude:%f longitude:%f quality:%s satellites:%d altitude:%f\n",
|
||||
mod.Session.GPS.Latitude,
|
||||
mod.Session.GPS.Longitude,
|
||||
mod.Session.GPS.FixQuality,
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package hid
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
|
@ -109,12 +107,12 @@ func (mod *HIDRecon) Show() (err error) {
|
|||
rows = append(rows, mod.getRow(dev))
|
||||
}
|
||||
|
||||
tui.Table(os.Stdout, mod.colNames(), rows)
|
||||
tui.Table(mod.Session.Events.Stdout, mod.colNames(), rows)
|
||||
|
||||
if mod.sniffAddrRaw == nil {
|
||||
fmt.Printf("\nchannel:%d\n\n", mod.channel)
|
||||
mod.Printf("\nchannel:%d\n\n", mod.channel)
|
||||
} else {
|
||||
fmt.Printf("\nchannel:%d sniffing:%s\n\n", mod.channel, tui.Red(mod.sniffAddr))
|
||||
mod.Printf("\nchannel:%d sniffing:%s\n\n", mod.channel, tui.Red(mod.sniffAddr))
|
||||
}
|
||||
|
||||
if len(rows) > 0 {
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"github.com/bettercap/bettercap/modules/api_rest"
|
||||
"github.com/bettercap/bettercap/modules/arp_spoof"
|
||||
"github.com/bettercap/bettercap/modules/ble"
|
||||
"github.com/bettercap/bettercap/modules/c2"
|
||||
"github.com/bettercap/bettercap/modules/caplets"
|
||||
"github.com/bettercap/bettercap/modules/dhcp6_spoof"
|
||||
"github.com/bettercap/bettercap/modules/dns_spoof"
|
||||
|
@ -59,6 +60,7 @@ func LoadModules(sess *session.Session) {
|
|||
sess.Register(wifi.NewWiFiModule(sess))
|
||||
sess.Register(wol.NewWOL(sess))
|
||||
sess.Register(hid.NewHIDRecon(sess))
|
||||
sess.Register(c2.NewC2(sess))
|
||||
|
||||
sess.Register(caplets.NewCapletsModule(sess))
|
||||
sess.Register(update.NewUpdateModule(sess))
|
||||
|
|
|
@ -2,7 +2,6 @@ package net_recon
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -223,7 +222,7 @@ func (mod *Discovery) showStatusBar() {
|
|||
parts = append(parts, fmt.Sprintf("%d errs", nErrors))
|
||||
}
|
||||
|
||||
fmt.Printf("\n%s\n\n", strings.Join(parts, " / "))
|
||||
mod.Printf("\n%s\n\n", strings.Join(parts, " / "))
|
||||
}
|
||||
|
||||
func (mod *Discovery) Show(arg string) (err error) {
|
||||
|
@ -263,7 +262,7 @@ func (mod *Discovery) Show(arg string) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
tui.Table(os.Stdout, colNames, rows)
|
||||
tui.Table(mod.Session.Events.Stdout, colNames, rows)
|
||||
|
||||
mod.showStatusBar()
|
||||
|
||||
|
@ -305,7 +304,7 @@ func (mod *Discovery) showMeta(arg string) (err error) {
|
|||
}
|
||||
|
||||
any = true
|
||||
tui.Table(os.Stdout, colNames, rows)
|
||||
tui.Table(mod.Session.Events.Stdout, colNames, rows)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ package wifi
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -265,9 +264,9 @@ func (mod *WiFiModule) colNames(nrows int) []string {
|
|||
} else {
|
||||
columns = []string{"RSSI", "BSSID", "Ch", "Sent", "Recvd", "Seen"}
|
||||
}
|
||||
fmt.Printf("\n%s clients:\n", mod.ap.HwAddress)
|
||||
mod.Printf("\n%s clients:\n", mod.ap.HwAddress)
|
||||
} else {
|
||||
fmt.Printf("\nNo authenticated clients detected for %s.\n", mod.ap.HwAddress)
|
||||
mod.Printf("\nNo authenticated clients detected for %s.\n", mod.ap.HwAddress)
|
||||
}
|
||||
|
||||
if columns != nil {
|
||||
|
@ -312,7 +311,7 @@ func (mod *WiFiModule) showStatusBar() {
|
|||
parts = append(parts, fmt.Sprintf("%d handshakes", nHandshakes))
|
||||
}
|
||||
|
||||
fmt.Printf("\n%s\n\n", strings.Join(parts, " / "))
|
||||
mod.Printf("\n%s\n\n", strings.Join(parts, " / "))
|
||||
}
|
||||
|
||||
func (mod *WiFiModule) Show() (err error) {
|
||||
|
@ -337,7 +336,7 @@ func (mod *WiFiModule) Show() (err error) {
|
|||
}
|
||||
nrows := len(rows)
|
||||
if nrows > 0 {
|
||||
tui.Table(os.Stdout, mod.colNames(nrows), rows)
|
||||
tui.Table(mod.Session.Events.Stdout, mod.colNames(nrows), rows)
|
||||
}
|
||||
|
||||
mod.showStatusBar()
|
||||
|
@ -396,7 +395,7 @@ func (mod *WiFiModule) ShowWPS(bssid string) (err error) {
|
|||
})
|
||||
}
|
||||
|
||||
tui.Table(os.Stdout, colNames, rows)
|
||||
tui.Table(mod.Session.Events.Stdout, colNames, rows)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -37,6 +37,19 @@ func (e Event) Label() string {
|
|||
return color + label + tui.RESET
|
||||
}
|
||||
|
||||
type EventBus <-chan Event
|
||||
|
||||
type PrintCallback func(format string, args ...interface{})
|
||||
|
||||
type PrintWriter struct {
|
||||
pool *EventPool
|
||||
}
|
||||
|
||||
func (w PrintWriter) Write(p []byte) (n int, err error) {
|
||||
w.pool.Printf("%s", string(p))
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
type EventPool struct {
|
||||
*sync.Mutex
|
||||
|
||||
|
@ -44,19 +57,35 @@ type EventPool struct {
|
|||
silent bool
|
||||
events []Event
|
||||
listeners []chan Event
|
||||
printLock sync.Mutex
|
||||
printCbs []PrintCallback
|
||||
Stdout PrintWriter
|
||||
}
|
||||
|
||||
func NewEventPool(debug bool, silent bool) *EventPool {
|
||||
return &EventPool{
|
||||
pool := &EventPool{
|
||||
Mutex: &sync.Mutex{},
|
||||
debug: debug,
|
||||
silent: silent,
|
||||
events: make([]Event, 0),
|
||||
listeners: make([]chan Event, 0),
|
||||
printCbs: make([]PrintCallback, 0),
|
||||
}
|
||||
|
||||
pool.Stdout = PrintWriter{
|
||||
pool: pool,
|
||||
}
|
||||
|
||||
return pool
|
||||
}
|
||||
|
||||
func (p *EventPool) Listen() <-chan Event {
|
||||
func (p *EventPool) OnPrint(cb PrintCallback) {
|
||||
p.printLock.Lock()
|
||||
defer p.printLock.Unlock()
|
||||
p.printCbs = append(p.printCbs, cb)
|
||||
}
|
||||
|
||||
func (p *EventPool) Listen() EventBus {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
l := make(chan Event)
|
||||
|
@ -76,7 +105,7 @@ func (p *EventPool) Listen() <-chan Event {
|
|||
return l
|
||||
}
|
||||
|
||||
func (p *EventPool) Unlisten(listener <-chan Event) {
|
||||
func (p *EventPool) Unlisten(listener EventBus) {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
|
||||
|
@ -123,6 +152,16 @@ func (p *EventPool) Add(tag string, data interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
func (p *EventPool) Printf(format string, a ...interface{}) {
|
||||
p.printLock.Lock()
|
||||
defer p.printLock.Unlock()
|
||||
|
||||
for _, cb := range p.printCbs {
|
||||
cb(format, a...)
|
||||
}
|
||||
fmt.Printf(format, a...)
|
||||
}
|
||||
|
||||
func (p *EventPool) Log(level log.Verbosity, format string, args ...interface{}) {
|
||||
if level == log.DEBUG && !p.debug {
|
||||
return
|
||||
|
|
|
@ -132,6 +132,10 @@ func (m *SessionModule) Fatal(format string, args ...interface{}) {
|
|||
m.Session.Events.Log(log.FATAL, m.tag+format, args...)
|
||||
}
|
||||
|
||||
func (m *SessionModule) Printf(format string, a ...interface{}) {
|
||||
m.Session.Events.Printf(format, a...)
|
||||
}
|
||||
|
||||
func (m *SessionModule) Requires(modName string) {
|
||||
m.requires = append(m.requires, modName)
|
||||
}
|
||||
|
|
|
@ -33,10 +33,10 @@ func (s *Session) generalHelp() {
|
|||
pad := "%" + strconv.Itoa(maxLen) + "s"
|
||||
|
||||
for _, h := range s.CoreHandlers {
|
||||
fmt.Printf(" "+tui.Yellow(pad)+" : %s\n", h.Name, h.Description)
|
||||
s.Events.Printf(" "+tui.Yellow(pad)+" : %s\n", h.Name, h.Description)
|
||||
}
|
||||
|
||||
fmt.Println(tui.Bold("\nModules\n"))
|
||||
s.Events.Printf("%s\n", tui.Bold("\nModules\n"))
|
||||
|
||||
maxLen = 0
|
||||
for _, m := range s.Modules {
|
||||
|
@ -54,7 +54,7 @@ func (s *Session) generalHelp() {
|
|||
} else {
|
||||
status = tui.Red("not running")
|
||||
}
|
||||
fmt.Printf(" "+tui.Yellow(pad)+" > %s\n", m.Name(), status)
|
||||
s.Events.Printf(" "+tui.Yellow(pad)+" > %s\n", m.Name(), status)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
|
@ -73,7 +73,7 @@ func (s *Session) moduleHelp(filter string) error {
|
|||
} else {
|
||||
status = tui.Red("not running")
|
||||
}
|
||||
fmt.Printf("%s (%s): %s\n\n", tui.Yellow(m.Name()), status, tui.Dim(m.Description()))
|
||||
s.Events.Printf("%s (%s): %s\n\n", tui.Yellow(m.Name()), status, tui.Dim(m.Description()))
|
||||
|
||||
maxLen := 0
|
||||
handlers := m.Handlers()
|
||||
|
@ -85,7 +85,7 @@ func (s *Session) moduleHelp(filter string) error {
|
|||
}
|
||||
|
||||
for _, h := range handlers {
|
||||
fmt.Print(h.Help(maxLen))
|
||||
s.Events.Printf("%s", h.Help(maxLen))
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
|
@ -105,9 +105,9 @@ func (s *Session) moduleHelp(filter string) error {
|
|||
return v[i].Name < v[j].Name
|
||||
})
|
||||
|
||||
fmt.Print(" Parameters\n\n")
|
||||
s.Events.Printf(" Parameters\n\n")
|
||||
for _, p := range v {
|
||||
fmt.Print(p.Help(maxLen))
|
||||
s.Events.Printf("%s", p.Help(maxLen))
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
@ -138,13 +138,13 @@ func (s *Session) activeHandler(args []string, sess *Session) error {
|
|||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("%s (%s)\n", tui.Bold(m.Name()), tui.Dim(m.Description()))
|
||||
s.Events.Printf("%s (%s)\n", tui.Bold(m.Name()), tui.Dim(m.Description()))
|
||||
params := m.Parameters()
|
||||
if len(params) > 0 {
|
||||
fmt.Println()
|
||||
for _, p := range params {
|
||||
_, val := s.Env.Get(p.Name)
|
||||
fmt.Printf(" %s : %s\n", tui.Yellow(p.Name), val)
|
||||
s.Events.Printf(" %s : %s\n", tui.Yellow(p.Name), val)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,13 +206,13 @@ func (s *Session) getHandler(args []string, sess *Session) error {
|
|||
prev_ns = ns
|
||||
}
|
||||
|
||||
fmt.Printf(" %"+strconv.Itoa(padding)+"s: '%s'\n", k, s.Env.Data[k])
|
||||
s.Events.Printf(" %"+strconv.Itoa(padding)+"s: '%s'\n", k, s.Env.Data[k])
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
} else if found, value := s.Env.Get(key); found {
|
||||
fmt.Println()
|
||||
fmt.Printf(" %s: '%s'\n", key, value)
|
||||
s.Events.Printf(" %s: '%s'\n", key, value)
|
||||
fmt.Println()
|
||||
} else {
|
||||
return fmt.Errorf("%s not found", key)
|
||||
|
@ -269,7 +269,7 @@ func (s *Session) includeHandler(args []string, sess *Session) error {
|
|||
func (s *Session) shHandler(args []string, sess *Session) error {
|
||||
out, err := core.Shell(args[0])
|
||||
if err == nil {
|
||||
fmt.Printf("%s\n", out)
|
||||
s.Events.Printf("%s\n", out)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue