Exemplo n.º 1
0
def show_target_info(target):
    columns: List[Column] = list()
    data_list: List[List[Any]] = list()

    columns.append(
        Column("",
               width=25,
               header_horiz_align=HorizontalAlignment.CENTER,
               data_horiz_align=HorizontalAlignment.RIGHT))
    columns.append(
        Column("",
               width=80,
               header_horiz_align=HorizontalAlignment.CENTER,
               data_horiz_align=HorizontalAlignment.LEFT))

    st = SimpleTable(columns)
    output = "\nTarget Information"

    data_list.append(["model name", target.model_name])
    data_list.append(["model data type", target.model_data_type])
    data_list.append(["model endpoint", target.model_endpoint])
    data_list.append(["model input shape", target.model_input_shape])
    data_list.append([
        f"model output classes ({len(target.model_output_classes)})",
        target.model_output_classes
    ])
    if target.__doc__:
        data_list.append(["model docs", target.__doc__])

    output += st.generate_table(data_list, row_spacing=0) + "\n"

    if target.active_attack:
        output += show_attack_info(target.active_attack)

    return output
Exemplo n.º 2
0
def show_current_sample(target, samples, heading1=None, sample_index=None):
    columns: List[Column] = list()
    data_list: List[List[Any]] = list()

    if sample_index is None:
        sample_index = target.active_attack.sample_index

    if heading1 is None:
        heading1 = "Sample Index"

    # future support for multiple indices
    if not hasattr(sample_index, "__iter__"):
        sample_index = [sample_index]

    columns.append(
        Column(
            heading1,
            width=20,
            header_horiz_align=HorizontalAlignment.CENTER,
            data_horiz_align=HorizontalAlignment.RIGHT,
        ))
    columns.append(
        Column(
            "Value",
            width=80,
            header_horiz_align=HorizontalAlignment.CENTER,
            data_horiz_align=HorizontalAlignment.LEFT,
        ))

    for index, value in zip(sample_index, samples):
        data_list.append([index, value])

    st = SimpleTable(columns)
    output = "\n" + st.generate_table(data_list, row_spacing=0) + "\n"
    return output
Exemplo n.º 3
0
def show_attack_options(attack):
    columns: List[Column] = list()
    data_list: List[List[Any]] = list()

    # create structure to ensure all params are present
    params_struct = namedtuple(
        "params",
        [i for i in attack.default.keys()] + ["sample_index", "target_class"],
        defaults=list(attack.default.values()) + [0, 0],
    )

    # get default parameters
    default_params = params_struct()

    if hasattr(attack, 'parameters'):
        # get current parameters
        current_params = {k: v for k, v in attack.parameters.items()}
        current_params["sample_index"] = attack.sample_index
        current_params["target_class"] = attack.target_class

        # ensure everything exists and is ordered correctly
        current_params = params_struct(**current_params)._asdict()

    columns.append(
        Column(
            "Attack Parameter (type)",
            width=25,
            header_horiz_align=HorizontalAlignment.LEFT,
            data_horiz_align=HorizontalAlignment.RIGHT,
        ))
    columns.append(
        Column(
            "Default",
            width=12,
            header_horiz_align=HorizontalAlignment.CENTER,
            data_horiz_align=HorizontalAlignment.LEFT,
        ))
    if hasattr(attack, 'parameters'):
        columns.append(
            Column(
                "Current",
                width=12,
                header_horiz_align=HorizontalAlignment.CENTER,
                data_horiz_align=HorizontalAlignment.LEFT,
            ))
    st = SimpleTable(columns)

    for k, v in zip(default_params._fields, default_params):
        param = f"{k} ({str(type(v).__name__)})"
        default_value = v
        if hasattr(attack,
                   'parameters'):  # active attack with current parameters?
            current_value = current_params.get(k, "")
            data_list.append([param, default_value, current_value])
        else:
            data_list.append([param, default_value])

    return st.generate_table(data_list, row_spacing=0) + "\n"
