new: ble.enum and ble.write now support autocompletion

This commit is contained in:
evilsocket 2019-02-18 13:06:41 +01:00
commit 49e2116d46
No known key found for this signature in database
GPG key ID: 1564D7F30393A456
4 changed files with 55 additions and 12 deletions

View file

@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
golog "log" golog "log"
"strings"
"time" "time"
"github.com/bettercap/bettercap/modules/utils" "github.com/bettercap/bettercap/modules/utils"
@ -63,7 +64,7 @@ func NewBLERecon(s *session.Session) *BLERecon {
return mod.Show() return mod.Show()
})) }))
mod.AddHandler(session.NewModuleHandler("ble.enum MAC", "ble.enum "+network.BLEMacValidator, enum := session.NewModuleHandler("ble.enum MAC", "ble.enum "+network.BLEMacValidator,
"Enumerate services and characteristics for the given BLE device.", "Enumerate services and characteristics for the given BLE device.",
func(args []string) error { func(args []string) error {
if mod.isEnumerating() { if mod.isEnumerating() {
@ -74,9 +75,13 @@ func NewBLERecon(s *session.Session) *BLERecon {
mod.writeUUID = nil mod.writeUUID = nil
return mod.enumAllTheThings(network.NormalizeMac(args[0])) return mod.enumAllTheThings(network.NormalizeMac(args[0]))
})) })
mod.AddHandler(session.NewModuleHandler("ble.write MAC UUID HEX_DATA", "ble.write "+network.BLEMacValidator+" ([a-fA-F0-9]+) ([a-fA-F0-9]+)", enum.Complete("ble.enum", mod.macCompleter)
mod.AddHandler(enum)
write := session.NewModuleHandler("ble.write MAC UUID HEX_DATA", "ble.write "+network.BLEMacValidator+" ([a-fA-F0-9]+) ([a-fA-F0-9]+)",
"Write the HEX_DATA buffer to the BLE device with the specified MAC address, to the characteristics with the given UUID.", "Write the HEX_DATA buffer to the BLE device with the specified MAC address, to the characteristics with the given UUID.",
func(args []string) error { func(args []string) error {
mac := network.NormalizeMac(args[0]) mac := network.NormalizeMac(args[0])
@ -90,7 +95,11 @@ func NewBLERecon(s *session.Session) *BLERecon {
} }
return mod.writeBuffer(mac, uuid, data) return mod.writeBuffer(mac, uuid, data)
})) })
write.Complete("ble.write", mod.macCompleter)
mod.AddHandler(write)
return mod return mod
} }
@ -107,6 +116,16 @@ func (mod BLERecon) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (mod *BLERecon) macCompleter(prefix string) []string {
macs := []string{""}
mod.Session.BLE.EachDevice(func(mac string, dev *network.BLEDevice) {
if prefix == "" || strings.HasPrefix(mac, prefix) {
macs = append(macs, mac)
}
})
return macs
}
func (mod *BLERecon) isEnumerating() bool { func (mod *BLERecon) isEnumerating() bool {
return mod.currDevice != nil return mod.currDevice != nil
} }

View file

@ -95,3 +95,12 @@ func (b *BLE) Devices() (devices []*BLEDevice) {
} }
return return
} }
func (b *BLE) EachDevice(cb func(mac string, d *BLEDevice)) {
b.Lock()
defer b.Unlock()
for m, dev := range b.devices {
cb(m, dev)
}
}

View file

@ -6,7 +6,10 @@ import (
"regexp" "regexp"
"strconv" "strconv"
"github.com/evilsocket/islazy/str"
"github.com/evilsocket/islazy/tui" "github.com/evilsocket/islazy/tui"
"github.com/bettercap/readline"
) )
const IPv4Validator = `^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$` const IPv4Validator = `^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`
@ -16,6 +19,7 @@ type ModuleHandler struct {
Description string Description string
Parser *regexp.Regexp Parser *regexp.Regexp
Exec func(args []string) error Exec func(args []string) error
Completer *readline.PrefixCompleter
} }
func NewModuleHandler(name string, expr string, desc string, exec func(args []string) error) ModuleHandler { func NewModuleHandler(name string, expr string, desc string, exec func(args []string) error) ModuleHandler {
@ -33,6 +37,13 @@ func NewModuleHandler(name string, expr string, desc string, exec func(args []st
return h return h
} }
func (h *ModuleHandler) Complete(name string, cb func(prefix string) []string) {
h.Completer = readline.PcItem(name, readline.PcItemDynamic(func(prefix string) []string {
prefix = str.Trim(prefix[len(name):])
return cb(prefix)
}))
}
func (h *ModuleHandler) Help(padding int) string { func (h *ModuleHandler) Help(padding int) string {
return fmt.Sprintf(" "+tui.Bold("%"+strconv.Itoa(padding)+"s")+" : %s\n", h.Name, h.Description) return fmt.Sprintf(" "+tui.Bold("%"+strconv.Itoa(padding)+"s")+" : %s\n", h.Name, h.Description)
} }

View file

@ -38,17 +38,21 @@ func (s *Session) setupReadline() (err error) {
tree := make(map[string][]string) tree := make(map[string][]string)
for _, m := range s.Modules { for _, m := range s.Modules {
for _, h := range m.Handlers() { for _, h := range m.Handlers() {
parts := strings.Split(h.Name, " ") if h.Completer == nil {
name := parts[0] parts := strings.Split(h.Name, " ")
name := parts[0]
if _, found := tree[name]; !found { if _, found := tree[name]; !found {
tree[name] = []string{} tree[name] = []string{}
} }
var appendedOption = strings.Join(parts[1:], " ") var appendedOption = strings.Join(parts[1:], " ")
if len(appendedOption) > 0 && !containsCapitals(appendedOption) { if len(appendedOption) > 0 && !containsCapitals(appendedOption) {
tree[name] = append(tree[name], appendedOption) tree[name] = append(tree[name], appendedOption)
}
} else {
prefixCompleters = append(prefixCompleters, h.Completer)
} }
} }
} }