コード例 #1
0
    def context_code(self):
        nb_insn = self.get_setting("nb_lines_code")
        nb_insn_prev = self.get_setting("nb_lines_code_prev")
        cur_insn_color = unigdb.config.get("theme.disassemble_current_instruction")
        pc = int(unigdb.arch.CURRENT_ARCH.pc)

        # frame = gdb.selected_frame()
        arch_name = "{}:{}".format(unigdb.arch.CURRENT_ARCH.arch.lower(), unigdb.arch.CURRENT_ARCH.mode)

        self.context_title("code:{}".format(arch_name))

        try:
            instruction_iterator = disass.capstone_disassemble
            # instruction_iterator = disass.ida_disassemble if use_ida else instruction_iterator
            for insn in instruction_iterator(pc, nb_insn, nb_prev=nb_insn_prev):
                line = []
                is_taken = False
                target = None
                text = str(insn)

                if insn.address < pc:
                    line += Color.grayify("   {}".format(text))
                elif insn.address == pc:
                    line += Color.colorify("{:s}{:s}".format(config_arrow_right.rjust(3), text), cur_insn_color)

                    if unigdb.arch.CURRENT_ARCH.is_conditional_branch(insn):
                        is_taken, reason = unigdb.arch.CURRENT_ARCH.is_branch_taken(insn)
                        if is_taken:
                            target = insn.operands[-1].split()[0]
                            reason = "[Reason: {:s}]".format(reason) if reason else ""
                            line += Color.colorify("\tTAKEN {:s}".format(reason), "bold green")
                        else:
                            reason = "[Reason: !({:s})]".format(reason) if reason else ""
                            line += Color.colorify("\tNOT taken {:s}".format(reason), "bold red")
                    elif unigdb.arch.CURRENT_ARCH.is_call(insn) and self.get_setting("peek_calls") is True:
                        target = insn.operands[-1].split()[0]
                    elif unigdb.arch.CURRENT_ARCH.is_ret(insn) and self.get_setting("peek_ret") is True:
                        target = int(unigdb.arch.CURRENT_ARCH.get_ra(insn))
                else:
                    line += "   {}".format(text)

                print("".join(line))
                if target:
                    try:
                        target = int(target, 0)
                    except TypeError:  # Already an int
                        pass
                    except ValueError:
                        # If the operand isn't an address right now we can't parse it
                        continue
                    for i, tinsn in enumerate(instruction_iterator(target, nb_insn)):
                        text = "   {}  {}".format(unigdb.config.DOWN_ARROW if i == 0 else " ", str(tinsn))
                        print(text)
                    break
        # except Exception as e:
            # message.error("Cannot disassemble from $PC: %s" % e)
        except Exception:
            import traceback
            print(traceback.format_exc())
        return None
コード例 #2
0
ファイル: registers.py プロジェクト: TinyMagicka/UniGDB
def print_registers(registers,
                    ignored_registers=[],
                    old_registers={},
                    flags=False):
    '''Print dereferenced registers

    Arguments:
        registers(list): List of printed registers
        ignored_registers(list): List of registers witch didn't printed
        old_registers(list): Old registers, needed for check if registers was changed
        flags(bool): Print flags

    Returns:
        A string representing pointers of each address and reference
        REG_NAME: 0x0804a10 —▸ 0x08061000 —▸ AAAA
    '''
    widest = max(map(len, registers))
    changed_color = unigdb.config.get("theme.registers_value_changed")
    regname_color = unigdb.config.get("theme.registers_register_name")
    line = ''
    # Print registers value
    for reg in registers:
        if reg in ignored_registers:
            continue

        try:
            r = unigdb.regs.get_register(reg)
            # if r.type.code == gdb.TYPE_CODE_VOID:
            #     continue
            new_value_type_flag = False
            new_value = int(r) if r >= 0 else unigdb.arch.ptrmask + int(r) + 1
        except Exception:
            # If this exception is triggered, it means that the current register
            # is corrupted. Just use the register "raw" value (not eval-ed)
            new_value = unigdb.regs.get_register(reg)
            new_value_type_flag = False
        except Exception:
            new_value = 0
            new_value_type_flag = False

        old_value = old_registers.get(reg, 0)
        padreg = reg.ljust(widest, " ")
        value = new_value
        if value == old_value:
            line += "{}: ".format(Color.colorify(padreg, regname_color))
        else:
            line += "{}: ".format(Color.colorify(padreg, changed_color))
        if new_value_type_flag:
            line += "{:s} ".format(str(value))
        else:
            line += unigdb.chain.format(value)
        print(line)
        line = ""
    # Print Flags
    if flags and unigdb.arch.CURRENT_ARCH.flags_table:
        print("Flags: {:s}".format(
            unigdb.arch.CURRENT_ARCH.flag_register_to_human()))