Exemplo n.º 4
0
def test_simple_table():
    column_1 = Column("Col 1", width=15)
    column_2 = Column("Col 2", width=15)

    row_data = list()
    row_data.append(["Col 1 Row 1", "Col 2 Row 1"])
    row_data.append(["Col 1 Row 2", "Col 2 Row 2"])

    # Default options
    st = SimpleTable([column_1, column_2])
    table = st.generate_table(row_data)

    assert table == ('Col 1            Col 2          \n'
                     '--------------------------------\n'
                     'Col 1 Row 1      Col 2 Row 1    \n'
                     '\n'
                     'Col 1 Row 2      Col 2 Row 2    \n')

    # Custom divider
    st = SimpleTable([column_1, column_2], divider_char='─')
    table = st.generate_table(row_data)

    assert table == ('Col 1            Col 2          \n'
                     '────────────────────────────────\n'
                     'Col 1 Row 1      Col 2 Row 1    \n'
                     '\n'
                     'Col 1 Row 2      Col 2 Row 2    \n')

    # No divider
    st = SimpleTable([column_1, column_2], divider_char=None)
    table = st.generate_table(row_data)

    assert table == ('Col 1            Col 2          \n'
                     'Col 1 Row 1      Col 2 Row 1    \n'
                     '\n'
                     'Col 1 Row 2      Col 2 Row 2    \n')

    # No row spacing
    st = SimpleTable([column_1, column_2])
    table = st.generate_table(row_data, row_spacing=0)
    assert table == ('Col 1            Col 2          \n'
                     '--------------------------------\n'
                     'Col 1 Row 1      Col 2 Row 1    \n'
                     'Col 1 Row 2      Col 2 Row 2    \n')

    # No header
    st = SimpleTable([column_1, column_2])
    table = st.generate_table(row_data, include_header=False)

    assert table == ('Col 1 Row 1      Col 2 Row 1    \n'
                     '\n'
                     'Col 1 Row 2      Col 2 Row 2    \n')

    # Invalid row spacing
    st = SimpleTable([column_1, column_2])
    with pytest.raises(ValueError) as excinfo:
        st.generate_table(row_data, row_spacing=-1)
    assert "Row spacing cannot be less than 0" in str(excinfo.value)
Exemplo n.º 5
0
def list_frameworks():
    columns: List[Column] = list()
    data_list: List[List[Any]] = list()
    columns.append(Column("Framework", width=20))
    columns.append(Column("# of Attacks", width=30))
    for framework, list_of_attacks in CFState.get_instance(
    ).loaded_frameworks.items():
        data_list.append([framework, len(list_of_attacks)])
    st = SimpleTable(columns)
    print()
    print(st.generate_table(data_list, row_spacing=0))
    print()
Exemplo n.º 6
0
def main():
    # Default to terminal mode so redirecting to a file won't include the ANSI style sequences
    ansi.allow_style = ansi.STYLE_TERMINAL

    st = SimpleTable(columns)
    table = st.generate_table(data_list)
    ansi_print(table)

    bt = BorderedTable(columns)
    table = bt.generate_table(data_list)
    ansi_print(table)

    at = AlternatingTable(columns)
    table = at.generate_table(data_list)
    ansi_print(table)
Exemplo n.º 7
0
def list_attacks():
    columns: List[Column] = list()
    data_list: List[List[Any]] = list()
    columns.append(Column("Name", width=25))
    columns.append(Column("Type", width=15))
    columns.append(Column("Category", width=15))
    columns.append(Column("Tags", width=15))
    columns.append(Column("Framework", width=10))
    for _, attack_obj in CFState.get_instance().loaded_attacks.items():
        tags = ", ".join(attack_obj.tags)
        data_list.append([
            attack_obj.attack_name, attack_obj.attack_type,
            attack_obj.category, tags, attack_obj.framework
        ])
    st = SimpleTable(columns)
    print()
    print(st.generate_table(data_list, row_spacing=0))
    print()
Exemplo n.º 8
0
def list_targets():
    columns: List[Column] = list()
    data_list: List[List[Any]] = list()
    columns.append(Column("Name", width=15))
    columns.append(Column("Type", width=15))
    columns.append(Column("Input Shape", width=15))
    columns.append(Column("Location", width=85))
    for _, target_obj in CFState.get_instance().loaded_targets.items():
        shp = str(target_obj.model_input_shape)
        data_list.append([
            target_obj.model_name, target_obj.model_data_type, shp,
            target_obj.model_endpoint
        ])
    st = SimpleTable(columns)
    print()
    print(st.generate_table(
        data_list,
        row_spacing=0,
    ))
    print()
