Esempio n. 1
0
 def do_auth(self, args):
     """Authenticate with a faraday server"""
     faraday_url = args.faraday_url
     user = args.user
     password = args.password
     ignore_ssl = args.ignore_ssl
     if not faraday_url:
         faraday_url = utils.validate_url(
             click.prompt("Faraday url", default=active_config.faraday_url))
         url_data = urlparse(faraday_url)
         if url_data.scheme == "https":
             ignore_ssl = (click.prompt(
                 f"Validate SSL certificate for [{faraday_url}]",
                 type=click.Choice(choices=["Y", "N"],
                                   case_sensitive=False),
                 default="Y",
             ) == "N")
     else:
         faraday_url = utils.validate_url(faraday_url)
     if not user:
         user = click.prompt("User")
     if not password:
         password = click.prompt("Password", hide_input=True)
     try:
         api_client = FaradayApi(faraday_url, ignore_ssl=ignore_ssl)
         login_ok = api_client.login(user, password)
         if login_ok is None or login_ok is True:
             if login_ok is None:
                 # 2FA Required
                 second_factor = click.prompt("2FA")
             else:
                 second_factor = None
             token = api_client.get_token(user, password, second_factor)
             active_config.faraday_url = faraday_url
             active_config.ignore_ssl = args.ignore_ssl
             active_config.token = token
             active_config.workspace = None
             active_config.save()
             self.api_client = FaradayApi(faraday_url,
                                          ignore_ssl=ignore_ssl,
                                          token=token)
             self.poutput(style("Saving config", fg="green"))
             self.poutput(
                 style(
                     f"{self.emojis['check']} Authenticated with faraday: {faraday_url}",
                     fg="green",
                 ))
             self.update_prompt()
         else:
             self.perror("Invalid credentials")
     except Invalid2FA:
         self.perror("Invalid 2FA")
     except InvalidCredentials:
         self.perror("Invalid credentials")
     except ClientError:
         self.perror("Invalid credentials")
     except ClientConnectionError as e:
         self.perror(f"Connection refused: {e}")
     except Exception as e:
         self.perror(f"{e}")
Esempio n. 2
0
    def postcmd(self, stop, line):
        def send_to_faraday(ws, data):
            spinner = Halo(text="Sending", text_color="green", spinner="dots")
            spinner.start()
            try:
                self.api_client.bulk_create(ws, data)
            except Exception as e:
                spinner.stop()
                return str(e)
            else:
                spinner.stop()
                return None

        while not self.data_queue.empty():
            data = self.data_queue.get()
            message = f"{self.emojis['arrow_up']} Sending data to workspace: {data['workspace']}"  # noqa: E501
            self.poutput(style(message, fg=COLORS.GREEN))
            upload_error = send_to_faraday(data["workspace"],
                                           data["json_data"])
            if upload_error is not None:
                self.poutput(
                    style(
                        f"\n{self.emojis['cross']} {upload_error}",
                        fg=COLORS.RED,
                    ))
            else:
                self.poutput(
                    style(f"\n{self.emojis['check']} Done", fg=COLORS.GREEN))
        return Cmd.postcmd(self, stop, line)
Esempio n. 3
0
 def ls(self):
     """Returns current directory listing."""
     entries = sorted(self.__currentdir.keys())
     listing = ""
     for entry in entries:
         if entry.endswith('d'):
             listing = listing + style(f'{entry[:-1]}\t', fg='cyan')
         else:
             listing = listing + style(f'{entry[:-1]}\t', fg='white')
     return listing
Esempio n. 4
0
    def postcmd(self, stop, line):
        @Halo(text="Sending", text_color="green", spinner="dots")
        def send_to_faraday(ws, data):
            self.api_client.bulk_create(ws, data)

        while not self.data_queue.empty():
            data = self.data_queue.get()
            message = f"{self.emojis['arrow_up']} Sending data to workspace: {data['workspace']}"
            self.poutput(style(message, fg="green"))
            send_to_faraday(data["workspace"], data["json_data"])
            self.poutput(style(f"{self.emojis['check']} Done", fg="green"))

        return Cmd.postcmd(self, stop, line)
