Exemple #1
0
def main():
    # Check the command line
    if len(argv) < 2:
        print("usage: %s program [arg1 arg2 ...]" % argv[0], file=stderr)
        print("   or: %s pid" % argv[0], file=stderr)
        exit(1)

    # Get the process identifier
    is_attached = False
    has_pid = False
    if len(argv) == 2:
        try:
            # User asked to attach a process
            pid = int(argv[1])
            has_pid = True
        except ValueError:
            pass

    if not has_pid:
        # User asked to create a new program and trace it
        arguments = argv[1:]
        pid = traceProgram(arguments)
        is_attached = True

    # Create the debugger and attach the process
    dbg = PtraceDebugger()
    process = dbg.addProcess(pid, is_attached)

    # Play with the process and then quit
    playWithProcess(process)
    dbg.quit()
Exemple #2
0
def fuzzProg(arguments, program):
  is_attached = False
  #create the debugger

  dbg = PtraceDebugger()
  #create list to fuzz the argument
  fuzzed = attack()
  
  index = 0
  fileProgName = program
  slashes = program.rfind('/') #if the user has put in the full program path
  if slashes!=-1:
    fileProgName = program[slashes+1:]
  filename = 'ErrorsIn' + fileProgName
  file = open(filename, 'w')

  #for fuzzing each argument in turn
  for arg in arguments:
    for fuzzedArg in fuzzed:
      toFuzz = [program, arg, fuzzedArg]
      pid = procFork(toFuzz)
      is_attached = True
      if len(toFuzz)==2:
        print "Fuzzing %s %s" % (toFuzz[0], toFuzz[1])
      elif len(toFuzz)>2:
        print "Fuzzing %s %s %s" % (toFuzz[0], toFuzz[1], toFuzz[2])
      error = fuzz(dbg, pid, is_attached, toFuzz)
      #if there's an error, print it to file
      if error != '':
        print error
        file.write(error)
  #make sure to close file after fuzzed
  file.close()
  #Quit the debugger after fuzzing everything  
  dbg.quit()
def main():
    # Check the command line
    if len(argv) < 2:
        print("usage: %s program [arg1 arg2 ...]" % argv[0], file=stderr)
        print("   or: %s pid" % argv[0], file=stderr)
        exit(1)

    # Get the process identifier
    is_attached = False
    has_pid = False
    if len(argv) == 2:
        try:
            # User asked to attach a process
            pid = int(argv[1])
            has_pid = True
        except ValueError:
            pass

    if not has_pid:
        # User asked to create a new program and trace it
        arguments = argv[1:]
        pid = traceProgram(arguments)
        is_attached = True

    # Create the debugger and attach the process
    dbg = PtraceDebugger()
    process = dbg.addProcess(pid, is_attached)

    # Play with the process and then quit
    playWithProcess(process)
    dbg.quit()
Exemple #4
0
def main(argv=sys.argv):
    if len(argv) < 2:
        print(T.red("Error: No command given."))
        print("Usage: %s COMMAND [ARGUMENT]..." % argv[0])
        return 1

    # This is basically "shlex.join"
    command = " ".join([(("'%s'" % arg) if (" " in arg) else arg) for arg in argv[1:]])

    arguments = argv[1:]
    arguments[0] = locateProgram(arguments[0])

    try:
        pid = createChild(arguments, False)
    except Exception as error:
        print(T.red("Error executing %s: %s." % (T.bold(command) + T.red, error)))
        return 1

    debugger = PtraceDebugger()
    debugger.traceExec()
    try:
        debugger.traceFork()
    except DebuggerError:
        print(T.yellow("Warning: Running without traceFork support. " +
                       "Syscalls from subprocesses can not be intercepted."))

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

    try:
        operations = get_operations(debugger)
    except Exception as error:
        print(T.red("Error tracing process: %s." % error))
        return 1
    except KeyboardInterrupt:
        print(T.yellow("%s terminated by keyboard interrupt." % (T.bold(command) + T.yellow)))
        return 2
    finally:
        # Cut down all processes no matter what happens
        # to prevent them from doing any damage
        debugger.quit()

    if operations:
        print("%s has prevented %s from performing %d file system operations:\n" %
              (T.bold("maybe"), T.bold(command), len(operations)))
        for operation in operations:
            print("  " + operation)
        try:
            choice = input("\nDo you want to rerun %s and permit these operations? [y/N] " % T.bold(command))
        except KeyboardInterrupt:
            choice = ""
            # Ctrl+C does not print a newline automatically
            print("")
        if choice.lower() == "y":
            subprocess.call(argv[1:])
    else:
        print("%s has not detected any file system operations from %s." %
              (T.bold("maybe"), T.bold(command)))
