diff --git a/caplets/env.go b/caplets/env.go index 4c803b6e..d62a516f 100644 --- a/caplets/env.go +++ b/caplets/env.go @@ -3,30 +3,46 @@ package caplets import ( "os" "path/filepath" + "runtime" "github.com/evilsocket/islazy/str" + "github.com/mitchellh/go-homedir" ) const ( EnvVarName = "CAPSPATH" Suffix = ".cap" InstallArchive = "https://github.com/bettercap/caplets/archive/master.zip" - InstallBase = "/usr/local/share/bettercap/" ) +func getInstallBase() string { + if runtime.GOOS == "windows" { + return filepath.Join(os.Getenv("ALLUSERSPROFILE"), "bettercap") + } + return "/usr/local/share/bettercap/" +} + +func getUserHomeDir() string { + usr, _ := homedir.Dir() + return usr +} + var ( + InstallBase = getInstallBase() InstallPathArchive = filepath.Join(InstallBase, "caplets-master") InstallPath = filepath.Join(InstallBase, "caplets") + ArchivePath = filepath.Join(os.TempDir(), "caplets.zip") LoadPaths = []string{ "./", "./caplets/", InstallPath, + filepath.Join(getUserHomeDir(), "caplets"), } ) func init() { - for _, path := range str.SplitBy(str.Trim(os.Getenv(EnvVarName)), ":") { + for _, path := range str.SplitBy(str.Trim(os.Getenv(EnvVarName)), string(os.PathListSeparator)) { if path = str.Trim(path); len(path) > 0 { LoadPaths = append(LoadPaths, path) } diff --git a/caplets/manager.go b/caplets/manager.go index cb004d0c..984fc4c8 100644 --- a/caplets/manager.go +++ b/caplets/manager.go @@ -25,7 +25,7 @@ func List() []*Caplet { for _, fileName := range append(files, files2...) { if _, err := os.Stat(fileName); err == nil { - base := strings.Replace(fileName, searchPath+"/", "", -1) + base := strings.Replace(fileName, searchPath+string(os.PathSeparator), "", -1) base = strings.Replace(base, Suffix, "", -1) if err, caplet := Load(base); err != nil { @@ -58,7 +58,7 @@ func Load(name string) (error, *Caplet) { name += Suffix } - if name[0] != '/' { + if !filepath.IsAbs(name) { for _, path := range LoadPaths { names = append(names, filepath.Join(path, name)) } diff --git a/modules/caplets/caplets.go b/modules/caplets/caplets.go index 61b5589a..648df2ac 100644 --- a/modules/caplets/caplets.go +++ b/modules/caplets/caplets.go @@ -120,7 +120,7 @@ func (mod *CapletsModule) Update() error { } } - out, err := os.Create("/tmp/caplets.zip") + out, err := os.Create(caplets.ArchivePath) if err != nil { return err } @@ -140,7 +140,7 @@ func (mod *CapletsModule) Update() error { mod.Info("installing caplets to %s ...", caplets.InstallPath) - if _, err = zip.Unzip("/tmp/caplets.zip", caplets.InstallBase); err != nil { + if _, err = zip.Unzip(caplets.ArchivePath, caplets.InstallBase); err != nil { return err } diff --git a/modules/tcp_proxy/tcp_proxy.go b/modules/tcp_proxy/tcp_proxy.go index 23ac6041..bb4bf736 100644 --- a/modules/tcp_proxy/tcp_proxy.go +++ b/modules/tcp_proxy/tcp_proxy.go @@ -8,6 +8,8 @@ import ( "github.com/bettercap/bettercap/firewall" "github.com/bettercap/bettercap/session" + + "github.com/robertkrimen/otto" ) type TcpProxy struct { @@ -150,7 +152,7 @@ func (mod *TcpProxy) Configure() error { return nil } -func (mod *TcpProxy) doPipe(from, to net.Addr, src, dst io.ReadWriter, wg *sync.WaitGroup) { +func (mod *TcpProxy) doPipe(from, to net.Addr, src *net.TCPConn, dst io.ReadWriter, wg *sync.WaitGroup) { defer wg.Done() buff := make([]byte, 0xffff) @@ -165,7 +167,11 @@ func (mod *TcpProxy) doPipe(from, to net.Addr, src, dst io.ReadWriter, wg *sync. b := buff[:n] if mod.script != nil { - ret := mod.script.OnData(from, to, b) + ret := mod.script.OnData(from, to, b, func(call otto.FunctionCall) otto.Value { + mod.Debug("onData dropCallback called") + src.Close() + return otto.Value{} + }) if ret != nil { nret := len(ret) diff --git a/modules/tcp_proxy/tcp_proxy_script.go b/modules/tcp_proxy/tcp_proxy_script.go index 0fc7864d..f4f07d88 100644 --- a/modules/tcp_proxy/tcp_proxy_script.go +++ b/modules/tcp_proxy/tcp_proxy_script.go @@ -7,9 +7,9 @@ import ( "github.com/bettercap/bettercap/log" "github.com/bettercap/bettercap/session" - "github.com/robertkrimen/otto" - "github.com/evilsocket/islazy/plugin" + + "github.com/robertkrimen/otto" ) type TcpProxyScript struct { @@ -46,12 +46,12 @@ func LoadTcpProxyScript(path string, sess *session.Session) (err error, s *TcpPr return } -func (s *TcpProxyScript) OnData(from, to net.Addr, data []byte) []byte { +func (s *TcpProxyScript) OnData(from, to net.Addr, data []byte, callback func(call otto.FunctionCall) otto.Value) []byte { if s.doOnData { addrFrom := strings.Split(from.String(), ":")[0] addrTo := strings.Split(to.String(), ":")[0] - if ret, err := s.Call("onData", addrFrom, addrTo, data); err != nil { + if ret, err := s.Call("onData", addrFrom, addrTo, data, callback); err != nil { log.Error("error while executing onData callback: %s", err) return nil } else if ret != nil { diff --git a/modules/utils/script_builtins.go b/modules/utils/script_builtins.go index cc49ec30..b197e9a9 100644 --- a/modules/utils/script_builtins.go +++ b/modules/utils/script_builtins.go @@ -5,6 +5,7 @@ import ( "compress/gzip" "encoding/base64" "io/ioutil" + "net/http" "github.com/bettercap/bettercap/log" "github.com/bettercap/bettercap/session" @@ -245,4 +246,66 @@ func init() { return nullOtto } + + // send http request + plugin.Defines["httpRequest"] = func(call otto.FunctionCall) otto.Value { + argv := call.ArgumentList + argc := len(argv) + if argc < 2 { + return errOtto("httpRequest: expected 2 or more, %d given instead.", argc) + } + + method := argv[0].String() + url := argv[1].String() + + client := &http.Client{} + req, err := http.NewRequest(method, url, nil) + if argc >= 3 { + data := argv[2].String() + req, err = http.NewRequest(method, url, bytes.NewBuffer([]byte(data))) + if err != nil { + return errOtto("Could create request to url %s: %s", url, err) + } + + if argc > 3 { + headers := argv[3].Object() + for _, key := range headers.Keys() { + v, err := headers.Get(key) + if err != nil { + return errOtto("Could add header %s to request: %s", key, err) + } + req.Header.Add(key, v.String()) + } + } + } else if err != nil { + return errOtto("Could create request to url %s: %s", url, err) + } + + resp, err := client.Do(req) + if err != nil { + return errOtto("Could not request url %s: %s", url, err) + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return errOtto("Could not read response: %s", err) + } + + object, err := otto.New().Object("({})") + if err != nil { + return errOtto("Could not create response object: %s", err) + } + + err = object.Set("body", string(body)) + if err != nil { + return errOtto("Could not populate response object: %s", err) + } + + v, err := otto.ToValue(object) + if err != nil { + return errOtto("Could not convert to object: %s", err) + } + return v + } }