mirror of
https://github.com/bettercap/bettercap
synced 2025-08-19 04:59:25 -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 (
|
const (
|
||||||
Suffix = ".cap"
|
EnvVarName = "CAPSPATH"
|
||||||
InstallPath = "/usr/local/share/bettercap/caplets/"
|
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 (
|
var (
|
||||||
|
@ -20,7 +24,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
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 {
|
if path = core.Trim(path); len(path) > 0 {
|
||||||
LoadPaths = append(LoadPaths, path)
|
LoadPaths = append(LoadPaths, path)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"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
|
return caplets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
47
core/core.go
47
core/core.go
|
@ -1,7 +1,9 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"archive/zip"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/user"
|
"os/user"
|
||||||
|
@ -102,3 +104,48 @@ func ExpandPath(path string) (string, error) {
|
||||||
}
|
}
|
||||||
return "", nil
|
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.NewEventsStream(sess))
|
||||||
sess.Register(modules.NewTicker(sess))
|
sess.Register(modules.NewTicker(sess))
|
||||||
sess.Register(modules.NewUpdateModule(sess))
|
sess.Register(modules.NewUpdateModule(sess))
|
||||||
|
sess.Register(modules.NewCapletsModule(sess))
|
||||||
sess.Register(modules.NewMacChanger(sess))
|
sess.Register(modules.NewMacChanger(sess))
|
||||||
sess.Register(modules.NewProber(sess))
|
sess.Register(modules.NewProber(sess))
|
||||||
sess.Register(modules.NewDiscovery(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
|
// will receive all the queued events
|
||||||
go func() {
|
go func() {
|
||||||
for i := len(p.events) - 1; i >= 0; i-- {
|
for i := len(p.events) - 1; i >= 0; i-- {
|
||||||
|
defer func() {
|
||||||
|
if recover() != nil {
|
||||||
|
|
||||||
|
}
|
||||||
|
}()
|
||||||
l <- p.events[i]
|
l <- p.events[i]
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue