Exemple #1
0
def execute(cmd_tokens, syscall_filters):
    with open(HISTORY_PATH, 'a') as history_file:
        history_file.write(' '.join(cmd_tokens) + os.linesep)

    if cmd_tokens:
        # Extract command name and arguments from tokens
        cmd_name = cmd_tokens[0]
        cmd_args = cmd_tokens[1:]

        DIRFD_ARGUMENTS.clear()
        SYSCALL_ARG_DICT.clear()
        ARGUMENT_CALLBACK.clear()
        # If the command is a built-in command,
        # invoke its function with arguments
        if cmd_name in built_in_cmds:
            return built_in_cmds[cmd_name](cmd_args)

        # Wait for a kill signal
        signal.signal(signal.SIGINT, handler_kill)

        try:
            # Spawn a child process
            cmd_tokens[0] = locateProgram(cmd_tokens[0])
            pid = createChild(cmd_tokens, False)
        except Exception as error:
            print("Error %s executing %s" % (error, cmd_name))
            return 1

        debugger = ptrace.debugger.PtraceDebugger()
        debugger.traceFork()
        debugger.traceExec()

        process = debugger.addProcess(pid, True)
        process.syscall()

        snapshots = None
        try:
            snapshots, exit_code = debug_process(debugger, syscall_filters)
            if exit_code != 0:
                print('Command unsuccessful - rollbacking changes')
                snapshots.rollback_all()
        except Exception as error:
            print("Error tracing process: %s." % error)
            return SHELL_STATUS_STOP
        except KeyboardInterrupt:
            print("%s terminated by keyboard interrupt." % cmd_name)
            return SHELL_STATUS_STOP
        finally:
            # Cut down all processes no matter what happens
            # to prevent them from doing any damage
            debugger.quit()
            if snapshots is not None:
                snapshots.clean()

    # Return status indicating to wait for next command in shell_loop
    return SHELL_STATUS_RUN
Exemple #2
0
def debugger_example(pid):
    debugger = ptrace.debugger.PtraceDebugger()

    print("Attach the running process %s" % pid)
    process = debugger.addProcess(pid, False)

    print("syscall()")
    # ptrace_syscall(pid)

    # syscall_options = FunctionCallOptions(
    #         write_types=True,
    #         write_argname=True,
    #         string_max_length=300,
    #         replace_socketcall=False,
    #         write_address=True,
    #         max_array_count=20,
    #     )
    # state = process.syscall_state
    # syscall = state.event(syscall_options)
    # if syscall and (syscall.result is not None):
    #     self.displaySyscall(syscall)

    for i in range(5):
        # Break at next syscall
        # process.syscall()
        # event = process.waitSyscall()
        event = debugger.waitProcessEvent()
        # event = process.waitSignals()
        # event = process.waitSignals(signal.SIGTRAP)
        print(event)
        regs = process.getregs()
        print("rax = {}".format(ctypes.c_long(regs.rax).value))
        print("rdi = {:#x}".format(regs.rdi))
        print("rsi = {:#x}".format(regs.rsi))
        print("rdx = {:#x}".format(regs.rdx))

        process.cont()

    ip = process.getInstrPointer()
    print("ip = {:#x}".format(ip))

    # res = process.getregs()
    # print(regs)

    print("detach()")
    process.detach()
    debugger.quit()

    print("="*8)
    def run(self):
        debugger = debug.SyscallDebugger()

        # Run entities and collect syscalls.
        self.prepare()
        try:
            log.info("\n*** {} / {} ***\n".format(self.testcase.name, self.name))

            try:
                self.server = self.start(debugger, "server")
                debugger.set_timeout(35)
                debugger.wait(self.server, "listen")
                debugger.set_timeout(5)
                debugger.wait(self.server, "listen")
            except debug.Timeout:
                self.error("Server timeout occured.")

            try:
                self.client = self.start(debugger, "client")
                debugger.set_timeout(20)
                debugger.wait(self.client)
            except debug.Timeout:
                self.error("Client timeout occured.")
        except BaseException as error:
            self.error("Python exception {} occured: {}".format(type(error), error))
            raise
        finally:
            debugger.quit()
            self.cleanup()

        self.events = debugger.events
        del debugger

        # Process collected events.
        for event in self.events:
            if isinstance(event, ptrace.debugger.process_event.ProcessExit):
                if event.exitcode != self.expected_exitcodes[event.origin]:
                    self.error("Unexpected {} exit code {}.".format(event.origin, event.exitcode))
                if event.process == self.server:
                    log.debug("Server exit code is {}.".format(event.exitcode))
                if event.process == self.client:
                    log.debug("Client exit code is {}.".format(event.exitcode))
            elif event.name == 'listen':
                if event.origin != 'server':
                    continue
                self.listeners.append(event.socket)
            elif event.name == 'connect':
                if event.origin != 'client':
                    continue
                if event.socket.domain.value not in (socket.AF_INET, socket.AF_INET6):
                    continue
                if re.search(" sin6?_port=0, ", event.arguments[1].text):
                    continue
                conn = event.socket
                conn.attempted = event.time
                conn.status = event.result
                conn.nonblocking = conn.status == errno.EINPROGRESS
                conn.shutdown = False
                conn.closed = None
                self.connections.append(conn)
            elif event.name == 'getsockopt':
                if event.origin != 'client':
                    continue
                if event.arguments[1].value != socket.SOL_SOCKET:
                    continue
                if event.arguments[2].value != socket.SO_ERROR:
                    continue
                event.socket.status = event.arguments[3].value
            elif event.name == 'shutdown' and event.result == 0:
                event.socket.shutdown = True
            elif event.name == 'close' and event.result == 0:
                event.socket.closed = event.time


        # Postprocess acquired data.
        self.postprocess()
#!/usr/bin/python3

import subprocess
import os
import ptrace.debugger

import containers

containers.pivot_temporary_overlay()
containers.netns_with_veth()

command = ["ping", "-n", "192.168.0.2"]

debugger = ptrace.debugger.PtraceDebugger()
process = debugger.addProcess(
    ptrace.debugger.child.createChild(command, False), True)

while True:
    process.syscall()
    event = debugger.waitProcessEvent()
    if isinstance(event, ptrace.debugger.ProcessExit):
        break
    elif isinstance(event, ptrace.debugger.ProcessSignal):
        #print(event.signum)
        #print(event.name)
        print(
            process.syscall_state.event(
                ptrace.func_call.FunctionCallOptions()))

debugger.quit()
Exemple #5
0
def main():

    signal.signal(signal.SIGINT, sigint_handler)

    if len(sys.argv) < 2:
        logging.error('Usage: %s TARGET_PID' % sys.argv[0])
        sys.exit(1)

    try:
        pid = int(sys.argv[1])
    except:
        logging.error('Wrong PID: %s' % sys.argv[1])
        sys.exit(1)

    logging.debug("Attach the running process %s" % pid)
    debugger = ptrace.debugger.PtraceDebugger()
    process = debugger.addProcess(pid, False)

    while not stop_script:
        try:
            process.syscall()
            time.sleep(0.001)

            regs = process.getregs()
            syscall_num = regs.orig_rax

            if syscall_num == 45 or syscall_num == 44:
                fd = regs.rdi
                buff = regs.rsi
                bufflen = regs.rdx

                logging.debug("%s(%d, 0x%x, %d)" %
                              (syscall_names[syscall_num], fd, buff, bufflen))

                if syscall_num == 44:
                    x = process.readBytes(buff, bufflen)
                    logging.debug('SEND: %s' % x.encode('hex'))
                    packet = vboxmanage.ipc_unserialize(x)
                    logging.info(packet)

            process.syscall()
            time.sleep(0.001)

            regs = process.getregs()
            ret = regs.rax

            if syscall_num == 45 or syscall_num == 44:

                logging.debug("    = %d" % (ret))

                if syscall_num == 45:
                    x = process.readBytes(buff, ret)
                    logging.debug('RECV: %s' % x.encode('hex'))
                    packet = vboxmanage.ipc_unserialize(x)
                    logging.info(packet)

        except Exception as e:
            pass

    process.detach()
    debugger.quit()
