def get_discreteNative(files_found, report_folder, seeker, wrap_text): data_list = [] for file_found in files_found: file_found = str(file_found) #check if file is abx if (checkabx(file_found)): multi_root = False tree = abxread(file_found, multi_root) else: tree = ET.parse(file_found) root = tree.getroot() for elem in root: for subelem1 in elem: ptag = subelem1.tag ptagattrib = subelem1.attrib ptagattrib = ptagattrib["pn"] for subelem2 in subelem1: otag = subelem2.tag otagattrib = subelem2.attrib otagattrib = otagattrib['op'] for subelem3 in subelem2: atag = subelem3.tag atagattrib = subelem3.attrib atagattrib = atagattrib.get('at', '') for subelem4 in subelem3: etag = subelem4.tag etagattrib = subelem4.attrib ntattrib = etagattrib.get('nt') ndattrib = etagattrib.get('nd') if ndattrib is None: ndattrib = '' else: ndattrib = round(int(ndattrib) / 60, 1) data_list.append((timestampcalc(ntattrib), ptagattrib, atagattrib, oplist(otagattrib), ndattrib)) if data_list: report = ArtifactHtmlReport('Privacy Dashboard') report.start_artifact_report(report_folder, 'Privacy Dashboard') report.add_script() data_headers = ('Timestamp', 'Bundle', 'Module', 'Operation', 'Usage in Seconds') report.write_artifact_data_table(data_headers, data_list, file_found) report.end_artifact_report() tsvname = f'Privacy Dashboard' tsv(report_folder, data_headers, data_list, tsvname) tlactivity = f'Privacy Dashboard' timeline(report_folder, tlactivity, data_list, data_headers) else: logfunc('No Privacy Dashboard data available')
def get_appopSetupWiz(files_found, report_folder, seeker, wrap_text): for file_found in files_found: file_found = str(file_found) if not file_found.endswith('appops.xml'): continue # Skip all other files data_list = [] #check if file is abx if (checkabx(file_found)): multi_root = False tree = abxread(file_found, multi_root) else: tree = ET.parse(file_found) root = tree.getroot() for elem in root.iter('pkg'): if elem.attrib['n'] == 'com.google.android.setupwizard': pkg = elem.attrib['n'] for subelem in elem: #print(subelem.attrib) for subelem2 in subelem: #print(subelem2.attrib) for subelem3 in subelem2: test = subelem3.attrib.get('t', 0) if int(test) > 0: timestamp = (datetime.datetime.fromtimestamp(int(subelem3.attrib['t'])/1000).strftime('%Y-%m-%d %H:%M:%S')) else: timestamp = '' data_list.append((timestamp, pkg)) if data_list: report = ArtifactHtmlReport('Appops.xml Setup Wizard') report.start_artifact_report(report_folder, 'Appops.xml Setup Wizard') report.add_script() data_headers = ('Timestamp','Package') report.write_artifact_data_table(data_headers, data_list, file_found) report.end_artifact_report() tsvname = f'Appops Setup Wizard data' tsv(report_folder, data_headers, data_list, tsvname) tlactivity = f'Appops Setup Wizard data' timeline(report_folder, tlactivity, data_list, data_headers) else: logfunc('No Appops Setup Wizard data available')
def process_ssecure(file_path, uid, report_folder): if (checkabx(file_path)): multi_root = True tree = abxread(file_path, multi_root) root = tree.getroot() else: try: tree = ET.parse(file_path) root = tree.getroot() except ET.ParseError: # Fix for android 11 invalid XML file (no root element present) with open(file_path) as f: xml = f.read() root = ET.fromstring( re.sub(r"(<\?xml[^>]+\?>)", r"\1<root>", xml) + "</root>") data_list = [] for setting in root.iter('setting'): nme = setting.get('name') val = setting.get('value') if nme == 'bluetooth_name': data_list.append((nme, val)) logdevinfo(f"Bluetooth name: {val}") elif nme == 'mock_location': data_list.append((nme, val)) elif nme == 'android_id': data_list.append((nme, val)) elif nme == 'bluetooth_address': data_list.append((nme, val)) logdevinfo(f"Bluetooth address: {val}") if len(data_list) > 0: report = ArtifactHtmlReport('Settings Secure') report.start_artifact_report(report_folder, f'Settings_Secure_{uid}') report.add_script() data_headers = ('Name', 'Value') report.write_artifact_data_table(data_headers, data_list, file_path) report.end_artifact_report() tsvname = f'settings secure' tsv(report_folder, data_headers, data_list, tsvname) else: logfunc('No Settings Secure data available')
def get_wifiConfigstore(files_found, report_folder, seeker, wrap_text): data_list = [] for file_found in files_found: file_found = str(file_found) if file_found.endswith('WifiConfigStore.xml'): #check if file is abx if (checkabx(file_found)): multi_root = False tree = abxread(file_found, multi_root) else: tree = ET.parse(file_found) root = tree.getroot() for elem in root.iter(): if elem.attrib.get('name') is not None: if elem.text is not None: data_list.append((elem.attrib.get('name'), elem.text)) elif elem.attrib.get('value') is not None: data_list.append((elem.attrib.get('name'), elem.attrib.get('value'))) if (elem.attrib.get('name')) == 'RandomizedMacAddress': logdevinfo(f'Randomized MAC Address: {elem.text}') if (elem.attrib.get('name') ) == 'wifi_sta_factory_mac_address': logdevinfo(f'WIFI Factory MAC Address: {elem.text}') if (elem.attrib.get('name')) == 'DefaultGwMacAddress': logdevinfo(f'Default Gw MAC Address: {elem.text}') if (elem.attrib.get('name')) == 'ConfigKey': splitted = elem.text.split('"') logdevinfo(f'Config Key: {splitted[1]}') logdevinfo(f'Protocol: {splitted[2]}') if (elem.attrib.get('name')) == 'SSID': splitted = elem.text.split('"') logdevinfo(f'SSID: {splitted[1]}') if (elem.attrib.get('name')) == 'PreSharedKey': splitted = elem.text.split('"') logdevinfo(f'Pre-Shared Key: {splitted[1]}') if (elem.attrib.get('name')) == 'LastConnectedTime': timestamp = datetime.datetime.fromtimestamp( int(elem.attrib.get("value")) / 1000).strftime('%Y-%m-%d %H:%M:%S.%f') logdevinfo(f'WIFI Last Connected Time: {timestamp}') if data_list: report = ArtifactHtmlReport('Wifi Configuration Store.xml') report.start_artifact_report(report_folder, 'Wifi Configuration Store') report.add_script() data_headers = ('Key', 'Value') report.write_artifact_data_table(data_headers, data_list, file_found) report.end_artifact_report() tsvname = f'Wifi Configuration Store data' tsv(report_folder, data_headers, data_list, tsvname) tlactivity = f'Wifi Configuration Store data' timeline(report_folder, tlactivity, data_list, data_headers) else: logfunc('No Wifi Configuration Store data available')
def get_permissions(files_found, report_folder, seeker, wrap_text): slash = '\\' if is_platform_windows() else '/' for file_found in files_found: file_found = str(file_found) data_list_permission_trees = [] data_list_permissions = [] data_list_packages_su = [] err = 0 user = '' parts = file_found.split(slash) if 'mirror' in parts: user = '******' if user == 'mirror': continue else: try: if (checkabx(file_found)): multi_root = False tree = abxread(file_found, multi_root) else: tree = ET.parse(file_found) except ET.ParseError: logfunc('Parse error - Non XML file.') err = 1 if err == 0: root = tree.getroot() for elem in root: #print('TAG LVL 1 '+ elem.tag, elem.attrib) #role = elem.attrib['name'] #print() if elem.tag == 'permission-trees': for subelem in elem: #print(elem.tag +' '+ subelem.tag, subelem.attrib) data_list_permission_trees.append( (subelem.attrib.get('name', ''), subelem.attrib.get('package', ''))) elif elem.tag == 'permissions': for subelem in elem: data_list_permissions.append( (subelem.attrib.get('name', ''), subelem.attrib.get('package', ''), subelem.attrib.get('protection', ''))) #print(elem.tag +' '+ subelem.tag, subelem.attrib) else: for subelem in elem: if subelem.tag == 'perms': for sub_subelem in subelem: #print(elem.tag, elem.attrib['name'], sub_subelem.attrib['name'], sub_subelem.attrib['granted'] ) data_list_packages_su.append( (elem.tag, elem.attrib.get('name', ''), sub_subelem.attrib.get('name', ''), sub_subelem.attrib.get('granted', ''))) if len(data_list_permission_trees) > 0: report = ArtifactHtmlReport('Permission Trees') report.start_artifact_report(report_folder, f'Permission Trees') report.add_script() data_headers = ('Name', 'Package') report.write_artifact_data_table( data_headers, data_list_permission_trees, file_found) report.end_artifact_report() tsvname = f'Permission Trees' tsv(report_folder, data_headers, data_list_permission_trees, tsvname) if len(data_list_permissions) > 0: report = ArtifactHtmlReport('Permissions') report.start_artifact_report(report_folder, f'Permissions') report.add_script() data_headers = ('Name', 'Package', 'Protection') report.write_artifact_data_table(data_headers, data_list_permissions, file_found) report.end_artifact_report() tsvname = f'Permissions' tsv(report_folder, data_headers, data_list_permissions, tsvname) if len(data_list_packages_su) > 0: report = ArtifactHtmlReport('Package and Shared User') report.start_artifact_report(report_folder, f'Package and Shared User') report.add_script() data_headers = ('Type', 'Package', 'Permission', 'Granted?') report.write_artifact_data_table(data_headers, data_list_packages_su, file_found) report.end_artifact_report() tsvname = f'Permissions - Packages and Shared User' tsv(report_folder, data_headers, data_list_packages_su, tsvname)
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: if (checkabx(filename)): multi_root = False tree = abxread(filename, multi_root) else: tree = 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() #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 if len(all_rows) > 0: report = ArtifactHtmlReport('Recent Tasks, Snapshots & Images') location = os.path.join(folder, 'recent_tasks') report.start_artifact_report(report_folder, f'Recent Activity_{uid}', f'Artifacts located at {location}') report.add_script() data_headers = ('Key', 'Value') image_data_headers = ('Snapshot_Image', 'Recent_Image') 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" title="{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" title="{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 get_package_info(files_found, report_folder, seeker, wrap_text): packages = [] for file_found in files_found: file_found = str(file_found) if file_found.find('{0}mirror{0}'.format(slash)) >= 0: # Skip sbin/.magisk/mirror/data/.. , it should be duplicate data continue elif os.path.isdir( file_found): # skip folders (there shouldn't be any) continue file_name = os.path.basename(file_found) if (checkabx(file_found)): multi_root = False tree = abxread(file_found, multi_root) xlmstring = (etree.tostring(tree.getroot()).decode()) doc = xmltodict.parse(xlmstring) else: with open(file_found) as fd: doc = xmltodict.parse(fd.read()) package_dict = doc.get('packages', {}).get('package', {}) for package in package_dict: name = package.get('@name', '') ft = ReadUnixTimeMs(package.get('@ft', None)) it = ReadUnixTimeMs(package.get('@it', None)) ut = ReadUnixTimeMs(package.get('@ut', None)) install_originator = package.get('@installOriginator', '') installer = package.get('@installer', '') code_path = package.get('@codePath', '') public_flags = hex( int(package.get('@publicFlags', 0)) & (2**32 - 1)) private_flags = hex( int(package.get('@privateFlags', 0)) & (2**32 - 1)) package = Package(name, ft, it, ut, install_originator, installer, code_path, public_flags, private_flags) packages.append(package) if len(packages): break if report_folder[-1] == slash: folder_name = os.path.basename(report_folder[:-1]) else: folder_name = os.path.basename(report_folder) entries = len(packages) if entries > 0: description = "All packages (user installed, oem installed and system) appear here. Many of these are not user apps" report = ArtifactHtmlReport('Packages') report.start_artifact_report(report_folder, 'Packages', description) report.add_script() data_headers = ('ft', 'Name', 'Install Time', 'Update Time', 'Install Originator', 'Installer', 'Code Path', 'Public Flags', 'Private Flags') data_list = [] for p in packages: data_list.append((p.ft, p.name, p.install_time, p.update_time, p.install_originator, p.installer, p.code_path, p.public_flags, p.private_flags)) report.write_artifact_data_table(data_headers, data_list, file_found) report.end_artifact_report() tsvname = f'Packages' tsv(report_folder, data_headers, data_list, tsvname) tlactivity = f'Packages' timeline(report_folder, tlactivity, data_list, data_headers) else: logfunc('No package data available')
def get_appops(files_found, report_folder, seeker, wrap_text): for file_found in files_found: file_found = str(file_found) if not file_found.endswith('appops.xml'): continue # Skip all other files data_list = [] #check if file is abx if (checkabx(file_found)): multi_root = False tree = abxread(file_found, multi_root) else: tree = ET.parse(file_found) root = tree.getroot() for elem in root.iter('pkg'): pkg = elem.attrib['n'] for subelem in elem: #print(subelem.attrib) for subelem2 in subelem: #print(subelem2.attrib) for subelem3 in subelem2: #print(subelem3.attrib) timesr = subelem3.attrib.get('r') timest = subelem3.attrib.get('t') pp = subelem3.attrib.get('pp') pu = subelem3.attrib.get('pu') n = subelem3.attrib.get('n') id = subelem3.attrib.get('id') if timesr: timestampr = (datetime.datetime.fromtimestamp(int(timesr)/1000).strftime('%Y-%m-%d %H:%M:%S')) else: timestampr = '' if timest: timestampt = (datetime.datetime.fromtimestamp(int(timest)/1000).strftime('%Y-%m-%d %H:%M:%S')) else: timestampt = '' if not pp: pp = '' if not pu: pu = '' if not n: n = '' if not id: id = '' data_list.append((timestampt, timestampr, pkg, id, pp, pu, n)) if data_list: report = ArtifactHtmlReport('Appops.xml') report.start_artifact_report(report_folder, 'Appops.xml') report.add_script() data_headers = ('Timestamp T', 'Timestamp R', 'PKG', 'ID', 'PP', 'PU', 'N') report.write_artifact_data_table(data_headers, data_list, file_found) report.end_artifact_report() tsvname = f'Appops.xml data' tsv(report_folder, data_headers, data_list, tsvname) tlactivity = f'Appops.xml data' timeline(report_folder, tlactivity, data_list, data_headers) else: logfunc('No Appops.xml data available')