Exemple #5
0
def main():
    if len(argv) < 2:
        print(T.red("Error: No command given."))
        print("Usage: %s COMMAND [ARGUMENT]..." % argv[0])
        exit(1)

    # This is basically "shlex.join"
    command = " ".join([(("'%s'" % arg) if (" " in arg) else arg) for arg in argv[1:]])

    arguments = argv[1:]
    arguments[0] = locateProgram(arguments[0])

    try:
        pid = createChild(arguments, False)
    except Exception as error:
        print(T.red("Error executing %s: %s." % (T.bold(command) + T.red, error)))
        exit(1)

    debugger = PtraceDebugger()
    debugger.traceExec()
    try:
        debugger.traceFork()
    except DebuggerError:
        print(T.yellow("Warning: Running without traceFork support. " +
                       "Syscalls from subprocesses can not be intercepted."))

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

    try:
        operations = get_operations(debugger)
    except Exception as error:
        print(T.red("Error tracing process: %s." % error))
        exit(1)
    except KeyboardInterrupt:
        print(T.yellow("%s terminated by keyboard interrupt." % (T.bold(command) + T.yellow)))
        exit(2)
    finally:
        # Cut down all processes no matter what happens
        # to prevent them from doing any damage
        debugger.quit()

    if operations:
        print("%s has prevented %s from performing %d file system operations:\n" %
              (T.bold("maybe"), T.bold(command), len(operations)))
        for operation in operations:
            print("  " + operation)
        try:
            choice = input("\nDo you want to rerun %s and permit these operations? [y/N] " % T.bold(command))
        except KeyboardInterrupt:
            choice = ""
        if choice.lower() == "y":
            call(argv[1:])
    else:
        print("%s has not detected any file system operations from %s." %
              (T.bold("maybe"), T.bold(command)))
class TibiaProcess:
	ips = [
		"login01.tibia.com",
		"login02.tibia.com",
		"login03.tibia.com",
		"login04.tibia.com",
		"login05.tibia.com",
		"tibia01.cipsoft.com",
		"tibia02.cipsoft.com",
		"tibia03.cipsoft.com",
		"tibia04.cipsoft.com",
		"tibia05.cipsoft.com",
		"test.tibia.com",
		"test.cipsoft.com",
		"tibia2.cipsoft.com",
		"tibia1.cipsoft.com",
		"server.tibia.com",
		"server2.tibia.com"
	]

	rsas = (
		"124710459426827943004376449897985582167801707960697037164044904862948569380850421396904597686953877022394604239428185498284169068581802277612081027966724336319448537811441719076484340922854929273517308661370727105382899118999403808045846444647284499123164879035103627004668521005328367415259939915284902061793",
		"132127743205872284062295099082293384952776326496165507967876361843343953435544496682053323833394351797728954155097012103928360786959821132214473291575712138800495033169914814069637740318278150290733684032524174782740134357629699062987023311132821016569775488792221429527047321331896351555606801473202394175817"
	)

	ot_rsa = "109120132967399429278860960508995541528237502902798129123468757937266291492576446330739696001110603907230888610072655818825358503429057592827629436413108566029093628212635953836686562675849720620786279431090218017681061521755056710823876476444260558147179707119674283982419152118103759076030616683978566631413"

	def __init__(self, process):
		self.maps = []
		self.current_ip = None
		self.tracer = PtraceDebugger()
		self.process = self.tracer.addProcess(process.pid, False)
		self.maps.extend(self.process.readMappings()[0:4])

	def detach(self):
		self.process.detach()
		self.tracer.quit()

	def changeRsa(self):
		for rsa in self.rsas:
			for res in self.maps[0].search(bytes(rsa, 'utf-8')):
				print("RSA modified.", res)
				self.process.writeBytes(res, bytes(self.ot_rsa, 'utf-8'))

	def changeIp(self, newip):
		for ip in self.ips:
			for maps in self.maps:
				for res in maps.search(bytes(ip, 'utf-8')):
					print("Found: " + ip)
					self.process.writeBytes(res, bytes(newip, 'utf-8'))
					if len(ip) > len(newip):
						for offset in range(len(newip), len(ip)):
							self.process.writeBytes(res + offset, bytes('\x00', 'utf-8'))
					print("Writing: " + newip)

		self.ips.insert(0, newip)
Exemple #7
0
def start(pid):
    # need to attach to the process with ptrace before you can read it's proc/$pid/maps
    # or be root I guess
    # https://unix.stackexchange.com/questions/6301/how-do-i-read-from-proc-pid-mem-under-linux
    # http://lkml.iu.edu/hypermail/linux/kernel/0505.0/0858.html
    dbg = PtraceDebugger()
    try:
        process = dbg.addProcess(pid, False)
    except:
        print("Could not attach to process {}".format(pid))
        return
    dump(process, pid)
    dbg.quit()