Exemple #6
0
def main(args):
    root.get_root()

    # Get parameters from args
    pid = args.pid
    patch_path = os.path.abspath(args.patch)

    # print(patch_path)

    # Calculating base address
    shell_base = 0
    main_base = 0
    proc_map_filename = "/proc/%d/maps" % pid

    try:
        fmap = open(proc_map_filename)
    except IOError as e:
        print("Couldn't open process map file (%s)!" % e)

    try:
        lines = fmap.readlines()
    except e:
        print(e)
        exit(-1)

    is_first = True
    lib_installation_path = "/usr/lib/"
    str_tiger = "libtfix.so"

    # TODO: 无链接则拒绝
    for line in lines:
        if is_first:
            end = line.find('-')
            str_base = line[0:end]
            main_base = int(str_base, base=16)
            is_first = False
        else:
            it = line.find(str_tiger)
            if (it != -1):
                end = line.find('-')
                str_base = line[0:end]
                shell_base = int(str_base, base=16)
                break

    # x86-64
    # nm /usr/lib/libtfix.so | grep do_fix_entry
    a = open(os.path.join(lib_installation_path, str_tiger), 'rb')
    elffile_tfix = ef.ELFFile(a)
    elffile_sym = elffile_tfix.get_section_by_name('.symtab')
    symbol_name = [x.name for x in elffile_sym.iter_symbols()]
    if "do_fix_entry" in symbol_name:
        for x in elffile_sym.iter_symbols():
            if x.name == "do_fix_entry":
                temp_address = x.entry['st_value']
    else:
        raise NameError("do_fix_entry not found")

    do_fix_entry = shell_base + temp_address

    # initialize debugger
    debugger = ptrace.debugger.PtraceDebugger()

    # attach the running process (pid)
    process = debugger.addProcess(pid, False)

    # next syscall
    # print("wait a syscall")
    ENOSYS = 38
    while True:
        process.syscall()
        wait_stopped(pid)
        # process.waitSignals(signal.SIGSTOP)
        eax = process.getreg('eax')
        if eax != -ENOSYS:  # if not invalid syscall
            break

    # save status
    old_regs = process.getregs()

    # set regs
    new_regs = process.getregs()
    if platform.architecture()[0] == "64bit":
        # 64 bit
        new_regs.rip = do_fix_entry
        new_regs.rsp = int((new_regs.rsp / 32)) * 32

        process.writeBytes(new_regs.rsp - 4096, patch_path.encode())
        process.writeBytes(new_regs.rsp - 64, str(main_base).encode())

        new_regs.rsp -= 4096
        new_regs.rdi = new_regs.rsp
        new_regs.rbp = new_regs.rsp

    elif platform.architecture()[0] == "32bit":
        # 32 bit
        new_regs.eip = do_fix_entry
        new_regs.esp = int((new_regs.esp / 32)) * 32

        process.writeBytes(new_regs.esp - 4096, patch_path.encode())
        process.writeBytes(new_regs.esp - 64, str(main_base).encode())

        new_regs.esp -= 4096
        new_regs.ebp = new_regs.esp

    else:
        raise SystemError("Unsupported architecture\n")

    # set new regs
    process.setregs(new_regs)

    process.cont()

    # print("wait a trap")
    # process.waitSignals(signal.SIGTRAP, signal.SIGSTOP)
    wait_trap(pid)

    # restore old regs
    process.setregs(old_regs)

    # detach and quit
    process.detach()
    debugger.quit()
Exemple #7
0
    def run(self):
        # this import is here to be able to run the client_server.py to anything except running tests also without
        # installed dependencies. To generate SRPM one has to run the client_server.py and it tracebacks without ptrace
        from . import debug
        import ptrace.debugger

        debugger = debug.SyscallDebugger()

        # Run entities and collect syscalls.
        self.prepare()
        try:
            logger.info("\n*** {} / {} ***\n".format(self.testcase.name,
                                                     self.name))

            try:
                self.server = self.start(debugger, "server")
                debugger.set_timeout(35)
                debugger.wait(self.server, "listen")
                debugger.set_timeout(5)
                debugger.wait(self.server, "listen")
            except debug.Timeout:
                self.error("Server timeout occured.")

            try:
                self.client = self.start(debugger, "client")
                debugger.set_timeout(20)
                debugger.wait(self.client)
            except debug.Timeout:
                self.error("Client timeout occured.")
        except BaseException as error:
            self.error("Python exception {} occured: {}".format(
                type(error), error))
            raise
        finally:
            debugger.quit()
            self.cleanup()

        self.events = debugger.events
        del debugger

        # Process collected events.
        for event in self.events:
            if isinstance(event, ptrace.debugger.process_event.ProcessExit):
                if event.exitcode != self.expected_exitcodes[event.origin]:
                    self.error("Unexpected {} exit code {}.".format(
                        event.origin, event.exitcode))
                if event.process == self.server:
                    logger.debug("Server exit code is {}.".format(
                        event.exitcode))
                if event.process == self.client:
                    logger.debug("Client exit code is {}.".format(
                        event.exitcode))
            elif event.name == 'listen':
                if event.origin != 'server':
                    continue
                logger.info(
                    "Server starts listening on family {} socktype {}.".format(
                        event.socket.domain, event.socket.socktype))
                self.listeners.append(event.socket)
            elif event.name == 'connect':
                if event.origin != 'client':
                    continue
                if event.socket.domain.value not in (socket.AF_INET,
                                                     socket.AF_INET6):
                    continue
                if event.socket.socktype.value not in [
                        listener.socktype.value for listener in self.listeners
                ]:
                    continue
                if re.search(" sin6?_port=0, ", event.arguments[1].text):
                    continue
                conn = event.socket
                conn.attempted = event.time
                conn.status = event.result
                conn.nonblocking = conn.status == errno.EINPROGRESS
                conn.shutdown = False
                conn.closed = None
                self.connections.append(conn)
            elif event.name == 'getsockopt':
                if event.origin != 'client':
                    continue
                if event.arguments[1].value != socket.SOL_SOCKET:
                    continue
                if event.arguments[2].value != socket.SO_ERROR:
                    continue
                event.socket.status = event.arguments[3].value
            elif event.name == 'shutdown' and event.result == 0:
                if event.socket:
                    event.socket.shutdown = True
            elif event.name == 'close' and event.result == 0:
                event.socket.closed = event.time

        # Postprocess acquired data.
        self.postprocess()