def calculate(self):
        address_space = utils.load_as(self._config, astype='physical')

        # definite values in Downloads records
        scanner = FirefoxScanner(needles=[
            '\x06\x06\x08',
            '\x06\x06\x09',
        ])
        downloads = {}
        for offset in scanner.scan(address_space):
            ff_buff = address_space.read(offset - 16, 3000)
            start = 16

            good = False

            start -= 1
            (tempPath_length,
             varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
            tempPath_length = sqlite_help.varint_to_text_length(
                tempPath_length)

            # work backward from the start of the needle to the first field payload_length
            start -= varint_len
            (target_length,
             varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
            target_length = sqlite_help.varint_to_text_length(target_length)

            start -= varint_len
            (source_length,
             varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
            source_length = sqlite_help.varint_to_text_length(source_length)

            start -= varint_len
            (name_length,
             varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
            name_length = sqlite_help.varint_to_text_length(name_length)

            start -= varint_len
            (id_length,
             varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)

            start -= varint_len
            (payload_header_length,
             varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)

            start -= varint_len
            (row_id,
             varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)

            start -= varint_len
            (payload_length,
             varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)

            # jump back to the needle, startTime_length
            start = 16

            # get all of the single byte lengths around the needle
            (startTime_length, startTime) = sqlite_help.varint_type_to_length(
                ord(ff_buff[start]))
            (endTime_length, endTime) = sqlite_help.varint_type_to_length(
                ord(ff_buff[start + 1]))
            (state_length, state) = sqlite_help.varint_type_to_length(
                ord(ff_buff[start + 2]))

            # get the rest of the fields in the row moving forward
            start = 19
            (referrer_length,
             varint_len) = sqlite_help.find_varint(ff_buff, start, FORWARD)
            referrer_length = sqlite_help.varint_to_text_length(
                referrer_length)
            start += varint_len

            (entityID_length,
             varint_len) = sqlite_help.find_varint(ff_buff, start, FORWARD)
            entityID_length = sqlite_help.varint_to_text_length(
                entityID_length)
            start += varint_len

            (currBytes_length, currBytes) = sqlite_help.varint_type_to_length(
                ord(ff_buff[start]))
            (maxBytes_length, maxBytes) = sqlite_help.varint_type_to_length(
                ord(ff_buff[start + 1]))

            start += 2

            (mimeType_length,
             varint_len) = sqlite_help.find_varint(ff_buff, start, FORWARD)
            mimeType_length = sqlite_help.varint_to_text_length(
                mimeType_length)
            start += varint_len

            (preferredApplication_length,
             varint_len) = sqlite_help.find_varint(ff_buff, start, FORWARD)
            preferredApplication_length = sqlite_help.varint_to_text_length(
                preferredApplication_length)
            start += varint_len

            (preferredAction_length,
             preferredAction) = sqlite_help.varint_type_to_length(
                 ord(ff_buff[start]))
            (autoResume_length,
             autoResume) = sqlite_help.varint_type_to_length(
                 ord(ff_buff[start + 1]))

            start += 2

            name = ff_buff[start:start + name_length]
            start += name_length

            source = ff_buff[start:start + source_length]
            start += source_length

            target = ff_buff[start:start + target_length]
            start += target_length

            tempPath = ff_buff[start:start + tempPath_length]
            start += tempPath_length

            # do some checks on the startTime/endTime to make sure they are valid
            startTime = ff_buff[start:start + startTime_length]
            startTime = sqlite_help.sql_unpack(startTime)
            if startTime > 0 and startTime:
                startTime = sqlite_help.get_nixtime_from_msec(startTime)
            if type(startTime) is not datetime:
                continue
            start += startTime_length

            endTime = ff_buff[start:start + endTime_length]
            endTime = sqlite_help.sql_unpack(endTime)
            if endTime > 0 and startTime:
                endTime = sqlite_help.get_nixtime_from_msec(endTime)
            if type(endTime) is not datetime:
                continue
            start += endTime_length

            # if both dates are 1970, it's probably a bad record and not very useful, so skip
            # if only 1 is 1970, print it because it may be an old record with one valid date
            if startTime.year == 1970 and endTime.year == 1970:
                continue

            if state_length > 0:
                state = sqlite_help.sql_unpack(ff_buff[start:start +
                                                       state_length])
            start += state_length

            referrer = ff_buff[start:start + referrer_length]
            start += referrer_length

            entityID = ff_buff[start:start + entityID_length]
            start += entityID_length

            currBytes = ff_buff[start:start + currBytes_length]
            currBytes = sqlite_help.sql_unpack(currBytes)
            # skip if negative or greater than 1TB
            if currBytes < 0 or currBytes > 1000000000000:
                continue
            start += currBytes_length

            maxBytes = ff_buff[start:start + maxBytes_length]
            maxBytes = sqlite_help.sql_unpack(maxBytes)
            # skip if negative or greater than 1TB
            if maxBytes < 0 or maxBytes > 1000000000000:
                continue
            start += maxBytes_length

            mimeType = ff_buff[start:start + mimeType_length]
            start += mimeType_length

            preferredApplication = ff_buff[start:start +
                                           preferredApplication_length]
            start += preferredApplication_length

            # these fields can have a value 0x8 or 0x9 in the length field
            # in that case, the "data" portion is not there, and the value is impled
            # to be 0 or 1, respectively
            if preferredAction_length > 0:
                preferredAction = ff_buff[start:start + preferredAction_length]
                preferredAction = sqlite_help.sql_unpack(preferredAction)
            start += preferredAction_length

            if autoResume_length > 0:
                autoResume = ff_buff[start:start + autoResume_length]
                autoResume = sqlite_help.sql_unpack(autoResume)
            start += autoResume_length

            # add all the fields to a tuple so we only print a unique record once
            downloads_tuple = (row_id, name, source, target, tempPath,
                               startTime, endTime, state, referrer, entityID,
                               currBytes, maxBytes, mimeType,
                               preferredApplication, preferredAction,
                               autoResume)
            if not downloads.get(downloads_tuple):
                downloads[downloads_tuple] = downloads.get(downloads_tuple,
                                                           0) + 1
                yield downloads_tuple
    def calculate(self):
        address_space = utils.load_as(self._config, astype='physical')

        # definite values in History records
        scanner = FirefoxScanner(needles=[
            '\x06\x25',
            '\x00\x25',
        ])
        urls = {}
        for offset in scanner.scan(address_space):
            ff_buff = address_space.read(offset - 21, 3000)
            start = 21
            # new field foreign_count added around Firefox v34
            foreign_count_length = 0
            foreign_count = "N/A"

            # start before the needle match and work backwards
            if ord(ff_buff[start - 1]) in (1, 2, 8, 9):
                start -= 1
                (frecency_length,
                 frecency) = sqlite_help.varint_type_to_length(
                     ord(ff_buff[start]))
            else:
                continue

            if ord(ff_buff[start - 1]) in (0, 1, 8, 9):
                start -= 1
                (favicon_id_length,
                 favicon_id) = sqlite_help.varint_type_to_length(
                     ord(ff_buff[start]))
            else:
                continue

            if ord(ff_buff[start - 1]) not in (8, 9):
                continue
            start -= 1
            (typed_length,
             typed) = sqlite_help.varint_type_to_length(ord(ff_buff[start]))

            if ord(ff_buff[start - 1]) not in (8, 9):
                continue
            start -= 1
            (hidden_length,
             hidden) = sqlite_help.varint_type_to_length(ord(ff_buff[start]))

            if ord(ff_buff[start - 1]) in (1, 8, 9):
                start -= 1
                (visit_count_length,
                 visit_count) = sqlite_help.varint_type_to_length(
                     ord(ff_buff[start]))
            else:
                continue

            start -= 1
            (rev_host_length,
             varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
            rev_host_length = sqlite_help.varint_to_text_length(
                rev_host_length)

            start -= varint_len
            (title_length,
             varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
            title_length = sqlite_help.varint_to_text_length(title_length)

            start -= varint_len
            (url_length,
             varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
            url_length = sqlite_help.varint_to_text_length(url_length)

            start -= varint_len
            url_id_length = ord(ff_buff[start])

            start -= 1
            payload_header_length = ord(ff_buff[start])
            payload_header_end = start + payload_header_length

            start -= 1
            (row_id,
             varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
            # can't have a negative row_id (index)
            if row_id < 0:
                continue

            start -= varint_len
            if start < 0:
                continue
            (payload_length,
             varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)

            # payload_length should be much longer than this, but this is a safe minimum
            if payload_length < 6:
                continue

            # go back to the needle match and start processing forward
            (last_visit_date_length,
             last_visit_date) = sqlite_help.varint_type_to_length(
                 ord(ff_buff[21]))
            (guid_length,
             varint_len) = sqlite_help.find_varint(ff_buff, 22, FORWARD)
            guid_length = sqlite_help.varint_to_text_length(guid_length)
            start = 22 + varint_len

            # Firefox added a "foreign_count" field that needs to be handled
            if start != payload_header_end:
                (foreign_count_length,
                 foreign_count) = sqlite_help.varint_type_to_length(
                     ord(ff_buff[start]))
                start += 1

            url_id = sqlite_help.sql_unpack(ff_buff[start:start +
                                                    url_id_length])

            start += url_id_length
            url = ff_buff[start:start + url_length]

            start += url_length
            title = ff_buff[start:start + title_length]

            start += title_length
            rev_host = ff_buff[start:start + rev_host_length]

            start += rev_host_length
            if visit_count_length > 0:
                visit_count = sqlite_help.sql_unpack(
                    ff_buff[start:start + visit_count_length])

            start += visit_count_length
            if hidden_length > 0:
                hidden = sqlite_help.sql_unpack(ff_buff[start:start +
                                                        hidden_length])

            start += hidden_length
            if typed_length > 0:
                typed = sqlite_help.sql_unpack(ff_buff[start:start +
                                                       typed_length])

            start += typed_length
            favicon_id = ""
            if favicon_id_length > 0:
                favicon_id = sqlite_help.sql_unpack(ff_buff[start:start +
                                                            favicon_id_length])

            start += favicon_id_length
            if frecency_length > 0:
                frecency = sqlite_help.sql_unpack(ff_buff[start:start +
                                                          frecency_length])

            # extract the time, unpack it to an integer, convert microseconds to string
            start += frecency_length
            last_visit_date = ff_buff[start:start + last_visit_date_length]
            last_visit_date = sqlite_help.sql_unpack(last_visit_date)
            if last_visit_date_length == 8 and last_visit_date < 0:
                continue
            if last_visit_date > 1 and last_visit_date:
                last_visit_date = sqlite_help.get_nixtime_from_msec(
                    last_visit_date)
            if last_visit_date_length == 8 and type(
                    last_visit_date
            ) is datetime and last_visit_date.year == 1970:
                continue

            start += last_visit_date_length
            guid = ff_buff[start:start + guid_length]

            start += guid_length
            if foreign_count_length > 0:
                foreign_count = sqlite_help.sql_unpack(
                    ff_buff[start:start + foreign_count_length])
                start += foreign_count_length

            # save the values as a tuple in a dictionary so we only print one unique row
            url_tuple = (row_id, url, title, rev_host, visit_count, hidden,
                         typed, favicon_id, frecency, last_visit_date, guid,
                         foreign_count)
            if not urls.get(url_tuple):
                urls[url_tuple] = urls.get(url_tuple, 0) + 1
                yield url_tuple
    def calculate(self):
        address_space = utils.load_as(self._config, astype='physical')

        # definite values in Cookie records
        scanner = FirefoxScanner(needles=[
            '\x04\x06\x06\x08',
            '\x04\x06\x06\x09',
            '\x05\x06\x06\x08',
            '\x05\x06\x06\x09',
        ])
        cookies = {}
        for offset in scanner.scan(address_space):
            ff_buff = address_space.read(offset - 16, 4200)
            start = 16
            if (ord(ff_buff[start + 4]) in (8, 9)):
                good = False

                # start before the needle match and work backwards to the first record payload length
                start -= 1
                (path_length,
                 varint_len) = sqlite_help.find_varint(ff_buff, start,
                                                       BACKWARD)
                path_length = sqlite_help.varint_to_text_length(path_length)

                start -= varint_len
                (host_length,
                 varint_len) = sqlite_help.find_varint(ff_buff, start,
                                                       BACKWARD)
                host_length = sqlite_help.varint_to_text_length(host_length)

                start -= varint_len
                (value_length,
                 varint_len) = sqlite_help.find_varint(ff_buff, start,
                                                       BACKWARD)
                value_length = sqlite_help.varint_to_text_length(value_length)

                start -= varint_len
                (name_length,
                 varint_len) = sqlite_help.find_varint(ff_buff, start,
                                                       BACKWARD)
                name_length = sqlite_help.varint_to_text_length(name_length)
                start -= varint_len

                # newer versions add appId and inBrowserElement, they are INTEGER type
                # so if they exist, they will both have length values less than 12
                inBrowserElement_length = 0
                inBrowserElement = "n/a"
                appId_length = 0
                appId = "n/a"
                # if they don't exist, the previous value is a var int and could be something
                # like 0x81 0x10, so wee need to check both bytes
                if 0 < ord(ff_buff[start]) < 12 and 0 < ord(
                        ff_buff[start - 1]) < 12:
                    (inBrowserElement_length,
                     inBrowserElement) = sqlite_help.varint_type_to_length(
                         ord(ff_buff[start]))
                    (appId_length, appId) = sqlite_help.varint_type_to_length(
                        ord(ff_buff[start - 1]))
                    start -= 2

                (baseDomain_length,
                 varint_len) = sqlite_help.find_varint(ff_buff, start,
                                                       BACKWARD)
                baseDomain_length = sqlite_help.varint_to_text_length(
                    baseDomain_length)

                start -= varint_len
                (cookie_id_length,
                 varint_len) = sqlite_help.find_varint(ff_buff, start,
                                                       BACKWARD)

                start -= varint_len
                (payload_header_length,
                 varint_len) = sqlite_help.find_varint(ff_buff, start,
                                                       BACKWARD)

                start -= varint_len
                (row_id,
                 varint_len) = sqlite_help.find_varint(ff_buff, start,
                                                       BACKWARD)

                start -= varint_len
                (payload_length,
                 varint_len) = sqlite_help.find_varint(ff_buff, start,
                                                       BACKWARD)

                # start of record reached, so jump back to the needle, then work forward
                start = 16

                (expiry_length, expiry) = sqlite_help.varint_type_to_length(
                    ord(ff_buff[start]))
                (lastAccessed_length,
                 lastAccessed) = sqlite_help.varint_type_to_length(
                     ord(ff_buff[start + 1]))
                (creationTime_length,
                 creationTime) = sqlite_help.varint_type_to_length(
                     ord(ff_buff[start + 2]))
                (isSecure_length,
                 isSecure) = sqlite_help.varint_type_to_length(
                     ord(ff_buff[start + 3]))
                (isHttpOnly_length,
                 isHttpOnly) = sqlite_help.varint_type_to_length(
                     ord(ff_buff[start + 4]))

                start += 5

                cookie_id = ff_buff[start:start + cookie_id_length]
                cookie_id = sqlite_help.sql_unpack(cookie_id)

                baseDomain = ff_buff[start:start + baseDomain_length]
                start += baseDomain_length

                # if the length is > 0, it will need to be set
                # if it == 0, it was already set in the call earlier
                # otherwise, the value should be "n/a" from initialization because it's an older version
                if inBrowserElement_length > 0:
                    inBrowserElement = ff_buff[start:start +
                                               inBrowserElement_length]
                    inBrowserElement = sqlite_help.sql_unpack(inBrowserElement)
                start += inBrowserElement_length

                if appId_length > 0:
                    appID = ff_buff[start:start + appId_length]
                    appId = sqlite_help.sql_unpack(appId)
                start += appId_length

                name = ff_buff[start:start + name_length]
                start += name_length

                value = ff_buff[start:start + value_length]
                start += value_length

                host = ff_buff[start:start + host_length]
                start += host_length

                path = ff_buff[start:start + path_length]
                start += path_length

                # get the 3 time fields and do a check that a valid date is returned
                expiry = ff_buff[start:start + expiry_length]
                expiry = sqlite_help.sql_unpack(expiry)
                if expiry > 0 and expiry:
                    expiry = sqlite_help.get_nixtime_from_sec(expiry)
                if type(expiry) is not datetime:
                    continue
                start += expiry_length

                lastAccessed = ff_buff[start:start + lastAccessed_length]
                lastAccessed = sqlite_help.sql_unpack(lastAccessed)
                if lastAccessed > 0 and lastAccessed:
                    lastAccessed = sqlite_help.get_nixtime_from_msec(
                        lastAccessed)
                if type(lastAccessed) is not datetime:
                    continue
                start += lastAccessed_length

                creationTime = ff_buff[start:start + creationTime_length]
                creationTime = sqlite_help.sql_unpack(creationTime)
                if creationTime > 0 and creationTime:
                    creationTime = sqlite_help.get_nixtime_from_msec(
                        creationTime)
                if type(creationTime) is not datetime:
                    continue
                start += creationTime_length

                # if all 3 dates are 1970, it's likely a garbage record, so skip
                # if any of them are real dates, it could be an old or partially overwritten record, so print
                if expiry.year == 1970 and lastAccessed.year == 1970 and creationTime.year == 1970:
                    continue

                if isSecure_length > 0:
                    isSecure = ff_buff[start:start + isSecure_length]
                    isSecure = sqlite_help.sql_unpack(isSecure)
                start += isSecure_length

                if isHttpOnly_length > 0:
                    isHttpOnly = ff_buff[start:start + isHttpOnly_length]
                    isHttpOnly = sqlite_help.sql_unpack(isHttpOnly)
                start += isHttpOnly_length

                # add all fields to the tuple so we only print unique records once
                cookie_tuple = (row_id, baseDomain, appId, inBrowserElement,
                                name, value, host, path, expiry, lastAccessed,
                                creationTime, isSecure, isHttpOnly)
                if not cookies.get(cookie_tuple):
                    cookies[cookie_tuple] = cookies.get(cookie_tuple, 0) + 1
                    yield cookie_tuple
Example #4
0
    def calculate(self):
        address_space = utils.load_as(self._config, astype = 'physical')

        # definite values in Downloads records
        scanner = FirefoxScanner(needles = ['\x06\x06\x08',
                                            '\x06\x06\x09',
                                          ])
        downloads = {}
        for offset in scanner.scan(address_space):
            ff_buff = address_space.read(offset-16, 3000)
            start = 16

            good = False

            start -= 1
            (tempPath_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
            tempPath_length = sqlite_help.varint_to_text_length(tempPath_length)

            # work backward from the start of the needle to the first field payload_length
            start -= varint_len
            (target_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
            target_length = sqlite_help.varint_to_text_length(target_length)

            start -= varint_len
            (source_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
            source_length = sqlite_help.varint_to_text_length(source_length)

            start -= varint_len
            (name_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
            name_length = sqlite_help.varint_to_text_length(name_length)

            start -= varint_len
            (id_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)

            start -= varint_len
            (payload_header_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)

            start -= varint_len
            (row_id, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)

            start -= varint_len
            (payload_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)

            # jump back to the needle, startTime_length
            start = 16

            # get all of the single byte lengths around the needle
            (startTime_length, startTime) = sqlite_help.varint_type_to_length(ord(ff_buff[start]))
            (endTime_length, endTime) = sqlite_help.varint_type_to_length(ord(ff_buff[start+1]))
            (state_length, state) = sqlite_help.varint_type_to_length(ord(ff_buff[start+2]))

            # get the rest of the fields in the row moving forward
            start = 19
            (referrer_length, varint_len) = sqlite_help.find_varint(ff_buff, start, FORWARD)
            referrer_length = sqlite_help.varint_to_text_length(referrer_length)
            start += varint_len

            (entityID_length, varint_len) = sqlite_help.find_varint(ff_buff, start, FORWARD)
            entityID_length = sqlite_help.varint_to_text_length(entityID_length)
            start += varint_len

            (currBytes_length, currBytes) = sqlite_help.varint_type_to_length(ord(ff_buff[start]))
            (maxBytes_length, maxBytes) = sqlite_help.varint_type_to_length(ord(ff_buff[start+1]))

            start += 2

            (mimeType_length, varint_len) = sqlite_help.find_varint(ff_buff, start, FORWARD)
            mimeType_length = sqlite_help.varint_to_text_length(mimeType_length)
            start += varint_len

            (preferredApplication_length, varint_len) = sqlite_help.find_varint(ff_buff, start, FORWARD)
            preferredApplication_length = sqlite_help.varint_to_text_length(preferredApplication_length)
            start += varint_len

            (preferredAction_length, preferredAction) = sqlite_help.varint_type_to_length(ord(ff_buff[start]))
            (autoResume_length, autoResume) = sqlite_help.varint_type_to_length(ord(ff_buff[start+1]))

            start += 2
            
            name = ff_buff[start:start+name_length]
            start += name_length

            source = ff_buff[start:start+source_length]
            start += source_length

            target = ff_buff[start:start+target_length]
            start += target_length

            tempPath = ff_buff[start:start+tempPath_length]
            start += tempPath_length

            # do some checks on the startTime/endTime to make sure they are valid
            startTime = ff_buff[start:start+startTime_length]
            startTime = sqlite_help.sql_unpack(startTime)
            if startTime > 0 and startTime:
                startTime = sqlite_help.get_nixtime_from_msec(startTime)
            if type(startTime) is not datetime:
                continue
            start += startTime_length

            endTime = ff_buff[start:start+endTime_length]
            endTime = sqlite_help.sql_unpack(endTime)
            if endTime > 0 and startTime:
                endTime = sqlite_help.get_nixtime_from_msec(endTime)
            if type(endTime) is not datetime:
                continue
            start += endTime_length

            # if both dates are 1970, it's probably a bad record and not very useful, so skip
            # if only 1 is 1970, print it because it may be an old record with one valid date
            if startTime.year == 1970 and endTime.year == 1970:
                continue

            if state_length > 0:
                state = sqlite_help.sql_unpack(ff_buff[start:start+state_length])
            start += state_length

            referrer = ff_buff[start:start+referrer_length]
            start += referrer_length

            entityID = ff_buff[start:start+entityID_length]
            start += entityID_length

            currBytes = ff_buff[start:start+currBytes_length]
            currBytes = sqlite_help.sql_unpack(currBytes)
            # skip if negative or greater than 1TB
            if currBytes < 0 or currBytes > 1000000000000:
                continue
            start += currBytes_length

            maxBytes = ff_buff[start:start+maxBytes_length]
            maxBytes = sqlite_help.sql_unpack(maxBytes)
            # skip if negative or greater than 1TB
            if maxBytes < 0 or maxBytes > 1000000000000:
                continue
            start += maxBytes_length

            mimeType = ff_buff[start:start+mimeType_length]
            start += mimeType_length

            preferredApplication = ff_buff[start:start+preferredApplication_length]
            start += preferredApplication_length

            # these fields can have a value 0x8 or 0x9 in the length field
            # in that case, the "data" portion is not there, and the value is impled 
            # to be 0 or 1, respectively
            if preferredAction_length > 0:
                preferredAction = ff_buff[start:start+preferredAction_length]
                preferredAction = sqlite_help.sql_unpack(preferredAction)
            start += preferredAction_length
                
            if autoResume_length > 0:
                autoResume = ff_buff[start:start+autoResume_length]
                autoResume = sqlite_help.sql_unpack(autoResume)
            start += autoResume_length

            # add all the fields to a tuple so we only print a unique record once
            downloads_tuple = (row_id, name, source, target, tempPath, startTime, endTime, state, referrer, entityID, currBytes, maxBytes, mimeType, preferredApplication, preferredAction, autoResume)
            if not downloads.get(downloads_tuple):
                downloads[downloads_tuple] = downloads.get(downloads_tuple, 0) + 1
                yield downloads_tuple
Example #5
0
    def calculate(self):
        address_space = utils.load_as(self._config, astype = 'physical')

        # definite values in History records
        scanner = FirefoxScanner(needles = ['\x06\x25',
                                            '\x00\x25',
                                           ])
        urls = {}
        for offset in scanner.scan(address_space):
            ff_buff = address_space.read(offset-21, 3000)
            start = 21
            # new field foreign_count added around Firefox v34
            foreign_count_length = 0
            foreign_count = "N/A"

            # start before the needle match and work backwards
            if ord(ff_buff[start-1]) in (1, 2, 8, 9):
                start -= 1
                (frecency_length, frecency) = sqlite_help.varint_type_to_length(ord(ff_buff[start]))
            else:
                continue

            if ord(ff_buff[start-1]) in (0, 1, 8, 9):
                start -= 1
                (favicon_id_length, favicon_id) = sqlite_help.varint_type_to_length(ord(ff_buff[start]))
            else:
                continue

            if ord(ff_buff[start-1]) not in (8, 9):
                continue
            start -= 1
            (typed_length, typed) = sqlite_help.varint_type_to_length(ord(ff_buff[start]))

            if ord(ff_buff[start-1]) not in (8, 9):
                continue
            start -= 1
            (hidden_length, hidden) = sqlite_help.varint_type_to_length(ord(ff_buff[start]))

            if ord(ff_buff[start-1]) in (1, 8, 9):
                start -= 1
                (visit_count_length, visit_count) = sqlite_help.varint_type_to_length(ord(ff_buff[start]))
            else:
                continue

            start -= 1
            (rev_host_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
            rev_host_length = sqlite_help.varint_to_text_length(rev_host_length)

            start -= varint_len
            (title_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
            title_length = sqlite_help.varint_to_text_length(title_length)
            
            start -= varint_len
            (url_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
            url_length = sqlite_help.varint_to_text_length(url_length)
            
            start -= varint_len
            url_id_length = ord(ff_buff[start])

            start -= 1
            payload_header_length = ord(ff_buff[start])
            payload_header_end = start + payload_header_length

            start -= 1
            (row_id, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
            # can't have a negative row_id (index)
            if row_id < 0:
                continue

            start -= varint_len
            if start < 0:
                continue
            (payload_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)

            # payload_length should be much longer than this, but this is a safe minimum
            if payload_length < 6:
                continue

            # go back to the needle match and start processing forward
            (last_visit_date_length, last_visit_date) = sqlite_help.varint_type_to_length(ord(ff_buff[21]))
            (guid_length, varint_len) = sqlite_help.find_varint(ff_buff, 22, FORWARD)
            guid_length = sqlite_help.varint_to_text_length(guid_length)
            start = 22 + varint_len

            # Firefox added a "foreign_count" field that needs to be handled
            if start != payload_header_end:
                (foreign_count_length, foreign_count) = sqlite_help.varint_type_to_length(ord(ff_buff[start]))
                start += 1

            url_id = sqlite_help.sql_unpack(ff_buff[start:start+url_id_length])

            start += url_id_length
            url = ff_buff[start:start+url_length]

            start += url_length
            title = ff_buff[start:start+title_length]

            start += title_length
            rev_host = ff_buff[start:start+rev_host_length]

            start += rev_host_length
            if visit_count_length > 0:
                visit_count = sqlite_help.sql_unpack(ff_buff[start:start+visit_count_length])

            start += visit_count_length
            if hidden_length > 0:
                hidden = sqlite_help.sql_unpack(ff_buff[start:start+hidden_length])

            start += hidden_length
            if typed_length > 0:
                typed = sqlite_help.sql_unpack(ff_buff[start:start+typed_length])

            start += typed_length
            favicon_id = ""
            if favicon_id_length > 0:
                favicon_id = sqlite_help.sql_unpack(ff_buff[start:start+favicon_id_length])

            start += favicon_id_length
            if frecency_length > 0:
                frecency = sqlite_help.sql_unpack(ff_buff[start:start+frecency_length])

            # extract the time, unpack it to an integer, convert microseconds to string
            start += frecency_length
            last_visit_date = ff_buff[start:start+last_visit_date_length]
            last_visit_date = sqlite_help.sql_unpack(last_visit_date)
            if last_visit_date_length == 8 and last_visit_date < 0:
                continue
            if last_visit_date > 1 and last_visit_date:
                last_visit_date = sqlite_help.get_nixtime_from_msec(last_visit_date)
            if last_visit_date_length == 8 and type(last_visit_date) is datetime and last_visit_date.year == 1970:
                continue

            start += last_visit_date_length
            guid = ff_buff[start:start+guid_length]

            start += guid_length
            if foreign_count_length > 0:
                foreign_count = sqlite_help.sql_unpack(ff_buff[start:start+foreign_count_length])
                start += foreign_count_length

            # save the values as a tuple in a dictionary so we only print one unique row
            url_tuple = (row_id, url, title, rev_host, visit_count, hidden, typed, favicon_id, frecency, last_visit_date, guid, foreign_count) 
            if not urls.get(url_tuple):
                urls[url_tuple] = urls.get(url_tuple, 0) + 1
                yield url_tuple
Example #6
0
    def calculate(self):
        address_space = utils.load_as(self._config, astype = 'physical')

        # definite values in Cookie records
        scanner = FirefoxScanner(needles = ['\x04\x06\x06\x08',
                                            '\x04\x06\x06\x09',
                                            '\x05\x06\x06\x08',
                                            '\x05\x06\x06\x09',
                                          ])
        cookies = {}
        for offset in scanner.scan(address_space):
            ff_buff = address_space.read(offset-16, 4200)
            start = 16
            if (ord(ff_buff[start+4]) in (8,9)):
                good = False
            
                # start before the needle match and work backwards to the first record payload length
                start -= 1
                (path_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
                path_length = sqlite_help.varint_to_text_length(path_length)

                start -= varint_len
                (host_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
                host_length = sqlite_help.varint_to_text_length(host_length)

                start -= varint_len
                (value_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
                value_length = sqlite_help.varint_to_text_length(value_length)

                start -= varint_len
                (name_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
                name_length = sqlite_help.varint_to_text_length(name_length)
                start -= varint_len

                # newer versions add appId and inBrowserElement, they are INTEGER type 
                # so if they exist, they will both have length values less than 12
                inBrowserElement_length = 0
                inBrowserElement = "n/a"
                appId_length = 0
                appId = "n/a"
                # if they don't exist, the previous value is a var int and could be something
                # like 0x81 0x10, so wee need to check both bytes
                if 0 < ord(ff_buff[start]) < 12 and 0 < ord(ff_buff[start-1]) < 12:
                    (inBrowserElement_length, inBrowserElement) = sqlite_help.varint_type_to_length(ord(ff_buff[start]))
                    (appId_length, appId) = sqlite_help.varint_type_to_length(ord(ff_buff[start-1]))
                    start -= 2

                (baseDomain_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)
                baseDomain_length = sqlite_help.varint_to_text_length(baseDomain_length)

                start -= varint_len
                (cookie_id_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)

                start -= varint_len
                (payload_header_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)

                start -= varint_len
                (row_id, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)

                start -= varint_len
                (payload_length, varint_len) = sqlite_help.find_varint(ff_buff, start, BACKWARD)

                # start of record reached, so jump back to the needle, then work forward
                start = 16

                (expiry_length, expiry) = sqlite_help.varint_type_to_length(ord(ff_buff[start]))
                (lastAccessed_length, lastAccessed) = sqlite_help.varint_type_to_length(ord(ff_buff[start+1]))
                (creationTime_length, creationTime) = sqlite_help.varint_type_to_length(ord(ff_buff[start+2]))
                (isSecure_length, isSecure) = sqlite_help.varint_type_to_length(ord(ff_buff[start+3]))
                (isHttpOnly_length, isHttpOnly) = sqlite_help.varint_type_to_length(ord(ff_buff[start+4]))

                start += 5

                cookie_id = ff_buff[start:start+cookie_id_length]
                cookie_id = sqlite_help.sql_unpack(cookie_id)

                baseDomain = ff_buff[start:start+baseDomain_length]
                start += baseDomain_length

                # if the length is > 0, it will need to be set
                # if it == 0, it was already set in the call earlier
                # otherwise, the value should be "n/a" from initialization because it's an older version
                if inBrowserElement_length > 0:
                    inBrowserElement = ff_buff[start:start+inBrowserElement_length]
                    inBrowserElement = sqlite_help.sql_unpack(inBrowserElement)
                start += inBrowserElement_length
                    
                if appId_length > 0:
                    appID = ff_buff[start:start+appId_length]
                    appId = sqlite_help.sql_unpack(appId)
                start += appId_length

                name = ff_buff[start:start+name_length]
                start += name_length

                value = ff_buff[start:start+value_length]
                start += value_length

                host = ff_buff[start:start+host_length]
                start += host_length

                path = ff_buff[start:start+path_length]
                start += path_length

                # get the 3 time fields and do a check that a valid date is returned
                expiry = ff_buff[start:start+expiry_length]
                expiry = sqlite_help.sql_unpack(expiry)
                if expiry > 0 and expiry:
                    expiry = sqlite_help.get_nixtime_from_sec(expiry)
                if type(expiry) is not datetime:
                    continue
                start += expiry_length

                lastAccessed = ff_buff[start:start+lastAccessed_length]
                lastAccessed = sqlite_help.sql_unpack(lastAccessed)
                if lastAccessed > 0 and lastAccessed:
                    lastAccessed = sqlite_help.get_nixtime_from_msec(lastAccessed)
                if type(lastAccessed) is not datetime:
                    continue
                start += lastAccessed_length

                creationTime = ff_buff[start:start+creationTime_length]
                creationTime = sqlite_help.sql_unpack(creationTime)
                if creationTime > 0 and creationTime:
                    creationTime = sqlite_help.get_nixtime_from_msec(creationTime)
                if type(creationTime) is not datetime:
                    continue
                start += creationTime_length

                # if all 3 dates are 1970, it's likely a garbage record, so skip
                # if any of them are real dates, it could be an old or partially overwritten record, so print
                if expiry.year == 1970 and lastAccessed.year == 1970 and creationTime.year ==1970:
                    continue

                if isSecure_length > 0:
                    isSecure = ff_buff[start:start+isSecure_length]
                    isSecure = sqlite_help.sql_unpack(isSecure)
                start += isSecure_length
                
                if isHttpOnly_length > 0:
                    isHttpOnly = ff_buff[start:start+isHttpOnly_length]
                    isHttpOnly = sqlite_help.sql_unpack(isHttpOnly)
                start += isHttpOnly_length
                    
                # add all fields to the tuple so we only print unique records once
                cookie_tuple = (row_id, baseDomain, appId, inBrowserElement, name, value, host, path, expiry, lastAccessed, creationTime, isSecure, isHttpOnly)
                if not cookies.get(cookie_tuple):
                    cookies[cookie_tuple] = cookies.get(cookie_tuple, 0) + 1
                    yield cookie_tuple