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() }