diff --git a/plaso/data/formatters/ios_wifi.yaml b/plaso/data/formatters/ios_wifi.yaml new file mode 100644 index 0000000000..2d41da8a8c --- /dev/null +++ b/plaso/data/formatters/ios_wifi.yaml @@ -0,0 +1,13 @@ +type: 'conditional' +data_type: 'ios:wifi:known_networks:knowing' +message: + - 'SSID={ssid}' + - 'BSSID={bssid}' + - 'Channel={channel}' + - 'Added At={added_at_time_str}' + - 'Last Associated={last_associated_time_str}' +short_message: + - 'SSID={ssid}' +short_source: 'PLIST' +source: 'Apple iOS WiFi Known Networks plist file' + diff --git a/plaso/data/timeliner.yaml b/plaso/data/timeliner.yaml index 1681f33d74..793594c7bb 100644 --- a/plaso/data/timeliner.yaml +++ b/plaso/data/timeliner.yaml @@ -581,6 +581,20 @@ attribute_mappings: description: 'Content Modification Time' place_holder_event: true --- +data_type: 'ios:wifi:known_networks:knowing' +attribute_mappings: + - name: 'added_at' + description: 'Time network was added' + - name: 'last_associated' + description: 'Last associated time' + - name: 'ssid' + description: 'SSID of the network' + - name: 'bssid' + description: 'BSSID of the network' + - name: 'channel' + description: 'Channel of the network' +place_holder_event: true +--- data_type: 'ipod:device:entry' attribute_mappings: - name: 'last_connected_time' diff --git a/plaso/parsers/plist_plugins/__init__.py b/plaso/parsers/plist_plugins/__init__.py index a3292555b6..f0a0f5ee12 100644 --- a/plaso/parsers/plist_plugins/__init__.py +++ b/plaso/parsers/plist_plugins/__init__.py @@ -8,6 +8,7 @@ from plaso.parsers.plist_plugins import install_history from plaso.parsers.plist_plugins import ios_carplay from plaso.parsers.plist_plugins import ios_identityservices +from plaso.parsers.plist_plugins import ios_wifi_known_networks from plaso.parsers.plist_plugins import ipod from plaso.parsers.plist_plugins import launchd from plaso.parsers.plist_plugins import macos_background_items diff --git a/plaso/parsers/plist_plugins/ios_wifi_known_networks.py b/plaso/parsers/plist_plugins/ios_wifi_known_networks.py new file mode 100644 index 0000000000..46e9657eac --- /dev/null +++ b/plaso/parsers/plist_plugins/ios_wifi_known_networks.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +"""Plist parser plugin for Apple iOS WiFi Known Networks plist files. + +The plist contains information about WiFi networks the device has connected to. +""" + +from dfdatetime import posix_time as dfdatetime_posix_time +from plaso.containers import events +from plaso.parsers import plist +from plaso.parsers.plist_plugins import interface + + +class IOSWiFiKnownNetworksEventData(events.EventData): + """Apple iOS WiFi Known Networks event data. + + Attributes: + ssid (str): SSID of the WiFi network. + added_at (dfdatetime.DateTimeValues): date the network was added. + last_associated (dfdatetime.DateTimeValues): date the network was last associated. + bssid (str): BSSID of the WiFi network. + channel (int): Channel used by the WiFi network. + """ + + DATA_TYPE = 'ios:wifi:known_networks:knowing' + + def __init__(self): + """Initializes event data.""" + super(IOSWiFiKnownNetworksEventData, self).__init__(data_type=self.DATA_TYPE) + self.ssid = None + self.added_at = None + self.last_associated = None + self.bssid = None + self.channel = None + + +class IOSWiFiKnownNetworksPlistPlugin(interface.PlistPlugin): + """Plist parser plugin for Apple iOS WiFi Known Networks plist files.""" + + NAME = 'ios_wifi_known_networks' + DATA_FORMAT = 'Apple iOS WiFi Known Networks plist file' + + PLIST_PATH_FILTERS = frozenset([ + interface.PlistPathFilter('com.apple.wifi.known-networks.plist')]) + + PLIST_KEYS = frozenset([]) + + + def _ParsePlist(self, parser_mediator, match=None, top_level=None, **unused_kwargs): + print(f"Top-level keys in plist: {list(top_level.keys())}") + """Extract WiFi known network entries. + + Args: + parser_mediator (ParserMediator): mediates interactions between parsers + and other components, such as storage and dfVFS. + match (Optional[dict[str: object]]): keys extracted from PLIST_KEYS. + top_level (Optional[dict[str: object]]): entire plist file. + """ + for ssid_key, ssid_data in top_level.items(): + added_at = ssid_data.get('AddedAt') + bssid_list = ssid_data.get('BSSList', []) + + + for bssid_data in bssid_list: + event_data = IOSWiFiKnownNetworksEventData() + event_data.ssid = ssid_key + + if added_at: + added_at_obj = dfdatetime_posix_time.PosixTime( + timestamp=added_at.timestamp()) + event_data.added_at = added_at_obj + event_data.added_at_time_str = added_at_obj.CopyToDateTimeString() + + event_data.bssid = bssid_data.get('BSSID') + event_data.channel = bssid_data.get('Channel') + + + last_associated = bssid_data.get('LastAssociatedAt') + if last_associated: + last_associated_obj = dfdatetime_posix_time.PosixTime( + timestamp=last_associated.timestamp()) + event_data.last_associated = last_associated_obj + event_data.last_associated_time_str = last_associated_obj.CopyToDateTimeString() + + print(f"Debug Event: SSID={event_data.ssid}, Added At={event_data.added_at_time_str}, Last Associated={event_data.last_associated_time_str}") + + parser_mediator.ProduceEventData(event_data) + + + +plist.PlistParser.RegisterPlugin(IOSWiFiKnownNetworksPlistPlugin) diff --git a/test_data/com.apple.wifi.known-networks.plist b/test_data/com.apple.wifi.known-networks.plist new file mode 100755 index 0000000000..37218a0f65 Binary files /dev/null and b/test_data/com.apple.wifi.known-networks.plist differ diff --git a/tests/parsers/plist_plugins/ios_wifi_known_networks.py b/tests/parsers/plist_plugins/ios_wifi_known_networks.py new file mode 100644 index 0000000000..05d4a12e1d --- /dev/null +++ b/tests/parsers/plist_plugins/ios_wifi_known_networks.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""Tests for the Apple iOS WiFi Known Networks plist plugin.""" + +import unittest + +from plaso.parsers.plist_plugins import ios_wifi_known_networks + +from tests.parsers.plist_plugins import test_lib + + +class IOSWiFiKnownNetworksPlistPluginTest(test_lib.PlistPluginTestCase): + """Tests for the Apple iOS WiFi Known Networks plist plugin.""" + + def testProcess(self): + """Tests the Process function.""" + plist_name = 'com.apple.wifi.known-networks.plist' + + plugin = ios_wifi_known_networks.IOSWiFiKnownNetworksPlistPlugin() + storage_writer = self._ParsePlistFileWithPlugin( + plugin, [plist_name], plist_name) + + number_of_event_data = storage_writer.GetNumberOfAttributeContainers( + 'event_data') + self.assertEqual(number_of_event_data, 9) + + number_of_warnings = storage_writer.GetNumberOfAttributeContainers( + 'extraction_warning') + self.assertEqual(number_of_warnings, 0) + + number_of_recovery_warnings = storage_writer.GetNumberOfAttributeContainers( + 'recovery_warning') + self.assertEqual(number_of_recovery_warnings, 0) + + expected_event_values = { + 'ssid': 'wifi.network.ssid.Matt_Foley', + 'bssid': '76:a7:41:e7:7c:9d', + 'data_type': 'ios:wifi:known_networks:knowing', + 'channel': 1, + 'added_at': '2023-04-15T13:53:47+00:00', + 'last_associated': '2023-05-14T01:15:45+00:00'} + + event_data = storage_writer.GetAttributeContainerByIndex('event_data', 0) + self.CheckEventData(event_data, expected_event_values) + + +if __name__ == '__main__': + unittest.main()