Esempio n. 5
0
class BlueSploit(cmd2.Cmd):
    intro = cmd2.style(
        """ \n ______  _               _____         _         _  _   
| ___ \| |             /  ___|       | |       (_)| |  
| |_/ /| | _   _   ___ \ `--.  _ __  | |  ___   _ | |_ 
| ___ \| || | | | / _ \ `--. \| '_ \ | | / _ \ | || __|
| |_/ /| || |_| ||  __//\__/ /| |_) || || (_) || || |_ 
\____/ |_| \__,_| \___|\____/ | .__/ |_| \___/ |_| \__|
                              | |                      
                              |_|                      

  """,
        bold=True,
        fg="blue")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.prompt = (Style.RESET_ALL + Style.BRIGHT + Back.BLUE +
                       "\nBlueSploit $> " + Style.RESET_ALL + Fore.GREEN)
        hidecomands(self)

    listmod = "List all available modules"

    @cmd2.with_category(listmod)
    def do_list_modules(self, args):
        print("\n")
        modules()
Esempio n. 6
0
    def __init__(self):
        # CMD2 init
        self.intro = style(INTRO, fg=Fg.BLUE, bold=True)
        self.prompt = "LightDance CLI> "

        shortcuts = dict(cmd2.DEFAULT_SHORTCUTS)

        super().__init__(shortcuts=shortcuts, startup_script="./cli/startup")

        # ZMQ methods init
        self.socket = ZMQSocket(port=8000)
        self.METHODS = {
            "shutDown": ShutDown(),
            "reboot": Reboot(),
            "boardinfo": BoardInfo(),
            "uploadControl": UploadJsonFile(socket=self.socket),
            "load": Load(socket=self.socket),
            "play": Play(socket=self.socket),
            "pause": Pause(socket=self.socket),
            "stop": Stop(socket=self.socket),
            "statuslight": StatusLight(socket=self.socket),
            "eltest": ELTest(socket=self.socket),
            "ledtest": LEDTest(socket=self.socket),
            "list": List(socket=self.socket),
            "quit": Quit(socket=self.socket),
            "send": Send(socket=self.socket),
        }

        # vars init
        self.load = False
Esempio n. 7
0
    def __init__(self):
        super().__init__(
            multiline_commands=['echo'],
            persistent_history_file='cmd2_history.dat',
            startup_script='scripts/startup.txt',
            use_ipython=True,
        )

        # Prints an intro banner once upon application startup
        self.intro = style('Welcome to cmd2!', fg=fg.red, bg=bg.white, bold=True)

        # Show this as the prompt when asking for input
        self.prompt = 'myapp> '

        # Used as prompt for multiline commands after the first line
        self.continuation_prompt = '... '

        # Allow access to your application in py and ipy via self
        self.self_in_py = True

        # Set the default category name
        self.default_category = 'cmd2 Built-in Commands'

        # Color to output text in with echo command
        self.foreground_color = 'cyan'

        # Make echo_fg settable at runtime
        self.add_settable(
            cmd2.Settable('foreground_color', str, 'Foreground color to use with echo command', self, choices=fg.colors())
        )
Esempio n. 8
0
def read_text_adv(prompt,
                  cmdobj,
                  bg=cmd2.bg.blue,
                  fg=cmd2.fg.white,
                  bold=True):
    '''
    Displays a prompt and reads in a string of text.
    Keyboard interrupts (CTRL+C) are ignored
    Takes a cmd style object for the prompt, and a cmd2.cmd instance as the cmdobj
    returns a string containing the string input by the user
    '''
    #background_choices = {'blue': cmd2.bg.blue}
    #foreground_choices = {'white': cmd2.fg.white}
    #print(cmdobj)
    # print(prompt)

    while True:  # repeat forever
        try:
            prompt_text = cmd2.style(
                text=prompt,
                bg=bg,  #cmd2.bg.blue,#foreground_choices.get(foreground),
                fg=fg,
                bold=bold)  #foreground_choices.get(background))
            cmdobj.poutput(prompt_text)
            #result2 = str(cmdobj.prompt)
            input_style = cmd2.style(text=cmdobj.prompt,
                                     fg=fg,
                                     bg=bg,
                                     bold=True)
            result = input(input_style)  # read the input
            # if we get here no exception was raised
            if result == '':
                #don't accept empty lines
                print('Please enter text')
            else:
                # break out of the loop
                break
        except KeyboardInterrupt:
            # if we get here the user pressed CTRL+C
            print('Please enter text')
            if DEBUG_MODE:
                raise Exception('Keyboard interrupt')

    # return the result
    return result