コード例 #3
0
ファイル: gdbu.py プロジェクト: TinyMagicka/UniGDB
def initial_message():
    msg = "{:s} for {:s} ready, type `{:s}' to start, `{:s}' to configure\n".format(
        Color.greenify("UniGDB"), get_os(),
        Color.colorify("self", "underline yellow"),
        Color.colorify("self config", "underline pink")
    )
    ver = "{:d}.{:d}".format(sys.version_info.major, sys.version_info.minor)
    nb_cmds = len(unigdb.commands.__commands__)
    msg += "{:s} commands loaded using Python engine {:s}".format(
        Color.colorify(nb_cmds, "bold green"),
        Color.colorify(ver, "bold red"))

    return msg
コード例 #4
0
    def show_legend(self):
        if unigdb.config.get("self.disable_colors") is not True:
            str_color = unigdb.config.get("theme.dereference_string")
            code_addr_color = unigdb.config.get("theme.address_code")
            stack_addr_color = unigdb.config.get("theme.address_stack")
            heap_addr_color = unigdb.config.get("theme.address_heap")
            changed_register_color = unigdb.config.get("theme.registers_value_changed")

            print("[ Legend: {} | {} | {} | {} | {} ]".format(
                Color.colorify("Modified register", changed_register_color),
                Color.colorify("Code", code_addr_color),
                Color.colorify("Heap", heap_addr_color),
                Color.colorify("Stack", stack_addr_color),
                Color.colorify("String", str_color)
            ))
        return None
コード例 #5
0
ファイル: self.py プロジェクト: TinyMagicka/UniGDB
    def invoke(self, args, from_tty):
        self.dont_repeat()
        if not os.access(unigdb.config.UNIGDB_RC, os.R_OK):
            return None

        quiet = args.lower() == "quiet"
        cfg = configparser.ConfigParser()
        cfg.read(unigdb.config.UNIGDB_RC)

        for section in cfg.sections():
            if section == "aliases":
                # load the aliases
                for key in cfg.options(section):
                    SelfAlias(key, cfg.get(section, key))
                continue

            # load the other options
            for optname in cfg.options(section):
                try:
                    key = "{:s}.{:s}".format(section, optname)
                    _value, _doc = unigdb.config.get(key, get_all=True)
                    new_value = cfg.get(section, optname)
                    if isinstance(_value, bool):
                        new_value = True if new_value == "True" else False
                    new_value = int(new_value) if new_value.isdigit(
                    ) or isinstance(_value, int) else new_value
                    unigdb.config.set(key, new_value, _doc)
                except Exception:
                    pass

        if not quiet:
            message.success("Configuration from '{:s}' restored".format(
                Color.colorify(unigdb.config.UNIGDB_RC, "bold blue")))
        return None
コード例 #6
0
def format(value, limit=LIMIT, code=True):
    """
    Recursively dereferences an address into string representation, or convert the list representation
    of address dereferences into string representation.

    Arguments:
        value(int|list): Either the starting address to be sent to get, or the result of get (a list)
        limit(int): Number of valid pointers
        code(bool): Hint that indicates the value may be an instruction
        offset(int): Offset into the address to get the next pointer
        hard_stop(int): Value to stop on
        hard_end: Value to append when hard_stop is reached: null, value of hard stop, a string.

    Returns:
        A string representing pointers of each address and reference
        Strings format: 0x0804a10 —▸ 0x08061000 ◂— 0x41414141
    """
    limit = int(limit)
    # Get config params
    base_address_color = unigdb.config.get("theme.dereference_base_address")
    string_color = unigdb.config.get("theme.dereference_string")
    config_arrow_right = unigdb.config.get("theme.chain_arrow_right")
    # Allow results from get function to be passed to format
    if isinstance(value, list):
        chain = value
    else:
        chain = examine_mem_value(value, limit)
    # Set arrow separate
    arrow_right = ' %s ' % config_arrow_right
    # Colorize the chain
    rest = []
    for link in chain:
        if isinstance(link, int):
            rest.append(Color.colorify('%#x' % link, base_address_color))
        if isinstance(link, str):
            rest.append(Color.colorify('"{:s}"'.format(link), string_color))
        # symbol = unigdb.symbol.get(link) or None
        # if symbol:
        #     symbol = '%#x (%s)' % (link, symbol)
        # rest.append(M.get(link, symbol))
    return arrow_right.join(rest)
コード例 #7
0
ファイル: self.py プロジェクト: TinyMagicka/UniGDB
    def load(self, initial=False):
        """Load all the commands and functions defined by UNIGDB into GDB."""
        nb_missing = 0
        self.commands = [(x._cmdline_, x)
                         for x in unigdb.commands.__commands__]

        # load all of the functions
        for function_class_name in unigdb.functions.__functions__:
            self.loaded_functions.append(function_class_name())

        def is_loaded(x):
            return any(filter(lambda u: x == u[0], self.loaded_commands))

        for cmd, class_name in self.commands:
            if is_loaded(cmd):
                continue

            try:
                self.loaded_commands.append((cmd, class_name, class_name()))

                if hasattr(class_name, "_aliases_"):
                    aliases = getattr(class_name, "_aliases_")
                    for alias in aliases:
                        SelfAlias(alias, cmd)

            except Exception as reason:
                self.missing_commands[cmd] = reason
                nb_missing += 1

        # sort by command name
        self.loaded_commands = sorted(self.loaded_commands,
                                      key=lambda x: x[1]._cmdline_)

        if initial:
            print(
                "{:s} for {:s} ready, type `{:s}' to start, `{:s}' to configure"
                .format(Color.greenify("UNIGDB"), get_os(),
                        Color.colorify("self", "underline yellow"),
                        Color.colorify("self config", "underline pink")))

            ver = "{:d}.{:d}".format(sys.version_info.major,
                                     sys.version_info.minor)
            nb_cmds = len(self.loaded_commands)
            print("{:s} commands loaded for GDB {:s} using Python engine {:s}".
                  format(Color.colorify(nb_cmds, "bold green"),
                         Color.colorify(gdb.VERSION, "bold yellow"),
                         Color.colorify(ver, "bold red")))

            if nb_missing:
                message.warn(
                    "{:s} command{} could not be loaded, run `{:s}` to know why."
                    .format(Color.colorify(nb_missing, "bold red"),
                            "s" if nb_missing > 1 else "",
                            Color.colorify("self missing", "underline pink")))
        return None
コード例 #8
0
    def do_theme(self, args: argparse.Namespace):
        if not args.key:
            for setting in sorted(self.settings):
                value = self.get_setting(setting)
                value = Color.colorify(value, value)
                print("{:40s}: {:s}".format(setting, value))
            return None

        setting = args.key
        if not self.has_setting(setting):
            message.error("Invalid key")
            return None

        if not args.value:
            value = self.get_setting(setting)
            value = Color.colorify(value, value)
            print("{:40s}: {:s}".format(setting, value))
            return None

        val = [x for x in args.value.split() if x in Color.colors]
        self.add_setting(setting, " ".join(val))
        return None
コード例 #9
0
ファイル: self.py プロジェクト: TinyMagicka/UniGDB
    def print_setting(self, plugin_name, verbose=False):
        res = unigdb.config.get(plugin_name, get_all=True)
        string_color = unigdb.config.get("theme.dereference_string")
        misc_color = unigdb.config.get("theme.dereference_base_address")

        if not res:
            return None

        _value, _desc = res
        _setting = Color.colorify(plugin_name, "green")
        _type = type(_value).__name__
        if isinstance(_value, str):
            _value = '"{:s}"'.format(Color.colorify(_value, string_color))
        else:
            _value = Color.colorify(_value, misc_color)

        print("{:s} ({:s}) = {:s}".format(_setting, _type, _value))

        if verbose:
            print(Color.colorify("\nDescription:", "bold underline"))
            print("\t{:s}".format(_desc))
        return None
コード例 #10
0
    def context_title(self, m):
        line_color = unigdb.config.get("theme.context_title_line")
        msg_color = unigdb.config.get("theme.context_title_message")

        if not m:
            print(Color.colorify(unigdb.config.HORIZONTAL_LINE * self.tty_columns, line_color))
            return None

        trail_len = len(m) + 6
        title = ""
        title += Color.colorify(
            "{:{padd}<{width}} ".format(
                "",
                width=max(self.tty_columns - trail_len, 0),
                padd=unigdb.config.HORIZONTAL_LINE
            ),
            line_color
        )
        title += Color.colorify(m, msg_color)
        title += Color.colorify(" {:{padd}<4}".format("", padd=unigdb.config.HORIZONTAL_LINE),
                                line_color)
        print(title)
        return None
コード例 #11
0
ファイル: self.py プロジェクト: TinyMagicka/UniGDB
 def __load_extra_plugins(self):
     nb_added = -1
     try:
         nb_inital = len(self.loaded_commands)
         directories = unigdb.config.get("self.extra_plugins_dir")
         if directories:
             for directory in directories.split(";"):
                 directory = os.path.realpath(os.path.expanduser(directory))
                 if os.path.isdir(directory):
                     sys.path.append(directory)
                     for fname in os.listdir(directory):
                         if not fname.endswith(".py"):
                             continue
                         fpath = "{:s}/{:s}".format(directory, fname)
                         if os.path.isfile(fpath):
                             gdb.execute("source {:s}".format(fpath))
         nb_added = len(self.loaded_commands) - nb_inital
         if nb_added > 0:
             message.success("{:s} extra commands added from '{:s}'".format(
                 Color.colorify(nb_added, "bold green"),
                 Color.colorify(directory, "bold blue")))
     except gdb.error as e:
         message.error("failed: {}".format(str(e)))
     return nb_added
コード例 #12
0
    def print_guessed_arguments(self, function_name):
        """When no symbol, read the current basic block and look for "interesting" instructions."""

        def __get_current_block_start_address():
            pc = int(unigdb.arch.CURRENT_ARCH.pc)
            try:
                block_start = gdb.block_for_pc(pc).start
            except RuntimeError:
                # if stripped, let's roll back 5 instructions
                block_start = disass.gdb_get_nth_previous_instruction_address(pc, 5)
            return block_start

        parameter_set = set()
        pc = int(unigdb.arch.CURRENT_ARCH.pc)
        block_start = __get_current_block_start_address()
        instruction_iterator = disass.capstone_disassemble
        function_parameters = unigdb.arch.CURRENT_ARCH.function_parameters
        arg_key_color = unigdb.config.get("theme.registers_register_name")

        insn_count = (pc - block_start) // unigdb.arch.CURRENT_ARCH.instruction_length
        if unigdb.arch.current == 'mips':
            insn_count += 1  # for branch delay slot
        for insn in instruction_iterator(block_start, insn_count):
            if not insn.operands:
                continue
            if unigdb.arch.current == 'i386':
                if insn.mnemonic == "push":
                    parameter_set.add(insn.operands[0])
            else:
                op = "$" + insn.operands[0]
                if op in function_parameters:
                    parameter_set.add(op)
                if unigdb.arch.current == 'x86-64':
                    # also consider extended registers
                    extended_registers = {"$rdi": ["$edi", "$di"],
                                          "$rsi": ["$esi", "$si"],
                                          "$rdx": ["$edx", "$dx"],
                                          "$rcx": ["$ecx", "$cx"],
                                          }
                    for exreg in extended_registers:
                        if op in extended_registers[exreg]:
                            parameter_set.add(exreg)
        # cicle end
        if unigdb.arch.current == 'i386':
            nb_argument = len(parameter_set)
        else:
            nb_argument = 0
            for p in parameter_set:
                nb_argument = max(nb_argument, function_parameters.index(p) + 1)

        args = []
        for i in range(nb_argument):
            _key, _value = unigdb.arch.CURRENT_ARCH.get_ith_parameter(i)
            _value = unigdb.chain.format(int(_value))
            args.append("{} = {}".format(Color.colorify(_key, arg_key_color), _value))

        self.context_title("arguments (guessed)")
        print("{} (".format(function_name))
        if args:
            print("   " + ",\n   ".join(args))
        print(")")
        return None
コード例 #13
0
ファイル: regs.py プロジェクト: TinyMagicka/UniGDB
 def flag_register_to_human(self, val=None):
     return Color.colorify("No flag register", "yellow underline")