Пример #1
0
def op_syscall(process):

    state = process.syscall_state
    syscall = state.event(FunctionCallOptions())

    words = get_words()

    if syscall.name == 'write':
        co = re.sub(r'(\\x.*?m)', '', syscall.format())
        matched = re.match(r".*\,(.*)\,.*", co)

        if matched:
            cleanup = re.sub(r'(\\r|\'|\\n)+', '', matched.group(1))

            if cleanup:
                splitted = cleanup.split(" ")
                for word in words:
                    for captured in splitted:
                        if captured.startswith(word):
                            v = virtkey.virtkey()

                            for key in word:
                                key_value = gtk.gdk.keyval_from_name(key)
                                v.press_unicode(key_value)
                                v.release_unicode(key_value)

                            v.press_keysym(enter_key)
                            v.release_keysym(enter_key)
    process.syscall()
Пример #2
0
    def __init__(self,
                 manager,
                 pid,
                 record,
                 old_debugger=None,
                 is_thread=False):
        """
        Create a new tracing thread
        :param manager: overall tracing management instance
        :param pid: Process to trace
        :param record: Action recording instance
        :param old_debugger: Old debugger the process might be attached to at the moment
        :param is_thread: True if the pid is a thread else False
        """
        super().__init__()
        self.manager = manager

        # Save tracing record
        self.record = record
        self.record.runtime_log(RuntimeActionRecord.TYPE_STARTED)
        self._debugger_options = FunctionCallOptions(replace_socketcall=False)

        self.is_thread = is_thread
        self.process = psutil.Process(pid)
        self.debugger = None
        self.traced_item = None
        self.stopped = False

        # Check if the process is attached to the debugger
        if old_debugger is not None and old_debugger.dict.get(
                self.process.pid):
            old_debugger.dict.get(self.process.pid).detach()
            posix.kill(self.process.pid, signal.SIGSTOP)
Пример #3
0
def watch_syscalls(dbg):
    syscall_options = FunctionCallOptions(
        write_types=False,
        write_argname=True,
        string_max_length=300,
        replace_socketcall=True,
        write_address=False,
        max_array_count=20,
    )
    syscall_options.instr_pointer = False

    # tell all processes to break at the next syscall
    for process in dbg:
        prepare_process(process)
        process.syscall()

    while True:
        if not dbg:
            break

        # wait for next syscall event
        try:
            event = dbg.waitSyscall()
        except ProcessExit as event:
            handle_exit(event)
            continue
        except ProcessSignal as event:
            handle_signal(event)
            continue
        except NewProcessEvent as event:
            handle_new_process(event)
            continue
        except ProcessExecution as event:
            handle_exec(event)
            continue

        # process syscall enter or exit
        handle_syscall(event, syscall_options)
Пример #4
0
    def __init__(self, args: LaunchArguments, pollobj: PaulaPoll):
        self.pollobj = pollobj  # PollObj used by the input monitor, needed to register new processes
        self.syscalls_to_trace = []

        self.processList = []
        self.debugger = self.startDebugger(args)
        self.currentProcess = self.processList[0]

        self.syscall_options = FunctionCallOptions(
            write_types=True,
            write_argname=True,
            write_address=True,
        )

        self.named_processes = BiDict()
Пример #5
0
    def runDebugger(self):
        # Create debugger and traced process
        self.setupDebugger()
        process = self.createProcess()
        if not process:
            return

        self.syscall_options = FunctionCallOptions(
            write_types=True,
            write_argname=True,
            replace_socketcall=False,
            string_max_length=300,
            write_address=False,
            max_array_count=20,
        )
        self.syscall_options.instr_pointer = self.options.show_ip
        self.syscallTrace(process)
Пример #6
0
    def runDebugger(self):
        # Create debugger and traced process
        self.setupDebugger()
        process = self.createProcess()
        if not process:
            return

        self.syscall_options = FunctionCallOptions(
            write_types=self.options.type,
            write_argname=self.options.name,
            string_max_length=self.options.string_length,
            replace_socketcall=not self.options.raw_socketcall,
            write_address=self.options.address,
            max_array_count=self.options.array_count,
        )
        self.syscall_options.instr_pointer = self.options.show_ip

        return self.syscallTrace(process)
Пример #7
0
    def __init__(self):
        Application.__init__(self)

        # Parse self.options
        self.parseOptions()

        # Setup output (log)
        self.setupLog()

        self.last_signal = {}

        # We assume user wants all possible information
        self.syscall_options = FunctionCallOptions(
            write_types=True,
            write_argname=True,
            write_address=True,
        )

        # FIXME: Remove self.breaks!
        self.breaks = dict()

        self.followterms = []