Esempio n. 9
0
 def activities_vulns_parser(activity_data):
     critical_text = cmd2.style(activity_data["criticalIssue"],
                                fg=SEVERITY_COLORS["critical"])
     high_text = cmd2.style(activity_data["highIssue"],
                            fg=SEVERITY_COLORS["high"])
     med_text = cmd2.style(activity_data["mediumIssue"],
                           fg=SEVERITY_COLORS["med"])
     low_text = cmd2.style(activity_data["lowIssue"],
                           fg=SEVERITY_COLORS["low"])
     info_text = cmd2.style(activity_data["infoIssue"],
                            fg=SEVERITY_COLORS["info"])
     vulns_text = (
         f"and {activity_data['vulnerabilities_count']} vulns ("
         f"{critical_text}/"
         f"{high_text}/"
         f"{med_text}/"
         f"{low_text}/"
         f"{info_text})")
     return vulns_text
Esempio n. 10
0
 def _show_success_sign(self):
     self.poutput(style("  +-------------+", fg=fg.bright_green))
     self.poutput(style("  +          ## +", fg=fg.bright_green))
     self.poutput(style("  +         ##  +", fg=fg.bright_green))
     self.poutput(style("  +  #    ##    +", fg=fg.bright_green))
     self.poutput(style("  +   ## #      +", fg=fg.bright_green))
     self.poutput(style("  +    ##       +", fg=fg.bright_green))
     self.poutput(style("  +-------------+", fg=fg.bright_green))
     self.poutput("")
Esempio n. 11
0
 def _show_failure_sign(self):
     self.poutput(style("  +-------------+", fg=fg.bright_red))
     self.poutput(style("  +   ##   ##   +", fg=fg.bright_red))
     self.poutput(style("  +    ## ##    +", fg=fg.bright_red))
     self.poutput(style("  +     ###     +", fg=fg.bright_red))
     self.poutput(style("  +    ## ##    +", fg=fg.bright_red))
     self.poutput(style("  +   ##   ##   +", fg=fg.bright_red))
     self.poutput(style("  +-------------+", fg=fg.bright_red))
     self.poutput("")
Esempio n. 12
0
    def __init__(self):
        super().__init__(multiline_commands=['echo'], persistent_history_file='cmd2_history.dat',
                         startup_script='scripts/startup.txt', use_ipython=True)

        self.intro = style('Welcome to PyOhio 2019 and cmd2!', fg=fg.red, bg=bg.white, bold=True) + ' 😀'

        # Allow access to your application in py and ipy via self
        self.self_in_py = True

        # Set the default category name
        self.default_category = 'cmd2 Built-in Commands'
Esempio n. 13
0
    def __init__(self):
        super().__init__(multiline_commands=[],
                         persistent_history_file='~/.slackdisk')
        del cmd2.Cmd.do_py
        del cmd2.Cmd.do_run_script
        del cmd2.Cmd.do_run_pyscript
        del cmd2.Cmd.do_shortcuts
        del cmd2.Cmd.do_macro
        del cmd2.Cmd.do_alias

        self.usabledirs = '/bin /etc /home /lib /lib32 /lib64 /opt /root'
        self.initialfile = '/bin/bash'
        self.password = '******'
        self.tree = filetree.Filetree()
        self.bmap = bmap.Bmap()
        self.encoder = encoder.Encoder()
        self.statement_parser.aliases = {
            'exit': 'quit',
            'q': 'quit',
            'h': 'help'
        }
        self.minimaltime = '100'  # days
        self.prompt = style("slack> ", fg='blue')
        self.settable[
            'usabledirs'] = "Directories to save hidden file system, separated by spaces."
        self.settable[
            'minimaltime'] = "Minimal time (in days) that the file must not have been modified"
        self.settable[
            'password'] = "******"
        self.settable[
            'initialfile'] = "File to save (or load) the beginning of the file system on slack space"
        self.intro = style(r"""
   _____ _            _    _____  _     _    
  / ____| |          | |  |  __ \(_)   | |   
 | (___ | | __ _  ___| | _| |  | |_ ___| | __
  \___ \| |/ _` |/ __| |/ / |  | | / __| |/ /
  ____) | | (_| | (__|   <| |__| | \__ \   < 
 |_____/|_|\__,_|\___|_|\_\_____/|_|___/_|\_\ v0.1
                                             """,
                           fg='yellow',
                           bold=True)
