Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create plist parser plugins to read com.apple.MobileBackup.plist #4916

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions plaso/data/formatters/ios.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,24 @@ short_source: 'LOG'
source: 'iOS lockdown daemon log'
---
type: 'conditional'
data_type: 'ios:mobile_backup:entry'
message:
- 'Activity description: {activity_description}'
short_message:
- 'Activity description: {activity_description}'
short_source: 'PLIST'
source: 'Apple iOS Mobile Backup application plist'
---
type: 'conditional'
data_type: 'ios:mobile_backup:state'
message:
- 'Description: {description}'
short_message:
- 'Description: {description}'
short_source: 'PLIST'
source: 'Apple iOS Mobile Backup application plist'
---
type: 'conditional'
data_type: 'ios:netusage:route'
enumeration_helpers:
- input_attribute: 'network_type'
Expand Down
14 changes: 14 additions & 0 deletions plaso/data/timeliner.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,20 @@ attribute_mappings:
description: 'Content Modification Time'
place_holder_event: false
---
data_type: 'ios:mobile_backup:entry'
attribute_mappings:
- name: 'account_enabled_time'
description: 'Account Enabled Time'
- name: 'backup_state_time'
description: 'Backup State Time'
place_holder_event: false
---
data_type: 'ios:mobile_backup:state'
attribute_mappings:
- name: 'backup_time'
description: 'Backup Time'
place_holder_event: false
---
data_type: 'ios:netusage:process'
attribute_mappings:
- name: 'start_time'
Expand Down
1 change: 1 addition & 0 deletions plaso/parsers/plist_plugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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_mobilebackup
from plaso.parsers.plist_plugins import ipod
from plaso.parsers.plist_plugins import launchd
from plaso.parsers.plist_plugins import macos_background_items
Expand Down
98 changes: 98 additions & 0 deletions plaso/parsers/plist_plugins/ios_mobilebackup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
"""Plist parser plugin for Apple iOS Mobile Backup plist files.

The plist contains history of opened applications in the Mobile Backup.
"""

from plaso.containers import events
from plaso.parsers import plist
from plaso.parsers.plist_plugins import interface


class IOSMobileBackupEventData(events.EventData):
"""Apple iOS Mobile Backup event data.

Attributes:
account_enabled_time (dfdatetime.DateTimeValues): date and time the mobile
backup account was enabled.
backup_state_time (dfdatetime.DateTimeValues): date and time if the backup
state.
backup_state (int): backup state.
"""

DATA_TYPE = 'ios:mobile_backup:entry'

def __init__(self):
"""Initializes event data."""
super(IOSMobileBackupEventData, self).__init__(data_type=self.DATA_TYPE)
self.account_enabled_time = None
self.backup_state = None
self.backup_state_time = None


class IOSMobileBackupStateEventData(events.EventData):
"""Apple iOS Mobile Backup state event data.

Attributes:
backup_time (dfdatetime.DateTimeValues): date and time of the backup.
description (str): localized description of the backup state.
"""

DATA_TYPE = 'ios:mobile_backup:state'

def __init__(self):
"""Initializes event data."""
super(IOSMobileBackupStateEventData, self).__init__(
data_type=self.DATA_TYPE)
self.backup_time = None
self.description = None


class IOSMobileBackupPlistPlugin(interface.PlistPlugin):
"""Plist parser plugin for Apple iOS Mobile Backup plist files."""

NAME = 'ios_mobile_backup'
DATA_FORMAT = 'Apple iOS Mobile Backup plist file'

PLIST_PATH_FILTERS = frozenset([
interface.PlistPathFilter('com.apple.MobileBackup.plist')])

PLIST_KEYS = frozenset(['AccountEnabledDate', 'BackupStateInfo'])

# pylint: disable=arguments-differ
def _ParsePlist(self, parser_mediator, top_level=None, **unused_kwargs):
"""Extract Mobile Backup history entries.

Args:
parser_mediator (ParserMediator): mediates interactions between parsers
and other components, such as storage and dfVFS.
top_level (Optional[dict[str, object]]): plist top-level item.
"""
event_data = IOSMobileBackupEventData()
event_data.account_enabled_time = self._GetDateTimeValueFromPlistKey(
top_level, 'AccountEnabledDate')

# TODO: add support for LastOnConditionEvents
# TODO: add support for RemoteConfigurationExpiration

backup_state_info = top_level.get('BackupStateInfo')
if backup_state_info:
event_data.backup_state = backup_state_info.get('state')
# TODO: determine what this time represents.
event_data.backup_state_time = self._GetDateTimeValueFromPlistKey(
backup_state_info, 'date')

parser_mediator.ProduceEventData(event_data)

if backup_state_info:
for error in backup_state_info.get('errors', []):
event_data = IOSMobileBackupStateEventData()
event_data.description = error.get('localizedDescription')
# TODO: determine if this is the start or end time of the backup.
event_data.backup_time = self._GetDateTimeValueFromPlistKey(
error, 'date')

parser_mediator.ProduceEventData(event_data)


plist.PlistParser.RegisterPlugin(IOSMobileBackupPlistPlugin)
Binary file added test_data/com.apple.MobileBackup.plist
Binary file not shown.
54 changes: 54 additions & 0 deletions tests/parsers/plist_plugins/ios_mobilebackup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Tests for the Apple iOS Mobile Backup plist plugin."""

import unittest

from plaso.parsers.plist_plugins import ios_mobilebackup

from tests.parsers.plist_plugins import test_lib


class IOSMobileBackupPlistPluginTest(test_lib.PlistPluginTestCase):
"""Tests for the Apple iOS Mobile Backup plist plugin."""

def testProcess(self):
"""Tests the Process function."""
plist_name = 'com.apple.MobileBackup.plist'

plugin = ios_mobilebackup.IOSMobileBackupPlistPlugin()
storage_writer = self._ParsePlistFileWithPlugin(
plugin, [plist_name], plist_name)

number_of_event_data = storage_writer.GetNumberOfAttributeContainers(
'event_data')
self.assertEqual(number_of_event_data, 11)

number_of_warnings = storage_writer.GetNumberOfAttributeContainers(
'extraction_warning')
self.assertEqual(number_of_warnings, 0)

number_of_warnings = storage_writer.GetNumberOfAttributeContainers(
'recovery_warning')
self.assertEqual(number_of_warnings, 0)

expected_event_values = {
'account_enabled_time': '2023-04-15T13:58:42.481634+00:00',
'backup_state': 4,
'backup_state_time': '2023-04-15T14:08:21.008032+00:00',
'data_type': 'ios:mobile_backup:entry'}

event_data = storage_writer.GetAttributeContainerByIndex('event_data', 0)
self.CheckEventData(event_data, expected_event_values)

expected_event_values = {
'backup_time': '2023-05-03T01:11:53.195466+00:00',
'data_type': 'ios:mobile_backup:state',
'description': 'Backup succeeded'}

event_data = storage_writer.GetAttributeContainerByIndex('event_data', 1)
self.CheckEventData(event_data, expected_event_values)


if __name__ == '__main__':
unittest.main()
Loading