Example #1
0
    def context_title(self, m):
        line_color = pwngef.config.get("theme.context_title_line")
        msg_color = pwngef.config.get("theme.context_title_message")

        if not m:
            print(
                Color.colorify(
                    pwngef.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=pwngef.config.HORIZONTAL_LINE),
            line_color)
        title += Color.colorify(m, msg_color)
        title += Color.colorify(
            " {:{padd}<4}".format("", padd=pwngef.config.HORIZONTAL_LINE),
            line_color)
        print(title)
        return None
Example #2
0
    def do_invoke(self, args):
        self.dont_repeat()
        argc = len(args)

        if argc == 0:
            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[0]
        if not self.has_setting(setting):
            message.error("Invalid key")
            return None

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

        val = [x for x in args[1:] if x in Color.colors]
        self.add_setting(setting, " ".join(val))
        return None
Example #3
0
 def flags_as_string(self):
     flags = []
     if self.has_p_bit():
         flags.append(Color.colorify("PREV_INUSE", "red bold"))
     if self.has_m_bit():
         flags.append(Color.colorify("IS_MMAPPED", "red bold"))
     if self.has_n_bit():
         flags.append(Color.colorify("NON_MAIN_ARENA", "red bold"))
     return "|".join(flags)
Example #4
0
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 = pwngef.config.get("theme.registers_value_changed")
    regname_color = pwngef.config.get("theme.registers_register_name")
    line = ''
    # Print registers value
    for reg in registers:
        if reg in ignored_registers:
            continue

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

        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 += pwngef.chain.format(value)
        print(line)
        line = ""
    # Print Flags
    if flags and pwngef.arch.CURRENT_ARCH.flags_table:
        print("Flags: {:s}".format(
            pwngef.arch.CURRENT_ARCH.flag_register_to_human()))
Example #5
0
    def context_threads(self):
        def reason():
            res = gdb.execute("info program", to_string=True).splitlines()
            if not res:
                return "NOT RUNNING"

            for line in res:
                line = line.strip()
                if line.startswith("It stopped with signal "):
                    return line.replace("It stopped with signal ",
                                        "").split(",", 1)[0]
                if line == "The program being debugged is not being run.":
                    return "NOT RUNNING"
                if line == "It stopped at a breakpoint that has since been deleted.":
                    return "TEMPORARY BREAKPOINT"
                if line.startswith("It stopped at breakpoint "):
                    return "BREAKPOINT"
                if line == "It stopped after being stepped.":
                    return "SINGLE STEP"

            return "STOPPED"

        self.context_title("threads")

        threads = gdb.selected_inferior().threads()[::-1]
        idx = self.get_setting("nb_lines_threads")
        if idx > 0:
            threads = threads[0:idx]

        if idx == 0:
            return None

        if not threads:
            message.error("No thread selected")
            return None

        for i, thread in enumerate(threads):
            line = """[{:s}] Id {:d}, Name: "{:s}", """.format(
                Color.colorify("#{:d}".format(i), "bold pink"), thread.num,
                thread.name or "")
            if thread.is_running():
                line += Color.colorify("running", "bold green")
            elif thread.is_stopped():
                line += Color.colorify("stopped", "bold red")
                line += ", reason: {}".format(
                    Color.colorify(reason(), "bold pink"))
            elif thread.is_exited():
                line += Color.colorify("exited", "bold yellow")
            print(line)
            i += 1
        return None
Example #6
0
    def show_legend(self):
        if pwngef.config.get("self.disable_colors") is not True:
            str_color = pwngef.config.get("theme.dereference_string")
            code_addr_color = pwngef.config.get("theme.address_code")
            stack_addr_color = pwngef.config.get("theme.address_stack")
            heap_addr_color = pwngef.config.get("theme.address_heap")
            changed_register_color = pwngef.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