Пример #8
0
def parse_argument(argument):
    argument = argument.createText()
    if argument.startswith(("'", '"')):
        # Remove quotes from string argument
        return argument[1:-1]
    elif argument.startswith(("b'", 'b"')):
        # Python 3 bytes literal
        return argument[2:-1]
    else:
        # Note that "int" with base 0 infers the base from the prefix
        return int(argument, 0)


format_options = FunctionCallOptions(
    replace_socketcall=False,
    string_max_length=4096,
)


def get_operations(debugger, syscall_filters, verbose):
    operations = []

    while True:
        if not debugger:
            # All processes have exited
            break

        # This logic is mostly based on python-ptrace's "strace" example
        try:
            syscall_event = debugger.waitSyscall()
        except ProcessSignal as event:
Пример #9
0
def debug_process(debugger, syscall_filters):
    format_options = FunctionCallOptions(
        replace_socketcall=False,
        string_max_length=4096,
    )

    processes = {}
    operations = []
    exit_code = 0
    snapshots = Snapshots()

    while True:
        if not debugger:
            # All processes have exited
            break

        # This logic is mostly based on python-ptrace's "strace" example
        try:
            syscall_event = debugger.waitSyscall()
        except ProcessSignal as event:
            event.process.syscall(event.signum)
            continue
        except NewProcessEvent as event:
            event.process.syscall()
            event.process.parent.syscall()
            continue
        except ProcessExecution as event:
            event.process.syscall()
            continue
        except ProcessExit as event:
            exit_code = event.exitcode
            continue

        process = syscall_event.process
        syscall_state = process.syscall_state

        syscall = syscall_state.event(format_options)

        if syscall and syscall_state.next_event == "exit":
            # Syscall is about to be executed (just switched from "enter" to "exit")
            # print(syscall.format())
            if syscall.name in syscall_filters:

                filter_function = syscall_filters[syscall.name]
                if process.pid not in processes:
                    processes[process.pid] = Process(process)
                arguments = [
                    parse_argument(argument) for argument in syscall.arguments
                ]

                name, paths, return_value = filter_function(
                    processes[process.pid], arguments)

                if name is not None:
                    operations.append(name)
                    for path in paths:
                        snapshots.snapshot_path(path)

        process.syscall()

    return snapshots, exit_code
Пример #10
0
    def start(self):
        # First query to break at next syscall
        self.root.syscall()

        while not self.stop_requested and self.debugger:
            try:
                try:
                    # FIXME: better mechanism to stop debugger
                    # debugger._waitPid(..., blocking=False) may help
                    # actually debugger receives SIGTERM, terminates all remaining process
                    # then this method is unblocked and fails with KeyError
                    event = self.debugger.waitSyscall()
                except:
                    if self.stop_requested:
                        return
                    raise
                state = event.process.syscall_state
                syscall = state.event(FunctionCallOptions())

                self.syscalls[event.process.pid] = syscall

                yield SyscallEvent(event.process.pid, syscall.name)

                # FIXME:
                # when exit_group is called, it seems that thread is still monitored
                # in next event we area accessing pid that is not running anymore
                # so when exit_group occurs, remove all processes with same Tgid and detach from them
                if syscall.name == 'exit_group':  # result is None, never return!

                    def read_group(pid):
                        with open('/proc/%d/status' % pid) as f:
                            return int({
                                i: j.strip()
                                for i, j in [
                                    i.split(':', 1)
                                    for i in f.read().splitlines()
                                ]
                            }['Tgid'])

                    me = read_group(syscall.process.pid)
                    for process in self.debugger:
                        if read_group(process.pid) == me:
                            process.detach()
                            self.debugger.deleteProcess(pid=process.pid)
                            yield ProcessExited(process.pid,
                                                syscall.arguments[0].value)

                else:
                    event.process.syscall()
            except ProcessExit as event:
                # Display syscall which has not exited
                state = event.process.syscall_state
                if (state.next_event == "exit") and state.syscall:
                    # self.syscall(state.process) TODO:
                    pass

                yield ProcessExited(event.process.pid, event.exitcode)
            except ProcessSignal as event:
                #                event.display()
                event.process.syscall(event.signum)
            except NewProcessEvent as event:
                process = event.process
                logging.info("*** New process %s ***", process.pid)

                yield ProcessCreated(pid=process.pid,
                                     parent_pid=process.parent.pid,
                                     is_thread=process.is_thread)

                process.syscall()
                process.parent.syscall()
            except ProcessExecution as event:
                logging.info("*** Process %s execution ***", event.process.pid)
                event.process.syscall()
            except DebuggerError:
                if self.stop_requested:
                    return
                raise
            except PtraceError as e:
                if e.errno == 3:  # FIXME: same problem as exit_group above ?
                    logging.warning("Process dead?")
                else:
                    raise
