Example #1
0
    def write(self, gdbmi_cmd):
        """
        Place gdbmi_cmd string in the output queue.

        Args:
            gdbmi_cmd: gdbmi command string.

        Returns:
            Associated gdbmi response message.
        """

        # Build command
        gdbmi_cmd = '{}{}'.format(self._token, gdbmi_cmd)
        self._out_q.put(gdbmi_cmd)

        # Wait for response
        while True:

            if not self._in_q.empty():
                resp = self._in_q.get()

                # Get PID
                if self.pid is None and \
                   resp['payload'] is not None and \
                   'pid' in resp['payload']:

                    # Set PID
                    self.pid = resp['payload']['pid']

                    # Debug
                    utils.dprint('[+] Process PID "{}"'.format(self.pid), self._verbose)

                # Console message
                if resp['type'] == 'console':
                    self.console.append(resp)
                    self._in_q.task_done()
                    continue

                # Stopped message
                elif resp['message'] == 'stopped':
                    self._stopped.append(resp)

                # Response message
                elif resp['message'] is not None and \
                     resp['token'] is not None and \
                     resp['token'] == self._token:
                    self._token += 1
                    self._in_q.task_done()

                    return resp

                # Release lock
                self._in_q.task_done()
Example #2
0
    def vmmap(self):
        """
        Downloads and parses the inferior memory maps file.

        Returns:
            A parsed Linux maps file in list/dictionary format.
        """

        # Get maps file
        maps_file = self.get_file('/proc/{}/maps'.format(self.pid), 'maps')

        # Debug
        utils.dprint('[+] Downloaded maps file "{}"'.format(maps_file), self._verbose)
        self._segments = utils.parse_map(maps_file)

        return self._segments
Example #3
0
    def run(self):
        """
        Main thread.
        """

        # Main listener loop
        while True:

            # Read from gdb
            resp = self._communicator.get_gdb_response(
                timeout_sec=0, raise_error_on_timeout=False)

            # Write to out queue
            if len(resp) > 0:
                for msg in resp:

                    # Debug
                    utils.dprint('[+] Read response', self._verbose)
                    utils.dprint(msg, self._verbose)

                    self._in_q.put(msg)

            # Out message to process
            if not self._out_q.empty():

                # Get out message
                out_msg = self._out_q.get()

                # Check for kill command
                if out_msg != 'die':

                    # Debug
                    utils.dprint('[+] Dispatched command "{}"'.format(out_msg),
                                 self._verbose)

                    # Write to gdb
                    self._communicator.write(out_msg, read_response=False)
                    self._out_q.task_done()

                # Kill thread
                else:

                    # Kill gdb
                    self._communicator.write('-gdb-exit', read_response=False)

                    # Debug
                    utils.dprint('[+] Killing thread', self._verbose)
                    return
Example #4
0
    def wait(self, reason):
        """
        Block until a stop event with specified reason is detected.

        Args:
            reason: Reason the debugger stopped.

        Returns:
            Message from the gdb stop event.
        """

        # Stop event already found
        if len(self._stopped) != 0:
            utils.dprint('[+] Event already stopped', self._verbose)

            for resp in self._stopped:
                if resp['message'] == 'stopped' and \
                   'reason' in resp['payload'] and \
                   resp['payload']['reason'] == reason:

                    return resp

        # Read in_q
        while True:

            if not self._in_q.empty():

                resp = self._in_q.get()

                if resp['message'] == 'stopped' and \
                   'reason' in resp['payload'] and \
                   resp['payload']['reason'] == reason:

                    self._in_q.task_done()
                    return resp

                self._in_q.task_done()
Example #5
0
def main(duzzle=DuzzleContext()):
    """
    Main function for duzzle.

    Args:
        duzzle: Duzzle context object.

    Returns:
        True if execution completes expectedly.
    """

    # Build parser
    parser = argparse.ArgumentParser(description= 'Remote process dumping' \
                                                  'utility for fuzzle')
    parser.add_argument('address', help='GDBServer IPv4 address')
    parser.add_argument('port', type=int, help='GDBServer TCP port')
    parser.add_argument('--arch',
                        '-a',
                        required=True,
                        help='Target architecture [x86_64]')
    parser.add_argument('--breakpoint',
                        '-b',
                        required=True,
                        help='Location to insert break')
    parser.add_argument('--out-file',
                        '-o',
                        required=True,
                        help='Output file path to write packed UZL file')
    parser.add_argument('--follow-child',
                        '-f',
                        action='store_true',
                        help='Follow child processes')
    parser.add_argument('--verbose',
                        '-v',
                        action='store_true',
                        help='Enable verbosity')
    parser.add_argument('--version', action='version', version='0.0.9')
    args = parser.parse_args()

    # Clean up args
    address = args.address
    port = args.port
    out_file = args.out_file
    follow_child = args.follow_child
    verbose = args.verbose

    # Import target architecture
    arch = importlib.import_module('fuzzle.duzzle.archs.{}'.format(args.arch))

    # Set context architecture
    duzzle.set_arch(arch)

    # Extract breakpoint
    breakpoint = ''
    if re.search(r'^0x[0-9a-fA-F]*$', args.breakpoint):
        breakpoint = '*{}'.format(args.breakpoint)
    else:
        breakpoint = args.breakpoint

    # Debug
    dprint('[+] Verbosity enabled', verbose)
    if verbose:
        duzzle.set_verbose()

    # Initialise context
    duzzle.init()

    # Connect to remote gdb instance
    duzzle.connect(address=address, port=port)
    print('[*] Process PID "{}"'.format(duzzle.pid))

    # Set breakpoint
    duzzle.breakpoint(breakpoint)

    # Follow child processes
    if follow_child:
        duzzle.follow_child()

    # Continue execution
    duzzle.run()

    # Wait for break point
    duzzle.wait(duzzle.BREAKPOINT)

    # Dump memory segments
    mem_segments = []
    for segment in duzzle.vmmap():

        if (segment['perms'] & pypzl.READ) != 0 and \
           segment['name'] not in duzzle.kernel_segments:

            try:
                file_path = duzzle.dump_segment(segment)
                mem_segments.append({
                    'start': segment['start'],
                    'end': segment['end'],
                    'perms': segment['perms'],
                    'name': segment['name'],
                    'data': file_path
                })

                # Debug
                print('[*] Dumped {} to {} - {}'.format(
                    segment['start'], segment['end'], segment['name']))

            except Exception:
                print('[*] Cannot dump {}'.format(segment['start']))

    # Dump user registers
    user_regs = duzzle.dump_registers()
    print('[*] Dumped user registers')

    # Shutdown
    duzzle.shutdown()

    # Pack
    ctx = pypzl.PuzzleContext(arch.ARCH)

    # Add memory segments
    for segment in mem_segments:

        # Debug
        print('[*] Packing "{}"'.format(segment['data']))

        # Add memory record
        ctx.add_mem_rec(int(segment['start'], 16),
                        int(segment['end'], 16),
                        segment['perms'],
                        read_file_bytes(segment['data']),
                        None if not segment['name'] else \
                        str.encode(segment['name']))

    # Add user registers
    ctx.add_reg_rec(arch.pack(user_regs))

    # Pack data
    pack_data = ctx.pack()

    # Write to file
    with open(out_file, 'wb') as file:
        file.write(pack_data)

    # Clean up

    ctx.free()

    return True