Example #7
0
    def invoke(self, args, from_tty):
        self.dont_repeat()
        if not os.access(pwngef.config.PWNGEF_RC, os.R_OK):
            return None

        quiet = args.lower() == "quiet"
        cfg = configparser.ConfigParser()
        cfg.read(pwngef.config.PWNGEF_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 = pwngef.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
                    pwngef.config.set(key, new_value, _doc)
                except Exception:
                    pass

        if not quiet:
            message.success("Configuration from '{:s}' restored".format(
                Color.colorify(pwngef.config.PWNGEF_RC, "bold blue")))
        return None
Example #8
0
    def context_source(self):
        try:
            pc = pwngef.arch.CURRENT_ARCH.pc
            symtabline = gdb.find_pc_line(pc)
            symtab = symtabline.symtab
            line_num = symtabline.line - 1  # we substract one because line number returned by gdb start at 1
            if not symtab.is_valid():
                return None

            fpath = symtab.fullname()
            with open(fpath, "r") as f:
                lines = [l.rstrip() for l in f.readlines()]

        except Exception:
            return None

        nb_line = self.get_setting("nb_lines_code")
        fn = symtab.filename
        if len(fn) > 20:
            fn = "{}[...]{}".format(fn[:15], os.path.splitext(fn)[1])
        title = "source:{}+{}".format(fn, line_num + 1)
        cur_line_color = pwngef.config.get("theme.source_current_line")
        self.context_title(title)

        for i in range(line_num - nb_line + 1, line_num + nb_line):
            if i < 0:
                continue

            if i < line_num:
                print(
                    Color.grayify("   {:4d}\t {:s}".format(
                        i + 1,
                        lines[i],
                    )))

            if i == line_num:
                extra_info = self.get_pc_context_info(pc, lines[i])
                prefix = "{}{:4d}\t ".format(config_arrow_right, i + 1)
                leading = len(lines[i]) - len(lines[i].lstrip())
                if extra_info:
                    print("{}{}".format(" " * (len(prefix) + leading),
                                        extra_info))
                print(
                    Color.colorify("{}{:s}".format(prefix, lines[i]),
                                   cur_line_color))

            if i > line_num:
                try:
                    print("   {:4d}\t {:s}".format(
                        i + 1,
                        lines[i],
                    ))
                except IndexError:
                    break
        return None
Example #9
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 = pwngef.config.get("theme.dereference_base_address")
    string_color = pwngef.config.get("theme.dereference_string")
    config_arrow_right = pwngef.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 = pwngef.symbol.get(link) or None
        # if symbol:
        #     symbol = '%#x (%s)' % (link, symbol)
        # rest.append(M.get(link, symbol))
    return arrow_right.join(rest)
Example #10
0
    def context_trace(self):
        self.context_title("trace")

        nb_backtrace = self.get_setting("nb_lines_backtrace")
        if nb_backtrace <= 0:
            return None
        orig_frame = current_frame = gdb.selected_frame()
        i = 0

        # backward compat for gdb (gdb < 7.10)
        if not hasattr(gdb, "FrameDecorator"):
            gdb.execute("backtrace {:d}".format(nb_backtrace))
            return None

        while current_frame:
            current_frame.select()
            if not current_frame.is_valid():
                continue

            pc = current_frame.pc()
            name = current_frame.name()
            items = []
            items.append("{:#x}".format(pc))
            if name:
                frame_args = gdb.FrameDecorator.FrameDecorator(
                    current_frame).frame_args() or []
                m = "{}({})".format(
                    Color.greenify(name), ", ".join([
                        "{}={!s}".format(Color.yellowify(x.sym),
                                         x.sym.value(current_frame))
                        for x in frame_args
                    ]))
                items.append(m)
            else:
                try:
                    insn = next(disass.gef_disassemble(pc, 1))
                except gdb.MemoryError:
                    break
                items.append(
                    Color.redify("{} {}".format(insn.mnemonic,
                                                ", ".join(insn.operands))))

            print("[{}] {}".format(
                Color.colorify("#{}".format(i), "bold pink"),
                config_arrow_right.join(items)))
            current_frame = current_frame.older()
            i += 1
            nb_backtrace -= 1
            if nb_backtrace == 0:
                break

        orig_frame.select()
        return None
Example #11
0
    def load(self, initial=False):
        """Load all the commands and functions defined by PWNGEF into GDB."""
        nb_missing = 0
        self.commands = [(x._cmdline_, x)
                         for x in pwngef.commands.__commands__]

        # load all of the functions
        for function_class_name in pwngef.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("PWNGEF"), 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
Example #12
0
    def print_setting(self, plugin_name, verbose=False):
        res = pwngef.config.get(plugin_name, get_all=True)
        string_color = pwngef.config.get("theme.dereference_string")
        misc_color = pwngef.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
Example #13
0
 def __load_extra_plugins(self):
     nb_added = -1
     try:
         nb_inital = len(self.loaded_commands)
         directories = pwngef.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
Example #14
0
    def context_code(self):
        nb_insn = self.get_setting("nb_lines_code")
        nb_insn_prev = self.get_setting("nb_lines_code_prev")
        use_capstone = self.has_setting("use_capstone") and self.get_setting(
            "use_capstone")
        use_ida = self.get_setting("use_ida")
        cur_insn_color = pwngef.config.get(
            "theme.disassemble_current_instruction")
        pc = int(pwngef.arch.CURRENT_ARCH.pc)

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

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

        try:
            instruction_iterator = disass.capstone_disassemble if use_capstone else disass.gef_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 pwngef.arch.CURRENT_ARCH.is_conditional_branch(insn):
                        is_taken, reason = pwngef.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 pwngef.arch.CURRENT_ARCH.is_call(
                            insn) and self.get_setting("peek_calls") is True:
                        target = insn.operands[-1].split()[0]
                    elif pwngef.arch.CURRENT_ARCH.is_ret(
                            insn) and self.get_setting("peek_ret") is True:
                        target = int(
                            pwngef.arch.CURRENT_ARCH.get_ra(insn, frame))
                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(
                            pwngef.config.DOWN_ARROW if i == 0 else " ",
                            str(tinsn))
                        print(text)
                    break
        except gdb.MemoryError:
            message.error("Cannot disassemble from $PC")
        except Exception:
            import traceback
            print(traceback.format_exc())
        return None
Example #15
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(pwngef.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(pwngef.arch.CURRENT_ARCH.pc)
        block_start = __get_current_block_start_address()
        use_capstone = self.has_setting("use_capstone") and self.get_setting(
            "use_capstone")
        instruction_iterator = disass.capstone_disassemble if use_capstone else disass.gef_disassemble
        function_parameters = pwngef.arch.CURRENT_ARCH.function_parameters
        arg_key_color = pwngef.config.get("theme.registers_register_name")

        insn_count = (
            pc - block_start) // pwngef.arch.CURRENT_ARCH.instruction_length
        if pwngef.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 pwngef.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 pwngef.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 pwngef.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 = pwngef.arch.CURRENT_ARCH.get_ith_parameter(i)
            _value = pwngef.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
Example #16
0
 def flag_register_to_human(self, val=None):
     return Color.colorify("No flag register", "yellow underline")
Example #17
0
 def __str__(self):
     msg = "{:s}(addr={:#x}, size={:#x}, flags={:s})".format(
         Color.colorify("Chunk", "yellow bold underline"),
         int(self.address), self.get_chunk_size(), self.flags_as_string())
     return msg