Exemplo n.º 9
0
def show_attack_info(attack):
    columns: List[Column] = list()
    data_list: List[List[Any]] = list()

    columns.append(
        Column(
            "",
            width=25,
            header_horiz_align=HorizontalAlignment.CENTER,
            data_horiz_align=HorizontalAlignment.RIGHT,
        ))
    columns.append(
        Column("",
               width=80,
               header_horiz_align=HorizontalAlignment.CENTER,
               data_horiz_align=HorizontalAlignment.LEFT))

    st = SimpleTable(columns)

    data_list.append(["attack name", attack.attack_name])
    data_list.append(["attack type", attack.attack_type])
    data_list.append(["attack category", attack.category])
    data_list.append(["attack tags", attack.tags])
    data_list.append(["attack framework", attack.framework])
    if attack.attack_cls.__doc__:
        data_list.append([
            "attack docs",
            attack.attack_cls.__doc__.replace('\n', ' ').replace('\t',
                                                                 '').replace(
                                                                     '  ', ' ')
        ])

    output = '\nAttack Information' + st.generate_table(data_list,
                                                        row_spacing=0) + "\n"

    output += "\n" + show_attack_options(attack)

    return output
Exemplo n.º 10
0
def do_predict(self, args):
    """Predict a single sample for the active target"""
    if CFState.get_instance().active_target is None:
        self.pwarning("\n [!] must first `interact` with a target.\n")
        return
    else:
        target = CFState.get_instance().active_target

    if sum([args.random, args.sample_index is not None, args.result]) > 1:
        self.pwarning("\n [!] must specify only one of {random, sample_index, result}.\n")
        return

    heading1 = "Sample Index"
    if args.random:
        sample_index = random.randint(0, len(target.X) - 1)
        samples = set_attack_samples(target, sample_index)

    elif args.sample_index:  # default behavior
        sample_index = args.sample_index
        samples = set_attack_samples(target, sample_index)

    elif args.result:
        try:
            samples = target.active_attack.results['final']['input']
            sample_index = [target.active_attack.attack_id] * len(samples)            
            heading1 = "Attack ID"
        except (KeyError, AttributeError):
            self.pwarning("\n [!] No results found. First 'run' an attack.\n")
            return

    elif target.active_attack is not None and target.active_attack.sample_index is not None:
        sample_index = target.active_attack.sample_index
        samples = set_attack_samples(target, sample_index)        

    else:
        self.pwarning("\n [!] No index sample, setting random index.\n")
        sample_index = random.randint(0, len(target.X) - 1)
        samples = set_attack_samples(target, sample_index)        

    result = target._submit(samples)

    columns: List[Column] = list()
    columns.append(
        Column(
            heading1,
            width=8,
            header_horiz_align=HorizontalAlignment.LEFT,
            data_horiz_align=HorizontalAlignment.RIGHT,
        )
    )
    columns.append(
        Column(
            "Sample",
            width=60,
            header_horiz_align=HorizontalAlignment.CENTER,
            data_horiz_align=HorizontalAlignment.RIGHT,
        )
    )
    columns.append(
        Column(
            "Output Scores\n" + str(target.model_output_classes).replace(',', ''),
            width=30,
            header_horiz_align=HorizontalAlignment.CENTER,
            data_horiz_align=HorizontalAlignment.RIGHT,
        )
    )

    if not hasattr(sample_index, "__iter__"):
        sample_index = [sample_index]

    samples_str = get_printable_batch(target, samples)
    results_str = printable_numpy(result)

    data_list: List[List[Any]] = list()
    for idx, samp, res in zip(sample_index, samples_str, results_str):
        data_list.append([idx, samp, res])

    st = SimpleTable(columns)
    self.poutput("\n" + st.generate_table(data_list, row_spacing=0) + "\n")
