Beispiel #1
0
    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()
Beispiel #2
0
    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()
Beispiel #3
0
    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
Beispiel #4
0
    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
Beispiel #5
0
    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 []
Beispiel #6
0
    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()
Beispiel #7
0
    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 []
Beispiel #8
0
    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()