def createText(self): value = self.value argtype = self.type name = self.name if not argtype or not name: return formatWordHex(self.value) syscall = self.function.name # Special cases try: return SYSCALL_ARG_DICT[syscall][name][value] except KeyError: pass try: callback = ARGUMENT_CALLBACK[syscall][name] except KeyError: callback = None if callback: return callback(value) if syscall == "execve": if name in ("argv", "envp"): return self.readCStringArray(value) if syscall == "socketcall": if name == "call": try: return SOCKETCALL[value][0] except KeyError: return str(value) if name == "args": func_call = FunctionCall("socketcall", self.options) setupSocketCall(func_call, self.function.process, self.function[0], self.value) text = "<%s>" % func_call.format() return self.formatPointer(text, self.value) if syscall == "write" and name == "buf": fd = self.function[0].value if fd < 3: length = self.function[2].value return self.readString(value, length) if name == "signum": return signalName(value) if name in FILENAME_ARGUMENTS: return self.readCString(value) # Remove "const " prefix if argtype.startswith("const "): argtype = argtype[6:] # Format depending on the type if argtype.endswith("*"): try: text = self.formatValuePointer(argtype[:-1]) if text: return text except PTRACE_ERRORS, err: writeError(getLogger(), err, "Format argument value error") value = None return formatAddress(self.value)
def main(self): self.debugger = PtraceDebugger() try: self.runDebugger() except KeyboardInterrupt: error("Interrupt debugger: quit!") except PTRACE_ERRORS as err: writeError(getLogger(), err, "Debugger error") self.process = None self.debugger.quit() error("Quit gdb.") self.restoreTerminal()
def __del__(self): try: if hasattr(self, 'is_active'): self.deactivate() if hasattr(self, "mailbox") and self.mailbox: self.mailbox.unregister() self.destroy() except KeyboardInterrupt: self.error("Agent destruction interrupted!") self.send('application_interrupt') except PTRACE_ERRORS, error: writeError(self, error, "Agent destruction error")
def connect(self, address, family, type, timeout=5.0): try: self.info("Create socket (family %s, type %s)" % (family, type)) self.socket = socket(family, type) self.socket.settimeout(timeout) self.info("Connect to %s" % formatAddress(family, address)) self.socket.connect(address) except socket_error, err: writeError( self, err, "Unable to connect to %s" % formatAddress(family, address)) self.socket = None self.send('application_error', 'Network connection failure')
def _main(self): self.debugger = PtraceDebugger() try: self.runDebugger() except ProcessExit as event: self.processExited(event) except PtraceError as err: error("ptrace() error: %s" % err) except KeyboardInterrupt: error("Interrupted.") except PTRACE_ERRORS as err: writeError(getLogger(), err, "Debugger error") self.debugger.quit()
def getText(self): if not self.text: try: text = self.createText() if text is not None: self.text = str(text) elif self.type and self.type.endswith("*"): self.text = formatAddress(self.value) else: self.text = repr(self.value) except PTRACE_ERRORS, err: writeError(getLogger(), err, "Format argument value error") self.text = repr(self.value)
def connect(self, address, family, type, timeout=5.0): try: self.info("Create socket (family %s, type %s)" % ( family, type)) self.socket = socket(family, type) self.socket.settimeout(timeout) self.info("Connect to %s" % formatAddress(family, address)) self.socket.connect(address) except socket_error, err: writeError(self, err, "Unable to connect to %s" % formatAddress(family, address)) self.socket = None self.send('application_error', 'Network connection failure')
def bind(self, address, family=AF_INET, type=SOCK_STREAM, reuse_address=True): try: self.socket = socket(family, type) if reuse_address: self.socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) self.family = family self.socket.bind(address) self.socket.listen(self.backlog) self.error("Server waiting on %s" % formatAddress(family, address)) except socket_error, err: writeError(self, err, "Unable to bind on %s" % formatAddress(family, address)) self.socket = None self.send('application_error', 'Network server bind error')
def getText(self): if not self.text: try: text = self.createText() if text is not None: self.text = str(text) elif self.type and self.type.endswith("*"): self.text = formatAddress(self.value) else: self.text = repr(self.value) except PTRACE_ERRORS as err: writeError(getLogger(), err, "Format argument %s of function %s() value error" % (self.name, self.function.name)) self.text = repr(self.value) return self.text
def getText(self): if not self.text: try: text = self.createText() if text is not None: self.text = str(text) elif self.type and self.type.endswith("*"): self.text = formatAddress(self.value) else: self.text = repr(self.value) except PTRACE_ERRORS as err: writeError( getLogger(), err, "Format argument %s of function %s() value error" % (self.name, self.function.name)) self.text = repr(self.value) return self.text
def readStruct(self, address, struct): address = self.value struct_name = struct.__name__ data = self.function.process.readStruct(address, struct) arguments = [] for name, argtype in struct._fields_: value = getattr(data, name) try: text = self.formatStructValue(struct_name, name, value) if text is not None: text = str(text) else: text = repr(value) except PTRACE_ERRORS, err: writeError(getLogger(), err, "Format struct value error") text = repr(value) arguments.append("%s=%s" % (name, text))
def _main(self): self.debugger = PtraceDebugger() try: self.runDebugger() except ProcessExit as event: self.processExited(event) except PtraceError as err: error("ptrace() error: %s" % err) except KeyboardInterrupt: error("Interrupted.") except PTRACE_ERRORS as err: writeError(getLogger(), err, "Debugger error") processes = list(self.debugger.list) self.debugger.quit() # python-ptrace seems iffy on actually detaching sometimes, so we make # sure we let the process continue for process in processes: subprocess.check_output(['kill', '-cont', str(process.pid)])
def _main(self): self.debugger = PtraceDebugger() exitcode = 0 try: exitcode = self.runDebugger() except ProcessExit as event: self.processExited(event) if event.exitcode is not None: exitcode = event.exitcode except PtraceError as err: error("ptrace() error: %s" % err) if err.errno is not None: exitcode = err.errno except KeyboardInterrupt: error("Interrupted.") exitcode = 1 except PTRACE_ERRORS as err: writeError(getLogger(), err, "Debugger error") exitcode = 1 self.debugger.quit() return exitcode
def runDebugger(self): self.setupDebugger() # Create new process try: self.process = self.createProcess() except ChildError as err: writeError(getLogger(), err, "Unable to create child process") return if not self.process: return # Trace syscalls self.invite = '(gdb) ' self.previous_command = None while True: if not self.debugger: # There is no more process: quit return done = self.mainLoop() if done: return
def main(self): self.debugger = PtraceDebugger() self.setupDebugger() # Create new process try: self.process = self.createProcess() except ChildError as err: writeError(getLogger(), err, "Unable to create child process") return if not self.process: return #self.backtrace() #self.process.dumpMaps() while True: if not self.debugger: # There is no more process: quit return # Execute the user command try: self.syscallTrace() except KeyboardInterrupt: self.interrupt() except NewProcessEvent as event: self.newProcess(event) except ProcessSignal as event: self.processSignal(event) except ProcessExit as event: error(event) self.nextProcess() except ProcessExecution as event: self.processExecution(event) except PtraceError as err: error("ERROR: %s" % err) if err.errno == ESRCH: self.deleteProcess(err.pid)
def runProcess(self, cmd): # print "Running", cmd signal(SIGALRM, alarm_handler) # if self.pid is None: # timeout = 20*self.timeout # else: timeout = 10 * self.timeout alarm(timeout) # Create new process try: self.process = self.createProcess(cmd, self.envs, self.no_stdout) self.process.no_frame_pointer = self.elf.no_frame_pointer #self.mm = MemoryMaps(self.program, self.pid) # print self.mm self.crashed = False except ChildError as err: print "a" writeError(getLogger(), err, "Unable to create child process") return except OSError as err: print "b" writeError(getLogger(), err, "Unable to create child process") return except IOError as err: print "c" writeError(getLogger(), err, "Unable to create child process") return if not self.process: return # Set the breakpoints self.breakpoint(self.elf.GetEntrypoint()) # print hex(self.elf.GetEntrypoint()) try: while True: # self.cont() # if self.nevents > self.max_events: # # self.events.append(Timeout(timeout)) # alarm(0) # return if not self.debugger or self.crashed: # There is no more process: quit alarm(0) return else: self.cont() # alarm(0) # except PtraceError: # print "deb:",self.debugger, "crash:", self.crashed # print "PtraceError" # alarm(0) # return except ProcessExit as event: alarm(0) self.events.append(Exit(event.exitcode)) return except OSError: alarm(0) self.events.append(Timeout(timeout)) self.timeouts += 1 return except IOError: alarm(0) self.events.append(Timeout(timeout)) self.timeouts += 1 return except TimeoutEx: self.events.append(Timeout(timeout)) return
def _destroy(self, agent): try: agent.deactivate() except PTRACE_ERRORS, error: writeError(None, error, "Agent deinit error")
def createText(self): value = self.value argtype = self.type name = self.name if not argtype or not name: return formatWordHex(self.value) syscall = self.function.name # Special cases try: return SYSCALL_ARG_DICT[syscall][name][value] except KeyError: pass try: callback = ARGUMENT_CALLBACK[syscall][name] except KeyError: callback = None if callback: return callback(self) if syscall == "execve": if name in ("argv", "envp"): return self.readCStringArray(value) if syscall == "socketcall": if name == "call": try: return SOCKETCALL[value] except KeyError: return str(value) if name == "args": func_call = FunctionCall("socketcall", self.options) setupSocketCall(func_call, self.function.process, self.function[0], self.value) text = "<%s>" % func_call.format() return self.formatPointer(text, self.value) if syscall == "write" and name == "buf": fd = self.function[0].value if fd < 3: length = self.function[2].value return self.readString(value, length) if name == "signum": return signalName(value) if name in DIRFD_ARGUMENTS and argtype == "int": return formatDirFd(uint2int(value)) # Remove "const " prefix if argtype.startswith("const "): argtype = argtype[6:] if name in FILENAME_ARGUMENTS and argtype == "char *": return self.readCString(value) # Format depending on the type if argtype.endswith("*"): try: text = self.formatValuePointer(argtype[:-1]) if text: return text except PTRACE_ERRORS as err: writeError(getLogger(), err, "Warning: Format %r value error" % self, log_level=INFO) return formatAddress(self.value) # Array like "int[2]" match = re.match("(.*)\[([0-9])+\]", argtype) if match: basetype = match.group(1) count = int(match.group(2)) if basetype == "int": return self.readArray(self.value, c_int, count) # Simple types if argtype in ("unsigned int", "unsigned long", "u32"): return str(self.value) if argtype in INTEGER_TYPES: return str(uint2int(self.value)) # Default formatter: hexadecimal return formatWordHex(self.value)
def runProcess(self, cmd): # print("Running", cmd) signal(SIGALRM, alarm_handler) # if self.pid is None: # timeout = 20*self.timeout # else: timeout = 10 * self.timeout alarm(timeout) # Create new process try: self.process = self.createProcess(cmd, self.envs, self.no_stdout) # create logger to get mappings dump ptrace_logger = getLogger('save_ptrace_logs') ptrace_logger.setLevel(INFO) # save to temp file to avoid console printing log_output_file = NamedTemporaryFile() fh = FileHandler(log_output_file.name) fh.setLevel(INFO) ptrace_logger.addHandler(fh) ptrace_logger.propagate = False #get dump of mappings to find offset self.process.dumpMaps(ptrace_logger.info) offset_mappings = open(log_output_file.name).read() self.offset = int(re.findall (r'0x[0-9a-fA-F]+-', offset_mappings)[0].replace("-", ""), 16) self.elf = ELF(self.program, plt=False, offset=self.offset) self.process.no_frame_pointer = self.elf.no_frame_pointer #self.mm = MemoryMaps(self.program, self.pid) # print(self.mm) self.crashed = False except ChildError as err: print("a") writeError(getLogger(), err, "Unable to create child process") return except OSError as err: print("b") writeError(getLogger(), err, "Unable to create child process") return except IOError as err: print("c") writeError(getLogger(), err, "Unable to create child process") return if not self.process: return # Set the breakpoints self.breakpoint(self.elf.GetEntrypoint()) # print(hex(self.elf.GetEntrypoint())) try: while True: # self.cont() # if self.nevents > self.max_events: # # self.events.append(Timeout(timeout)) # alarm(0) # return if not self.debugger or self.crashed: # There is no more process: quit alarm(0) return else: self.cont() # alarm(0) # except PtraceError: # print("deb:",self.debugger, "crash:", self.crashed) # print("PtraceError") # alarm(0) # return except ProcessExit as event: alarm(0) self.events.append(Exit(event.exitcode)) return except OSError: alarm(0) self.events.append(Timeout(timeout)) self.timeouts += 1 return except IOError: alarm(0) self.events.append(Timeout(timeout)) self.timeouts += 1 return except TimeoutEx: self.events.append(Timeout(timeout)) return