Example #1
0
    def callafter(self, pid, call, result, state):
        # XXX: this needs work -- can't we just map on the way out of the
        # first execve or fork/vfork/clone, as appropriate?
        # NB: we don't want to map for the CLONE_VM case, since the map will
        # already be there (?)
        # How does CLONE_FILES and CLONE_FS affect this?

	if call != 'execve':
            if not _mapped.has_key(pid):
                # print 'Scratch: Deciding to poison ', pid, 's address space'
                _mapped[pid] = 1
                r = p_linux_i386.force_syscall(pid,
                                               syscallmap.lookup_number('mmap2'),
                                               scratch.base(),
                                               scratch.safe_len(),
                                               1, # PROT_READ
                                               0x12, # PRIVATE | FIXED
                                               123, 0)
                assert r == scratch.base(), "mmap failed (%s)" % r

	if call == 'execve':
#	    print 'Scratch: execve -- forgetting on pid', pid
	    try:
	        del _mapped[pid]
	    except:
	        print '%d did execve but I had not him mapped?' % pid
Example #2
0
    def callafter(self, pid, call, result, state):
        # XXX: this needs work -- can't we just map on the way out of the
        # first execve or fork/vfork/clone, as appropriate?
        # NB: we don't want to map for the CLONE_VM case, since the map will
        # already be there (?)
        # How does CLONE_FILES and CLONE_FS affect this?

        if call != 'execve':
            if not _mapped.has_key(pid):
                # print 'Scratch: Deciding to poison ', pid, 's address space'
                _mapped[pid] = 1
                r = p_linux_i386.force_syscall(
                    pid,
                    syscallmap.lookup_number('mmap2'),
                    scratch.base(),
                    scratch.safe_len(),
                    1,  # PROT_READ
                    0x12,  # PRIVATE | FIXED
                    123,
                    0)
                assert r == scratch.base(), "mmap failed (%s)" % r

        if call == 'execve':
            #	    print 'Scratch: execve -- forgetting on pid', pid
            try:
                del _mapped[pid]
            except:
                print '%d did execve but I had not him mapped?' % pid
Example #3
0
 def _print_call(self, call, args, mem):
     printed = call + '('
     callentry = syscallmap.table[syscallmap.lookup_number(call)]
     sig = callentry[syscallmap.SIGNATURE]
     nargs = callentry[syscallmap.NARGS]
     for i in xrange(nargs):
         if i:
             printed += ','
         if sig and sig[i] == 'P':
             printed += repr(mem.get_string(args[i])[:max_string_limit])
         else:
             printed += str(args[i])
     return printed + ')'
Example #4
0
    def _printargs(self, call, args, mem):
        sys.stdout.write('(')
        callentry = syscallmap.table[syscallmap.lookup_number(call)]
        sig = callentry[syscallmap.SIGNATURE]
        nargs = callentry[syscallmap.NARGS]
        assert sig == None or len(sig) == nargs, "oops: bogus syscallmap for %s" % call

        for i in xrange(nargs):
            if i:
                print ", ",
            if sig and sig[i] == 'P':
                sys.stdout.write(repr(mem.get_string(args[i])[:self._stringlimit]))
            else:
                sys.stdout.write("%s" % args[i])
        print ')',
Example #5
0
    def _printargs(self, call, args, mem):
        sys.stdout.write('(')
        callentry = syscallmap.table[syscallmap.lookup_number(call)]
        sig = callentry[syscallmap.SIGNATURE]
        nargs = callentry[syscallmap.NARGS]
        assert sig == None or len(
            sig) == nargs, "oops: bogus syscallmap for %s" % call

        for i in xrange(nargs):
            if i:
                print ", ",
            if sig and sig[i] == 'P':
                sys.stdout.write(
                    repr(mem.get_string(args[i])[:self._stringlimit]))
            else:
                sys.stdout.write("%s" % args[i])
        print ')',
Example #6
0
 def match_args(self, call, rule_args, args, mem):
     if rule_args == None:
         return 1
     callentry = syscallmap.table[syscallmap.lookup_number(call)]
     sig = callentry[syscallmap.SIGNATURE]
     nargs = callentry[syscallmap.NARGS]
     assert nargs == len(args) == len(rule_args), "Internal error"
     for i in xrange(nargs):
         if rule_args[i] == None:
             continue
         elif sig and sig[i] == 'P':
             arg = repr(mem.get_string(args[i])[:max_string_limit])
             if rule_args[i].match(arg):
                 continue
             else:
                 return 0
         elif rule_args[i] == args[i]:
             continue
         return 0     # something doesn't match
     return 1    # everything matched
Example #7
0
 def parse_args(self, call, args, lineno):
     if len(args) == 1 and args[0] in wildcards:
         return None
     callentry = syscallmap.table[syscallmap.lookup_number(call)]
     sig = callentry[syscallmap.SIGNATURE]
     nargs = callentry[syscallmap.NARGS]
     assert sig == None or len(sig) == nargs, "Bogus %s syscallmap" % call
     if not nargs == len(args):
         sys.exit("%s() has %d arguments (line %d)." % (call, nargs, lineno))
     for i in xrange(nargs):
         if args[i] in wildcards:
             args[i] = None
         elif sig and sig[i] == 'P':
             args[i] = re.sub('\*', '[^/]*', repr(args[i]))
             args[i] = re.sub('\.', '\.', args[i])
             args[i] = re.compile(args[i])
         else:
             try:
                 args[i] = int(args[i])
             except ValueError,e:
                 sys.exit("Integer argument expected at line %d" % lineno)
Example #8
0
def trace_syscall_before(pid, flags, tricklist, call, scno, sysent):
    nargs = sysent[syscallmap.NARGS]
    args = peek_args(pid, nargs)

    call_save = call
    args_save = args[:]
    call_changes = {}

    state = {}
    for trick, callmask, signalmask in tricklist:
        if (not callmask or callmask.has_key(call)) and trick.is_enabled(pid):
            r = trick.callbefore(pid, call, args)
            # r is None or (state, result, call, args)
            if r:
                assert len(r) == 4, "callbefore must return None or a 4-tuple"
                if r[1] != None:
                    # annul the call
                    call_changes[trick] = call
                    call = _badcall
                    args = []
                    flags["annul"] = (r[1], trick)
                    break
                if r[0] != None:
                    state[trick] = r[0]
                if r[2] != None:
                    call_changes[trick] = call
                    call = r[2]
                    assert isinstance(call, types.StringType)
                if r[3] != None:
                    args = r[3]
                    assert len(args) <= 6, "kernel doesn't support 7+ args?"

                # STATE at this point ?
                # call_changes, args, args_save, scno, call, call_save, state, ???

    flags["call_changes"] = call_changes

    # XXX: maybe faster to just brute force args rather than this careful
    # delta stuff?

    # make any necessary changes to child's args, saving undo info
    # (XXX: hmm, is this actually better than the iterative version?)
    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)

    n = len(args)
    args_delta = filter(None, map(_alter_arg, range(n), args, args_save[:n]))
    if args_delta:
        flags["args_delta"] = args_delta

    if call == "sigreturn" or call == "rt_sigreturn":
        flags["sigreturn"] = call

    if call != call_save:
        if isinstance(call, types.StringType):
            callno = syscallmap.lookup_number(call)
        else:
            callno = call

        try:
            if debug():
                print "ptrace.pokeuser(%s, %s, %s)" % (pid, ORIG_EAX, callno)
            ptrace.pokeuser(pid, ORIG_EAX, callno)
            flags["call_delta"] = scno
        except OSError, e:
            # FIX: do something better here
            sys.exit("panic: call alter failed in trick %s (%s)" % (trick, e))
Example #9
0
def trace_syscall_before(pid, flags, tricklist, call, scno, sysent):
    nargs = sysent[syscallmap.NARGS]
    args = peek_args(pid, nargs)

    call_save = call
    args_save = args[:]
    call_changes = {}

    state = {}
    for trick, callmask, signalmask in tricklist:
        if (not callmask or callmask.has_key(call)) \
                                         and trick.is_enabled(pid):
            r = trick.callbefore(pid, call, args)
            # r is None or (state, result, call, args)
            if r:
                assert len(r) == 4, "callbefore must return None or a 4-tuple"
                if r[1] != None:
                    # annul the call
                    call_changes[trick] = call
                    call = _badcall
                    args = []
                    flags['annul'] = (r[1], trick)
                    break
                if r[0] != None:
                    state[trick] = r[0]
                if r[2] != None:
                    call_changes[trick] = call
                    call = r[2]
                    assert isinstance(call, types.StringType)
                if r[3] != None:
                    args = r[3]
                    assert len(args) <= 6, "kernel doesn't support 7+ args?"

    # STATE at this point ?
    # call_changes, args, args_save, scno, call, call_save, state, ???

    flags['call_changes'] = call_changes

    # XXX: maybe faster to just brute force args rather than this careful
    # delta stuff?

    # make any necessary changes to child's args, saving undo info
    # (XXX: hmm, is this actually better than the iterative version?)
    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)

    n = len(args)
    args_delta = filter(None, map(_alter_arg, range(n), args, args_save[:n]))
    if args_delta:
        flags['args_delta'] = args_delta

    if call == 'sigreturn' or call == 'rt_sigreturn':
        flags['sigreturn'] = call

    if call != call_save:
        if isinstance(call, types.StringType):
            callno = syscallmap.lookup_number(call)
        else:
            callno = call

        try:
            if debug():
                print "ptrace.pokeuser(%s, %s, %s)" % (pid, ORIG_EAX, callno)
            ptrace.pokeuser(pid, ORIG_EAX, callno)
            flags['call_delta'] = scno
        except OSError, e:
            # FIX: do something better here
            sys.exit('panic: call alter failed in trick %s (%s)' % (trick, e))