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:
evilsocket 2018-08-25 11:31:25 +02:00
commit f213d0d0ca
No known key found for this signature in database
GPG key ID: 1564D7F30393A456
4 changed files with 265 additions and 254 deletions

View file

@ -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?