Пример #11
0
    def __init__(self,
                 args=None,
                 debugger=None,
                 redirect=False,
                 parent=None,
                 ptraceprocess=None):

        self.syscall_options = FunctionCallOptions(
            write_types=True,
            write_argname=True,
            write_address=True,
        )
        self.stdinRequested = False
        self.remember_insert_bp = False
        self.atBreakpoint = False
        self.inserted_function_data = False
        self.parent = None
        self.children = []
        self.is_terminated = False
        self.syscalls_to_trace = parent.syscalls_to_trace if parent else None  # first will be set by ProcessManager
        self.own_segment = None

        if args:
            assert debugger is not None
            assert not parent

            self.disable_randomization = not args.random

            # create three pseudo terminals
            self.in_pipe = Pipe()
            self.out_pipe = Pipe()
            self.err_pipe = Pipe()

            self.stdin_buf = b""
            self.stdout_buf = b""
            self.stderr_buf = b""

            # if we want to redirect, tell the subprocess to write to our pipe, else it will print to normal stdout
            if redirect:
                stdout_arg = self.out_pipe.writeobj
                stderr_arg = self.err_pipe.writeobj
            else:
                stdout_arg = None
                stderr_arg = None

            args = [path_launcher] + args.argvlist
            self.popen_obj = Popen(args,
                                   stdin=self.in_pipe.readobj,
                                   stdout=stdout_arg,
                                   stderr=stderr_arg)

            self.debugger = debugger
            self.ptraceProcess = self.setupPtraceProcess(
            )  # launches actual program, halts immediately

            self.heap = None

            self.programinfo = ProgramInfo(args[1], self.getPid(), self)

            self.get_own_segment()  # setup own mmap page

        # this is used when a process is forked by user
        else:
            assert isinstance(parent, ProcessWrapper) and isinstance(
                ptraceprocess, PtraceProcess)
            self.parent = parent
            self.in_pipe = parent.in_pipe  # TODO
            self.out_pipe = parent.out_pipe
            self.err_pipe = parent.err_pipe

            self.stdin_buf = parent.stdin_buf
            self.stdout_buf = parent.stdout_buf
            self.stderr_buf = parent.stderr_buf

            self.debugger = parent.debugger
            self.ptraceProcess = ptraceprocess
            self._copyBreakpoints()

            self.remember_insert_bp = parent.remember_insert_bp

            self.heap = None
            self.own_segment = parent.own_segment

            # if the process spawns new children for other purposes, it might load another library.
            # the loaded path could be determined TODO
            if LOAD_PROGRAMINFO:  # can be disabled in Constants to improve performance
                try:
                    self.programinfo = ProgramInfo(
                        parent.programinfo.path_to_hack,
                        self.ptraceProcess.pid, self)
                except ValueError as e:  # if another library is loaded instead of our initial executable
                    self.programinfo = ProgramInfo(None,
                                                   self.ptraceProcess.pid,
                                                   self)
Пример #12
0
def get_operations(debugger, syscall_filters, verbose):
    format_options = FunctionCallOptions(
        replace_socketcall=False,
        string_max_length=4096,
    )

    processes = {}
    operations = []

    while True:
        if not debugger:
            # All processes have exited
            break

        # This logic is mostly based on python-ptrace's "strace" example
        try:
            syscall_event = debugger.waitSyscall()
        except ProcessSignal as event:
            event.process.syscall(event.signum)
            continue
        except NewProcessEvent as event:
            event.process.syscall()
            event.process.parent.syscall()
            continue
        except ProcessExecution as event:
            event.process.syscall()
            continue
        except ProcessExit as event:
            continue

        process = syscall_event.process
        syscall_state = process.syscall_state

        syscall = syscall_state.event(format_options)

        if syscall and syscall_state.next_event == "exit":
            # Syscall is about to be executed (just switched from "enter" to "exit")
            if syscall.name in syscall_filters:
                if verbose == 1:
                    print(syscall.format())
                elif verbose == 2:
                    print(T.bold(syscall.format()))

                filter_function = syscall_filters[syscall.name]
                if process.pid not in processes:
                    processes[process.pid] = Process(process)
                arguments = [parse_argument(argument) for argument in syscall.arguments]

                operation, return_value = filter_function(processes[process.pid], arguments)

                if operation is not None:
                    operations.append(operation)

                if return_value is not None:
                    # Set invalid syscall number to prevent call execution
                    process.setreg(SYSCALL_REGISTER, -1)
                    # Substitute return value to make syscall appear to have succeeded
                    process.setreg(RETURN_VALUE_REGISTER, return_value)

            elif verbose == 2:
                print(syscall.format())

        process.syscall()

    return operations