def process_recentactivity(folder, uid, report_folder): slash = '\\' if is_platform_windows() else '/' db = sqlite3.connect( os.path.join(report_folder, 'RecentAct_{}.db'.format(uid))) cursor = db.cursor() #Create table recent. cursor.execute(''' CREATE TABLE recent(task_id TEXT, effective_uid TEXT, affinity TEXT, real_activity TEXT, first_active_time TEXT, last_active_time TEXT, last_time_moved TEXT, calling_package TEXT, user_id TEXT, action TEXT, component TEXT, snap TEXT,recimg TXT, fullat1 TEXT, fullat2 TEXT) ''') db.commit() err = 0 if report_folder[-1] == slash: folder_name = os.path.basename(report_folder[:-1]) else: folder_name = os.path.basename(report_folder) for filename in glob.iglob(os.path.join(folder, 'recent_tasks', '**'), recursive=True): if os.path.isfile(filename): # filter dirs file_name = os.path.basename(filename) #logfunc(filename) #logfunc(file_name) #numid = file_name.split('_')[0] try: ET.parse(filename) except ET.ParseError: logfunc('Parse error - Non XML file? at: ' + filename) err = 1 #print(filename) if err == 1: err = 0 continue else: tree = ET.parse(filename) root = tree.getroot() #print('Processed: '+filename) for child in root: #All attributes. Get them in using json dump thing fullat1 = json.dumps(root.attrib) task_id = (root.attrib.get('task_id')) effective_uid = (root.attrib.get('effective_uid')) affinity = (root.attrib.get('affinity')) real_activity = (root.attrib.get('real_activity')) first_active_time = (root.attrib.get('first_active_time')) last_active_time = (root.attrib.get('last_active_time')) last_time_moved = (root.attrib.get('last_time_moved')) calling_package = (root.attrib.get('calling_package')) user_id = (root.attrib.get('user_id')) #print(root.attrib.get('task_description_icon_filename')) #All attributes. Get them in using json dump thing fullat2 = json.dumps(child.attrib) action = (child.attrib.get('action')) component = (child.attrib.get('component')) icon_image_path = ( root.attrib.get('task_description_icon_filename')) #Snapshot section picture snapshot = task_id + '.jpg' #print(snapshot) #check for image in directories check1 = os.path.join(folder, 'snapshots', snapshot) isit1 = os.path.isfile(check1) if isit1: #copy snaphot image to report folder shutil.copy2(check1, report_folder) #snap = r'./snapshots/' + snapshot snap = snapshot else: snap = 'NO IMAGE' #Recent_images section if icon_image_path is not None: recent_image = os.path.basename(icon_image_path) check2 = os.path.join(folder, 'recent_images', recent_image) isit2 = os.path.isfile(check2) if isit2: shutil.copy2(check2, report_folder) #recimg = r'./recent_images/' + recent_image recimg = recent_image else: recimg = 'NO IMAGE' else: #check for other files not in the XML - all types check3 = glob.glob( os.path.join(folder, 'recent_images', task_id, '*.*')) if check3: check3 = check3[0] isit3 = os.path.isfile(check3) else: isit3 = 0 if isit3: shutil.copy2(check3, report_folder) recimg = os.path.basename(check3) else: recimg = 'NO IMAGE' #else: # recimg = 'NO IMAGE' #insert all items in database cursor = db.cursor() datainsert = ( task_id, effective_uid, affinity, real_activity, first_active_time, last_active_time, last_time_moved, calling_package, user_id, action, component, snap, recimg, fullat1, fullat2, ) cursor.execute( 'INSERT INTO recent (task_id, effective_uid, affinity, real_activity, first_active_time, last_active_time, last_time_moved, calling_package, user_id, action, component, snap, recimg, fullat1, fullat2) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', datainsert) db.commit() report = ArtifactHtmlReport('Recent Tasks, Snapshots & Images') report.start_artifact_report(report_folder, f'Recent Activity_{uid}') report.add_script() data_headers = ('Key', 'Value') image_data_headers = ('Snapshot_Image', 'Recent_Image') #Query to create report db = sqlite3.connect( os.path.join(report_folder, 'RecentAct_{}.db'.format(uid))) cursor = db.cursor() #Query to create report cursor.execute(''' SELECT task_id as Task_ID, effective_uid as Effective_UID, affinity as Affinity, real_activity as Real_Activity, datetime(first_active_time/1000, 'UNIXEPOCH') as First_Active_Time, datetime(last_active_time/1000, 'UNIXEPOCH') as Last_Active_Time, datetime(last_time_moved/1000, 'UNIXEPOCH') as Last_Time_Moved, calling_package as Calling_Package, user_id as User_ID, action as Action, component as Component, snap as Snapshot_Image, recimg as Recent_Image FROM recent ''') all_rows = cursor.fetchall() colnames = cursor.description for row in all_rows: if row[2] is None: row2 = '' #'NO DATA' else: row2 = row[2] report.write_minor_header(f'Application: {row2}') #do loop for headers data_list = [] for x in range(0, 13): if row[x] is None: pass else: data_list.append((colnames[x][0], str(row[x]))) report.write_artifact_data_table(data_headers, data_list, folder, table_id='', write_total=False, write_location=False, cols_repeated_at_bottom=False) image_data_row = [] image_data_list = [image_data_row] if row[11] == 'NO IMAGE': image_data_row.append('No Image') else: image_data_row.append( '<a href="{1}/{0}"><img src="{1}/{0}" class="img-fluid z-depth-2 zoom" style="max-height: 400px" alt="{0}"></a>' .format(str(row[11]), folder_name)) if row[12] == 'NO IMAGE': image_data_row.append('No Image') else: image_data_row.append( '<a href="{1}/{0}"><img src="{1}/{0}" class="img-fluid z-depth-2 zoom" style="max-height: 400px" alt="{0}"></a>' .format(str(row[12]), folder_name)) report.write_artifact_data_table(image_data_headers, image_data_list, folder, table_id='', table_style="width: auto", write_total=False, write_location=False, html_escape=False, cols_repeated_at_bottom=False) report.write_raw_html('<br />') report.end_artifact_report()
def generate_location_map(reportfolderbase, legend_title): KML_path = os.path.join(reportfolderbase, iLEAPP_KMLs) if not os.path.isdir(KML_path) or not os.listdir(KML_path): return location_path = os.path.join(reportfolderbase, 'LOCATIONS') os.makedirs(location_path, exist_ok=True) db = sqlite3.connect(os.path.join(KML_path, "_latlong.db")) df = pd.read_sql_query( "SELECT key as Name, Activity as Description, latitude, longitude FROM data ;", db) df["Point"] = df.apply( lambda row: Point(float(row['longitude']), float(row['latitude']), .0), axis=1) #sorting is needed for correct display df.sort_values(by=['Name'], inplace=True) #Parse geo data and add to Folium Map data_names = df[~df.Description.str.contains('Photos')].Description.unique( ) featuresProp = {} for c, d in zip(colors, data_names): descFilter = d if 'ZRT' in d: fType = 'LineString' icon = 'marker' iconUrl = defaultIconUrl.format(c) shadowUrl = defaultShadowUrl else: fType = 'MultiPoint' icon = 'circle' iconUrl = '' shadowUrl = '' color = c featuresProp[d] = { 'fType': fType, 'color': c, 'icon': icon, 'iconUrl': iconUrl, 'shadowUrl': defaultShadowUrl, } location_map = folium.Map([df.iloc[0].Point.y, df.iloc[0].Point.x], prefer_canvas=True, zoom_start=6) bounds = ( df[~df.Description.str.contains('Photos')]['longitude'].min(), df[~df.Description.str.contains('Photos')]['latitude'].min(), df[~df.Description.str.contains('Photos')]['longitude'].max(), df[~df.Description.str.contains('Photos')]['latitude'].max(), ) location_map.fit_bounds([ (bounds[1], bounds[0]), (bounds[3], bounds[2]), ]) tsGeo = TimestampedGeoJson( { 'type': 'FeatureCollection', 'features': [geodfToFeatures(df, f, featuresProp) for f in data_names] }, period="PT1M", duration="PT1H", loop=False, transition_time=50, time_slider_drag_update=True, add_last_point=True, max_speed=200).add_to(location_map) #legend legend = '\n'.join([ legend_tag.format(featuresProp[f]['color'], htmlencode(f)) for f in data_names ]) template = '\n'.join([ template_part1, legend_title_tag.format(htmlencode(legend_title)), legend_div.format(legend), template_part2 ]) macro = MacroElement() macro._template = Template(template) location_map.get_root().add_child(macro) location_map.save(os.path.join(location_path, "Locations_Map.html")) report = ArtifactHtmlReport('Locations Map') report.start_artifact_report(location_path, 'Locations Map', 'Map plotting all locations') report.write_raw_html( open(os.path.join(location_path, "Locations_Map.html")).read()) report.end_artifact_report()
def get_sms(files_found, report_folder, seeker): file_found = str(files_found[0]) db = open_sqlite_db_readonly(file_found) sms_df = pd.read_sql_query( ''' SELECT CASE WHEN LENGTH(MESSAGE.DATE)=18 THEN DATETIME(MESSAGE.DATE/1000000000+978307200,'UNIXEPOCH') WHEN LENGTH(MESSAGE.DATE)=9 THEN DATETIME(MESSAGE.DATE + 978307200,'UNIXEPOCH') ELSE "N/A" END "MESSAGE DATE", MESSAGE.ROWID as "MESSAGE ID", CASE WHEN LENGTH(MESSAGE.DATE_DELIVERED)=18 THEN DATETIME(MESSAGE.DATE_DELIVERED/1000000000+978307200,"UNIXEPOCH") WHEN LENGTH(MESSAGE.DATE_DELIVERED)=9 THEN DATETIME(MESSAGE.DATE_DELIVERED+978307200,"UNIXEPOCH") ELSE "N/A" END "DATE DELIVERED", CASE WHEN LENGTH(MESSAGE.DATE_READ)=18 THEN DATETIME(MESSAGE.DATE_READ/1000000000+978307200,"UNIXEPOCH") WHEN LENGTH(MESSAGE.DATE_READ)=9 THEN DATETIME(MESSAGE.DATE_READ+978307200,"UNIXEPOCH") ELSE "N/A" END "DATE READ", MESSAGE.TEXT as "MESSAGE", HANDLE.ID AS "CONTACT ID", MESSAGE.SERVICE AS "SERVICE", MESSAGE.ACCOUNT AS "ACCOUNT", MESSAGE.IS_DELIVERED AS "IS DELIVERED", MESSAGE.IS_FROM_ME AS "IS FROM ME", ATTACHMENT.FILENAME AS "FILENAME", ATTACHMENT.MIME_TYPE AS "MIME TYPE", ATTACHMENT.TRANSFER_NAME AS "TRANSFER TYPE", ATTACHMENT.TOTAL_BYTES AS "TOTAL BYTES" FROM MESSAGE LEFT OUTER JOIN MESSAGE_ATTACHMENT_JOIN ON MESSAGE.ROWID = MESSAGE_ATTACHMENT_JOIN.MESSAGE_ID LEFT OUTER JOIN ATTACHMENT ON MESSAGE_ATTACHMENT_JOIN.ATTACHMENT_ID = ATTACHMENT.ROWID LEFT OUTER JOIN HANDLE ON MESSAGE.HANDLE_ID = HANDLE.ROWID ''', db) usageentries = sms_df.shape[0] if usageentries > 0: data_list = sms_df.to_records(index=False) report = ArtifactHtmlReport('SMS - iMessage') report.start_artifact_report(report_folder, 'SMS - iMessage') report.add_script() sms_df = sms_df.rename( columns={ "MESSAGE DATE": "data-time", 'MESSAGE ID': "message-id", "MESSAGE": "message", "CONTACT ID": "data-name", "IS FROM ME": "from_me", "MIME TYPE": "content-type" }) sms_df["data-time"] = pd.to_datetime(sms_df["data-time"]) def copyAttachments(rec): pathToAttachment = None if rec["FILENAME"]: attachment = seeker.search('**' + rec["FILENAME"].replace('~', '', 1), return_on_first_hit=True) if not attachment: logfunc( ' [!] Unable to extract attachment file: "{}"'.format( rec['FILENAME'])) return if is_platform_windows(): destFileName = sanitize_file_name( os.path.basename(rec["FILENAME"])) else: destFileName = os.path.basename(rec["FILENAME"]) pathToAttachment = os.path.join( (os.path.basename(os.path.abspath(report_folder))), destFileName) shutil.copy(attachment[0], os.path.join(report_folder, destFileName)) return pathToAttachment sms_df["file-path"] = sms_df.apply(lambda rec: copyAttachments(rec), axis=1) num_entries = sms_df.shape[0] report.write_minor_header(f'Total number of entries: {num_entries}', 'h6') if file_found.startswith('\\\\?\\'): file_found = file_found[4:] report.write_lead_text(f'SMS - iMessage located at: {file_found}') report.write_raw_html(chat_HTML) report.add_script(render_chat(sms_df)) data_headers = ('Message Date', 'Message ID', 'Date Delivered', 'Date Read', 'Message', 'Contact ID', 'Service', 'Account', 'Is Delivered', 'Is from Me', 'Filename', 'MIME Type', 'Transfer Type', 'Total Bytes') report.write_artifact_data_table(data_headers, data_list, file_found, write_total=False, write_location=False) report.end_artifact_report() tsvname = 'SMS - iMessage' tsv(report_folder, data_headers, data_list, tsvname) tlactivity = 'SMS - iMessage' timeline(report_folder, tlactivity, data_list, data_headers) else: logfunc('No SMS & iMessage data available') db.close() return