:py:mod:`dissect.target.plugins.os.unix.log.journal` ==================================================== .. py:module:: dissect.target.plugins.os.unix.log.journal Module Contents --------------- Classes ~~~~~~~ .. autoapisummary:: dissect.target.plugins.os.unix.log.journal.JournalFile dissect.target.plugins.os.unix.log.journal.JournalPlugin Functions ~~~~~~~~~ .. autoapisummary:: :nosignatures: dissect.target.plugins.os.unix.log.journal.get_optional Attributes ~~~~~~~~~~ .. autoapisummary:: dissect.target.plugins.os.unix.log.journal.JournalRecord dissect.target.plugins.os.unix.log.journal.journal_def dissect.target.plugins.os.unix.log.journal.c_journal .. py:data:: JournalRecord .. py:data:: journal_def :value: Multiline-String .. raw:: html
Show Value .. code-block:: python """ typedef uint8 uint8_t; typedef uint32 le32_t; typedef uint64 le64_t; enum State : uint8_t { OFFLINE = 0, ONLINE = 1, ARCHIVED = 2, UNKNOWN }; union sd_id128_t { uint8_t bytes[16]; uint64_t qwords[2]; }; flag IncompatibleFlag : le32_t { HEADER_INCOMPATIBLE_COMPRESSED_XZ = 1, HEADER_INCOMPATIBLE_COMPRESSED_LZ4 = 2, HEADER_INCOMPATIBLE_KEYED_HASH = 4, HEADER_INCOMPATIBLE_COMPRESSED_ZSTD = 8, HEADER_INCOMPATIBLE_COMPACT = 16, // indicates that the Journal file uses the new binary format }; struct Header { uint8_t signature[8]; le32_t compatible_flags; IncompatibleFlag incompatible_flags; State state; uint8_t reserved[7]; sd_id128_t file_id; sd_id128_t machine_id; sd_id128_t tail_entry_boot_id; sd_id128_t seqnum_id; le64_t header_size; le64_t arena_size; le64_t data_hash_table_offset; le64_t data_hash_table_size; le64_t field_hash_table_offset; le64_t field_hash_table_size; le64_t tail_object_offset; le64_t n_objects; le64_t n_entries; le64_t tail_entry_seqnum; le64_t head_entry_seqnum; le64_t entry_array_offset; le64_t head_entry_realtime; le64_t tail_entry_realtime; le64_t tail_entry_monotonic; le64_t n_data; le64_t n_fields; le64_t n_tags; le64_t n_entry_arrays; le64_t data_hash_chain_depth; le64_t field_hash_chain_depth; le32_t tail_entry_array_offset; le32_t tail_entry_array_n_entries; le64_t tail_entry_offset; }; enum ObjectType : uint8 { OBJECT_UNUSED, OBJECT_DATA, OBJECT_FIELD, OBJECT_ENTRY, OBJECT_DATA_HASH_TABLE, OBJECT_FIELD_HASH_TABLE, OBJECT_ENTRY_ARRAY, OBJECT_TAG, _OBJECT_TYPE_MAX }; flag ObjectFlag : uint8 { OBJECT_UNCOMPRESSED = 0, OBJECT_COMPRESSED_XZ = 1, OBJECT_COMPRESSED_LZ4 = 2, OBJECT_COMPRESSED_ZSTD = 4, _OBJECT_COMPRESSED_MASK = 7 }; struct ObjectHeader { ObjectType type; // The type field is one of the object types listed above uint8_t flags; // If DATA object the value is ObjectFlag uint8_t reserved[6]; le64_t size; // The size field encodes the size of the object including all its headers and payload }; // The first four members are copied from ObjectHeader, so that the size can be used as the length of payload struct DataObject { ObjectType type; ObjectFlag flags; uint8_t reserved[6]; le64_t size; le64_t hash; le64_t next_hash_offset; le64_t next_field_offset; le64_t entry_offset; le64_t entry_array_offset; le64_t n_entries; char payload[size - 64]; // Data objects carry actual field data in the payload[] array. }; // If the HEADER_INCOMPATIBLE_COMPACT flag is set, two extra fields are stored to allow immediate access // to the tail entry array in the DATA object's entry array chain. struct DataObject_Compact { ObjectType type; ObjectFlag flags; uint8_t reserved[6]; le64_t size; le64_t hash; le64_t next_hash_offset; le64_t next_field_offset; le64_t entry_offset; le64_t entry_array_offset; le64_t n_entries; le32_t tail_entry_array_offset; le32_t tail_entry_array_n_entries; char payload[size - 72]; // Data objects carry actual field data in the payload[] array. }; struct EntryItem { le64_t object_offset; le64_t hash; }; struct EntryItem_Compact { le32_t object_offset; } // The first four members are copied from ObjectHeader, so that the size can be used as the length of items struct EntryObject { ObjectType type; uint8_t flags; uint8_t reserved[6]; le64_t size; le64_t seqnum; le64_t realtime; le64_t monotonic; sd_id128_t boot_id; le64_t xor_hash; EntryItem items[(size - 64) / 16]; // The size minus the previous members divided by the size of the items }; // If the HEADER_INCOMPATIBLE_COMPACT flag is set, DATA object offsets are stored as 32-bit integers instead of 64bit // and the unused hash field per data object is not stored anymore. struct EntryObject_Compact { ObjectType type; uint8_t flags; uint8_t reserved[6]; le64_t size; le64_t seqnum; le64_t realtime; le64_t monotonic; sd_id128_t boot_id; le64_t xor_hash; EntryItem_Compact items[(size - 64) / 4]; }; // The first four members are copied from from ObjectHeader, so that the size can be used as the length of entry_object_offsets struct EntryArrayObject { ObjectType type; uint8_t flags; uint8_t reserved[6]; le64_t size; le64_t next_entry_array_offset; le64_t entry_object_offsets[(size - 24) / 8]; // The size minus the previous members divided by the size of the offset }; struct EntryArrayObject_Compact { ObjectType type; uint8_t flags; uint8_t reserved[6]; le64_t size; le64_t next_entry_array_offset; le32_t entry_object_offsets[(size - 24) / 4]; }; """ .. raw:: html
.. py:data:: c_journal .. py:function:: get_optional(value: str, to_type: Callable) Return the value if True, otherwise return None. .. py:class:: JournalFile(fh: BinaryIO, target: dissect.target.Target) Parse Systemd Journal file format. .. rubric:: References - https://github.com/systemd/systemd/blob/206f0f397edf1144c63a158fb30f496c3e89f256/docs/JOURNAL_FILE_FORMAT.md - https://github.com/libyal/dtformats/blob/c4fc2b8102702c64b58f145971821986bf74e6c0/documentation/Systemd%20journal%20file%20format.asciidoc .. py:method:: entry_object_offsets() -> Iterator[int] Read object entry arrays. .. py:method:: decode_value(value: bytes) -> tuple[str, str] .. py:method:: __iter__() -> Iterator[dissect.cstruct.Instance] Iterate over the entry objects to read payloads. .. py:class:: JournalPlugin(target: dissect.target.Target) Bases: :py:obj:`dissect.target.plugin.Plugin` Base class for plugins. Plugins can optionally be namespaced by specifying the ``__namespace__`` class attribute. Namespacing results in your plugin needing to be prefixed with this namespace when being called. For example, if your plugin has specified ``test`` as namespace and a function called ``example``, you must call your plugin with ``test.example``:: A ``Plugin`` class has the following private class attributes: - ``__namespace__`` - ``__record_descriptors__`` With the following three being assigned in :func:`register`: - ``__plugin__`` - ``__functions__`` - ``__exports__`` Additionally, the methods and attributes of :class:`Plugin` receive more private attributes by using decorators. The :func:`export` decorator adds the following private attributes - ``__exported__`` - ``__output__``: Set with the :func:`export` decorator. - ``__record__``: Set with the :func:`export` decorator. The :func:`internal` decorator and :class:`InternalPlugin` set the ``__internal__`` attribute. Finally. :func:`args` decorator sets the ``__args__`` attribute. :param target: The :class:`~dissect.target.target.Target` object to load the plugin for. .. py:attribute:: JOURNAL_PATHS :value: ['/var/log/journal'] .. py:attribute:: JOURNAL_GLOB :value: '*/*.journal*' .. py:attribute:: JOURNAL_SIGNATURE :value: 'LPKSHHRH' .. py:method:: check_compatible() -> None Perform a compatibility check with the target. This function should return ``None`` if the plugin is compatible with the current target (``self.target``). For example, check if a certain file exists. Otherwise it should raise an ``UnsupportedPluginError``. :raises UnsupportedPluginError: If the plugin could not be loaded. .. py:method:: journal() -> Iterator[JournalRecord] Return the content of Systemd Journal log files. .. rubric:: References - https://wiki.archlinux.org/title/Systemd/Journal - https://github.com/systemd/systemd/blob/9203abf79f1d05fdef9b039e7addf9fc5a27752d/man/systemd.journal-fields.xml