Skip to content

Commit

Permalink
implemented biome parser and app_launch biom parser plugin
Browse files Browse the repository at this point in the history
implemented ApplicationInstallBiomePluging
  • Loading branch information
rick committed Apr 18, 2024
1 parent af5e658 commit 4201b1c
Show file tree
Hide file tree
Showing 20 changed files with 857 additions and 1 deletion.
10 changes: 10 additions & 0 deletions plaso/data/formatters/ios.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
# Plaso iOS related event formatters.
---
type: 'conditional'
data_type: 'apple:biome:app_launch'
message:
- 'Launcher: {launcher}'
- 'Launched Application: {launched_application}'
short_message:
- 'Launched Application: {launched_application}'
short_source: 'LOG'
source: 'Apple biome application launch'
---
type: 'conditional'
data_type: 'ios:app_privacy:access'
message:
- 'Accessor Identifier: {accessor_identifier}'
Expand Down
4 changes: 4 additions & 0 deletions plaso/data/presets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ parsers:
name: ios
description: Preset for iOS.
parsers:
- biome/app_install
- biome/app_launch
- jsonl/ios_application_privacy
- plist/ios_identityservices
- sqlite/imessage
Expand Down Expand Up @@ -70,6 +72,8 @@ operating_systems:
- {family: MacOS}
parsers:
- asl_log
- biome/app_install
- biome/app_launch
- bencode
- bsm_log
- cups_ipp
Expand Down
24 changes: 24 additions & 0 deletions plaso/data/timeliner.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,30 @@ attribute_mappings:
description: 'Recorded Time'
place_holder_event: true
---
data_type: 'apple:biome:app_launch'
attribute_mappings:
- name: 'event_time'
description: 'Event Time'
- name: 'launcher'
description: 'process that launched the application'
- name: 'launched application'
description': 'name of the launched application'
place_holder_event: true
---
data_type: 'apple:biome:app_linstall'
attribute_mappings:
- name: 'event_time'
description: 'Event Time'
- name: 'action_guid'
description: 'GUID for the action of installing the application'
- name: 'action_name'
description: 'name of the action'
- name: 'application_name'
description: 'name of the application'
- name: 'bundle_identifier'
description: 'bundle identifier of the application'
place_holder_event: true
---
data_type: 'av:defender:detection_history'
attribute_mappings:
- name: 'recorded_time'
Expand Down
2 changes: 2 additions & 0 deletions plaso/parsers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"""This file imports Python modules that register parsers."""

from plaso.parsers import android_app_usage
from plaso.parsers import apple_biome
from plaso.parsers import asl
from plaso.parsers import bencode_parser
from plaso.parsers import bodyfile
Expand Down Expand Up @@ -53,6 +54,7 @@
from plaso.parsers import winrestore

# Register parser plugins.
from plaso.parsers import biome_plugins
from plaso.parsers import bencode_plugins
from plaso.parsers import czip_plugins
from plaso.parsers import esedb_plugins
Expand Down
180 changes: 180 additions & 0 deletions plaso/parsers/apple_biome.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
"""A parser for Apple biome files, aka SEGB files."""
import os

from plaso.lib import dtfabric_helper
from plaso.lib import errors
from plaso.lib import specification
from plaso.parsers import interface
from plaso.parsers import manager


class AppleBiomeFile(dtfabric_helper.DtFabricHelper):
"""Apple biome (aka SEGB) file.
Attributes:
header (segb_header): Header of the file.
records (list[segb_record]): All the records recovered from the file.
version (str): file version number.
"""

_DEFINITION_FILE = os.path.join(
os.path.dirname(__file__), 'apple_biome.yaml')

def __init__(self):
"""Initializes an Apple biome file."""
super(AppleBiomeFile, self).__init__()
self.header = None
self.records = []
self.version = None

def _ReadAllRecords(self, file_object, starting_offset):
"""Iterates over all the records in the Apple biome file.
Args:
file_object (dfvfs.FileIO): file-like object.
starting_offset (int): offset from which to start reading records.
"""
data_type_map = self._GetDataTypeMap(self.version)
file_size = file_object.get_size()
file_offset = starting_offset

while file_offset < file_size:
record, record_size = self._ReadStructureFromFileObject(
file_object, file_offset, data_type_map)

file_offset += record_size

# Padding
_, alignment = divmod(file_offset, 8)
if alignment > 0:
alignment = 8 - alignment

file_offset += alignment

# Case where the record has a blank header and no content
# record_size includes the record header, record.size only counts content
# This signals the end of records.
if record_size == 32 and record.size == 0:
break

# Case where the record has a valid header but the content is all nulls.
# These can be at the top of the file.
if set(record.protobuf) == {0}:
continue

self.records.append(record)

def _ReadFileHeader(self, file_object):
"""Determines the version of the Apple biome file and returns its header.
Args:
file_object (dfvfs.FileIO): file-like object.
Returns:
File header and data size of the header.
"""
data_type_map = self._GetDataTypeMap('segb_header_v1')

header, header_size = self._ReadStructureFromFileObject(
file_object, 0, data_type_map)

if header.segb_magic == b'SEGB':
return header, header_size

return None, 0

def Open(self, file_object):
"""Opens an Apple biome file.
Args:
file_object (dfvfs.FileIO): file-like object.
Raises:
ValueError: if the file object is missing.
errors.WrongParser: if the segb_record version is not recognized.
"""
if not file_object:
raise ValueError('Missing file_object.')

self.header, header_size = self._ReadFileHeader(file_object)

if header_size == 56:
self.version = 'segb_record_v1'
else:
raise errors.WrongParser('File could not be parsed.')

self._ReadAllRecords(file_object, header_size)


class AppleBiomeParser(interface.FileObjectParser):
"""Parses Apple biome file-like objects."""

NAME = 'biome'
DATA_FORMAT = 'Apple biome'

_plugin_classes = {}

def __int__(self):
"""Initializes a parser."""
super(AppleBiomeParser, self).__init__()

@classmethod
def GetFormatSpecification(cls):
"""Retrieves the format specification.
Returns:
FormatSpecification: format specification.
"""
format_specification = specification.FormatSpecification(cls.NAME)
format_specification.AddNewSignature(b'SEGB', offset=52)
return format_specification

def ParseFileObject(self, parser_mediator, file_object):
"""Parses an Apple biome files.
Args:
parser_mediator (ParserMediator): mediates interactions between parsers
and other components, such as storage and dfVFS.
file_object (dfvfs.FileIO): file-like object.
Raises:
WrongParser: when the file cannot be parsed.
"""
biome_file = AppleBiomeFile()
biome_file.Open(file_object)

for plugin_name, plugin in self._plugins_per_name.items():
if parser_mediator.abort:
break

profiling_name = '/'.join([self.NAME, plugin.NAME])
parser_mediator.SampleFormatCheckStartTiming(profiling_name)

try:
result = False
# Some of the records may have missing fields
for record in biome_file.records:
result = plugin.CheckRequiredSchema(record.protobuf)
if result:
break
finally:
parser_mediator.SampleFormatCheckStopTiming(profiling_name)

if not result:
continue

parser_mediator.SampleStartTiming(profiling_name)

try:
plugin.UpdateChainAndProcess(parser_mediator, biome_file=biome_file)

except Exception as exception: # pylint: disable=broad-except
parser_mediator.ProduceExtractionWarning((
'plugin: {0:s} unable to parse Apple biome file with error: '
'{1!s}').format(plugin_name, exception))

finally:
parser_mediator.SampleStopTiming(profiling_name)


manager.ParsersManager.RegisterParser(AppleBiomeParser)
81 changes: 81 additions & 0 deletions plaso/parsers/apple_biome.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# dtFabric format specification.
---
name: apple_biome
type: format
description: Apple biome file (aka SEGB file)
---
name: byte
type: integer
attributes:
format: unsigned
size: 1
units: bytes
---
name: uint32
type: integer
attributes:
format: unsigned
size: 4
units: bytes
---
name: float64
aliases: [double, DOUBLE]
type: floating-point
description: 64-bit double precision floating-point type
attributes:
size: 8
units: bytes
---
name: segb_header_v1
type: structure
attributes:
byte_order: little-endian
members:
- name: unknown0
data_type: uint32
- name: unknown1
type: stream
element_data_type: byte
number_of_elements: 4
- name: unknown2
type: stream
element_data_type: byte
number_of_elements: 8
- name: unknown3
data_type: uint32
- name: filename
type: stream
element_data_type: byte
number_of_elements: 16
- name: unknown4
type: stream
element_data_type: byte
number_of_elements: 16
- name: segb_magic
type: stream
element_data_type: byte
number_of_elements: 4
---
name: segb_record_v1
type: structure
attributes:
byte_order: little-endian
members:
- name: size
data_type: uint32
- name: unknown1
data_type: uint32
- name: timestamp1
data_type: float64
- name: timestamp2
data_type: float64
- name: unknown2
data_type: uint32
- name: unknown3
data_type: uint32
- name: protobuf
type: stream
element_data_type: byte
number_of_elements: segb_record_v1.size


5 changes: 5 additions & 0 deletions plaso/parsers/biome_plugins/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
"""Imports for the apple biome parser plugins."""

from plaso.parsers.biome_plugins import app_launch
from plaso.parsers.biome_plugins import app_install
Loading

0 comments on commit 4201b1c

Please sign in to comment.