def module(): headers = [ 'user', 'timestamp', 'bundle_id', 'quarantine_agent', 'download_url', 'sender_name', 'sender_address', 'typeno', 'origin_title', 'origin_title', 'origin_url', 'origin_alias' ] output = data_writer(_modName, headers) qevents_list = multiglob(inputdir, [ 'Users/*/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2', 'private/var/*/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2' ]) qry = 'SELECT * FROM LSQuarantineEvent' if len(qevents_list) == 0: log.debug("Files not found in: {0}".format(qevents_loc)) for i in qevents_list: data = query_db(i, qry, outputdir) userpath = i.split('/') if 'Users' in userpath: userindex = len(userpath) - 1 - userpath[::-1].index('Users') + 1 else: userindex = len(userpath) - 1 - userpath[::-1].index('var') + 1 user = userpath[userindex] for item in data: item = list(item) record = OrderedDict((h, '') for h in headers) record['user'] = user record['timestamp'] = cocoa_time(item[1]) record['bundle_id'] = item[2] record['quarantine_agent'] = item[3] record['download_url'] = item[4] record['sender_name'] = item[5] record['sender_address'] = item[6] record['typeno'] = str(item[7]) record['origin_title'] = item[8] record['origin_url'] = item[9] record['origin_alias'] = item[10] line = [ x.encode('utf-8') if isinstance(x, unicode) else x for x in record.values() ] output.write_entry(line)
def module(): headers = [ 'uid', 'path', 'name', 'last_hit_date', 'hit_count', 'file_last_modified', 'generator', 'file_size' ] output = data_writer(_modName, headers) q_loc = os.path.join( inputdir, 'private/var/folders/*/*/C/com.apple.QuickLook.thumbnailcache/index.sqlite' ) qlist = glob.glob(q_loc) if OSVersion is not None: ver = float('.'.join(OSVersion.split('.')[1:])) if ver > 14.0 and ver is not None and forensic_mode is not True: log.error( "Artifacts are inaccessible on and above OS version 10.14 on live systems." ) return else: if forensic_mode is not True: log.debug( "OSVersion not detected, but going to try to parse anyway.") else: log.error( "OSVersion not detected, so will not risk parsing as artifacts are inaccessible on and above OS version 10.14 on live systems." ) return if len(qlist) == 0: log.debug("Files not found in: {0}".format(q_loc)) ql_sql = 'SELECT distinct k.folder, k.file_name, t.hit_count, t.last_hit_date, k.version \ FROM (SELECT rowid AS f_rowid,folder,file_name,version FROM files) k \ LEFT JOIN thumbnails t ON t.file_id = k.f_rowid ORDER BY t.hit_count DESC' for qfile in qlist: uid = stats2(qfile)['uid'] data = query_db(qfile, ql_sql, outputdir) for item in data: item = list(item) record = OrderedDict((h, '') for h in headers) record['uid'] = uid record['path'] = item[0].encode('utf-8') record['name'] = item[1].encode('utf-8') if item[3]: record['last_hit_date'] = cocoa_time(item[3]) else: record['last_hit_date'] = '' if item[2]: record['hit_count'] = item[2] else: record['hit_count'] = '' try: plist_array = read_stream_bplist(item[4]) record['file_last_modified'] = cocoa_time(plist_array['date']) record['generator'] = plist_array['gen'] try: record['file_size'] = int(plist_array['size']) except KeyError: record['file_size'] = 'Error' except Exception, e: log.error( "Could not parse: embedded binary plist for record {0}". format(record['name'])) output.write_entry(record.values())
def pull_visit_history(recently_closed_plist, history_db, user, history_output, history_headers): try: log.debug("Trying to access RecentlyClosedTabs.plist...") recently_closed = read_bplist( recently_closed_plist)[0]['ClosedTabOrWindowPersistentStates'] d = {} log.debug("Success. Found {0} lines of data.".format( len(recently_closed))) for i in recently_closed: for k, v in i['PersistentState'].items(): if k == 'TabURL': tab_title = i['PersistentState']['TabTitle'].encode( 'utf-8') date_closed = parser.parse( str(i['PersistentState']['DateClosed'])).replace( tzinfo=None).isoformat() + 'Z' try: last_visit_time = i['PersistentState']['LastVisitTime'] last_visit_time = cocoa_time(last_visit_time) except KeyError: last_visit_time = '' d[i['PersistentState']['TabURL']] = [ tab_title, date_closed, last_visit_time ] except IOError: log.debug("File not found: {0}".format(recently_closed_plist)) d = {} pass desired_columns = ['visit_time', 'title', 'url', 'visit_count'] available_columns = get_column_headers( history_db, 'history_visits') + get_column_headers( history_db, 'history_items') query_columns_list = [i for i in desired_columns if i in available_columns] query_columns = ', '.join( [i for i in desired_columns if i in available_columns]) unavailable = ','.join( list(set(desired_columns) - set(query_columns_list))) if len(unavailable) > 0: log.debug( 'The following desired columns are not available in the database: {0}' .format(unavailable)) log.debug("Executing sqlite query for visit history...") try: history_data = sqlite3.connect(history_db).cursor().execute( 'SELECT {0} from history_visits \ left join history_items on history_items.id = history_visits.history_item' .format(query_columns)).fetchall() log.debug("Success. Found {0} lines of data.".format( len(history_data))) except sqlite3.OperationalError: error = [ x for x in traceback.format_exc().split('\n') if x.startswith("OperationalError") ] log.error('Failed to run query. [{0}]'.format(error[0])) return log.debug("Parsing and writing visits data...") nondict = dict.fromkeys(desired_columns) for item in history_data: record = OrderedDict((h, '') for h in history_headers) item_dict = dict(zip(query_columns_list, item)) nondict.update(item_dict) record['user'] = user record['visit_time'] = cocoa_time(nondict['visit_time']) if nondict['title'] is not None: record['title'] = nondict['title'].encode('utf-8') record['url'] = nondict['url'] record['visit_count'] = nondict['visit_count'] if nondict['url'] in d.keys(): record['recently_closed'] = 'Yes' record['tab_title'] = d[nondict['url']][0] record['date_closed'] = d[nondict['url']][1] record['last_visit_time'] = d[nondict['url']][2] history_output.write_entry(record.values())