Esempio n. 14
0
 def __init__(self):
     super().__init__(self)
     self.completekey = "Tab"
     self.prompt = "vault > "
     self.do_exit = self.do_quit
     self.register_postloop_hook(self.exithook)
     self.intro = cmd2.style(
         "Welcome to the password vault!\nTo start, either `create` or `load` a vault.",
         fg=cmd2.fg.white,
         bold=True)
     self.disable_category(self.GET_SET_CATEGORY,
                           "Must create or load database first")
Esempio n. 15
0
    def __init__(self):
        super().__init__(multiline_commands=['echo'],
                         persistent_history_file='cmd2_history.dat',
                         use_ipython=True)

        self.intro = style("Welcome to the Linux Rootkit C2!",
                           fg=fg.red,
                           bg=bg.white,
                           bold=True)

        self.self_in_py = True

        self.prompt = 'J.O.B. > '
Esempio n. 16
0
    def __init__(self):
        super().__init__(multiline_commands=['command'],
                         persistent_history_file='cmd2_history.dat',
                         use_ipython=True)

        self.intro = style("Welcome to the Post Exploitation Menu!",
                           fg=fg.red,
                           bg=bg.white,
                           bold=True)

        self.self_in_py = True

        self.prompt = '(post-exploit) > '
Esempio n. 17
0
 def do_status(self, args):
     """Show Cli status"""
     valid_token = self.api_client.is_token_valid()
     user = None
     version = "-"
     if valid_token:
         version_data = self.api_client.get_version()
         version = f"{version_data['product']}-{version_data['version']}"
         user = self.api_client.get_user()
     data = [{
         "FARADAY SERVER":
         active_config.faraday_url,
         "IGNORE SSL":
         active_config.ignore_ssl,
         "SERVER VERSION":
         version,
         "USER":
         user if user else "-",
         "VALID TOKEN":
         "\U00002714" if valid_token else "\U0000274c",
         "WORKSPACE":
         active_config.workspace,
         "CLI VERSION":
         __version__ if not self.update_available else style(
             f"{__version__} (latest: {self.latest_version})",
             fg=COLORS.RED,
         ),
     }]
     self.print_output(
         style(
             tabulate(
                 data,
                 headers="keys",
                 tablefmt=self.TABLE_PRETTY_FORMAT
                 if args.pretty else "simple",
             ),
             fg=COLORS.GREEN,
         ))
Esempio n. 18
0
 def __init__(self, *args, **kwargs):
     super().__init__(*args, **kwargs)
     self.TABLE_PRETTY_FORMAT = "psql"
     # hide unwanted settings
     settings_to_hide = ["debug"]
     for setting_name in settings_to_hide:
         self.remove_settable(setting_name)
     f = Figlet(font="slant")
     intro = []
     intro.append(style(f.renderText("Faraday Cli"), fg="red"))
     if active_config.faraday_url and active_config.token:
         intro.append(
             style(f"Server: {active_config.faraday_url}", fg="green"))
         self.api_client = FaradayApi(
             active_config.faraday_url,
             ignore_ssl=active_config.ignore_ssl,
             token=active_config.token,
         )
     else:
         self.api_client = FaradayApi()
         intro.append(
             style(f"Missing faraday server, run 'auth'", fg="yellow"))
     self.intro = "\n".join(intro)
     self.data_queue = queue.Queue()
     self.custom_plugins_path = None
     self.update_prompt()
     self.add_settable(
         Settable(
             "custom_plugins_path",
             str,
             "Path of custom plugins",
             onchange_cb=self._onchange_custom_plugins_path,
         ))
     self.plugins_manager = PluginsManager(
         active_config.custom_plugins_folder)
     self.report_analyzer = ReportAnalyzer(self.plugins_manager)
     self.command_analyzer = CommandAnalyzer(self.plugins_manager)
Esempio n. 19
0
 def select_ws(self, args: argparse.Namespace):
     """Select active Workspace"""
     if self._cmd.api_client.is_workspace_available(args.workspace_name):
         active_config.workspace = args.workspace_name
         active_config.save()
         self._cmd.poutput(
             cmd2.style(
                 f"{self._cmd.emojis['check']} "
                 f"Selected workspace: {args.workspace_name}",
                 fg=COLORS.GREEN,
             ))
         self._cmd.update_prompt()
     else:
         self._cmd.perror(f"{self._cmd.emojis['cross']} "
                          f"Invalid workspace: {args.workspace_name}")