Exemplo n.º 11
0
def test_simple_table_creation():
    column_1 = Column("Col 1", width=16)
    column_2 = Column("Col 2", width=16)

    row_data = list()
    row_data.append(["Col 1 Row 1", "Col 2 Row 1"])
    row_data.append(["Col 1 Row 2", "Col 2 Row 2"])

    # Default options
    st = SimpleTable([column_1, column_2])
    table = st.generate_table(row_data)

    assert table == ('Col 1             Col 2           \n'
                     '----------------------------------\n'
                     'Col 1 Row 1       Col 2 Row 1     \n'
                     '\n'
                     'Col 1 Row 2       Col 2 Row 2     ')

    # Custom divider
    st = SimpleTable([column_1, column_2], divider_char='─')
    table = st.generate_table(row_data)

    assert table == ('Col 1             Col 2           \n'
                     '──────────────────────────────────\n'
                     'Col 1 Row 1       Col 2 Row 1     \n'
                     '\n'
                     'Col 1 Row 2       Col 2 Row 2     ')

    # No divider
    st = SimpleTable([column_1, column_2], divider_char=None)
    table = st.generate_table(row_data)

    assert table == ('Col 1             Col 2           \n'
                     'Col 1 Row 1       Col 2 Row 1     \n'
                     '\n'
                     'Col 1 Row 2       Col 2 Row 2     ')

    # No row spacing
    st = SimpleTable([column_1, column_2])
    table = st.generate_table(row_data, row_spacing=0)
    assert table == ('Col 1             Col 2           \n'
                     '----------------------------------\n'
                     'Col 1 Row 1       Col 2 Row 1     \n'
                     'Col 1 Row 2       Col 2 Row 2     ')

    # No header
    st = SimpleTable([column_1, column_2])
    table = st.generate_table(row_data, include_header=False)

    assert table == ('Col 1 Row 1       Col 2 Row 1     \n'
                     '\n'
                     'Col 1 Row 2       Col 2 Row 2     ')

    # Wide custom divider (divider needs no padding)
    st = SimpleTable([column_1, column_2], divider_char='深')
    table = st.generate_table(row_data)

    assert table == ('Col 1             Col 2           \n'
                     '深深深深深深深深深深深深深深深深深\n'
                     'Col 1 Row 1       Col 2 Row 1     \n'
                     '\n'
                     'Col 1 Row 2       Col 2 Row 2     ')

    # Wide custom divider (divider needs padding)
    column_2 = Column("Col 2", width=17)
    st = SimpleTable([column_1, column_2], divider_char='深')
    table = st.generate_table(row_data)

    assert table == ('Col 1             Col 2            \n'
                     '深深深深深深深深深深深深深深深深深 \n'
                     'Col 1 Row 1       Col 2 Row 1      \n'
                     '\n'
                     'Col 1 Row 2       Col 2 Row 2      ')

    # Invalid divider character
    with pytest.raises(TypeError) as excinfo:
        SimpleTable([column_1, column_2], divider_char='too long')
    assert "Divider character must be exactly one character long" in str(excinfo.value)

    with pytest.raises(ValueError) as excinfo:
        SimpleTable([column_1, column_2], divider_char='\n')
    assert "Divider character is an unprintable character" in str(excinfo.value)

    # Invalid row spacing
    st = SimpleTable([column_1, column_2])
    with pytest.raises(ValueError) as excinfo:
        st.generate_table(row_data, row_spacing=-1)
    assert "Row spacing cannot be less than 0" in str(excinfo.value)
