mirror of
https://github.com/bettercap/bettercap
synced 2025-08-14 02:36:57 -07:00
new: new caplets module to manage system caplets
This commit is contained in:
parent
9721c1d6e0
commit
e79ba4952e
6 changed files with 213 additions and 3 deletions
|
@ -8,8 +8,12 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
Suffix = ".cap"
|
||||
InstallPath = "/usr/local/share/bettercap/caplets/"
|
||||
EnvVarName = "CAPSPATH"
|
||||
Suffix = ".cap"
|
||||
InstallArchive = "https://github.com/bettercap/caplets/archive/master.zip"
|
||||
InstallBase = "/usr/local/share/bettercap/"
|
||||
InstallPathArchive = "/usr/local/share/bettercap/caplets-master/"
|
||||
InstallPath = "/usr/local/share/bettercap/caplets/"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -20,7 +24,7 @@ var (
|
|||
)
|
||||
|
||||
func init() {
|
||||
for _, path := range core.SepSplit(core.Trim(os.Getenv("CAPSPATH")), ":") {
|
||||
for _, path := range core.SepSplit(core.Trim(os.Getenv(EnvVarName)), ":") {
|
||||
if path = core.Trim(path); len(path) > 0 {
|
||||
LoadPaths = append(LoadPaths, path)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
|
@ -38,6 +39,10 @@ func List() []Caplet {
|
|||
}
|
||||
}
|
||||
|
||||
sort.Slice(caplets, func(i, j int) bool {
|
||||
return strings.Compare(caplets[i].Name, caplets[j].Name) == -1
|
||||
})
|
||||
|
||||
return caplets
|
||||
}
|
||||
|
||||
|
|
47
core/core.go
47
core/core.go
|
@ -1,7 +1,9 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
|
@ -102,3 +104,48 @@ func ExpandPath(path string) (string, error) {
|
|||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Unzip will decompress a zip archive, moving all files and folders
|
||||
// within the zip file (parameter 1) to an output directory (parameter 2).
|
||||
// Credits to https://golangcode.com/unzip-files-in-go/
|
||||
func Unzip(src string, dest string) ([]string, error) {
|
||||
var filenames []string
|
||||
|
||||
r, err := zip.OpenReader(src)
|
||||
if err != nil {
|
||||
return filenames, err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
for _, f := range r.File {
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
return filenames, err
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
// Store filename/path for returning and using later on
|
||||
fpath := filepath.Join(dest, f.Name)
|
||||
|
||||
// Check for ZipSlip. More Info: https://snyk.io/research/zip-slip-vulnerability#go
|
||||
if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
|
||||
return filenames, fmt.Errorf("%s: illegal file path", fpath)
|
||||
}
|
||||
|
||||
filenames = append(filenames, fpath)
|
||||
if f.FileInfo().IsDir() {
|
||||
os.MkdirAll(fpath, os.ModePerm)
|
||||
} else if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
|
||||
return filenames, err
|
||||
} else if outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()); err != nil {
|
||||
return filenames, err
|
||||
} else {
|
||||
defer outFile.Close()
|
||||
if _, err = io.Copy(outFile, rc); err != nil {
|
||||
return filenames, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filenames, nil
|
||||
}
|
||||
|
|
1
main.go
1
main.go
|
@ -35,6 +35,7 @@ func main() {
|
|||
sess.Register(modules.NewEventsStream(sess))
|
||||
sess.Register(modules.NewTicker(sess))
|
||||
sess.Register(modules.NewUpdateModule(sess))
|
||||
sess.Register(modules.NewCapletsModule(sess))
|
||||
sess.Register(modules.NewMacChanger(sess))
|
||||
sess.Register(modules.NewProber(sess))
|
||||
sess.Register(modules.NewDiscovery(sess))
|
||||
|
|
148
modules/caplets.go
Normal file
148
modules/caplets.go
Normal file
|
@ -0,0 +1,148 @@
|
|||
package modules
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/bettercap/bettercap/caplets"
|
||||
"github.com/bettercap/bettercap/core"
|
||||
"github.com/bettercap/bettercap/log"
|
||||
"github.com/bettercap/bettercap/session"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
)
|
||||
|
||||
type CapletsModule struct {
|
||||
session.SessionModule
|
||||
}
|
||||
|
||||
func NewCapletsModule(s *session.Session) *CapletsModule {
|
||||
c := &CapletsModule{
|
||||
SessionModule: session.NewSessionModule("caplets", s),
|
||||
}
|
||||
|
||||
c.AddHandler(session.NewModuleHandler("caplets.show", "",
|
||||
"Show a list of installed caplets.",
|
||||
func(args []string) error {
|
||||
return c.Show()
|
||||
}))
|
||||
|
||||
c.AddHandler(session.NewModuleHandler("caplets.paths", "",
|
||||
"Show a list caplet search paths.",
|
||||
func(args []string) error {
|
||||
return c.Paths()
|
||||
}))
|
||||
|
||||
c.AddHandler(session.NewModuleHandler("caplets.update", "",
|
||||
"Install/updates the caplets.",
|
||||
func(args []string) error {
|
||||
return c.Update()
|
||||
}))
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CapletsModule) Name() string {
|
||||
return "caplets"
|
||||
}
|
||||
|
||||
func (c *CapletsModule) Description() string {
|
||||
return "A module to list and update caplets."
|
||||
}
|
||||
|
||||
func (c *CapletsModule) Author() string {
|
||||
return "Simone Margaritelli <evilsocket@protonmail.com>"
|
||||
}
|
||||
|
||||
func (c *CapletsModule) Configure() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CapletsModule) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CapletsModule) Start() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CapletsModule) Show() error {
|
||||
caplets := caplets.List()
|
||||
if len(caplets) == 0 {
|
||||
return fmt.Errorf("no installed caplets on this system, use the caplets.update command to download them")
|
||||
}
|
||||
|
||||
colNames := []string{
|
||||
"Name",
|
||||
"Path",
|
||||
"Size",
|
||||
}
|
||||
rows := [][]string{}
|
||||
|
||||
for _, caplet := range caplets {
|
||||
rows = append(rows, []string{
|
||||
core.Bold(caplet.Name),
|
||||
caplet.Path,
|
||||
core.Dim(humanize.Bytes(uint64(caplet.Size))),
|
||||
})
|
||||
}
|
||||
|
||||
core.AsTable(os.Stdout, colNames, rows)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CapletsModule) Paths() error {
|
||||
colNames := []string{
|
||||
"Path",
|
||||
}
|
||||
rows := [][]string{[]string{"."}}
|
||||
|
||||
for _, path := range caplets.LoadPaths {
|
||||
rows = append(rows, []string{path})
|
||||
}
|
||||
|
||||
core.AsTable(os.Stdout, colNames, rows)
|
||||
fmt.Printf("(paths can be customized by defining the %s environment variable)\n", core.Bold(caplets.EnvVarName))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CapletsModule) Update() error {
|
||||
if !core.Exists(caplets.InstallBase) {
|
||||
log.Info("creating caplets install path %s ...", caplets.InstallBase)
|
||||
if err := os.MkdirAll(caplets.InstallBase, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
out, err := os.Create("/tmp/caplets.zip")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
log.Info("downloading caplets from %s ...", caplets.InstallArchive)
|
||||
|
||||
resp, err := http.Get(caplets.InstallArchive)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if _, err := io.Copy(out, resp.Body); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info("installing caplets to %s ...", caplets.InstallPath)
|
||||
|
||||
if _, err = core.Unzip("/tmp/caplets.zip", caplets.InstallBase); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
os.RemoveAll(caplets.InstallPath)
|
||||
|
||||
return os.Rename(caplets.InstallPathArchive, caplets.InstallPath)
|
||||
}
|
|
@ -63,6 +63,11 @@ func (p *EventPool) Listen() <-chan Event {
|
|||
// will receive all the queued events
|
||||
go func() {
|
||||
for i := len(p.events) - 1; i >= 0; i-- {
|
||||
defer func() {
|
||||
if recover() != nil {
|
||||
|
||||
}
|
||||
}()
|
||||
l <- p.events[i]
|
||||
}
|
||||
}()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue