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
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
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 + ')'
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 ')',
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 ')',
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
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)
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))
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))