Esempio n. 1
0
def trace_syscall(pid, flags, tricklist):
    scno = ptrace.peekuser(pid, ORIG_EAX)

    assert (0 <= scno < len(syscallmap.table)
            or scno == _badcall
            or flags.has_key('sigreturn')), \
            "unknown system call (=%s, pid=%s, flags=%s)" % (scno, pid, flags)

    if scno == _badcall:
        call = 'badcall'
    elif flags.has_key('sigreturn'):
        call = flags['sigreturn']  # !beforecall
    else:
        sysent = syscallmap.table[scno]
        call = sysent[syscallmap.CALL]

    eax = ptrace.peekuser(pid, EAX)

    beforecall = not flags.has_key('insyscall')
    if eax != -errno.ENOSYS and beforecall:  # XXX: is this test right?
        if call == 'execve' and debug():
            print 'debug: ignoring additional execve stop'
            return
        if 0 <= eax <= len(syscallmap.table):
            eaxcall = syscallmap.table[eax][3]
        else:
            eaxcall = ""
        # FIX: this probably fires for SIG_DFL stop calls (except SIGSTOP)
        print 'warning: received SIGTRAP or stray syscall exit: eax = %d (%s)' % (
            eax, eaxcall)
        # FIX: is this right?  what's really going on here?
        # no, don't do this, because of the SIG_DFL issue above!!!!!  --mkc
        #raise 'warning: received SIGTRAP or stray syscall exit:' \
        #      'pid = %d, eax = %d (%s)' % (pid, eax, eaxcall)
        #return
        # FIX: is this the right thing to do?
        flags['insyscall'] = 1
        flags['state'] = {}
        flags['call_changes'] = {}

    global _skipcallafter
    if beforecall:
        if not _call_weedout_mask[scno]:
            _skipcallafter[pid] = 1
            flags['insyscall'] = 1
            ptrace.syscall(pid, 0)
            return
        return trace_syscall_before(pid, flags, tricklist, call, scno, sysent)

    if _skipcallafter.has_key(pid):
        del _skipcallafter[pid]
        del flags['insyscall']
        ptrace.syscall(pid, 0)
        return
    return trace_syscall_after(pid, flags, tricklist, call, eax)
Esempio n. 2
0
def trace_syscall(pid, flags, tricklist):
    scno = ptrace.peekuser(pid, ORIG_EAX)

    assert (
        0 <= scno < len(syscallmap.table) or scno == _badcall or flags.has_key("sigreturn")
    ), "unknown system call (=%s, pid=%s, flags=%s)" % (scno, pid, flags)

    if scno == _badcall:
        call = "badcall"
    elif flags.has_key("sigreturn"):
        call = flags["sigreturn"]  # !beforecall
    else:
        sysent = syscallmap.table[scno]
        call = sysent[syscallmap.CALL]

    eax = ptrace.peekuser(pid, EAX)

    beforecall = not flags.has_key("insyscall")
    if eax != -errno.ENOSYS and beforecall:  # XXX: is this test right?
        if call == "execve" and debug():
            print "debug: ignoring additional execve stop"
            return
        if 0 <= eax <= len(syscallmap.table):
            eaxcall = syscallmap.table[eax][3]
        else:
            eaxcall = ""
        # FIX: this probably fires for SIG_DFL stop calls (except SIGSTOP)
        print "warning: received SIGTRAP or stray syscall exit: eax = %d (%s)" % (eax, eaxcall)
        # FIX: is this right?  what's really going on here?
        # no, don't do this, because of the SIG_DFL issue above!!!!!  --mkc
        # raise 'warning: received SIGTRAP or stray syscall exit:' \
        #      'pid = %d, eax = %d (%s)' % (pid, eax, eaxcall)
        # return
        # FIX: is this the right thing to do?
        flags["insyscall"] = 1
        flags["state"] = {}
        flags["call_changes"] = {}

    global _skipcallafter
    if beforecall:
        if not _call_weedout_mask[scno]:
            _skipcallafter[pid] = 1
            flags["insyscall"] = 1
            ptrace.syscall(pid, 0)
            return
        return trace_syscall_before(pid, flags, tricklist, call, scno, sysent)

    if _skipcallafter.has_key(pid):
        del _skipcallafter[pid]
        del flags["insyscall"]
        ptrace.syscall(pid, 0)
        return
    return trace_syscall_after(pid, flags, tricklist, call, eax)
Esempio n. 3
0
 def _alter_arg(number, arg, saved_arg, pid=pid):
     if not saved_arg:
         saved_arg = ptrace.peekuser(pid, 4 * number)
     if arg != saved_arg:
         if debug():
             print "ptrace.pokeuser(%s, %s, %s)" % (pid, 4 * number, arg)
         ptrace.pokeuser(pid, 4 * number, arg)
         return (number, saved_arg)
Esempio n. 4
0
 def _alter_arg(number, arg, saved_arg, pid=pid):
     if not saved_arg:
         saved_arg = ptrace.peekuser(pid, 4 * number)
     if arg != saved_arg:
         if debug():
             print "ptrace.pokeuser(%s, %s, %s)" % (pid, 4 * number, arg)
         ptrace.pokeuser(pid, 4 * number, arg)
         return (number, saved_arg)
Esempio n. 5
0
def force_syscall(pid, scno, p1=0, p2=0, p3=0, p4=0, p5=0, p6=0):
    registers = peek_args(pid, 6)
    eip = ptrace.peekuser(pid, EIP)
    eax = ptrace.peekuser(pid, EAX)
    ptrace.pokeuser(pid, EIP, eip - 2)
    ptrace.pokeuser(pid, EAX, scno)  # Select new scno and point eip to syscall
    poke_args(pid, 6, [p1, p2, p3, p4, p5, p6])
    ptrace.syscall(pid, 0)  # We make it return to userland and do syscal
    wpid, status = os.waitpid(pid, wait_flags)
    assert pid == wpid
    ptrace.syscall(pid, 0)  # Kernel stops us before syscall is done
    wpid, status = os.waitpid(pid, wait_flags)
    if wpid != pid:
        print "problem: other syscall stopped woke up /2: ", pid, " != ", wpid
    assert pid == wpid  # Kernel stops us when syscall is done
    res = ptrace.peekuser(pid, EAX)  # We get the syscall result
    ptrace.pokeuser(pid, EAX, eax)  # and then mimic like nothing happened
    poke_args(pid, 6, registers)
    return res
Esempio n. 6
0
def force_syscall(pid, scno, p1=0, p2=0, p3=0, p4=0, p5=0, p6=0):
    registers = peek_args(pid, 6)
    eip = ptrace.peekuser(pid, EIP)
    eax = ptrace.peekuser(pid, EAX)
    ptrace.pokeuser(pid, EIP, eip - 2)
    ptrace.pokeuser(pid, EAX, scno)  # Select new scno and point eip to syscall
    poke_args(pid, 6, [p1, p2, p3, p4, p5, p6])
    ptrace.syscall(pid, 0)  # We make it return to userland and do syscal
    wpid, status = os.waitpid(pid, wait_flags)
    assert pid == wpid
    ptrace.syscall(pid, 0)  # Kernel stops us before syscall is done
    wpid, status = os.waitpid(pid, wait_flags)
    if wpid != pid:
        print "problem: other syscall stopped woke up /2: ", pid, " != ", wpid
    assert pid == wpid  # Kernel stops us when syscall is done
    res = ptrace.peekuser(pid, EAX)  # We get the syscall result
    ptrace.pokeuser(pid, EAX, eax)  # and then mimic like nothing happened
    poke_args(pid, 6, registers)
    return res
Esempio n. 7
0
            else:
                sys.exit("%s wait error [%s]" % (sys.argv[0], e))
        except KeyboardInterrupt:
	    assert 0, "this can't happen--we're ignoring SIGINT"

        if fastmainloop and not beforecall:
            allflags[lastpid]['insyscall'] = 1
            set_skipcallafter(lastpid)
        lastpid = wpid

        if not allflags.has_key(wpid):
            # new child
            # FIX: what happens if parent or child already dead?
            # FIX: what happens if parent waits before child reports?
            try:
                ppid = ptrace.peekuser(wpid, EDI)
            except OSError, e:
                if e.errno == errno.ESRCH:
                    # If a trick has started a process and it dies, we find
                    # out here.  Might get here for other reasons, though.
                    print 'non-traced process exited (?)'
                    continue
                else:
                    raise
            if debug():
                print "[%s] new child, parent is %s" % (wpid, ppid)

            # ppid could be 1 here if the parent died very quickly and init
            # inherited the child.  With the new tagging scheme, though, we'll
            # still have the old ppid here, even though the process is gone.
            # So, for example, depending on the order of events,
Esempio n. 8
0
def peek_args(pid, nargs):
    args = []
    assert nargs <= 6, "kernel doesn't support 7+ args?"
    for i in range(nargs):
        args.append(ptrace.peekuser(pid, 4 * i))
    return args
Esempio n. 9
0
            else:
                sys.exit("%s wait error [%s]" % (sys.argv[0], e))
        except KeyboardInterrupt:
            assert 0, "this can't happen--we're ignoring SIGINT"

        if fastmainloop and not beforecall:
            allflags[lastpid]['insyscall'] = 1
            set_skipcallafter(lastpid)
        lastpid = wpid

        if not allflags.has_key(wpid):
            # new child
            # FIX: what happens if parent or child already dead?
            # FIX: what happens if parent waits before child reports?
            try:
                ppid = ptrace.peekuser(wpid, EDI)
            except OSError, e:
                if e.errno == errno.ESRCH:
                    # If a trick has started a process and it dies, we find
                    # out here.  Might get here for other reasons, though.
                    print 'non-traced process exited (?)'
                    continue
                else:
                    raise
            if debug():
                print "[%s] new child, parent is %s" % (wpid, ppid)

            # ppid could be 1 here if the parent died very quickly and init
            # inherited the child.  With the new tagging scheme, though, we'll
            # still have the old ppid here, even though the process is gone.
            # So, for example, depending on the order of events,
Esempio n. 10
0
 def callafter(self, pid, call, result, state):
     v = ptrace.peekuser(pid, self.options['offset'])
     print '[%s] found %s at offset %s' % (pid, v, self.options['offset'])
     print '[%s] restoring %s at offset %s' % (pid, state,
                                               self.options['offset'])
     ptrace.pokeuser(pid, self.options['offset'], state)
Esempio n. 11
0
 def callbefore(self, pid, call, args):
     v = ptrace.peekuser(pid, self.options['offset'])
     print '[%s] poking %s at offset %s' % (pid, self.options['data'],
                                            self.options['offset'])
     ptrace.pokeuser(pid, self.options['offset'], self.options['data'])
     return (v, None, None, None)
Esempio n. 12
0
 def callafter(self, pid, call, result, state):
     v = ptrace.peekuser(pid, self.options['offset'])
     print '[%s] found %s at offset %s' % (pid, v, self.options['offset'])
     print '[%s] restoring %s at offset %s' % (pid, state, self.options['offset'])
     ptrace.pokeuser(pid, self.options['offset'], state)
Esempio n. 13
0
 def callbefore(self, pid, call, args):
     v = ptrace.peekuser(pid, self.options['offset'])
     print '[%s] poking %s at offset %s' % (pid, self.options['data'], self.options['offset'])
     ptrace.pokeuser(pid, self.options['offset'], self.options['data'])
     return (v, None, None, None)
Esempio n. 14
0
def peek_args(pid, nargs):
    args = []
    assert nargs <= 6, "kernel doesn't support 7+ args?"
    for i in range(nargs):
        args.append(ptrace.peekuser(pid, 4 * i))
    return args