def count(self, signature=None): """ Counts how many crash dumps have been stored in this database. Optionally filters the count by heuristic signature. @type signature: object @param signature: (Optional) Count only the crashes that match this signature. See L{Crash.signature} for more details. @rtype: int @return: Count of crash dumps stored in this database. """ query = self._session.query(CrashDTO.id) if signature: sig_pickled = pickle.dumps(signature, protocol=0) query = query.filter_by(signature=sig_pickled) return query.count()
def count(self, signature = None): """ Counts how many crash dumps have been stored in this database. Optionally filters the count by heuristic signature. @type signature: object @param signature: (Optional) Count only the crashes that match this signature. See L{Crash.signature} for more details. @rtype: int @return: Count of crash dumps stored in this database. """ query = self._session.query(CrashDTO.id) if signature: sig_pickled = pickle.dumps(signature, protocol = 0) query = query.filter_by(signature = sig_pickled) return query.count()
def add(self, crash, allow_duplicates=True): """ Add a new crash dump to the database, optionally filtering them by signature to avoid duplicates. @type crash: L{Crash} @param crash: Crash object. @type allow_duplicates: bool @param allow_duplicates: (Optional) C{True} to always add the new crash dump. C{False} to only add the crash dump if no other crash with the same signature is found in the database. Sometimes, your fuzzer turns out to be I{too} good. Then you find youself browsing through gigabytes of crash dumps, only to find a handful of actual bugs in them. This simple heuristic filter saves you the trouble by discarding crashes that seem to be similar to another one you've already found. """ # Filter out duplicated crashes, if requested. if not allow_duplicates: signature = pickle.dumps(crash.signature, protocol=0) if self._session.query(CrashDTO.id) \ .filter_by(signature = signature) \ .count() > 0: return # Fill out a new row for the crashes table. crash_id = self.__add_crash(crash) # Fill out new rows for the memory dump. self.__add_memory(crash_id, crash.memoryMap) # On success set the row ID for the Crash object. # WARNING: In nested calls, make sure to delete # this property before a session rollback! crash._rowid = crash_id
def add(self, crash, allow_duplicates = True): """ Add a new crash dump to the database, optionally filtering them by signature to avoid duplicates. @type crash: L{Crash} @param crash: Crash object. @type allow_duplicates: bool @param allow_duplicates: (Optional) C{True} to always add the new crash dump. C{False} to only add the crash dump if no other crash with the same signature is found in the database. Sometimes, your fuzzer turns out to be I{too} good. Then you find youself browsing through gigabytes of crash dumps, only to find a handful of actual bugs in them. This simple heuristic filter saves you the trouble by discarding crashes that seem to be similar to another one you've already found. """ # Filter out duplicated crashes, if requested. if not allow_duplicates: signature = pickle.dumps(crash.signature, protocol = 0) if self._session.query(CrashDTO.id) \ .filter_by(signature = signature) \ .count() > 0: return # Fill out a new row for the crashes table. crash_id = self.__add_crash(crash) # Fill out new rows for the memory dump. self.__add_memory(crash_id, crash.memoryMap) # On success set the row ID for the Crash object. # WARNING: In nested calls, make sure to delete # this property before a session rollback! crash._rowid = crash_id
def find(self, signature=None, order=0, since=None, until=None, offset=None, limit=None): """ Retrieve all crash dumps in the database, optionally filtering them by signature and timestamp, and/or sorting them by timestamp. Results can be paged to avoid consuming too much memory if the database is large. @see: L{find_by_example} @type signature: object @param signature: (Optional) Return only through crashes matching this signature. See L{Crash.signature} for more details. @type order: int @param order: (Optional) Sort by timestamp. If C{== 0}, results are not sorted. If C{> 0}, results are sorted from older to newer. If C{< 0}, results are sorted from newer to older. @type since: datetime @param since: (Optional) Return only the crashes after and including this date and time. @type until: datetime @param until: (Optional) Return only the crashes before this date and time, not including it. @type offset: int @param offset: (Optional) Skip the first I{offset} results. @type limit: int @param limit: (Optional) Return at most I{limit} results. @rtype: list(L{Crash}) @return: List of Crash objects. """ # Validate the parameters. if since and until and since > until: warnings.warn("CrashDAO.find() got the 'since' and 'until'" " arguments reversed, corrected automatically.") since, until = until, since if limit is not None and not limit: warnings.warn("CrashDAO.find() was set a limit of 0 results," " returning without executing a query.") return [] # Build the SQL query. query = self._session.query(CrashDTO) if signature is not None: sig_pickled = pickle.dumps(signature, protocol=0) query = query.filter(CrashDTO.signature == sig_pickled) if since: query = query.filter(CrashDTO.timestamp >= since) if until: query = query.filter(CrashDTO.timestamp < until) if order: if order > 0: query = query.order_by(asc(CrashDTO.timestamp)) else: query = query.order_by(desc(CrashDTO.timestamp)) else: # Default ordering is by row ID, to get consistent results. # Also some database engines require ordering when using offsets. query = query.order_by(asc(CrashDTO.id)) if offset: query = query.offset(offset) if limit: query = query.limit(limit) # Execute the SQL query and convert the results. try: return [dto.toCrash() for dto in query.all()] except NoResultFound: return []
def __init__(self, crash): """ @type crash: Crash @param crash: L{Crash} object to store into the database. """ # Timestamp and signature. self.timestamp = datetime.datetime.fromtimestamp(crash.timeStamp) self.signature = pickle.dumps(crash.signature, protocol=0) # Marshalled Crash object, minus the memory dump. # This code is *not* thread safe! memoryMap = crash.memoryMap try: crash.memoryMap = None self.data = buffer(Marshaller.dumps(crash)) finally: crash.memoryMap = memoryMap # Exploitability test. self.exploitability_rating, \ self.exploitability_rule, \ self.exploitability_desc = crash.isExploitable() # Exploitability test as an integer result (for sorting). self.exploitable = [ "Not an exception", "Not exploitable", "Not likely exploitable", "Unknown", "Probably exploitable", "Exploitable", ].index(self.exploitability_rating) # Platform description. self.os = crash.os self.arch = crash.arch self.bits = crash.bits # Event description. self.event = crash.eventName self.pid = crash.pid self.tid = crash.tid self.pc = crash.pc self.sp = crash.sp self.fp = crash.fp self.pc_label = crash.labelPC # Exception description. self.exception = crash.exceptionName self.exception_text = crash.exceptionDescription self.exception_address = crash.exceptionAddress self.exception_label = crash.exceptionLabel self.first_chance = crash.firstChance self.fault_type = crash.faultType self.fault_address = crash.faultAddress self.fault_label = crash.faultLabel self.fault_disasm = CrashDump.dump_code(crash.faultDisasm, crash.pc) self.stack_trace = CrashDump.dump_stack_trace_with_labels( crash.stackTracePretty) # Command line. self.command_line = crash.commandLine # Environment. if crash.environment: envList = crash.environment.items() envList.sort() environment = '' for envKey, envVal in envList: # Must concatenate here instead of using a substitution, # so strings can be automatically promoted to Unicode. environment += envKey + '=' + envVal + '\n' if environment: self.environment = environment # Debug string. self.debug_string = crash.debugString # Notes. self.notes = crash.notesReport()
def find(self, signature = None, order = 0, since = None, until = None, offset = None, limit = None): """ Retrieve all crash dumps in the database, optionally filtering them by signature and timestamp, and/or sorting them by timestamp. Results can be paged to avoid consuming too much memory if the database is large. @see: L{find_by_example} @type signature: object @param signature: (Optional) Return only through crashes matching this signature. See L{Crash.signature} for more details. @type order: int @param order: (Optional) Sort by timestamp. If C{== 0}, results are not sorted. If C{> 0}, results are sorted from older to newer. If C{< 0}, results are sorted from newer to older. @type since: datetime @param since: (Optional) Return only the crashes after and including this date and time. @type until: datetime @param until: (Optional) Return only the crashes before this date and time, not including it. @type offset: int @param offset: (Optional) Skip the first I{offset} results. @type limit: int @param limit: (Optional) Return at most I{limit} results. @rtype: list(L{Crash}) @return: List of Crash objects. """ # Validate the parameters. if since and until and since > until: warnings.warn("CrashDAO.find() got the 'since' and 'until'" " arguments reversed, corrected automatically.") since, until = until, since if limit is not None and not limit: warnings.warn("CrashDAO.find() was set a limit of 0 results," " returning without executing a query.") return [] # Build the SQL query. query = self._session.query(CrashDTO) if signature is not None: sig_pickled = pickle.dumps(signature, protocol = 0) query = query.filter(CrashDTO.signature == sig_pickled) if since: query = query.filter(CrashDTO.timestamp >= since) if until: query = query.filter(CrashDTO.timestamp < until) if order: if order > 0: query = query.order_by(asc(CrashDTO.timestamp)) else: query = query.order_by(desc(CrashDTO.timestamp)) else: # Default ordering is by row ID, to get consistent results. # Also some database engines require ordering when using offsets. query = query.order_by(asc(CrashDTO.id)) if offset: query = query.offset(offset) if limit: query = query.limit(limit) # Execute the SQL query and convert the results. try: return [dto.toCrash() for dto in query.all()] except NoResultFound: return []
def __init__(self, crash): """ @type crash: Crash @param crash: L{Crash} object to store into the database. """ # Timestamp and signature. self.timestamp = datetime.datetime.fromtimestamp( crash.timeStamp ) self.signature = pickle.dumps(crash.signature, protocol = 0) # Marshalled Crash object, minus the memory dump. # This code is *not* thread safe! memoryMap = crash.memoryMap try: crash.memoryMap = None self.data = buffer( Marshaller.dumps(crash) ) finally: crash.memoryMap = memoryMap # Exploitability test. self.exploitability_rating, \ self.exploitability_rule, \ self.exploitability_desc = crash.isExploitable() # Exploitability test as an integer result (for sorting). self.exploitable = [ "Not an exception", "Not exploitable", "Not likely exploitable", "Unknown", "Probably exploitable", "Exploitable", ].index(self.exploitability_rating) # Platform description. self.os = crash.os self.arch = crash.arch self.bits = crash.bits # Event description. self.event = crash.eventName self.pid = crash.pid self.tid = crash.tid self.pc = crash.pc self.sp = crash.sp self.fp = crash.fp self.pc_label = crash.labelPC # Exception description. self.exception = crash.exceptionName self.exception_text = crash.exceptionDescription self.exception_address = crash.exceptionAddress self.exception_label = crash.exceptionLabel self.first_chance = crash.firstChance self.fault_type = crash.faultType self.fault_address = crash.faultAddress self.fault_label = crash.faultLabel self.fault_disasm = CrashDump.dump_code( crash.faultDisasm, crash.pc ) self.stack_trace = CrashDump.dump_stack_trace_with_labels( crash.stackTracePretty ) # Command line. self.command_line = crash.commandLine # Environment. if crash.environment: envList = crash.environment.items() envList.sort() environment = '' for envKey, envVal in envList: # Must concatenate here instead of using a substitution, # so strings can be automatically promoted to Unicode. environment += envKey + '=' + envVal + '\n' if environment: self.environment = environment # Debug string. self.debug_string = crash.debugString # Notes. self.notes = crash.notesReport()