mirror of
https://github.com/bettercap/bettercap
synced 2025-08-14 10:46:57 -07:00
new: new -script allows to run JS code to instrument session
This commit is contained in:
parent
d5e5abcb9b
commit
40727063ec
13 changed files with 610 additions and 312 deletions
21
session/script.go
Normal file
21
session/script.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
package session
|
||||
|
||||
import (
|
||||
"github.com/evilsocket/islazy/plugin"
|
||||
|
||||
_ "github.com/bettercap/bettercap/js"
|
||||
)
|
||||
|
||||
type Script struct {
|
||||
*plugin.Plugin
|
||||
}
|
||||
|
||||
func LoadScript(fileName string, ses *Session) (*Script, error) {
|
||||
if p, err := plugin.Load(fileName); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return &Script{
|
||||
Plugin: p,
|
||||
}, nil
|
||||
}
|
||||
}
|
33
session/script_builtin.go
Normal file
33
session/script_builtin.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
package session
|
||||
|
||||
import (
|
||||
"github.com/bettercap/bettercap/js"
|
||||
"github.com/robertkrimen/otto"
|
||||
)
|
||||
|
||||
func jsEnvFunc(call otto.FunctionCall) otto.Value {
|
||||
argv := call.ArgumentList
|
||||
argc := len(argv)
|
||||
|
||||
if argc == 1 {
|
||||
// get
|
||||
varName := call.Argument(0).String()
|
||||
if found, varValue := I.Env.Get(varName); found {
|
||||
v, err := otto.ToValue(varValue)
|
||||
if err != nil {
|
||||
return js.ReportError("could not convert to string: %s", varValue)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
} else if argc == 2 {
|
||||
// set
|
||||
varName := call.Argument(0).String()
|
||||
varValue := call.Argument(1).String()
|
||||
I.Env.Set(varName, varValue)
|
||||
} else {
|
||||
return js.ReportError("env: expected 1 or 2 arguments, %d given instead.", argc)
|
||||
}
|
||||
return js.NullValue
|
||||
}
|
||||
|
67
session/script_builtin_runtime.go
Normal file
67
session/script_builtin_runtime.go
Normal file
|
@ -0,0 +1,67 @@
|
|||
package session
|
||||
|
||||
import (
|
||||
"github.com/bettercap/bettercap/js"
|
||||
"github.com/evilsocket/islazy/log"
|
||||
"github.com/robertkrimen/otto"
|
||||
)
|
||||
|
||||
func jsRunFunc(call otto.FunctionCall) otto.Value {
|
||||
argv := call.ArgumentList
|
||||
argc := len(argv)
|
||||
if argc != 1 {
|
||||
return js.ReportError("run accepts one string argument")
|
||||
} else if argv[0].IsString() == false {
|
||||
return js.ReportError("run accepts one string argument")
|
||||
}
|
||||
|
||||
for _, cmd := range ParseCommands(argv[0].String()) {
|
||||
if err := I.Run(cmd); err != nil {
|
||||
return js.ReportError("error running '%s': %v", cmd, err)
|
||||
}
|
||||
}
|
||||
|
||||
return js.NullValue
|
||||
}
|
||||
|
||||
func jsOnEventFunc(call otto.FunctionCall) otto.Value {
|
||||
argv := call.ArgumentList
|
||||
argc := len(argv)
|
||||
cb := otto.NullValue()
|
||||
filterExpr := ""
|
||||
|
||||
// just one argument, a function to receive all events
|
||||
if argc == 1 {
|
||||
if argv[0].IsFunction() == false {
|
||||
return js.ReportError("the single argument must be a function")
|
||||
}
|
||||
cb = argv[0]
|
||||
} else {
|
||||
if argc != 2 {
|
||||
return js.ReportError("expected two arguments (event_name, callback), got %d", argc)
|
||||
} else if argv[0].IsString() == false {
|
||||
return js.ReportError("first argument must be a string")
|
||||
} else if argv[1].IsFunction() == false {
|
||||
return js.ReportError("second argument must be a function")
|
||||
}
|
||||
|
||||
filterExpr = argv[0].String()
|
||||
cb = argv[1]
|
||||
}
|
||||
|
||||
// start a go routine for this event listener
|
||||
go func(expr string, cb otto.Value) {
|
||||
listener := I.Events.Listen()
|
||||
defer I.Events.Unlisten(listener)
|
||||
|
||||
for event := range listener {
|
||||
if expr == "" || event.Tag == expr {
|
||||
if _, err := cb.Call(otto.NullValue(), event); err != nil {
|
||||
I.Events.Log(log.ERROR, "error dispatching event %s: %v", event.Tag, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}(filterExpr, cb)
|
||||
|
||||
return js.NullValue
|
||||
}
|
|
@ -3,6 +3,7 @@ package session
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/evilsocket/islazy/plugin"
|
||||
"net"
|
||||
"os"
|
||||
"regexp"
|
||||
|
@ -89,6 +90,8 @@ type Session struct {
|
|||
EventsIgnoreList *EventsIgnoreList
|
||||
UnkCmdCallback UnknownCommandCallback
|
||||
Firewall firewall.FirewallManager
|
||||
|
||||
script *Script
|
||||
}
|
||||
|
||||
func New() (*Session, error) {
|
||||
|
@ -299,13 +302,28 @@ func (s *Session) Start() error {
|
|||
s.Events.Add("session.started", nil)
|
||||
}
|
||||
|
||||
// register js functions here to avoid cyclic dependency between
|
||||
// js and session
|
||||
plugin.Defines["env"] = jsEnvFunc
|
||||
plugin.Defines["run"] = jsRunFunc
|
||||
plugin.Defines["onEvent"] = jsOnEventFunc
|
||||
plugin.Defines["session"] = s
|
||||
|
||||
// load the script here so the session and its internal objects are ready
|
||||
if *s.Options.Script != "" {
|
||||
if s.script, err = LoadScript(*s.Options.Script, s); err != nil {
|
||||
return fmt.Errorf("error loading %s: %v", *s.Options.Script, err)
|
||||
}
|
||||
log.Debug("session script %s loaded", *s.Options.Script)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Session) Skip(ip net.IP) bool {
|
||||
if ip.IsLoopback() {
|
||||
return true
|
||||
} else if ip.Equal(s.Interface.IP) || ip.Equal(s.Interface.IPv6){
|
||||
} else if ip.Equal(s.Interface.IP) || ip.Equal(s.Interface.IPv6) {
|
||||
return true
|
||||
} else if ip.Equal(s.Gateway.IP) {
|
||||
return true
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue