protomolecule/cmd.go

325 lines
6.1 KiB
Go

package main
import (
"fmt"
"os"
"strconv"
"strings"
cli "git.tcp.direct/Mirrors/go-prompt"
. "github.com/logrusorgru/aurora"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"protomolecule/src/eros"
// "protomolecule/src/wrath"
projVars "protomolecule/src/config"
"protomolecule/src/deimos"
)
var suggestions = []cli.Suggest{
// Main Commands
// {"scan",
// "Start and stop scans"},
{"scan start",
"Start default scan"},
{"scan start attack",
"Start scan that also attempts to connect to all discovered BLE devices"},
{"scan start tracking",
"Start continuous RSSI tracking of all BLE devices within range"},
{"eros recall mac",
"Retrieve device info from database by MAC address"},
{"eros recall all",
"Retrieve info on all devices"},
{"eros backup",
"Backup all databases to the supplied directory"},
{"arboghast start",
"Start entropic fuzzing via advertising"},
/*
{"wrath",
"attack by address"},
*/
{"exit",
"Exit ProtoMolecule"},
{"debug",
"Toggle debug messages"},
{"help",
"in-app documentation"},
}
func completer(in cli.Document) []cli.Suggest {
c := in.CurrentLineBeforeCursor()
if c == "" {
return []cli.Suggest{}
}
return cli.FilterHasPrefix(suggestions, c, true)
}
// Interpret is where we will actuall define our commands
func executor(cmd string) {
cmd = strings.TrimSpace(cmd)
var args []string
args = strings.Split(cmd, " ")
getArgs := func(args []string) string {
var ret string
for i, a := range args {
if i == 0 {
ret = a
continue
}
ret = ret + " " + a
if i != len(args)-1 {
ret = ret + " "
}
}
return ret
}
switch args[0] {
case "exit":
fallthrough
case "quit":
eros.Slumber()
os.Exit(0)
case "debug":
switch log.Logger.GetLevel() {
case zerolog.DebugLevel:
zerolog.SetGlobalLevel(zerolog.InfoLevel)
log.Info().
Msg("Debug mode turned " + Sprintf(BrightRed("OFF\n").Bold()))
case zerolog.InfoLevel:
zerolog.SetGlobalLevel(zerolog.DebugLevel)
log.Debug().
Msg("Debug mode turned " + Sprintf(BrightGreen("ON\n").Bold()))
default:
return
}
case "eros":
if len(args) < 2 {
getHelp("eros")
return
}
switch args[1] {
case "recall":
if len(args) < 3 {
getHelp("eros recall")
return
}
switch args[2] {
case "mac":
if len(args) < 4 {
getHelp("eros recall")
return
}
fromEros, err := eros.Recall(args[3])
if err != nil {
log.Error().Err(err).Str("target", args[3]).
Msg("Failed to recall MAC")
println()
return
}
log.Info().
Str("Name", fromEros.Name).
Str("Addr", fromEros.Addr).
Str("ManuF", fromEros.Manufacturer). // needs to be changed back to fromEros.Manufacturer
Int16("Current_RSSI", fromEros.RSSIlast).
Int("Service_Count", len(fromEros.Services)).
Msg("EROS_RECALL")
case "backup":
if len(args) < 3 {
getHelp("eros backup")
return
}
if err := eros.Backup(args[3]); err != nil {
log.Error().Err(err).Msg("Failed to backup databases!")
}
}
}
case "help":
if len(args) < 2 {
getHelp("meta")
return
}
getHelp(getArgs(args))
case "loadnames":
if len(args) < 2 {
log.Error().Msg("missing argument: path to json file with manufacturer UUIDs")
println()
}
projVars.GlobalConfig.ManuFile = args[1]
eros.ManufLoad()
case "adapter":
if len(args) > 1 {
switch args[1] {
case "list":
deimos.PrintBlueDevices()
case "sniff":
var (
err error
devint int
)
if len(args) < 2 {
log.Error().Msg("not enough parameters, missing adapter ID")
println()
return
}
if devint, err = strconv.Atoi(args[2]); err != nil {
log.Error().Msg("invalid parameter, must be integer of adapter ID")
println()
return
}
deimos.Sniff(devint)
default:
log.Error().Msg("unknown sub-command: " + args[1])
println()
}
} else {
getHelp(getArgs(args))
}
case "scan":
if len(args) > 1 {
switch args[1] {
case "list":
fallthrough
case "status":
fmt.Println(getArgs(args) + ": start new default BLE scan")
case "start":
if len(args) > 2 {
switch args[2] {
case "tracking":
*projVars.GlobalConfig.CooleanFlags.Tracking = true
*projVars.GlobalConfig.CooleanFlags.Attack = false
case "attack":
*projVars.GlobalConfig.CooleanFlags.Tracking = false
*projVars.GlobalConfig.CooleanFlags.Attack = true
default:
// getHelp(getArgs(args))
log.Error().Msg("unknown sub command: " + args[2])
println()
}
}
bleScan()
}
} else {
getHelp(getArgs(args))
}
case "rpc":
if len(args) > 1 {
switch args[1] {
case "status":
fmt.Println(getArgs(args) + ": ")
case "server":
fmt.Println(getArgs(args) + ": ")
case "client":
fmt.Println(getArgs(args) + ": ")
}
} else {
getHelp(getArgs(args))
}
/*
case "wrath":
if len(args) < 2 {
getHelp("wrath")
return
}
wrath(args[1])
*/
case "clear":
print("\033[H\033[2J")
// termenv.ClearScreen()
default:
log.Error().Msg("unknown command: " + cmd)
println()
}
}
func getHelp(target string) {
fmt.Println("pRaNkeD! (help not available just yet.)")
fmt.Println()
return
/*
var lines []string
lines = append(lines, "help: "+target)
switch target {
case "meta":
var list string
for _, cmd := range cmds {
list = list + cmd + ", "
}
fmt.Println("Enabled commands: ")
list = strings.TrimSuffix(list, ", ")
fmt.Println(list)
fmt.Println()
default:
log.Error().Msg("Help entry not found!")
fmt.Println()
}
*/
}
func StartCLI() {
var hist []string
p := cli.New(
executor,
completer,
cli.OptionPrefix("ProtoMolecule"+"> "),
// cli.OptionPrefixBackgroundColor(cli.Black),
cli.OptionPrefixTextColor(cli.Cyan),
cli.OptionHistory(hist),
cli.OptionSuggestionBGColor(cli.Black),
cli.OptionSuggestionTextColor(cli.White),
cli.OptionSelectedSuggestionBGColor(cli.Black),
cli.OptionSelectedSuggestionTextColor(cli.Cyan),
// prompt.OptionLivePrefix
cli.OptionTitle("ProtoMolecule"),
)
p.Run()
}