mirror of
https://github.com/bettercap/bettercap
synced 2025-08-14 02:36:57 -07:00
fix: working directory is temporarily switched when running a caplet in order to properly load/include files relative to the caplet itself
This commit is contained in:
parent
9a3a514f6a
commit
f213d0d0ca
4 changed files with 265 additions and 254 deletions
|
@ -5,13 +5,10 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"sort"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/bettercap/readline"
|
||||
|
@ -65,70 +62,6 @@ type Session struct {
|
|||
UnkCmdCallback UnknownCommandCallback `json:"-"`
|
||||
}
|
||||
|
||||
func ParseCommands(line string) []string {
|
||||
args := []string{}
|
||||
buf := ""
|
||||
|
||||
singleQuoted := false
|
||||
doubleQuoted := false
|
||||
finish := false
|
||||
|
||||
for _, c := range line {
|
||||
switch c {
|
||||
case ';':
|
||||
if !singleQuoted && !doubleQuoted {
|
||||
finish = true
|
||||
} else {
|
||||
buf += string(c)
|
||||
}
|
||||
|
||||
case '"':
|
||||
if doubleQuoted {
|
||||
// finish of quote
|
||||
doubleQuoted = false
|
||||
} else if singleQuoted {
|
||||
// quote initiated with ', so we ignore it
|
||||
buf += string(c)
|
||||
} else {
|
||||
// quote init here
|
||||
doubleQuoted = true
|
||||
}
|
||||
|
||||
case '\'':
|
||||
if singleQuoted {
|
||||
singleQuoted = false
|
||||
} else if doubleQuoted {
|
||||
buf += string(c)
|
||||
} else {
|
||||
singleQuoted = true
|
||||
}
|
||||
|
||||
default:
|
||||
buf += string(c)
|
||||
}
|
||||
|
||||
if finish {
|
||||
args = append(args, buf)
|
||||
finish = false
|
||||
buf = ""
|
||||
}
|
||||
}
|
||||
|
||||
if len(buf) > 0 {
|
||||
args = append(args, buf)
|
||||
}
|
||||
|
||||
cmds := make([]string, 0)
|
||||
for _, cmd := range args {
|
||||
cmd = core.Trim(cmd)
|
||||
if cmd != "" || (len(cmd) > 0 && cmd[0] != '#') {
|
||||
cmds = append(cmds, cmd)
|
||||
}
|
||||
}
|
||||
|
||||
return cmds
|
||||
}
|
||||
|
||||
func New() (*Session, error) {
|
||||
var err error
|
||||
|
||||
|
@ -182,70 +115,6 @@ func (s *Session) Module(name string) (err error, mod Module) {
|
|||
return fmt.Errorf("Module %s not found", name), mod
|
||||
}
|
||||
|
||||
func (s *Session) setupReadline() error {
|
||||
var err error
|
||||
|
||||
pcompleters := make([]readline.PrefixCompleterInterface, 0)
|
||||
for _, h := range s.CoreHandlers {
|
||||
if h.Completer == nil {
|
||||
pcompleters = append(pcompleters, readline.PcItem(h.Name))
|
||||
} else {
|
||||
pcompleters = append(pcompleters, h.Completer)
|
||||
}
|
||||
}
|
||||
|
||||
tree := make(map[string][]string)
|
||||
for _, m := range s.Modules {
|
||||
for _, h := range m.Handlers() {
|
||||
parts := strings.Split(h.Name, " ")
|
||||
name := parts[0]
|
||||
|
||||
if _, found := tree[name]; !found {
|
||||
tree[name] = []string{}
|
||||
}
|
||||
|
||||
var appendedOption = strings.Join(parts[1:], " ")
|
||||
|
||||
if len(appendedOption) > 0 && !containsCapitals(appendedOption) {
|
||||
tree[name] = append(tree[name], appendedOption)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for root, subElems := range CapletsTree {
|
||||
item := readline.PcItem(root)
|
||||
item.Children = []readline.PrefixCompleterInterface{}
|
||||
for _, child := range subElems {
|
||||
item.Children = append(item.Children, readline.PcItem(child))
|
||||
}
|
||||
pcompleters = append(pcompleters, item)
|
||||
}
|
||||
|
||||
history := ""
|
||||
if !*s.Options.NoHistory {
|
||||
history, _ = core.ExpandPath(HistoryFile)
|
||||
}
|
||||
|
||||
cfg := readline.Config{
|
||||
HistoryFile: history,
|
||||
InterruptPrompt: "^C",
|
||||
EOFPrompt: "exit",
|
||||
AutoComplete: readline.NewPrefixCompleter(pcompleters...),
|
||||
}
|
||||
|
||||
s.Input, err = readline.NewEx(&cfg)
|
||||
return err
|
||||
}
|
||||
|
||||
func containsCapitals(s string) bool {
|
||||
for _, ch := range s {
|
||||
if ch < 133 && ch > 101 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *Session) Close() {
|
||||
if *s.Options.Debug {
|
||||
fmt.Printf("\nStopping modules and cleaning session state ...\n")
|
||||
|
@ -290,77 +159,6 @@ func (s *Session) Register(mod Module) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Session) startNetMon() {
|
||||
// keep reading network events in order to add / update endpoints
|
||||
go func() {
|
||||
for event := range s.Queue.Activities {
|
||||
if !s.Active {
|
||||
return
|
||||
}
|
||||
|
||||
if s.IsOn("net.recon") && event.Source {
|
||||
addr := event.IP.String()
|
||||
mac := event.MAC.String()
|
||||
|
||||
existing := s.Lan.AddIfNew(addr, mac)
|
||||
if existing != nil {
|
||||
existing.LastSeen = time.Now()
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (s *Session) setupSignals() {
|
||||
c := make(chan os.Signal)
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-c
|
||||
fmt.Println()
|
||||
s.Events.Log(core.WARNING, "Got SIGTERM")
|
||||
s.Close()
|
||||
os.Exit(0)
|
||||
}()
|
||||
}
|
||||
|
||||
func (s *Session) setupEnv() {
|
||||
s.Env.Set("iface.index", fmt.Sprintf("%d", s.Interface.Index))
|
||||
s.Env.Set("iface.name", s.Interface.Name())
|
||||
s.Env.Set("iface.ipv4", s.Interface.IpAddress)
|
||||
s.Env.Set("iface.ipv6", s.Interface.Ip6Address)
|
||||
s.Env.Set("iface.mac", s.Interface.HwAddress)
|
||||
s.Env.Set("gateway.address", s.Gateway.IpAddress)
|
||||
s.Env.Set("gateway.mac", s.Gateway.HwAddress)
|
||||
|
||||
if found, v := s.Env.Get(PromptVariable); !found || v == "" {
|
||||
s.Env.Set(PromptVariable, DefaultPrompt)
|
||||
}
|
||||
|
||||
dbg := "false"
|
||||
if *s.Options.Debug {
|
||||
dbg = "true"
|
||||
}
|
||||
s.Env.WithCallback("log.debug", dbg, func(newValue string) {
|
||||
newDbg := false
|
||||
if newValue == "true" {
|
||||
newDbg = true
|
||||
}
|
||||
s.Events.SetDebug(newDbg)
|
||||
})
|
||||
|
||||
silent := "false"
|
||||
if *s.Options.Silent {
|
||||
silent = "true"
|
||||
}
|
||||
s.Env.WithCallback("log.silent", silent, func(newValue string) {
|
||||
newSilent := false
|
||||
if newValue == "true" {
|
||||
newSilent = true
|
||||
}
|
||||
s.Events.SetSilent(newSilent)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Session) Start() error {
|
||||
var err error
|
||||
|
||||
|
@ -445,19 +243,6 @@ func (s *Session) IsOn(moduleName string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (s *Session) parseEnvTokens(str string) (string, error) {
|
||||
// replace all {env.something} with their values
|
||||
for _, m := range reEnvVarCapture.FindAllString(str, -1) {
|
||||
varName := strings.Trim(strings.Replace(m, "env.", "", -1), "{}")
|
||||
if found, value := s.Env.Get(varName); found {
|
||||
str = strings.Replace(str, m, value, -1)
|
||||
} else {
|
||||
return "", fmt.Errorf("variable '%s' is not defined", varName)
|
||||
}
|
||||
}
|
||||
return str, nil
|
||||
}
|
||||
|
||||
func (s *Session) Refresh() {
|
||||
p, _ := s.parseEnvTokens(s.Prompt.Render(s))
|
||||
s.Input.SetPrompt(p)
|
||||
|
@ -475,13 +260,7 @@ func (s *Session) RunCaplet(filename string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
for _, line := range caplet.Code {
|
||||
if err = s.Run(line + "\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return caplet.Eval(s, nil)
|
||||
}
|
||||
|
||||
func (s *Session) Run(line string) error {
|
||||
|
@ -491,6 +270,7 @@ func (s *Session) Run(line string) error {
|
|||
// to 'arp.spoof on' (fixes #178)
|
||||
line = reCmdSpaceCleaner.ReplaceAllString(line, "$1 $2")
|
||||
|
||||
// replace all {env.something} with their values
|
||||
line, err := s.parseEnvTokens(line)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -514,18 +294,7 @@ func (s *Session) Run(line string) error {
|
|||
|
||||
// is it a caplet command?
|
||||
if parsed, caplet, argv := parseCapletCommand(line); parsed {
|
||||
for _, line := range caplet.Code {
|
||||
// replace $0 with argv[0], $1 with argv[1] and so on
|
||||
for i, arg := range argv {
|
||||
line = strings.Replace(line, fmt.Sprintf("$%d", i), arg, -1)
|
||||
}
|
||||
|
||||
if err = s.Run(line + "\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return caplet.Eval(s, argv)
|
||||
}
|
||||
|
||||
// is it a proxy module custom command?
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue