Пример #1
0
def register() -> None:
    PluginCommand.register(
        "Screenshot Ninja \\ Capture view image @ 1x...",
        "Save an image of the currently visible linear/graph view at 1x scaling",
        lambda bv: _ui_save_image(bv, False, 1),
    )

    PluginCommand.register(
        "Screenshot Ninja \\ Capture view image @ 2x...",
        "Save an image of the currently visible linear/graph view at 2x scaling",
        lambda bv: _ui_save_image(bv, False, 2),
    )

    PluginCommand.register(
        "Screenshot Ninja \\ Capture view image...",
        "Save an image of the currently visible linear/graph view at custom scaling",
        lambda bv: _ui_save_image(bv, False),
    )

    PluginCommand.register(
        "Screenshot Ninja \\ Capture window image @ 1x...",
        "Save an image of the main window at 1x scaling",
        lambda bv: _ui_save_image(bv, True, 1),
    )

    PluginCommand.register(
        "Screenshot Ninja \\ Capture window image @ 2x...",
        "Save an image of the main window at 2x scaling",
        lambda bv: _ui_save_image(bv, True, 2),
    )

    PluginCommand.register(
        "Screenshot Ninja \\ Capture window image...",
        "Save an image of the main window at custom scaling",
        lambda bv: _ui_save_image(bv, True),
    )
Пример #2
0
 def _install_open_coverage_overview(self):
     PluginCommand.register("Lighthouse - Coverage Overview",
                            "Open the database code coverage overview",
                            self.interactive_load_batch)
     logger.info("Installed the 'Coverage Overview' menu entry")
Пример #3
0
        rpc.register_instance(Lobotomy(rpc, bv))
        print("[*] Started lobotomy service (!)")
        while True:
            # Handle inbound requests
            rpc.handle_request()
    except Exception as e:
        ExceptionHandler(e)


def start_thread(bv):
    """
    Create a new thread that will run the lobotomy service
    """
    global t
    global running

    print(bv)
    try:
        t = threading.Thread(target=start_lobotomy, args=[bv])
        t.daemon = True
        t.start()
        if not running:
            running = True
    except Exception as e:
        ExceptionHandler(e)


# Register plugin
PluginCommand.register("jni", "Find all registered JNI functions",
                       start_thread)
Пример #4
0
    rules = [RULES_DIR]
    paths = Settings().get_string("yara.customRulesPath")

    for path in paths.split(";"):
        rules.append(path.strip())

    ys = YaraScan(bv, directories=rules)
    ys.start()


def scan_with_file(bv):
    filepath = get_open_filename_input("Open YARA rule",
                                       "YARA rules (*.yar *.yara)")
    if filepath:
        ys = YaraScan(bv, filepath=filepath.decode())
        ys.start()


def crypto_scan(bv):
    crypto_rules = RULES_DIR + os.sep + "crypto_signatures.yar"
    ys = YaraScan(bv, filepath=crypto_rules)
    ys.start()


PluginCommand.register("YARA\\Scan", "Scan file using YARA rules", scan)
PluginCommand.register("YARA\\Scan with File",
                       "Scan file using a specific YARA rule", scan_with_file)
PluginCommand.register(
    "YARA\\Scan for Crypto",
    "Scan file for known crypto constants using YARA rules", crypto_scan)
Пример #5
0
 def _install_load_file(self):
     PluginCommand.register("Lighthouse - Load code coverage file...",
                            "Load individual code coverage file(s)",
                            self.interactive_load_file)
     logger.info("Installed the 'Code coverage file' menu entry")
Пример #6
0
from binaryninja import PluginCommand, Architecture

from .coverage import function_coverage_start
from .evm import EVM, EVMView
from .flowgraph import render_flowgraphs


def is_valid_evm(view, function=None):
    return view.arch == Architecture['EVM']


PluginCommand.register(r"Ethersplay\Manticore Highlight",
                       "EVM Manticore Highlight",
                       function_coverage_start,
                       is_valid=is_valid_evm)

PluginCommand.register(
    r'Ethersplay\Render Flowgraphs',
    'Render flowgraphs of every function, removing stack variable annotations',
    render_flowgraphs,
    is_valid=is_valid_evm)

EVM.register()
EVMView.register()
        if ptr_s == 4:
            bv.define_data_var(addr, bv.parse_type_string('uint32_t x')[0])
            if not isinstance(f, Symbol):
                s = Symbol(SymbolType.DataSymbol, addr, "ecall_table_size")
                bv.define_user_symbol(s)

            ecalls_count = unpack('I', bv.read(addr, 4))[0]
        else:
            bv.define_data_var(addr, bv.parse_type_string('uint64_t x')[0])
            if not isinstance(f, Symbol):
                s = Symbol(SymbolType.DataSymbol, addr, "ecall_table_size")
                bv.define_user_symbol(s)

            ecalls_count = unpack('Q', bv.read(addr, 8))[0]

        log_info(f"identified {ecalls_count} ecalls")

        table_addr = addr + ptr_s
        table_type, _ = bv.parse_type_string(
            f"struct {_SGX_ECALL_TYPE_NAME} ecall_table[{ecalls_count}]")

        bv.define_data_var(table_addr, table_type)
        s = Symbol(SymbolType.DataSymbol, table_addr, "ecall_table")
        bv.define_user_symbol(s)


PluginCommand.register("SGX\\find ecall table",
                       "In a SGX binary, try to identify the ecall table",
                       find_ecall_table)
Пример #8
0
#!/usr/bin/env python
# author: carstein <*****@*****.**>
# Syscaller - decoreate syscall with arguments

from binaryninja import PluginCommand

from .modules import syscaller

# register plugin
PluginCommand.register_for_function(
    "Syscaller\Decorate syscalls in current function",
    "Annotate syscalls with arguments in current function",
    syscaller.run_plugin_current)

PluginCommand.register(
    "Syscaller\Decorate syscalls in all functions",
    "Annotate syscalls with arguments in all defined functions",
    syscaller.run_plugin_all)
Пример #9
0
                    self.caller.add_user_code_ref(src, dst, from_arch=None)
                    self.add_call_comment(src, dst)
                    self.call_cnt += 1
        log.log(1, "Devirtualized {} calls".format(self.call_cnt))

    def devirtualize_calls_v01(self, call_list):
        for v_call in call_list:
            for call in v_call:
                to_addr = int(v_call[call])
                #print(hex(int(call)))
                #print(hex(to_addr))
                from_addr = int(call)
                self.caller = self.bv.get_functions_containing(from_addr)[0]
                self.caller.add_user_code_ref(from_addr,
                                              to_addr,
                                              from_arch=None)
                self.add_call_comment(from_addr, to_addr)
                self.call_cnt += 1
        log.log(1, "Devirtualized {} calls".format(self.call_cnt))

    def add_call_comment(self, from_addr, to_addr):
        to_func = self.bv.get_function_at(to_addr)
        _, name = demangle.demangle_gnu3(self.bv.arch, to_func.name)
        old_comment = self.caller.get_comment_at(from_addr)
        self.caller.set_comment_at(
            from_addr,
            demangle.get_qualified_name(name) + "\n" + old_comment)


PluginCommand.register("devi", "DEvirtualize VIrtual calls", binja_devi)
Пример #10
0
from binaryninja import PluginCommand

from .obfuscation_detection import detect_obfuscation
from .obfuscation_detection.heuristics import *

PluginCommand.register("Obfuscation Detection\\All",
                       "Detects obfuscated code via heuristics", detect_obfuscation)

PluginCommand.register("Obfuscation Detection\\Flattened Functions",
                       "Heuristic to detect flattened functions", find_flattened_functions)

PluginCommand.register("Obfuscation Detection\\Complex Functions",
                       "Heuristic to detect complex functions", find_complex_functions)

PluginCommand.register("Obfuscation Detection\\Large Basic Blocks",
                       "Heuristic to detect functions with large basic blocks", find_large_basic_blocks)

PluginCommand.register("Obfuscation Detection\\Instruction Overlapping",
                       "Heuristic to detect instruction overlapping", find_instruction_overlapping)

PluginCommand.register("Obfuscation Detection\\Uncommon Instruction Sequences",
                       "Heuristic to detect uncommon instruction sequences", find_uncommon_instruction_sequences)
            for instr in bb:
                if instr[0][0].text not in ("nop", "jmp") or (
                        instr[0][0].text == "jmp" and not bb.outgoing_edges):
                    print(instr[0])
                    n.lines += [
                        DisassemblyTextLine(instr[0], address=current_addr)
                    ]

                current_addr += instr[1]
                if (instr[0][0].text == "jmp" and bb.outgoing_edges
                        and bb.outgoing_edges[0].target.start in bbs
                        and bb.outgoing_edges[0].target in bb.dominators):
                    n.add_outgoing_edge(
                        BranchType.UnconditionalBranch,
                        bbs[bb.outgoing_edges[0].target.start],
                    )
                else:
                    # Keep using the same FlowGraphNode
                    pass
        g.append(n)
        g.layout_and_wait()
        g.show(func.name)


PluginCommand.register(
    r"Unlock\Generate Graphs",
    "Generate Deobfuscated Graphs",
    generate_graphs,
    lambda v: "obfuscated" in v.file.filename,
)
Пример #12
0
#!/usr/bin/env python
# Author: carstein <*****@*****.**>
# Annotate function arguments

from binaryninja import PluginCommand
from modules import annotate

# register plugin
PluginCommand.register_for_function(
    "[Annotator] Annotate Functions",
    "Annotate standard libc functions with arguments", annotate.run_plugin)

PluginCommand.register("[Annotator All] Annotate Functions",
                       "Annotate standard libc functions with arguments",
                       annotate.run_plugin_all)
Пример #13
0
    bv = BinaryViewType["PE"].open(args.driver)
    if not bv:
        print("[-] Error loading file: {:s}".format(args.driver),
              file=sys.stderr)
        return 1

    analysis = analyze.Analysis(bv)
    analysis.label_driver_dispatch_routines()
    if args.ioctls:
        analysis.find_ioctls()


if __name__ == "__main__":
    cmdline_main()
else:
    PluginCommand.register(
        "Label Driver Dispatch Routines",
        "Label driver dispatch routines for IRPs and other callbacks",
        action=label_driver_dispatch_routines)
    #PluginCommand.register(
    #    "Label Callback Routines", "Label callback routines used in common kernel APIs",
    #    action=label_callback_routines)
    PluginCommand.register(
        "Find IOCTLs [global]",
        "Find supported IOCTLs and generate CTL_CODE macros",
        action=find_ioctls)
    PluginCommand.register_for_function(
        "Find IOCTLs [current function]",
        "Find supported IOCTLs and generate CTL_CODE macros",
        action=find_ioctls)
Пример #14
0
    dbg("Starting background service...")
    __service_thread = threading.Thread(target=start_service,
                                        args=(HOST, PORT, bv))
    __service_thread.daemon = True
    __service_thread.start()
    register_gef_breakpoint_menu()
    show_message_box(
        "GEF",
        "Service successfully started, you can now have gef connect to it",
        MessageBoxButtonSet.OKButtonSet, MessageBoxIcon.InformationIcon)
    return


def gef_stop(bv):
    "Stopping background service... "
    stop_service()
    show_message_box("GEF", "Service successfully stopped",
                     MessageBoxButtonSet.OKButtonSet,
                     MessageBoxIcon.InformationIcon)
    return


PluginCommand.register("GEF\\Start service",
                       "Start the service for communicating with gef",
                       gef_start,
                       is_valid=lambda view: not is_service_started())

PluginCommand.register("GEF\\Stop service",
                       "Stop the service for communicating with gef",
                       gef_stop,
                       is_valid=lambda view: is_service_started())
Пример #15
0
    notification = EditFunctionNotification(view, controller)
    view.register_notification(notification)


UIAction.registerAction("Configure BinSync...")
UIActionHandler.globalActions().bindAction("Configure BinSync...",
                                           UIAction(launch_binsync_configure))
Menu.mainMenu("Tools").addAction("Configure BinSync...", "BinSync")

open_control_panel_id = "BinSync: Open control panel"
UIAction.registerAction(open_control_panel_id)
UIActionHandler.globalActions().bindAction(open_control_panel_id,
                                           UIAction(open_control_panel))
Menu.mainMenu("Tools").addAction(open_control_panel_id, "BinSync")

# register the control panel dock widget
dock_handler = DockHandler.getActiveDockHandler()
dock_handler.addDockWidget(
    "BinSync: Control Panel",
    lambda n, p, d: create_widget(ControlPanelDockWidget, n, p, d, controller),
    Qt.RightDockWidgetArea, Qt.Vertical, True)

PluginCommand.register_for_function("Push function upwards",
                                    "Push function upwards",
                                    controller.push_function)
# TODO how can we avoid having users to click on this menu option?
PluginCommand.register("Start Sharing Patches", "Start Sharing Patches",
                       start_patch_monitor)
PluginCommand.register("Start Sharing Functions", "Start Sharing Functions",
                       start_function_monitor)
Пример #16
0
            # Print warnings when our janky parser goes awry.
            if len(words)>0 and words[0]!="/*" and words[0]!="*/":
                print("#Warning in: %s\n"%words);
                log_error(traceback.format_exc())

def md380ldsymbols(view):
    """This loads an MD380Tools symbols file in GNU LD format."""
    filename=get_open_filename_input("Select GNU LD symbols file from MD380Tools.")
    if filename:
        print("Opening: %s"%filename);
        importldsymbols(view,filename);
    else:
        print("Aborting.");

PluginCommand.register("Load MD380 LD Symbols",
                       "Load GNU LD symbols from MD380Tools",
                       md380ldsymbols);


def importr2symbols(bv,filename):
    """Janky shotgun parser to import Radare2 symbols file to Binary Ninja."""
    f=open(filename,"r");
    for l in f:
        words=l.strip().split();

        try:
            if words[0][0]=="#":
                pass;
            elif words[0]=="f" and words[2]=="@":
                #f name @ 0xDEADBEEF
                name=words[1];
Пример #17
0
def get_coverage(view):
    tv = TraceVisualizer(view, None, live=False)
    if tv.workspace is None:
        tv.workspace = get_workspace()
    tv.visualize()
    c = CoverageHelper(view, tv)
    c.start()


def clear_all(view):
    tv = TraceVisualizer(view, None)
    for addr in tv.highlighted:
        tv.highlight_block(addr, clear)
    tv.clear_stats()
    tv.workspace = None
    tv.live_update = False


PluginCommand.register("ManticoreTrace: Highlight",
                       "Highlight Manticore Execution Trace", viz_trace)
PluginCommand.register("ManticoreTrace: BB Coverage",
                       "Compute cumulative BB coverage for each function ",
                       get_coverage)
PluginCommand.register(
    "ManticoreTrace: Live Highlight",
    "Highlight Manticore Execution Trace at Real-Time",
    viz_live_trace,
)
PluginCommand.register("ManticoreTrace: Clear",
                       "Clear Manticore Trace Highlight", clear_all)
Пример #18
0
from binaryninja import plugin, PluginCommand


class bnlink_task(plugin.BackgroundTaskThread):
    def __init__(self, bv):
        plugin.BackgroundTaskThread.__init__(self, "bnlink", True)
        self.bv = bv

    def run(self):
        from rpyc.core import SlaveService
        from rpyc.utils.server import ThreadedServer
        ThreadedServer(SlaveService, port=6666).start()


def run_task(bv):
    bnlink_task(bv).start()


PluginCommand.register("Start bnlink", "Run's rpc service on port 6666",
                       run_task)
Пример #19
0
"""Binary Ninja plugin for applying kernel symbols from /proc/kallsyms output
"""

from binaryninja import BinaryView, PluginCommand
from .kallsyms import *


def apply_kernel_symbols(view: BinaryView):
    """Registered plugin handler function
    """

    kallsyms = KAllSyms(view)
    kallsyms.start()


PluginCommand.register("kallsyms: Apply kernel symbols",
                       "Apply kernel symbols from /proc/kallsyms output",
                       apply_kernel_symbols)
Пример #20
0
#from __future__ import print_function

from binaryninja import PluginCommand

from printSourceCode import function_source_code_start

from coverage import function_coverage_start
from evm import EVM, EVMView

PluginCommand.register("EVM Source Code", "EVM Source Code Printer.",
                       function_source_code_start)

PluginCommand.register("EVM Manticore Highlight", "EVM Manticore Highlight",
                       function_coverage_start)

EVM.register()
EVMView.register()
Пример #21
0
    task.start()


def command_label_tls(view):
    label_tls(view)


def check_view_platform(view, *platforms):
    platform = view.platform
    if platform is None:
        return False
    return platform.name in platforms


PluginCommand.register(
    'Windows\\Scan for RTTI', 'Scans for MSVC RTTI',
    lambda view: command_scan_for_rtti(view),
    lambda view: check_view_platform(view, 'windows-x86', 'windows-x86_64'))

PluginCommand.register_for_address(
    'Windows\\Create vftable', 'Creates a vftable at the current address',
    lambda view, address: command_create_vtable(view, address), lambda view,
    address: check_view_platform(view, 'windows-x86', 'windows-x86_64'))

PluginCommand.register(
    'Windows\\Parse exception handlers',
    'Create functions based on exception handlers',
    lambda view: command_parse_unwind_info(view),
    lambda view: check_view_platform(view, 'windows-x86_64'))

PluginCommand.register(
    'Windows\\Fix thiscall\'s',
Пример #22
0
    if not __check_executor():
        return

    executor.bncache.settings = {}


PluginCommand.register_for_address(
    "SENinja\\0 - Start symbolic execution",
    "create the first state for symbolic execution at current address",
    _async_start_se)
PluginCommand.register_for_address(
    "SENinja\\1 - Change current state",
    "change current state with the deferred one at current address (if any)",
    _async_change_current_state)
PluginCommand.register("SENinja\\2 - Step",
                       "execute one instruction with the current state",
                       _async_step)
PluginCommand.register(
    "SENinja\\3 - Continue until branch",
    "execute instructions in the current state until a fork occurs",
    _async_continue_until_branch)
PluginCommand.register_for_address(
    "SENinja\\4 - Continue until address",
    "execute instructions in the current state until the currently selected address is reached",
    _async_continue_until_address)
PluginCommand.register_for_address(
    "SENinja\\5 - Merge states",
    "merge all states at current address in one state", _async_merge_states)
PluginCommand.register("SENinja\\6 - Save active state",
                       "save active state in deferred queue",
                       _async_save_active_state)
Пример #23
0
from .coverage import function_coverage_start
from .evm import EVM, EVMView
from .flowgraph import render_flowgraphs
from .annotator import annotate_all
from .lookup4byte import (rename_all_functions, lookup_one_inst,
                          update_cache_bn, lookup_all_push4)
from .misc import dump_codecopy_data


def is_valid_evm(view, function=None):
    return view.arch == Architecture['EVM']


PluginCommand.register(r"Ethersplay\Manticore Highlight",
                       "EVM Manticore Highlight",
                       function_coverage_start,
                       is_valid=is_valid_evm)

PluginCommand.register(
    r'Ethersplay\Render Flowgraphs',
    'Render flowgraphs of every function, removing stack variable annotations',
    render_flowgraphs,
    is_valid=is_valid_evm)

# non-upstream things
PluginCommand.register("Ethersplay-contrib\\Annotate Instructions",
                       "[EVM] Annotate Instructions",
                       annotate_all,
                       is_valid=is_valid_evm)

PluginCommand.register(
Пример #24
0
def add_image_button(filename, size, fun=None, tooltip=None):
    """ Adds a pushbutton with an icon to the toolbar  """
    button = QtWidgets.QPushButton('', toolbar)
    button.setIcon(QtGui.QIcon(filename))
    if fun is not None:
        button.clicked.connect(lambda: fun(get_binary_view()))
    if tooltip is not None:
        button.setToolTip(tooltip)
    button.setIconSize(QtCore.QSize(size[0], size[1]))
    toolbar.add_widget(button)


def add_picker(pickeritems, callback):
    """ Adds a combobox widget to the toolbar """
    picker = QtWidgets.QComboBox()
    for item in pickeritems:
        picker.addItem(item)
    picker.currentIndexChanged.connect(callback)
    toolbar.add_widget(picker)


def set_bv(binary_view):
    """ Caches the binary view so that button callbacks can have access to it """
    global global_binary_view
    global_binary_view = binary_view
    if not toolbar.isVisible():
        toolbar.toggle()


PluginCommand.register("Initialize Toolbar for this view", "", set_bv)
Пример #25
0
 def _install_load_batch(self):
     PluginCommand.register("Lighthouse - Load code coverage batch...",
                            "Load and aggregate code coverage files",
                            self.interactive_load_batch)
     logger.info("Installed the 'Code coverage batch' menu entry")
            for specifier in specifiers[1:]:
                if not specifier:
                    continue

                if specifier.startswith('d'):
                    param_types.append(Type.int(4, sign=True))
                elif specifier.startswith('s'):
                    param_types.append(Type.pointer(view.arch, Type.char()))
                elif specifier.startswith('p'):
                    param_types.append(Type.pointer(view.arch, Type.void()))
                else:
                    log.log_warn(
                        f'Unknown format specifier: {specifier}; skipping')
                    param_types.append(Type.pointer(view.arch, Type.void()))

            param_idx = 1
            params = [
                FunctionParameter(Type.pointer(view.arch, Type.char()), 'fmt')
            ]
            for param in param_types:
                params.append(FunctionParameter(param, f'arg{param_idx}'))
                param_idx += 1

            caller.set_call_type_adjustment(xref.address,
                                            Type.function(Type.int(4), params))


PluginCommand.register(
    'Fix up printf signatures',
    'Fix up printf signatures so that the variadic arguments are correctly typed',
    fix_printfs)
        src = self.visit(expr.src)

        if src is not None:
            self.br.seek(src)
            return self.br.read8()

    def visit_LLIL_XOR(self, expr):
        left = self.visit(expr.left)
        right = self.visit(expr.right)

        if None not in (left, right):
            return left ^ right

    def visit_LLIL_REG(self, expr):
        src = expr.src

        return self.regs[src.name]

    def visit_LLIL_NORET(self, expr):
        log_alert("VM Halted.")


def run_emulator(view):
    v = VMVisitor(view)
    for il in view.llil_instructions:
        v.visit(il)


PluginCommand.register('Emulate VMArch', 'Emulate VMArch LLIL', run_emulator,
                       lambda view: view.arch == Architecture['VMArch'])
Пример #28
0
from binaryninja import PluginCommand
from .binja import import_data_in_background, export_data_in_background

PluginCommand.register('bnida: Import analysis data',
                       'Import analysis data from JSON file',
                       import_data_in_background)

PluginCommand.register('bnida: Export analysis data',
                       'Export analysis data to a JSON file',
                       export_data_in_background)
Пример #29
0
    def symbol_added(self, *args):
        log.log_info(inspect.stack()[0][3] + str(args))

    def symbol_updated(self, *args):
        log.log_info(inspect.stack()[0][3] + str(args))

    def symbol_removed(self, *args):
        log.log_info(inspect.stack()[0][3] + str(args))

    def string_found(self, *args):
        log.log_info(inspect.stack()[0][3] + str(args))

    def string_removed(self, *args):
        log.log_info(inspect.stack()[0][3] + str(args))

    def type_defined(self, *args):
        log.log_info(inspect.stack()[0][3] + str(args))

    def type_undefined(self, *args):
        log.log_info(inspect.stack()[0][3] + str(args))

    def type_ref_changed(self, *args):
        log.log_info(inspect.stack()[0][3] + str(args))

    def type_field_ref_changed(self, *args):
        log.log_info(inspect.stack()[0][3] + str(args))


PluginCommand.register("Register Notification", "", reg_notif)
Пример #30
0
"""

"""

from binaryninja import (
    PluginCommand, )

from .server import (
    rpyc_start,
    rpyc_stop,
    is_service_started,
)

PluginCommand.register("RPyC\\Start service",
                       "Start the RPyC server",
                       rpyc_start,
                       is_valid=lambda view: not is_service_started())

PluginCommand.register("RPyC\\Stop service",
                       "Start the RPyC server",
                       rpyc_stop,
                       is_valid=lambda view: is_service_started())
Пример #31
0
    """Returns true if a function has a 'strange loop' (ignore this, inside joke)"""
    for bb in fn.basic_blocks:
        if bb in bb.dominance_frontier:
            return True
    return False

tags = [ \
{'emoji': '🍃', 'name': 'Leaf Function', 'description': 'Leaf function (does not call anything else)', 'fn': isleaf},
{'emoji': '🔄', 'name': 'Loop Function', 'description': 'Function contains a loop', 'fn': hasloop},
{'emoji': '🥾', 'name': 'Stub Function', 'description': 'Function is likely a stub (only contains one basic block and one call or indirect jump)', 'fn': isstub},
{'emoji': '🐘', 'name': 'Large Function', 'description': 'Function is "large" (IE, it has more than the blocks defined above)', 'fn': islarge},
{'emoji': '🤯', 'name': 'Complex Function', 'description': 'Function is "complex" (IE, it has a cyclomatic complexity greater than a defined constant)', 'fn': iscomplex},
{'emoji': '🌴', 'name': 'Switchy Function', 'description': 'Function contains a large switch statemen', 'fn': isswitchy},
        ]


def start(bv):
    init_tags(bv)
    for fn in bv.functions:
        for tagType in tags:
            if tagType['fn'](fn):
                fn.create_user_function_tag(bv.tag_types[tagType['name']],
                                            '',
                                            unique=True)
                #fn.name = fn.name + tagType['emoji']


PluginCommand.register("TagTeam",
                       "Tag Functions with Emoji for Various Properties",
                       start)
		log.log_info(inspect.stack()[0][3] + str(args))

	def function_removed(self, *args):
		log.log_info(inspect.stack()[0][3] + str(args))

	def function_updated(self, *args):
		log.log_info(inspect.stack()[0][3] + str(args))

	def data_var_added(self, *args):
		log.log_info(inspect.stack()[0][3] + str(args))

	def data_var_updated(self, *args):
		log.log_info(inspect.stack()[0][3] + str(args))

	def data_var_removed(self, *args):
		log.log_info(inspect.stack()[0][3] + str(args))

	def string_found(self, *args):
		log.log_info(inspect.stack()[0][3] + str(args))

	def string_removed(self, *args):
		log.log_info(inspect.stack()[0][3] + str(args))

	def type_defined(self, *args):
		log.log_info(inspect.stack()[0][3] + str(args))

	def type_undefined(self, *args):
		log.log_info(inspect.stack()[0][3] + str(args))

PluginCommand.register("Register Notification", "", reg_notif)