Esempio n. 20
0
 def do_select_ws(self, args):
     """Select active Workspace"""
     if self._cmd.api_client.is_workspace_valid(args.workspace_name):
         active_config.workspace = args.workspace_name
         active_config.save()
         self._cmd.poutput(
             style(
                 f"{self._cmd.emojis['check']} "
                 f"Selected workspace: {args.workspace_name}",
                 fg="green",
             ))
         self._cmd.update_prompt()
     else:
         self._cmd.perror(f"{self._cmd.emojis['cross']} "
                          f"Invalid workspace: {args.workspace_name}")
Esempio n. 21
0
 def do_delete_ws(self, args):
     """Delete Workspace"""
     workspaces = self._cmd.api_client.get_workspaces()
     workspace_choices = [ws for ws in map(lambda x: x["name"], workspaces)]
     workspace_name = args.workspace_name
     if workspace_name not in workspace_choices:
         self._cmd.perror(f"Invalid workspace: {workspace_name}")
         return
     self._cmd.poutput(f"Deleting workspace: {workspace_name}")
     self._cmd.api_client.delete_workspace(workspace_name)
     self._cmd.poutput(
         style(f"Deleted workspace: {args.workspace_name}", fg="green"))
     if active_config.workspace == workspace_name:
         active_config.workspace = None
         active_config.save()
     self._cmd.update_prompt()
Esempio n. 22
0
 def enable_ws(self, args: argparse.Namespace):
     """Enable Workspace"""
     workspace_name = args.workspace_name
     try:
         self._cmd.api_client.enable_workspace(workspace_name)
     except NotFoundError:
         self._cmd.perror(f"Invalid Workspace: {workspace_name}")
     except Exception as e:
         self._cmd.perror(f"{e}")
     else:
         self._cmd.poutput(
             cmd2.style(
                 f"{self._cmd.emojis['check']} "
                 f"Enable workspace: {workspace_name}",
                 fg=COLORS.GREEN,
             ))
Esempio n. 23
0
 def do_create_ws(self, args):
     """Create Workspace"""
     workspace_name = args.workspace_name
     try:
         self._cmd.api_client.create_workspace(workspace_name)
     except Exception as e:
         self._cmd.perror(f"{e}")
     else:
         self._cmd.poutput(
             style(
                 f"{self._cmd.emojis['check']} "
                 f"Created workspace: {args.workspace_name}",
                 fg="green",
             ))
         if not args.dont_select:
             active_config.workspace = workspace_name
             active_config.save()
             self._cmd.update_prompt()
Esempio n. 24
0
 def do_delete_host(self, args):
     """Delete Host"""
     if not args.workspace_name:
         if active_config.workspace:
             workspace_name = active_config.workspace
         else:
             self._cmd.perror("No active Workspace")
             return
     else:
         workspace_name = args.workspace_name
     try:
         self._cmd.api_client.delete_host(workspace_name, args.host_id)
     except NotFoundError:
         self._cmd.perror("Host not found")
     except Exception as e:
         self._cmd.perror(f"{e}")
     else:
         self._cmd.poutput(style("Deleted host", fg="green"))
Esempio n. 25
0
 def create_ws(self, args: argparse.Namespace):
     """Create Workspace"""
     workspace_name = args.workspace_name
     try:
         self._cmd.api_client.create_workspace(workspace_name)
     except Exception as e:
         self._cmd.perror(f"{e}")
     else:
         self._cmd.poutput(
             cmd2.style(
                 f"{self._cmd.emojis['check']} "
                 f"Created workspace: {args.workspace_name}",
                 fg=COLORS.GREEN,
             ))
         if not args.dont_select:
             active_config.workspace = workspace_name
             active_config.save()
             self._cmd.update_prompt()
Esempio n. 26
0
 def disable_ws(self, args: argparse.Namespace):
     """Disable Workspace"""
     workspace_name = args.workspace_name
     try:
         self._cmd.api_client.disable_workspace(workspace_name)
     except NotFoundError:
         self._cmd.perror(f"Invalid Workspace: {workspace_name}")
     except Exception as e:
         self._cmd.perror(f"{e}")
     else:
         self._cmd.poutput(
             cmd2.style(
                 f"{self._cmd.emojis['check']} "
                 f"Disabled workspace: {workspace_name}",
                 fg=COLORS.GREEN,
             ))
     if active_config.workspace == workspace_name:
         active_config.workspace = None
         active_config.save()
     self._cmd.update_prompt()
Esempio n. 27
0
 def __init__(self, card, rs, script=None):
     basic_commands = [Iso7816Commands(), UsimCommands()]
     super().__init__(persistent_history_file='~/.pysim_shell_history',
                      allow_cli_args=False,
                      use_ipython=True,
                      auto_load_commands=False,
                      command_sets=basic_commands,
                      startup_script=script)
     self.intro = style('Welcome to pySim-shell!', fg=fg.red)
     self.default_category = 'pySim-shell built-in commands'
     self.card = card
     self.rs = rs
     self.py_locals = {'card': self.card, 'rs': self.rs}
     self.numeric_path = False
     self.add_settable(
         cmd2.Settable('numeric_path',
                       bool,
                       'Print File IDs instead of names',
                       onchange_cb=self._onchange_numeric_path))
     self.update_prompt()
Esempio n. 28
0
 def do_process_report(self, args):
     """Send Tool report to Faraday"""
     report_path = Path(args.report_path)
     if not report_path.is_file():
         self._cmd.perror(f"File {report_path} dont exists")
         return
     if not args.workspace_name:
         if active_config.workspace:
             workspace_name = active_config.workspace
         else:
             self._cmd.perror("No active Workspace")
             return
     else:
         workspace_name = args.workspace_name
     if not self._cmd.api_client.is_workspace_valid(workspace_name):
         self._cmd.perror(f"Invalid workspace: {workspace_name}")
         return
     else:
         destination_workspace = workspace_name
     if args.plugin_id:
         plugin = self._cmd.plugins_manager.get_plugin(args.plugin_id)
         if not plugin:
             self._cmd.perror(f"Invalid Plugin: {args.plugin_id}")
             return
     else:
         plugin = self._cmd.report_analyzer.get_plugin(report_path)
         if not plugin:
             self._cmd.perror(f"{self._cmd.emojis['cross']} "
                              f"Failed to detect report: {report_path}")
             return
     self._cmd.poutput(
         style(
             f"{self._cmd.emojis['page']} Processing {plugin.id} report",
             fg="green",
         ))
     plugin.processReport(report_path.absolute().as_posix(),
                          getpass.getuser())
     self._cmd.data_queue.put({
         "workspace": destination_workspace,
         "json_data": plugin.get_data(),
     })
Esempio n. 29
0
    def _generate_colored_prompt(self) -> str:
        """
        Randomly generates a colored prompt
        :return: the new prompt
        """
        rand_num = random.randint(1, 20)

        status_color = fg.reset

        if rand_num == 1:
            status_color = fg.bright_red
        elif rand_num == 2:
            status_color = fg.bright_yellow
        elif rand_num == 3:
            status_color = fg.cyan
        elif rand_num == 4:
            status_color = fg.bright_green
        elif rand_num == 5:
            status_color = fg.bright_blue

        return style(self.visible_prompt, fg=status_color)
Esempio n. 30
0
 def __init__(self, card, rs, script=None):
     basic_commands = [Iso7816Commands(), PySimCommands()]
     super().__init__(persistent_history_file='~/.pysim_shell_history',
                      allow_cli_args=False,
                      use_ipython=True,
                      auto_load_commands=False,
                      command_sets=basic_commands,
                      startup_script=script)
     self.intro = style('Welcome to pySim-shell!', fg=fg.red)
     self.default_category = 'pySim-shell built-in commands'
     self.card = card
     iccid, sw = self.card.read_iccid()
     self.iccid = iccid
     self.rs = rs
     self.py_locals = {'card': self.card, 'rs': self.rs}
     self.numeric_path = False
     self.add_settable(
         cmd2.Settable('numeric_path',
                       bool,
                       'Print File IDs instead of names',
                       onchange_cb=self._onchange_numeric_path))
     self.conserve_write = True
     self.add_settable(
         cmd2.Settable('conserve_write',
                       bool,
                       'Read and compare before write',
                       onchange_cb=self._onchange_conserve_write))
     self.update_prompt()
     self.json_pretty_print = True
     self.add_settable(
         cmd2.Settable('json_pretty_print', bool,
                       'Pretty-Print JSON output'))
     self.apdu_trace = False
     self.add_settable(
         cmd2.Settable('apdu_trace',
                       bool,
                       'Trace and display APDUs exchanged with card',
                       onchange_cb=self._onchange_apdu_trace))