Exemplo n.º 12
0
def get_printable_scan_summary(summaries_by_attack, summaries_by_label=None):
    output = "\n =============== \n SCAN SUMMARY \n ===============\n\n"

    terminal_cols = os.get_terminal_size().columns
    results_width = terminal_cols - 128  # default Windows is 120x30

    if results_width <= 0:
        output += bold_yellow(
            """\nIncrease terminal width to show parameters.\n\n""")

    columns: List[Column] = list()
    columns.append(
        Column(
            "Attack Name",
            width=15,
            header_horiz_align=HorizontalAlignment.LEFT,
            data_horiz_align=HorizontalAlignment.RIGHT,
        ))
    columns.append(
        Column(
            "Total Runs",
            width=10,
            header_horiz_align=HorizontalAlignment.LEFT,
            data_horiz_align=HorizontalAlignment.RIGHT,
        ))
    columns.append(
        Column(
            "Successes (%)",
            width=13,
            header_horiz_align=HorizontalAlignment.LEFT,
            data_horiz_align=HorizontalAlignment.RIGHT,
        ))
    columns.append(
        Column(
            "Time[sec] (min/avg/max)",
            width=15,
            header_horiz_align=HorizontalAlignment.LEFT,
            data_horiz_align=HorizontalAlignment.RIGHT,
        ))
    columns.append(
        Column(
            "Queries (min/avg/max)",
            width=18,
            header_horiz_align=HorizontalAlignment.LEFT,
            data_horiz_align=HorizontalAlignment.RIGHT,
        ))
    columns.append(
        Column(
            "Best Score (attack_id)",
            width=15,
            header_horiz_align=HorizontalAlignment.LEFT,
            data_horiz_align=HorizontalAlignment.RIGHT,
        ))
    if results_width > 0:
        columns.append(
            Column(
                "Best Parameters",
                width=25,
                header_horiz_align=HorizontalAlignment.RIGHT,
                data_horiz_align=HorizontalAlignment.RIGHT,
            ))

    data_list: List[List[Any]] = list()

    for name, summary in summaries_by_attack.items():
        frac = summary["total_successes"] / summary["total_runs"]
        successes = f"{summary['total_successes']} ({frac:>.1%})"
        times = f"{summary['min_time']:>4.1f}/{summary['avg_time']:>4.1f}/{summary['max_time']:>4.1f}"
        queries = f"{summary['min_queries']:>5d}/{summary['avg_queries']:>5d}/{summary['max_queries']:>5d}"
        best = (
            f"{summary['best_attack_score']:0.1f} ({summary['best_attack_id']})"
            if summary["best_attack_score"] else "N/A")
        if results_width > 0:
            if summary["best_params"] is not None:
                trunc_params = shallow_dict_to_fixed_width(
                    (summary["best_params"]))
                param_str = json.dumps(trunc_params,
                                       indent=1,
                                       separators=("", "="))[2:-1].replace(
                                           '"', "")
            else:
                param_str = "N/A"
            data_list.append([
                name, summary["total_runs"], successes, times, queries, best,
                param_str
            ])
        else:
            data_list.append(
                [name, summary["total_runs"], successes, times, queries, best])
    st = SimpleTable(columns)
    output += '\n' + st.generate_table(data_list, row_spacing=0) + '\n'

    if summaries_by_label is not None:
        output += "\n"

        # table by sample_index
        columns: List[Column] = list()
        columns.append(
            Column(
                "Class Label",
                width=15,
                header_horiz_align=HorizontalAlignment.LEFT,
                data_horiz_align=HorizontalAlignment.RIGHT,
            ))
        columns.append(
            Column(
                "Total Runs",
                width=10,
                header_horiz_align=HorizontalAlignment.LEFT,
                data_horiz_align=HorizontalAlignment.RIGHT,
            ))
        columns.append(
            Column(
                "Successes (%)",
                width=13,
                header_horiz_align=HorizontalAlignment.LEFT,
                data_horiz_align=HorizontalAlignment.RIGHT,
            ))
        columns.append(
            Column(
                "Time[sec] (min/avg/max)",
                width=15,
                header_horiz_align=HorizontalAlignment.LEFT,
                data_horiz_align=HorizontalAlignment.RIGHT,
            ))
        columns.append(
            Column(
                "Queries (min/avg/max)",
                width=18,
                header_horiz_align=HorizontalAlignment.LEFT,
                data_horiz_align=HorizontalAlignment.RIGHT,
            ))
        columns.append(
            Column(
                "Best Score (Attack)",
                width=15,
                header_horiz_align=HorizontalAlignment.LEFT,
                data_horiz_align=HorizontalAlignment.RIGHT,
            ))

        data_list: List[List[Any]] = list()

        for name, summary in sorted(summaries_by_label.items()):
            frac = summary["total_successes"] / summary["total_runs"]
            successes = f"{summary['total_successes']} ({frac:>.1%})"
            times = f"{summary['min_time']:>4.1f}/{summary['avg_time']:>4.1f}/{summary['max_time']:>4.1f}"
            queries = f"{summary['min_queries']:>5d}/{summary['avg_queries']:>5d}/{summary['max_queries']:>5d}"
            best = (
                f"{summary['best_attack_score']:0.1f} ({summary['best_attack_name']})"
                if summary["best_attack_score"] else "N/A")
            data_list.append(
                [name, summary["total_runs"], successes, times, queries, best])

        st = SimpleTable(columns)
        output += '\n' + st.generate_table(data_list, row_spacing=0) + '\n'

    return output
