def ReadPlist(path_or_file, deserialize=False): ''' Safely open and read a plist. Returns a tuple (True/False, plist/None, "error_message") ''' #log.debug("Trying to open plist file : " + path) error = '' path = '' f = None if isinstance(path_or_file, str): path = path_or_file try: f = open(path, 'rb') except OSError as ex: error = 'Could not open file, Error was : ' + str(ex) else: # its a file f = path_or_file if f: try: plist = biplist.readPlist(f) if deserialize: try: f.seek(0) plist = process_nsa_plist('', f) return (True, plist, '') except Exception as ex: error = 'Could not read deserialized plist: ' + path + " Error was : " + str( ex) return (True, plist, '') except biplist.InvalidPlistException as ex: try: # Perhaps this is manually edited or incorrectly formatted by a non-Apple utility # that has left whitespaces at the start of file before <?xml tag f.seek(0) data = f.read().decode('utf8', 'ignore') data = data.lstrip(" \r\n\t").encode( 'utf8', 'backslashreplace') if deserialize: try: temp_file = BytesIO(data) plist = process_nsa_plist('', temp_file) temp_file.close() return (True, plist, '') except Exception as ex: error = 'Could not read deserialized plist: ' + path + " Error was : " + str( ex) else: plist = biplist.readPlistFromString(data) return (True, plist, '') plist = biplist.readPlistFromString(data) return (True, plist, '') except biplist.InvalidPlistException as ex: error = 'Could not read plist: ' + path + " Error was : " + str( ex) except OSError as ex: error = 'OSError while reading plist: ' + path + " Error was : " + str( ex) return (False, None, error)
def get_decoded_plist_data(data): data_size = len(data) name = '' if data_size > 8: name_len = struct.unpack('>I', data[4:8])[0] name = data[8:8 + name_len] log.debug('NSName = {}'.format(name)) rchv = data[8 + name_len:12 + name_len] # "rchv" if rchv != b"rchv": log.warning('magic was not "rchv", it was {}'.format(str(rchv))) nsa_plist_len = struct.unpack('>I', data[12 + name_len:16 + name_len])[0] nsa_plist = data[16 + name_len:16 + name_len + nsa_plist_len] f = io.BytesIO(nsa_plist) try: deserialized_plist = process_nsa_plist("", f) except Exception as ex: log.exception("") f.close() return (name, None) f.close() return (name, deserialized_plist) else: log.warning('Plist seems empty!') return (name, None)
def Plugin_Start(mac_info): '''Main Entry point function for plugin''' applist_path = '{}/Library/Application Support/com.apple.spotlight/appList.dat' # PList within each users directory. apps = [] processed_paths = [] for user in mac_info.users: user_name = user.user_name if user.home_dir == '/private/var/empty': continue # Optimization, nothing should be here! elif user.home_dir == '/private/var/root': user_name = 'root' # Some other users use the same root folder, we will list such all users as 'root', as there is no way to tell if user.home_dir in processed_paths: continue # Avoid processing same folder twice (some users have same folder! (Eg: root & daemon)) processed_paths.append(user.home_dir) source_path = applist_path.format(user.home_dir) if mac_info.IsValidFilePath( source_path): # Determine if the above path is valid. mac_info.ExportFile(source_path, __Plugin_Name, user_name + "_", False) f = mac_info.Open(source_path) if f != None: deserialized_plist = process_nsa_plist(source_path, f) if deserialized_plist: parse_appList_plist(deserialized_plist, apps, user_name, source_path) else: log.error('Could not open file {}'.format(path)) if len(apps) > 0: PrintAll(apps, mac_info.output_params, '') else: log.info('No apps found')
def read_appList_plist_file(input_file, apps): try: with open(input_file, 'rb') as f: deserialized_plist = process_nsa_plist(input_file, f) parse_appList_plist(deserialized_plist, apps, '', input_file) except (InvalidPlistException, ValueError, KeyError, IndexError, OSError): log.exception("Could not open/process plist")
def ReadCloudTabsDb(conn, safari_items, source_path, user): try: conn.row_factory = sqlite3.Row cursor = conn.execute( """SELECT device_name, tab_uuid, t.system_fields, title, url, is_showing_reader, is_pinned FROM cloud_tabs t LEFT JOIN cloud_tab_devices d on d.device_uuid=t.device_uuid ORDER BY device_name""") try: for row in cursor: try: pinned = row['is_pinned'] system_fields = row['system_fields'] created = '' modified = '' if system_fields: serialized_plist_file_obj = io.BytesIO(system_fields) try: deserialized_plist = process_nsa_plist( '', serialized_plist_file_obj) created = GetItemFromCloudDbPlist( deserialized_plist, 'RecordCtime') modified = GetItemFromCloudDbPlist( deserialized_plist, 'RecordMtime') except (biplist.NotBinaryPlistException, biplist.InvalidPlistException, ccl_bplist.BplistError, ValueError, TypeError, OSError, OverflowError) as ex: log.exception('plist deserialization error') si = SafariItem( SafariItemType.CLOUDTAB, row['url'], row['title'], created, f'Modified={modified}' + (' pinned=1' if pinned else ''), user, source_path) safari_items.append(si) except sqlite3.Error as ex: log.exception("Error while fetching row data") except sqlite3.Error as ex: log.exception("Db cursor error while reading file " + source_path) conn.close() except sqlite3.Error as ex: log.exception("Sqlite error")