def injectmex64(pid, shellcode): from sys import platform if platform.startswith('win'): print("\nPtrace not working on windows machines ..\n") return False else: try: from ptrace.debugger.debugger import PtraceDebugger from ptrace.debugger.debugger import PtraceProcess except ImportError: print( "\nYou must install ptrace library before use this script.\n") return False else: try: dbg = PtraceDebugger() process = dbg.addProcess(int(pid), False) rip = process.getInstrPointer() bytes = process.writeBytes( rip, shellcode.replace("\\x", "").decode("hex")) process.setreg("rbx", 0) process.cont() except Exception as error: print(error) print("\nPlease do not forget report !\n") else: print("\nInject complate !\n")
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()
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 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 injectmex64(pid, shellcode): from sys import platform if platform.startswith('win'): print ("\nPtrace not working on windows machines ..\n") return False else: try: from ptrace.debugger.debugger import PtraceDebugger from ptrace.debugger.debugger import PtraceProcess except ImportError: print ("\nYou must install ptrace library before use this script.\n") return False else: try: dbg = PtraceDebugger() process = dbg.addProcess(int(pid), False) rip = process.getInstrPointer() bytes = process.writeBytes(rip, shellcode.replace("\\x", "").decode("hex")) process.setreg("rbx", 0) process.cont() except Exception as error: print (error) print ("\nPlease do not forget report !\n") else: print ("\nInject complate !\n")
def __init__(self, pid): self.maps = [] self.pid = pid self.current_ip = None self.tracer = PtraceDebugger() self.process = False self.attached = False
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)
def start(self): pid = createChild(["/tmp/test"], False) debugger = PtraceDebugger() debugger.addProcess(pid, True) debugger.enableSysgood() process = debugger[pid] process.syscall() e = process.waitEvent() assert isinstance(e, ptrace_debugger.ProcessSignal) return debugger, process
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()
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]
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)))
def fuzzPOPmain(ip, port, username, password, toAttach, pid): if toAttach: #local service, being attached if int(pid)<0: print 'Invalid PID. Make sure is correct if you want to attach a local service' exit(1) else: #valid PID, so create debugger & attach it dbg=PtraceDebugger() process = dbg.addProcess(pid, is_attached) is_attached = True process.cont() else: process='' #last parameter of actualPOPfuzz here should be process, but turns out library cannot work like this. Perhaps due to way programs are implemented, or way operating systems. Either way it cannot actually work, meaning that a debugger will need to be manually attached to the running server. actualPOPfuzz(ip, port, username, password, '')
def findCipherContext(): dbg=PtraceDebugger() process=dbg.addProcess(pid,is_attached=False) if process is None: log.error("Error initializing Process debugging for %d"% pid) sys.exit(-1) mappings=readProcessMappings(process) stack=process.findStack() for m in mappings: #if m.pathname != '[heap]': # continue if not abouchet.hasValidPermissions(m): continue print m,m.permissions abouchet.find_struct(process, m, ctypes_openssh.CipherContext, printme)
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)))
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()
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]
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()
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()
def fuzzFTPmain(ip, port, username, password, toAttach, pid): is_attached = False if toAttach: if int(pid)>=0: #valid PID, so create debugger & attach it dbg=PtraceDebugger() process = dbg.addProcess(pid, is_attached) print 'Attaching debugger...' is_attached = True process.cont() else: print 'If connecting a server, need a valid PID, otherwise set 4th arguments to False' exit(1) else: #not attaching process = '' #call to actualFTPfuzz should have process as last argument, but turns out the library will not work like that, making it impossible to implement as I would've liked. This means a debugger will have to be physically attached. actualFTPfuzz(True, username, password, port, ip, '') actualFTPfuzz(False, username, password, port, ip, '')
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}")
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
def readRsa(addr): dbg=PtraceDebugger() process=dbg.addProcess(PID, is_attached=False) if process is None: log.error("Error initializing Process debugging for %d"% PID) sys.exit(-1) # read where it is ######################### RAAAAAAAAAAAAH rsa=ctypes_openssl.RSA.from_buffer_copy(process.readStruct(addr,ctypes_openssl.RSA)) mappings=readProcessMappings(process) print "isValid : ", rsa.isValid(mappings) #rsa.printValid(maps) print rsa #print rsa.n #print rsa.n.contents #print ctypes.byref(rsa.n.contents) #print rsa print '------------ === Loading members' ret=rsa.loadMembers(process,mappings) print '------------ === Loading members finished' print ret,rsa return rsa
def readDsa(addr): dbg=PtraceDebugger() process=dbg.addProcess(PID, is_attached=False) if process is None: log.error("Error initializing Process debugging for %d"% pid) sys.exit(-1) # read where it is dsa=ctypes_openssl.DSA.from_buffer_copy(process.readStruct(addr,ctypes_openssl.DSA)) mappings=readProcessMappings(process) print "isValid : ", dsa.isValid(mappings) #dsa.printValid(maps) #print 'DSA1 -> ', dsa #print '------------' #print 'DSA1.q -> ', dsa.q print '------------ === Loading members' dsa.loadMembers(process,mappings) #print '------------ ===== ==== ' #print 'DSA2.q -> ', dsa.q #print 'DSA2.q.contents -> ', dsa.q.contents #print ctypes.byref(rsa.n.contents) #print dsa return dsa
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(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)))
def attach(pid): print "%s{+} Attaching to %s %s" % (cyan, pid, clear) dbg = PtraceDebugger() process = dbg.addProcess(int(pid), False) return process
def __init__(self, pid) : self.tracer = PtraceProcess(PtraceDebugger(), pid, True)
def doFuzz(config, setupEnvironment=_setupEnvironment, chooseInput=_chooseInput, generateSeed=_generateSeed, runFuzzer=_runFuzzer, runTarget=_runTarget, checkForCrash=_checkForCrash, handleOutcome=_handleOutcome): seed = 0 count = 0 haveOutcome = False outcome = None done = False # Step 1: Setup environment setupEnvironment(config) print "Running fuzzer:", config["fuzzer"] sys.stdout.write("%8d: " % (0)) sys.stdout.flush() while not done: # Step 2: Choose an input inFile = chooseInput(config) # We're done if no input is returned if inFile is None: print "\nNo more inputs, exiting." break # Step 3: Generate a seed seed = generateSeed(config) # Generate a name for the output file outExt = os.path.splitext(inFile)[1] outFile = os.path.join(os.getcwd(), str(seed) + outExt) # Step 4: Run fuzzer runFuzzer(config, inFile, seed, outFile, count) # Step 5: Run the target pid = runTarget(config, outFile) ####################################################################### # This is where the magic happens. We monitor the process to determine # if it has crashed # Attach to the process with ptrace dbg = PtraceDebugger() proc = dbg.addProcess(pid, True) proc.cont() # Calculate the maximum time the target will be allowed to run endTime = time.time() + config["target_timeout"] outcome = None while True: try: # Check if there is an event pending for the target applicaiton # This will return immediately with either an event or None if # there is no event. We do this so we can kill the target after # it reaches the timeout event = dbg.waitProcessEvent(blocking=False) # Check if the process exited if type(event) == ProcessExit: # Step 6: Check for crash outcome = checkForCrash(config, event) # The target application exited so we're done here break elif type(event) == ProcessSignal: # SIGCHLD simply notifies the parent that one of it's # children processes has exited or changed (exec another # process). It's not a bug so we tell the process to # continue and we loop again to get the next event if event.signum == SIGCHLD: event.process.cont() continue outcome = checkForCrash(config, event) break except KeyboardInterrupt: done = True break # Check if the process has reached the timeout if time.time() >= endTime: break else: # Give the CPU some timeslices to run other things time.sleep(0.1) # Step 7: Handle any crashes if outcome is not None: handleOutcome(config, outcome, inFile, seed, outFile, count) haveOutcome = True # Done with the process proc.terminate() # Delete the output try: os.remove(outFile) except: print "Failed to remove file %s!" % outFile # Update the counter and display the visual feedback count += 1 if count % 2 == 0: if haveOutcome: sys.stdout.write("!") haveOutcome = False else: sys.stdout.write(".") sys.stdout.flush() if count % 100 == 0: sys.stdout.write("\n%8d: " % count) sys.stdout.flush()
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)))
def __init__(self, pid=None): self.sessions = {} self.connections = {} self.dbg = PtraceDebugger() self.processes = {}
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])
pool = Pool(processes=1) result = pool.apply_async(async_call) while not isStarted: for pid in psutil.pids(): if psutil.Process(pid).name() == 'hon-x86_64': hon_pid = pid isStarted = True print('isStarted == True\npid={}'.format(hon_pid)) break time.sleep(10.0) print('sleeping...') print('starting debugger') dbg = PtraceDebugger() process = dbg.addProcess(hon_pid, False) memory_mapping = readProcessMappings(process) print('found memory mappings') _next = False for addr in memory_mapping: if _next == True: for a in range(addr.start, addr.end, 4): value = bytesToFloat(process.readBytes(a, 4)) if value == 1850.: print("value is {} at addr {}".format(value, hex(a))) process.writeBytes(a, floatToBytes(2400.)) break if 'rw' in addr.permissions and addr.pathname and 'libgame_shared' in addr.pathname:
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()
def attach(pid): print "%s{+} Attaching to %s %s" %(cyan, pid, clear) dbg = PtraceDebugger() process = dbg.addProcess(int(pid), False) return process
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
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)))
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)))