Exemplo n.º 13
0
def get_printable_run_summary(summary):
    output = ""
    output += f"\n[+] {summary['successes']}/{summary['batch_size']} succeeded\n\n"
    if summary['elapsed_time'] > summary['queries']:
        query_rate = summary['elapsed_time'] / summary['queries']
        units = 'sec/query'
    else:
        query_rate = summary["queries"] / summary["elapsed_time"]
        units = "query/sec"

    metric = summary["input_change_metric"]
    terminal_cols = os.get_terminal_size().columns
    results_width = terminal_cols - 125  # default Windows is 120x30

    columns: List[Column] = list()
    columns.append(Column("", width=3))  # number
    columns.append(
        Column(
            "Sample Index",
            width=13,
            header_horiz_align=HorizontalAlignment.CENTER,
            data_horiz_align=HorizontalAlignment.RIGHT,
        ))
    columns.append(
        Column(
            "Label (conf)",
            width=18,
            header_horiz_align=HorizontalAlignment.CENTER,
            data_horiz_align=HorizontalAlignment.RIGHT,
        ))
    columns.append(
        Column(
            "Attack Label (conf)",
            width=19,
            header_horiz_align=HorizontalAlignment.CENTER,
            data_horiz_align=HorizontalAlignment.RIGHT,
        ))
    columns.append(
        Column(
            metric,
            width=len(metric),
            header_horiz_align=HorizontalAlignment.CENTER,
            data_horiz_align=HorizontalAlignment.RIGHT,
        ))
    columns.append(
        Column(
            "Elapsed Time [sec]",
            width=18,
            header_horiz_align=HorizontalAlignment.CENTER,
            data_horiz_align=HorizontalAlignment.RIGHT,
        ))
    columns.append(
        Column(
            "Queries (rate)",
            width=18,
            header_horiz_align=HorizontalAlignment.CENTER,
            data_horiz_align=HorizontalAlignment.RIGHT,
        ))
    if results_width > 0:
        columns.append(
            Column(
                "Attack Input",
                width=results_width,
                header_horiz_align=HorizontalAlignment.CENTER,
                data_horiz_align=HorizontalAlignment.LEFT,
            ))

    data_list: List[List[Any]] = list()

    elapsed_time_str = f"{summary['elapsed_time']:.1f}"
    query_rate_str = f"{summary['queries']:.0f} ({query_rate:.1f} {units})"

    for i, (si, li, conf_0, lf, conf_f, change, res, d) in enumerate(
            zip(summary["sample_index"], summary["initial_label"],
                summary["initial_confidence"], summary["final_label"],
                summary["final_confidence"], summary["input_change"],
                summary["result"], summary["degenerate"])):
        label_confidence = f"{li} ({conf_0:.4f})"
        final_confidence = f"{lf} ({conf_f:.4f})"

        if d:
            label_confidence = f"{bold_yellow('*')} " + label_confidence
            final_confidence = f"{bold_yellow('*')} " + final_confidence

        change_str = f"{change:.5%}"
        if results_width > 0:
            data_list.append([
                f"{i+1}.",
                si,
                label_confidence,
                final_confidence,
                change_str,
                elapsed_time_str,
                query_rate_str,
                str(np.array(res)),
            ])
        else:
            data_list.append([
                f"{i+1}.",
                si,
                label_confidence,
                final_confidence,
                change_str,
                elapsed_time_str,
                query_rate_str,
            ])

    if sum(summary["degenerate"]) > 0:
        output += bold_yellow(
            " * target_class is the same as the original class") + "\n\n"

    if results_width <= 0:
        output = bold_yellow(
            """\nIncrease terminal width to show results.\n""") + output

    # return table as output
    st = SimpleTable(columns)
    return output + '\n' + st.generate_table(data_list, row_spacing=0) + '\n'
Exemplo n.º 14
0
def do_set(self, args):
    """Set parameters of the active attack on the active target using param1=val1 param2=val2 notation.
    This command replaces built-in "set" command, which is renamed to "setg".
    """

    if not CFState.get_instance().active_target:
        self.pwarning(
            '\n [!] No active target. Try "setg" for setting global arguments.\n'
        )
        return

    if not CFState.get_instance().active_target.active_attack:
        self.pwarning('\n [!] No active attack. Try "use <attack>".\n')
        return

    # 'set' with no options shows current variables, similar to "show options"
    if not args.what:
        self.pwarning(
            '\n [!] No arguments specified.  Try "set <param>=<value>".\n')

    # create structure to ensure all params are present and ordered properly. Defaults to current params to prevent over writing with default values
    params_struct = namedtuple(
        "params",
        [
            i for i in CFState.get_instance().active_target.active_attack.
            parameters.keys()
        ] + ["sample_index", "target_class"],
        defaults=list(CFState.get_instance(
        ).active_target.active_attack.parameters.values()) + [
            CFState.get_instance().active_target.active_attack.sample_index,
            CFState.get_instance().active_target.active_attack.target_class,
        ],
    )

    # parse parameters and new values from the args
    try:
        params_to_update = re.findall(r"(\w+)\s?=\s?([\w\.]+)",
                                      " ".join(args.what))
    except:
        self.pwarning("\n [!] Failed to parse arguments.\n")
        return

    # create default params struct
    default_params = {
        k: v
        for k, v in
        CFState.get_instance().active_target.active_attack.default.items()
    }
    default_params["sample_index"] = CFState.get_instance(
    ).active_target.active_attack.sample_index
    default_params["target_class"] = CFState.get_instance(
    ).active_target.active_attack.target_class

    # ensure all current params exist and are ordered correctly
    default_params = params_struct(**default_params)._asdict()

    # convert string "True"/"true" and "False"/"false" to boolean
    for i, v in enumerate(params_to_update):
        if type(default_params.get(v[0], None)) is bool:
            if v[1].lower() == "true" or int(v[1]) == 1:
                params_to_update[i] = (v[0], True)
            elif v[1].lower() == "false" or int(v[1]) == 0:
                params_to_update[i] = (v[0], False)

    # create new params struct using default values where no new values are spec'd
    new_params = params_struct(**{
        i[0]: type(default_params.get(i[0], ""))(i[1])
        for i in params_to_update
    })

    # create current params struct
    current_params = {
        k: v
        for k, v in
        CFState.get_instance().active_target.active_attack.parameters.items()
    }
    current_params["sample_index"] = CFState.get_instance(
    ).active_target.active_attack.sample_index
    current_params["target_class"] = CFState.get_instance(
    ).active_target.active_attack.target_class

    # ensure all current params exist and are ordered correctly
    current_params = params_struct(**current_params)._asdict()

    # separate target_class and sample_index from struct and update the relevant values
    CFState.get_instance().active_target.active_attack.parameters = {
        k: v
        for k, v in zip(new_params._fields[:-2], new_params[:-2])
    }
    CFState.get_instance(
    ).active_target.active_attack.sample_index = new_params.sample_index
    CFState.get_instance(
    ).active_target.active_attack.target_class = new_params.target_class

    # print info
    print_new_params = new_params._asdict()

    columns: List[Column] = list()
    data_list: List[List[Any]] = list()
    columns.append(
        Column("Attack Parameter (type)",
               width=25,
               header_horiz_align=HorizontalAlignment.LEFT,
               data_horiz_align=HorizontalAlignment.RIGHT))
    columns.append(
        Column("Default",
               width=12,
               header_horiz_align=HorizontalAlignment.CENTER,
               data_horiz_align=HorizontalAlignment.LEFT))
    columns.append(
        Column("Previous",
               width=12,
               header_horiz_align=HorizontalAlignment.CENTER,
               data_horiz_align=HorizontalAlignment.LEFT))
    columns.append(
        Column("New",
               width=12,
               header_horiz_align=HorizontalAlignment.CENTER,
               data_horiz_align=HorizontalAlignment.LEFT))

    for k, default_value in default_params.items():
        param = f"{k} ({str(type(default_value).__name__)})"
        previous_value = current_params.get(k, "")
        new_value = print_new_params.get(k, "")
        if new_value != previous_value:
            data_list.append([
                param,
                str(default_value),
                str(previous_value),
                str(new_value)
            ])

        else:
            data_list.append(
                [param,
                 str(default_value)[:11],
                 str(previous_value)[:11], ""])

    st = SimpleTable(columns)
    print()
    print(st.generate_table(data_list, row_spacing=0))
    print()