Exemple #8
0
class Sniffer(object):
    def __init__(self, pid=None):
        self.sessions = {}
        self.connections = {}
        self.dbg = PtraceDebugger()
        self.processes = {}

    def __del__(self):
        for pid in dict(self.processes):
            self.deleteProcess(pid)
        self.dbg.quit()

    def tcp_handler(self, tcp):
        if tcp.nids_state == nids.NIDS_JUST_EST and tcp.addr[1][1] in PORTS:
            self.connections[tcp.addr] = Connection(self, tcp)
        elif tcp.nids_state == nids.NIDS_DATA:
            if tcp.addr not in self.connections:
                return

            connection = self.connections[tcp.addr]

            try:
                if tcp.client.count_new:
                    connection.handle_data(
                        connection.server,
                        tcp.client.data[:tcp.client.count_new])
                if tcp.server.count_new:
                    connection.handle_data(
                        connection.client,
                        tcp.server.data[:tcp.server.count_new])
            except Connection.InvalidDataException:
                del self.connections[tcp.addr]

        elif tcp.nids_state in (nids.NIDS_CLOSE, nids.NIDS_TIMEOUT,
                                nids.NIDS_RESET):
            if tcp.addr in self.connections:
                del self.connections[tcp.addr]

    def message_handler(self, message):
        pass

    def session_handler(self, session):
        pass

    def addProcess(self, pid):
        self.processes[pid] = self.dbg.addProcess(pid, False)
        self.processes[pid].cont()

    def deleteProcess(self, pid):
        self.dbg.deleteProcess(pid)
        del self.processes[pid]
Exemple #9
0
def main():
    sys.argv = sys.argv[1:]
    filter_scopes = SYSCALL_FILTERS.keys()
    syscall_filters = {}

    for filter_scope in SYSCALL_FILTERS:
        if filter_scope in filter_scopes:
            for syscall in SYSCALL_FILTERS[filter_scope]:
                syscall_filters[syscall] = SYSCALL_FILTERS[filter_scope][
                    syscall]

    # Suppress logging output from python-ptrace
    getLogger().addHandler(NullHandler())

    # Prevent python-ptrace from decoding arguments to keep raw numerical values
    DIRFD_ARGUMENTS.clear()
    SYSCALL_ARG_DICT.clear()
    ARGUMENT_CALLBACK.clear()

    try:
        sys.argv[0] = locateProgram(sys.argv[0])
        pid = createChild(sys.argv, False)
    except Exception as error:
        print(f"Error executing {sys.argv}: {error}.")
        return 1

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

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

    try:
        operations = get_operations(debugger, syscall_filters, True)
    except Exception as error:
        print(f"Error tracing process: {error}.")
        return 1
    finally:
        # Cut down all processes no matter what happens
        # to prevent them from doing any damage
        debugger.quit()

    if operations:
        for operation in operations:
            print("  " + operation)
    else:
        print(f"Not detected any file system operations from: {sys.argv}")
Exemple #10
0
class CPtraceDumper:
    """ Ptrace Dumper """

    # Output base file
    outFile = None
    # Pid of the process to dump
    pid = None

    # PtraceDebugger instance
    dbg = None
    # Process name
    processName = None

    def __init__(self, pid, outFile):
        """ Set the pid and the base output filename """
        self.pid = pid
        self.outFile = outFile

    def dump(self):
        """ Dump the memory """
        self.dbg = PtraceDebugger()
        #print "Created object"
        try:
            self.dbg.addProcess(self.pid, False)
            #print "Attached to process"
        except:
            #print "Error adding process", sys.exc_info()[1]
            pass
        try:
            #print "Resolving process's name"
            self.processName = getProcessName(self.pid)
            #print "Resolving segmnents"
            segments = getMemorySegments(self.pid, True)
            #print "SEGMENTS:", segments
            #print "Now dumping memory"
            dumpProcessMemory(self.pid, self.outFile, segments, True)
        except:
            pass
            #print "Exception in self.dump"
            #print sys.exc_info()[1]
            #raise

    def quit(self):
        """ Exit from ptrace debugger """
        #print "Quiting from ptrace debugger"
        self.dbg.quit()
Exemple #11
0
class Sniffer(object):
	def __init__(self, pid=None):
		self.sessions = {}
		self.connections = {}
		self.dbg = PtraceDebugger()
		self.processes = {}
	
	def __del__(self):
		for pid in dict(self.processes):
			self.deleteProcess(pid)
		self.dbg.quit()
	
	def tcp_handler(self, tcp):	
		if tcp.nids_state == nids.NIDS_JUST_EST and tcp.addr[1][1] in PORTS:
			self.connections[tcp.addr] = Connection(self, tcp)
		elif tcp.nids_state == nids.NIDS_DATA:
			if tcp.addr not in self.connections:
				return
			
			connection = self.connections[tcp.addr]
			
			try:
				if tcp.client.count_new:
					connection.handle_data(connection.server, tcp.client.data[:tcp.client.count_new])
				if tcp.server.count_new:
					connection.handle_data(connection.client, tcp.server.data[:tcp.server.count_new])
			except Connection.InvalidDataException:
				del self.connections[tcp.addr]
		
		elif tcp.nids_state in (nids.NIDS_CLOSE, nids.NIDS_TIMEOUT, nids.NIDS_RESET):
			if tcp.addr in self.connections:
				del self.connections[tcp.addr]
	
	def message_handler(self, message):
		pass
	
	def session_handler(self, session):
		pass
	
	def addProcess(self, pid):
		self.processes[pid] = self.dbg.addProcess(pid, False)
		self.processes[pid].cont()
	
	def deleteProcess(self, pid):
		self.dbg.deleteProcess(pid)
		del self.processes[pid]
Exemple #12
0
class Fuzz(object):

	def try_arg(self, str_argument):
	
		print "Trying argument %s" % str_argument
	
		process = self.test_process
		new_str_addr = self.mem + 0x100
		arg_addr = process.getreg("esp") + 4
		arg = process.readWord(arg_addr)
		process.writeBytes(new_str_addr, str_argument)
		process.writeWord(arg_addr, new_str_addr)
		arg = process.readWord(arg_addr)
		playWithProcess(process)
	
	
	def fuzz(self, arguments, address):
		self.arguments = arguments
   		self.address = address
		self.mem = None
		self.pid = traceProgram(self.arguments)
		self.is_attached = True
	
		self.dbg = PtraceDebugger()
		self.process = self.dbg.addProcess(self.pid, self.is_attached)
	
		self.process.createBreakpoint(self.address, None)
		self.process.setoptions(ptrace_bindings.PTRACE_O_TRACEFORK)
		
		self.mem = allocateMemory(self.process)
		
		playWithProcess(self.process)
		
		ip = self.process.getInstrPointer() - 1
		breakpoint = self.process.findBreakpoint(ip)
		if breakpoint:
		    print ("Stopped at %s" % breakpoint)
		    breakpoint.desinstall(set_ip=True)
		
		for length in range(0, 20):
			self.test_process = createCheckpoint(self.process)
			self.try_arg("a" * length)
			#self.test_process.terminate(True)
		
		self.dbg.quit()
Exemple #13
0
def main():
  parser = argparse.ArgumentParser(
      description='Utility to reset user\'s health to full.')
  parser.add_argument('pid', nargs='?', type=int,
      help='Specify the PID of the game')

  args = parser.parse_args()

  pid = args.pid
  if not pid:
    pid = find_hack_pid()

  if pid == -1:
    logging.error('Unable to find hack process to attach to.')
    return

  dbg = PtraceDebugger()
  proc = dbg.addProcess(pid, False)

  # Read the value for full health, need just the lower 4 bytes
  full_hp = proc.readWord(0x6425a0) & 0xffffffff

  # Value is (curr hp, ???)
  value = proc.readWord(0x642598)

  curr_hp = value >> 32

  logging.info('Changing health from %d -> %d', curr_hp, full_hp)

  # Calculate the new value to write back
  value = (full_hp << 32) + (value & 0xffffffff)

  # Write the new value
  proc.writeWord(0x642598, value)

  dbg.quit()
def main():
    if len(argv) < 2: usage()
 
    # create process
    env = None
    arguments = argv[1:]
    arguments[0] = locateProgram(arguments[0])
    pid = createChild(arguments, False, env)
 
    # create debugger
    debugger = PtraceDebugger()
    debugger.enableSysgood()
    debugger.traceExec()
    debugger.traceFork()
 
    # attach process
    debugger.addProcess(pid, True)
    process = debugger[pid]
    process.syscall()
 
    # start event loop
    loop(debugger)
 
    debugger.quit()
Exemple #15
0
def main(argv=sys.argv[1:]):
    if PY2:
        argv = [unicode(arg, sys.getfilesystemencoding()) for arg in argv]  # noqa

    # Insert positional argument separator, if not already present
    if "--" not in argv:
        for i, argument in enumerate(argv):
            if not argument.startswith("-"):
                argv.insert(i, "--")
                break

    arg_parser = ArgumentParser(
        prog="maybe",
        usage="%(prog)s [options] command [argument ...]",
        description="Run a command without the ability to make changes to your system " +
                    "and list the changes it would have made.",
        epilog="For more information, to report issues or to contribute, " +
               "visit https://github.com/p-e-w/maybe.",
    )
    arg_parser.add_argument("command", nargs="+", help="the command to run under maybe's control")
    arg_group = arg_parser.add_mutually_exclusive_group()
    arg_group.add_argument("-a", "--allow", nargs="+", metavar="OPERATION",
                           help="allow the command to perform the specified operation(s). " +
                                "all other operations will be denied. " +
                                "possible values for %(metavar)s are: " +
                                ", ".join(sorted(SYSCALL_FILTERS.keys())) +
                                "; as well as any filter scopes defined by loaded plugins")
    arg_group.add_argument("-d", "--deny", nargs="+", metavar="OPERATION",
                           help="deny the command the specified operation(s). " +
                                "all other operations will be allowed. " +
                                "see --allow for a list of possible values for %(metavar)s. " +
                                "--allow and --deny cannot be combined")
    arg_parser.add_argument("-p", "--plugin", nargs="+", metavar="FILE",
                            help="load the specified plugin script(s). " +
                                 "see the README for details and plugin API documentation")
    arg_parser.add_argument("-l", "--list-only", action="store_true",
                            help="list operations without header, indentation and rerun prompt")
    arg_parser.add_argument("--style-output", choices=["yes", "no", "auto"], default="auto",
                            help="colorize output using ANSI escape sequences (yes/no) " +
                                 "or automatically decide based on whether stdout is a terminal (auto, default)")
    arg_parser.add_argument("-v", "--verbose", action="count",
                            help="if specified once, print every filtered syscall. " +
                                 "if specified twice, print every syscall, highlighting filtered syscalls")
    arg_parser.add_argument("--version", action="version", version="%(prog)s 0.4.0")
    args = arg_parser.parse_args(argv)

    initialize_terminal(args.style_output)

    if args.plugin is not None:
        for plugin_path in args.plugin:
            try:
                module_name = splitext(basename(plugin_path))[0]
                # Note: imp.load_source is *long* deprecated and not even documented
                # in Python 3 anymore, but it still seems to work and the "alternatives"
                # (see http://stackoverflow.com/a/67692) are simply too insane to use
                load_source(module_name, plugin_path)
            except Exception as error:
                print(T.red("Error loading %s: %s." % (T.bold(plugin_path) + T.red, error)))
                return 1

    if args.allow is not None:
        for filter_scope in args.allow:
            if filter_scope not in SYSCALL_FILTERS:
                print(T.red("Unknown operation in --allow: %s." % (T.bold(filter_scope) + T.red)))
                return 1
        filter_scopes = set(SYSCALL_FILTERS.keys()) - set(args.allow)
    elif args.deny is not None:
        for filter_scope in args.deny:
            if filter_scope not in SYSCALL_FILTERS:
                print(T.red("Unknown operation in --deny: %s." % (T.bold(filter_scope) + T.red)))
                return 1
        filter_scopes = args.deny
    else:
        filter_scopes = SYSCALL_FILTERS.keys()

    syscall_filters = {}

    for filter_scope in SYSCALL_FILTERS:
        if filter_scope in filter_scopes:
            for syscall in SYSCALL_FILTERS[filter_scope]:
                syscall_filters[syscall] = SYSCALL_FILTERS[filter_scope][syscall]

    # Suppress logging output from python-ptrace
    getLogger().addHandler(NullHandler())

    # Prevent python-ptrace from decoding arguments to keep raw numerical values
    DIRFD_ARGUMENTS.clear()
    SYSCALL_ARG_DICT.clear()
    ARGUMENT_CALLBACK.clear()

    # This is basically "shlex.join"
    command = " ".join([(("'%s'" % arg) if (" " in arg) else arg) for arg in args.command])

    try:
        args.command[0] = locateProgram(args.command[0])
        pid = createChild(args.command, False)
    except Exception as error:
        print(T.red("Error executing %s: %s." % (T.bold(command) + T.red, error)))
        return 1

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

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

    try:
        operations = get_operations(debugger, syscall_filters, args.verbose)
    except Exception as error:
        print(T.red("Error tracing process: %s." % error))
        return 1
    except KeyboardInterrupt:
        print(T.yellow("%s terminated by keyboard interrupt." % (T.bold(command) + T.yellow)))
        return 2
    finally:
        # Cut down all processes no matter what happens
        # to prevent them from doing any damage
        debugger.quit()

    if operations:
        if not args.list_only:
            print("%s has prevented %s from performing %d file system operations:\n" %
                  (T.bold("maybe"), T.bold(command), len(operations)))
        for operation in operations:
            print(("" if args.list_only else "  ") + operation)
        if not args.list_only:
            print("\nDo you want to rerun %s and permit these operations? [y/N] " % T.bold(command), end="")
            try:
                choice = input()
            except KeyboardInterrupt:
                choice = ""
                # Ctrl+C does not print a newline automatically
                print("")
            if choice.lower() == "y":
                subprocess.call(args.command)
    else:
        print("%s has not detected any file system operations from %s." %
              (T.bold("maybe"), T.bold(command)))
Exemple #16
0
def main(argv=sys.argv[1:]):
    filter_scopes = sorted(SYSCALL_FILTERS.keys())

    # Insert positional argument separator, if not already present
    if "--" not in argv:
        for i, argument in enumerate(argv):
            if not argument.startswith("-"):
                argv.insert(i, "--")
                break

    arg_parser = ArgumentParser(
        prog="maybe",
        usage="%(prog)s [options] command [argument ...]",
        description=
        "Run a command without the ability to make changes to your system " +
        "and list the changes it would have made.",
        epilog="For more information, to report issues or to contribute, " +
        "visit https://github.com/p-e-w/maybe.",
    )
    arg_parser.add_argument("command",
                            nargs="+",
                            help="the command to run under maybe's control")
    arg_group = arg_parser.add_mutually_exclusive_group()
    arg_group.add_argument(
        "-a",
        "--allow",
        nargs="+",
        choices=filter_scopes,
        metavar="OPERATION",
        help="allow the command to perform the specified operation(s). " +
        "all other operations will be denied. " +
        "possible values for %(metavar)s are: %(choices)s")
    arg_group.add_argument(
        "-d",
        "--deny",
        nargs="+",
        choices=filter_scopes,
        metavar="OPERATION",
        help="deny the command the specified operation(s). " +
        "all other operations will be allowed. " +
        "see --allow for a list of possible values for %(metavar)s. " +
        "--allow and --deny cannot be combined")
    arg_parser.add_argument(
        "-l",
        "--list-only",
        action="store_true",
        help="list operations without header, indentation and rerun prompt")
    arg_parser.add_argument(
        "--style-output",
        choices=["yes", "no", "auto"],
        default="auto",
        help="colorize output using ANSI escape sequences (yes/no) " +
        "or automatically decide based on whether stdout is a terminal (auto, default)"
    )
    arg_parser.add_argument(
        "-v",
        "--verbose",
        action="count",
        help="if specified once, print every filtered syscall. " +
        "if specified twice, print every syscall, highlighting filtered syscalls"
    )
    arg_parser.add_argument("--version",
                            action="version",
                            version="%(prog)s 0.4.0")
    args = arg_parser.parse_args(argv)

    initialize_terminal(args.style_output)

    if args.allow is not None:
        filter_scopes = set(filter_scopes) - set(args.allow)
    elif args.deny is not None:
        filter_scopes = args.deny

    syscall_filters = {}

    for filter_scope in filter_scopes:
        for syscall in SYSCALL_FILTERS[filter_scope]:
            syscall_filters[syscall] = SYSCALL_FILTERS[filter_scope][syscall]

    # Prevent python-ptrace from decoding arguments to keep raw numerical values
    DIRFD_ARGUMENTS.clear()
    SYSCALL_ARG_DICT.clear()
    ARGUMENT_CALLBACK.clear()

    # This is basically "shlex.join"
    command = " ".join([(("'%s'" % arg) if (" " in arg) else arg)
                        for arg in args.command])

    try:
        args.command[0] = locateProgram(args.command[0])
        pid = createChild(args.command, False)
    except Exception as error:
        print(
            T.red("Error executing %s: %s." %
                  (T.bold(command) + T.red, error)))
        return 1

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

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

    try:
        operations = get_operations(debugger, syscall_filters, args.verbose)
    except Exception as error:
        print(T.red("Error tracing process: %s." % error))
        return 1
    except KeyboardInterrupt:
        print(
            T.yellow("%s terminated by keyboard interrupt." %
                     (T.bold(command) + T.yellow)))
        return 2
    finally:
        # Cut down all processes no matter what happens
        # to prevent them from doing any damage
        debugger.quit()

    if operations:
        if not args.list_only:
            print(
                "%s has prevented %s from performing %d file system operations:\n"
                % (T.bold("maybe"), T.bold(command), len(operations)))
        for operation in operations:
            print(("" if args.list_only else "  ") + operation)
        if not args.list_only:
            try:
                choice = input(
                    "\nDo you want to rerun %s and permit these operations? [y/N] "
                    % T.bold(command))
            except KeyboardInterrupt:
                choice = ""
                # Ctrl+C does not print a newline automatically
                print("")
            if choice.lower() == "y":
                subprocess.call(args.command)
    else:
        print("%s has not detected any file system operations from %s." %
              (T.bold("maybe"), T.bold(command)))
Exemple #17
0
def main(argv=sys.argv[1:]):
    filter_scopes = sorted(SYSCALL_FILTERS.keys())

    # Insert positional argument separator, if not already present
    if "--" not in argv:
        for i, argument in enumerate(argv):
            if not argument.startswith("-"):
                argv.insert(i, "--")
                break

    arg_parser = ArgumentParser(
        prog="maybe",
        usage="%(prog)s [options] command [argument ...]",
        description="Run a command without the ability to make changes to your system " +
                    "and list the changes it would have made.",
        epilog="For more information, to report issues or to contribute, " +
               "visit https://github.com/p-e-w/maybe.",
    )
    arg_parser.add_argument("command", nargs="+", help="the command to run under maybe's control")
    arg_group = arg_parser.add_mutually_exclusive_group()
    arg_group.add_argument("-a", "--allow", nargs="+", choices=filter_scopes, metavar="OPERATION",
                           help="allow the command to perform the specified operation(s). " +
                                "all other operations will be denied. " +
                                "possible values for %(metavar)s are: %(choices)s")
    arg_group.add_argument("-d", "--deny", nargs="+", choices=filter_scopes, metavar="OPERATION",
                           help="deny the command the specified operation(s). " +
                                "all other operations will be allowed. " +
                                "see --allow for a list of possible values for %(metavar)s. " +
                                "--allow and --deny cannot be combined")
    arg_parser.add_argument("-l", "--list-only", action="store_true",
                            help="list operations without header, indentation and rerun prompt")
    arg_parser.add_argument("--style-output", choices=["yes", "no", "auto"], default="auto",
                            help="colorize output using ANSI escape sequences (yes/no) " +
                                 "or automatically decide based on whether stdout is a terminal (auto, default)")
    arg_parser.add_argument("-v", "--verbose", action="count",
                            help="if specified once, print every filtered syscall. " +
                                 "if specified twice, print every syscall, highlighting filtered syscalls")
    arg_parser.add_argument("--version", action="version", version="%(prog)s 0.4.0")
    args = arg_parser.parse_args(argv)

    initialize_terminal(args.style_output)

    if args.allow is not None:
        filter_scopes = set(filter_scopes) - set(args.allow)
    elif args.deny is not None:
        filter_scopes = args.deny

    syscall_filters = {}

    for filter_scope in filter_scopes:
        for syscall_filter in SYSCALL_FILTERS[filter_scope]:
            syscall_filters[syscall_filter.syscall] = syscall_filter

    # Prevent python-ptrace from decoding arguments to keep raw numerical values
    DIRFD_ARGUMENTS.clear()
    SYSCALL_ARG_DICT.clear()
    ARGUMENT_CALLBACK.clear()

    # This is basically "shlex.join"
    command = " ".join([(("'%s'" % arg) if (" " in arg) else arg) for arg in args.command])

    try:
        args.command[0] = locateProgram(args.command[0])
        pid = createChild(args.command, False)
    except Exception as error:
        print(T.red("Error executing %s: %s." % (T.bold(command) + T.red, error)))
        return 1

    debugger = PtraceDebugger()
    debugger.traceExec()
    try:
        debugger.traceFork()
    except DebuggerError:
        print(T.yellow("Warning: Running without traceFork support. " +
                       "Syscalls from subprocesses can not be intercepted."))

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

    try:
        operations = get_operations(debugger, syscall_filters, args.verbose)
    except Exception as error:
        print(T.red("Error tracing process: %s." % error))
        return 1
    except KeyboardInterrupt:
        print(T.yellow("%s terminated by keyboard interrupt." % (T.bold(command) + T.yellow)))
        return 2
    finally:
        # Cut down all processes no matter what happens
        # to prevent them from doing any damage
        debugger.quit()

    if operations:
        if not args.list_only:
            print("%s has prevented %s from performing %d file system operations:\n" %
                  (T.bold("maybe"), T.bold(command), len(operations)))
        for operation in operations:
            print(("" if args.list_only else "  ") + operation)
        if not args.list_only:
            try:
                choice = input("\nDo you want to rerun %s and permit these operations? [y/N] " % T.bold(command))
            except KeyboardInterrupt:
                choice = ""
                # Ctrl+C does not print a newline automatically
                print("")
            if choice.lower() == "y":
                subprocess.call(args.command)
    else:
        print("%s has not detected any file system operations from %s." %
              (T.bold("maybe"), T.bold(command)))
Exemple #18
0
def main(argv=sys.argv[1:]):
    # Insert positional argument separator, if not already present
    if "--" not in argv:
        for i, argument in enumerate(argv):
            if not argument.startswith("-"):
                argv.insert(i, "--")
                break

    arg_parser = ArgumentParser(
        prog="maybe",
        usage="%(prog)s [options] command [argument ...]",
        description="Run a command without the ability to make changes to your system " +
                    "and list the changes it would have made.",
        epilog="For more information, to report issues or to contribute, " +
               "visit https://github.com/p-e-w/maybe.",
    )
    arg_parser.add_argument("command", nargs="+", help="the command to run under maybe's control")
    arg_parser.add_argument("-l", "--list-only", action="store_true",
                            help="list operations without header, indentation and rerun prompt")
    arg_parser.add_argument("--style-output", choices=["yes", "no", "auto"], default="auto",
                            help="colorize output using ANSI escape sequences (yes/no) " +
                                 "or automatically decide based on whether stdout is a terminal (auto, default)")
    arg_parser.add_argument("-v", "--verbose", action="count",
                            help="if specified once, print every filtered syscall. " +
                                 "if specified twice, print every syscall, highlighting filtered syscalls")
    arg_parser.add_argument("--version", action="version", version="%(prog)s 0.4.0")
    args = arg_parser.parse_args(argv)

    initialize_terminal(args.style_output)

    # This is basically "shlex.join"
    command = " ".join([(("'%s'" % arg) if (" " in arg) else arg) for arg in args.command])

    try:
        args.command[0] = locateProgram(args.command[0])
        pid = createChild(args.command, False)
    except Exception as error:
        print(T.red("Error executing %s: %s." % (T.bold(command) + T.red, error)))
        return 1

    debugger = PtraceDebugger()
    debugger.traceExec()
    try:
        debugger.traceFork()
    except DebuggerError:
        print(T.yellow("Warning: Running without traceFork support. " +
                       "Syscalls from subprocesses can not be intercepted."))

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

    try:
        operations = get_operations(debugger, args)
    except Exception as error:
        print(T.red("Error tracing process: %s." % error))
        return 1
    except KeyboardInterrupt:
        print(T.yellow("%s terminated by keyboard interrupt." % (T.bold(command) + T.yellow)))
        return 2
    finally:
        # Cut down all processes no matter what happens
        # to prevent them from doing any damage
        debugger.quit()

    if operations:
        if not args.list_only:
            print("%s has prevented %s from performing %d file system operations:\n" %
                  (T.bold("maybe"), T.bold(command), len(operations)))
        for operation in operations:
            print(("" if args.list_only else "  ") + operation)
        if not args.list_only:
            try:
                choice = input("\nDo you want to rerun %s and permit these operations? [y/N] " % T.bold(command))
            except KeyboardInterrupt:
                choice = ""
                # Ctrl+C does not print a newline automatically
                print("")
            if choice.lower() == "y":
                subprocess.call(args.command)
    else:
        print("%s has not detected any file system operations from %s." %
              (T.bold("maybe"), T.bold(command)))
Exemple #19
0
class DebugServerManager(ServerManager):
    def __init__(self, config, queue_sync, queue_out, targetPort):
        ServerManager.__init__(self, config, queue_sync, queue_out, targetPort)
        self.dbg = None
        self.crashEvent = None
        self.proc = None
        self.p = None

    def _startServer(self):
        # create child via ptrace debugger
        # API: createChild(arguments[], no_stdout, env=None)
        logging.debug("START: " + str(
            serverutils.getInvokeTargetArgs(self.config, self.targetPort +
                                            1000)))
        self.pid = createChild(
            serverutils.getInvokeTargetArgs(self.config, self.targetPort),
            False,  # no_stdout
            None,
        )

        # Attach to the process with ptrace and let it run
        self.dbg = PtraceDebugger()
        self.proc = self.dbg.addProcess(self.pid, True)
        self.proc.cont()

        time.sleep(1)

        # i dont think this works here...
        # FIXME
        event = self.dbg.waitProcessEvent(blocking=False)
        if event is not None and type(event) == ProcessExit:
            logging.error("Started server, but it already exited: " +
                          str(event))
            return False

        return True

    def _stopServer(self):
        try:
            self.dbg.quit()
            os.kill(self.pid, signal.SIGTERM)
        except:
            # is already dead...
            pass

    def _waitForCrash(self):
        #subprocess.call("echo AAA1; ls -l /proc/" + str(self.pid), shell=True)
        while True:
            logging.info("DebugServer: Waiting for process event")
            event = self.dbg.waitProcessEvent()
            logging.info("DebugServer: Got event: " + str(event))
            # If this is a process exit we need to check if it was abnormal
            if type(event) == ProcessExit:
                if event.signum is None or event.exitcode == 0:
                    # Clear the event since this was a normal exit
                    event = None

            # If this is a signal we need to check if we're ignoring it
            elif type(event) == ProcessSignal:
                if event.signum == signal.SIGCHLD:
                    # Ignore these signals and continue waiting
                    continue
                elif event.signum == signal.SIGTERM:
                    # server cannot be started, return
                    event = None
                    self.queue_sync.put(("err", event.signum))

            break

        if event is not None and event.signum != 15:
            logging.info("DebugServer: Event Result: Crash")
            #subprocess.call("echo AAA2; ls -l /proc/" + str(self.pid), shell=True)
            self.crashEvent = event
            return True
        else:
            logging.info("DebugServer: Event Result: No crash")
            self.crashEvent = None
            return False

    def _getCrashDetails(self):
        event = self.crashEvent
        # Get the address where the crash occurred
        faultAddress = 0
        try:
            faultAddress = event.process.getInstrPointer()
        except Exception as e:
            # process already dead, hmm
            print(("GetCrashDetails exception: " + str(e)))

        # Find the module that contains this address
        # Now we need to turn the address into an offset. This way when the process
        # is loaded again if the module is loaded at another address, due to ASLR,
        # the offset will be the same and we can correctly detect those as the same
        # crash
        module = None
        faultOffset = 0

        try:
            for mapping in event.process.readMappings():
                if faultAddress >= mapping.start and faultAddress < mapping.end:
                    module = mapping.pathname
                    faultOffset = faultAddress - mapping.start
                    break
        except Exception as error:
            print("getCrashDetails Exception: " + str(error))
            # it always has a an exception...
            pass

        # Apparently the address didn't fall within a mapping
        if module is None:
            module = "Unknown"
            faultOffset = faultAddress

        # Get the signal
        sig = event.signum

        # Get the details of the crash
        details = None

        details = ""
        stackAddr = 0
        stackPtr = 0
        backtraceFrames = None
        pRegisters = None
        try:
            if event._analyze() is not None:
                details = event._analyze().text

            # more data
            stackAddr = self.proc.findStack()
            stackPtr = self.proc.getStackPointer()

            # convert backtrace
            backtrace = self.proc.getBacktrace()
            backtraceFrames = []
            for frame in backtrace.frames:
                backtraceFrames.append(str(frame))

            # convert registers from ctype to python
            registers = self.proc.getregs()
            pRegisters = {}
            for field_name, field_type in registers._fields_:
                regName = str(field_name)
                regValue = str(getattr(registers, field_name))
                pRegisters[regName] = regValue

        except Exception as e:
            # process already dead, hmm
            print(("GetCrashDetails exception: " + str(e)))

        vCrashData = verifycrashdata.VerifyCrashData(
            faultAddress=faultAddress,
            faultOffset=faultOffset,
            module=module,
            sig=sig,
            details=details,
            stackPointer=stackPtr,
            stackAddr=str(stackAddr),
            backtrace=backtraceFrames,
            registers=pRegisters,
        )

        asanOutput = serverutils.getAsanOutput(self.config, self.pid)
        vCrashData.setTemp(asanOutput)

        return vCrashData