dissect.target 3.21.dev7__py3-none-any.whl → 3.21.dev9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -567,7 +567,7 @@ def parse_unix_dhcp_log_messages(target: Target, iter_all: bool = False) -> set[
567
567
  continue
568
568
 
569
569
  # Debian and CentOS dhclient
570
- if hasattr(record, "daemon") and record.daemon == "dhclient" and "bound to" in line:
570
+ if hasattr(record, "service") and record.service == "dhclient" and "bound to" in line:
571
571
  ip = line.split("bound to")[1].split(" ")[1].strip()
572
572
  ips.add(ip)
573
573
  continue
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import itertools
4
3
  import logging
5
4
  import re
6
5
  from abc import ABC, abstractmethod
@@ -12,24 +11,18 @@ from typing import Any, Iterator
12
11
 
13
12
  from dissect.target import Target
14
13
  from dissect.target.exceptions import UnsupportedPluginError
15
- from dissect.target.helpers.fsutil import open_decompress
16
14
  from dissect.target.helpers.record import DynamicDescriptor, TargetRecordDescriptor
17
15
  from dissect.target.helpers.utils import year_rollover_helper
18
16
  from dissect.target.plugin import Plugin, alias, export
17
+ from dissect.target.plugins.os.unix.log.helpers import (
18
+ RE_LINE,
19
+ RE_TS,
20
+ is_iso_fmt,
21
+ iso_readlines,
22
+ )
19
23
 
20
24
  log = logging.getLogger(__name__)
21
25
 
22
- RE_TS = re.compile(r"^[A-Za-z]{3}\s*\d{1,2}\s\d{1,2}:\d{2}:\d{2}")
23
- RE_TS_ISO = re.compile(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}\+\d{2}:\d{2}")
24
- RE_LINE = re.compile(
25
- r"""
26
- \d{2}:\d{2}\s # First match on the similar ending of the different timestamps
27
- (?P<hostname>\S+)\s # The hostname
28
- (?P<service>\S+?)(\[(?P<pid>\d+)\])?: # The service with optionally the PID between brackets
29
- \s*(?P<message>.+?)\s*$ # The log message stripped from spaces left and right
30
- """,
31
- re.VERBOSE,
32
- )
33
26
 
34
27
  # Generic regular expressions
35
28
  RE_IPV4_ADDRESS = re.compile(
@@ -347,27 +340,3 @@ class AuthPlugin(Plugin):
347
340
 
348
341
  for ts, line in iterable:
349
342
  yield self._auth_log_builder.build_record(ts, auth_file, line)
350
-
351
-
352
- def iso_readlines(file: Path) -> Iterator[tuple[datetime, str]]:
353
- """Iterator reading the provided auth log file in ISO format. Mimics ``year_rollover_helper`` behaviour."""
354
- with open_decompress(file, "rt") as fh:
355
- for line in fh:
356
- if not (match := RE_TS_ISO.match(line)):
357
- log.warning("No timestamp found in one of the lines in %s!", file)
358
- log.debug("Skipping line: %s", line)
359
- continue
360
-
361
- try:
362
- ts = datetime.strptime(match[0], "%Y-%m-%dT%H:%M:%S.%f%z")
363
- except ValueError as e:
364
- log.warning("Unable to parse ISO timestamp in line: %s", line)
365
- log.debug("", exc_info=e)
366
- continue
367
-
368
- yield ts, line
369
-
370
-
371
- def is_iso_fmt(file: Path) -> bool:
372
- """Determine if the provided auth log file uses new ISO format logging or not."""
373
- return any(itertools.islice(iso_readlines(file), 0, 2))
@@ -0,0 +1,46 @@
1
+ import itertools
2
+ import logging
3
+ import re
4
+ from datetime import datetime
5
+ from pathlib import Path
6
+ from typing import Iterator
7
+
8
+ from dissect.target.helpers.fsutil import open_decompress
9
+
10
+ log = logging.getLogger(__name__)
11
+
12
+ RE_TS = re.compile(r"^[A-Za-z]{3}\s*\d{1,2}\s\d{1,2}:\d{2}:\d{2}")
13
+ RE_TS_ISO = re.compile(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}\+\d{2}:\d{2}")
14
+ RE_LINE = re.compile(
15
+ r"""
16
+ \d{2}:\d{2}\s # First match on the similar ending of the different timestamps
17
+ (?:\S+)\s # The hostname, but do not capture it
18
+ (?P<service>\S+?)(\[(?P<pid>\d+)\])?: # The service / daemon with optionally the PID between brackets
19
+ \s*(?P<message>.+?)\s*$ # The log message stripped from spaces left and right
20
+ """,
21
+ re.VERBOSE,
22
+ )
23
+
24
+
25
+ def iso_readlines(file: Path) -> Iterator[tuple[datetime, str]]:
26
+ """Iterator reading the provided log file in ISO format. Mimics ``year_rollover_helper`` behaviour."""
27
+ with open_decompress(file, "rt") as fh:
28
+ for line in fh:
29
+ if not (match := RE_TS_ISO.match(line)):
30
+ log.warning("No timestamp found in one of the lines in %s!", file)
31
+ log.debug("Skipping line: %s", line)
32
+ continue
33
+
34
+ try:
35
+ ts = datetime.strptime(match[0], "%Y-%m-%dT%H:%M:%S.%f%z")
36
+ except ValueError as e:
37
+ log.warning("Unable to parse ISO timestamp in line: %s", line)
38
+ log.debug("", exc_info=e)
39
+ continue
40
+
41
+ yield ts, line
42
+
43
+
44
+ def is_iso_fmt(file: Path) -> bool:
45
+ """Determine if the provided log file uses ISO 8601 timestamp format logging or not."""
46
+ return any(itertools.islice(iso_readlines(file), 0, 2))
@@ -11,12 +11,18 @@ from dissect.target.helpers.fsutil import open_decompress
11
11
  from dissect.target.helpers.record import TargetRecordDescriptor
12
12
  from dissect.target.helpers.utils import year_rollover_helper
13
13
  from dissect.target.plugin import Plugin, alias, export
14
+ from dissect.target.plugins.os.unix.log.helpers import (
15
+ RE_LINE,
16
+ RE_TS,
17
+ is_iso_fmt,
18
+ iso_readlines,
19
+ )
14
20
 
15
21
  MessagesRecord = TargetRecordDescriptor(
16
22
  "linux/log/messages",
17
23
  [
18
24
  ("datetime", "ts"),
19
- ("string", "daemon"),
25
+ ("string", "service"),
20
26
  ("varint", "pid"),
21
27
  ("string", "message"),
22
28
  ("path", "source"),
@@ -24,12 +30,8 @@ MessagesRecord = TargetRecordDescriptor(
24
30
  )
25
31
 
26
32
  DEFAULT_TS_LOG_FORMAT = "%b %d %H:%M:%S"
27
- RE_TS = re.compile(r"(\w+\s{1,2}\d+\s\d{2}:\d{2}:\d{2})")
28
- RE_DAEMON = re.compile(r"^[^:]+:\d+:\d+[^\[\]:]+\s([^\[:]+)[\[|:]{1}")
29
- RE_PID = re.compile(r"\w\[(\d+)\]")
30
- RE_MSG = re.compile(r"[^:]+:\d+:\d+[^:]+:\s(.*)$")
31
33
  RE_CLOUD_INIT_LINE = re.compile(
32
- r"^(?P<ts>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3}) - (?P<daemon>.*)\[(?P<log_level>\w+)\]\: (?P<message>.*)$"
34
+ r"^(?P<ts>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3}) - (?P<service>.*)\[(?P<log_level>\w+)\]\: (?P<message>.*)$"
33
35
  )
34
36
 
35
37
 
@@ -56,7 +58,7 @@ class MessagesPlugin(Plugin):
56
58
  def messages(self) -> Iterator[MessagesRecord]:
57
59
  """Return contents of /var/log/messages*, /var/log/syslog* and cloud-init logs.
58
60
 
59
- Due to year rollover detection, the contents of the files are returned in reverse.
61
+ Due to year rollover detection, the log contents could be returned in reversed or mixed chronological order.
60
62
 
61
63
  The messages log file holds information about a variety of events such as the system error messages, system
62
64
  startups and shutdowns, change in the network configuration, etc. Aims to store valuable, non-debug and
@@ -75,16 +77,23 @@ class MessagesPlugin(Plugin):
75
77
  yield from self._parse_cloud_init_log(log_file, tzinfo)
76
78
  continue
77
79
 
78
- for ts, line in year_rollover_helper(log_file, RE_TS, DEFAULT_TS_LOG_FORMAT, tzinfo):
79
- daemon = dict(enumerate(RE_DAEMON.findall(line))).get(0)
80
- pid = dict(enumerate(RE_PID.findall(line))).get(0)
81
- message = dict(enumerate(RE_MSG.findall(line))).get(0, line)
80
+ if is_iso_fmt(log_file):
81
+ iterable = iso_readlines(log_file)
82
+
83
+ else:
84
+ iterable = year_rollover_helper(log_file, RE_TS, DEFAULT_TS_LOG_FORMAT, tzinfo)
85
+
86
+ for ts, line in iterable:
87
+ match = RE_LINE.search(line)
88
+
89
+ if not match:
90
+ self.target.log.warning("Unable to parse message line in %s", log_file)
91
+ self.target.log.debug("Line %s", line)
92
+ continue
82
93
 
83
94
  yield MessagesRecord(
84
95
  ts=ts,
85
- daemon=daemon,
86
- pid=pid,
87
- message=message,
96
+ **match.groupdict(),
88
97
  source=log_file,
89
98
  _target=self.target,
90
99
  )
@@ -134,7 +143,7 @@ class MessagesPlugin(Plugin):
134
143
 
135
144
  yield MessagesRecord(
136
145
  ts=ts,
137
- daemon=values["daemon"],
146
+ service=values["service"],
138
147
  pid=None,
139
148
  message=values["message"],
140
149
  source=log_file,
@@ -632,8 +632,8 @@ def local_wintimestamp(target, ts):
632
632
  class CITPlugin(Plugin):
633
633
  """Plugin that parses CIT data from the registry.
634
634
 
635
- Reference:
636
- - https://dfir.ru/2018/12/02/the-cit-database-and-the-syscache-hive/
635
+ References:
636
+ - https://dfir.ru/2018/12/02/the-cit-database-and-the-syscache-hive/
637
637
  """
638
638
 
639
639
  __namespace__ = "cit"
@@ -641,7 +641,7 @@ class CITPlugin(Plugin):
641
641
  KEY = "HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\CIT"
642
642
 
643
643
  def check_compatible(self) -> None:
644
- if not len(list(self.target.registry.keys(self.KEY))) > 0:
644
+ if not list(self.target.registry.keys(self.KEY)):
645
645
  raise UnsupportedPluginError("No CIT registry key found")
646
646
 
647
647
  @export(record=get_args(CITRecords))
@@ -770,8 +770,9 @@ class CITPlugin(Plugin):
770
770
  yield from _yield_bitmap_records(
771
771
  self.target, cit, entry.use_data.bitmaps.foreground, CITProgramBitmapForegroundRecord
772
772
  )
773
- except Exception:
774
- self.target.log.exception("Failed to parse CIT value: %s", value.name)
773
+ except Exception as e:
774
+ self.target.log.warning("Failed to parse CIT value: %s", value.name)
775
+ self.target.log.debug("", exc_info=e)
775
776
 
776
777
  @export(record=CITPostUpdateUseInfoRecord)
777
778
  def puu(self) -> Iterator[CITPostUpdateUseInfoRecord]:
@@ -788,10 +789,16 @@ class CITPlugin(Plugin):
788
789
  for reg_key in keys:
789
790
  for key in self.target.registry.keys(reg_key):
790
791
  try:
791
- puu = c_cit.CIT_POST_UPDATE_USE_INFO(key.value("PUUActive").value)
792
+ key_value = key.value("PUUActive").value
793
+ puu = c_cit.CIT_POST_UPDATE_USE_INFO(key_value)
792
794
  except RegistryValueNotFoundError:
793
795
  continue
794
796
 
797
+ except EOFError as e:
798
+ self.target.log.warning("Exception reading CIT structure in key %s", key.path)
799
+ self.target.log.debug("Unable to parse value %s", key_value, exc_info=e)
800
+ continue
801
+
795
802
  yield CITPostUpdateUseInfoRecord(
796
803
  log_time_start=wintimestamp(puu.LogTimeStart),
797
804
  update_key=puu.UpdateKey,
@@ -852,10 +859,16 @@ class CITPlugin(Plugin):
852
859
  for reg_key in keys:
853
860
  for key in self.target.registry.keys(reg_key):
854
861
  try:
855
- dp = c_cit.CIT_DP_DATA(key.value("DP").value)
862
+ key_value = key.value("DP").value
863
+ dp = c_cit.CIT_DP_DATA(key_value)
856
864
  except RegistryValueNotFoundError:
857
865
  continue
858
866
 
867
+ except EOFError as e:
868
+ self.target.log.warning("Exception reading CIT structure in key %s", key.path)
869
+ self.target.log.debug("Unable to parse value %s", key_value, exc_info=e)
870
+ continue
871
+
859
872
  user = self.target.registry.get_user(key)
860
873
  log_time_start = wintimestamp(dp.LogTimeStart)
861
874
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.target
3
- Version: 3.21.dev7
3
+ Version: 3.21.dev9
4
4
  Summary: This module ties all other Dissect modules together, it provides a programming API and command line tools which allow easy access to various data sources inside disk images or file collections (a.k.a. targets)
5
5
  Author-email: Dissect Team <dissect@fox-it.com>
6
6
  License: Affero General Public License v3
@@ -234,7 +234,7 @@ dissect/target/plugins/os/unix/linux/iptables.py,sha256=qTzY5PHHXA33WnPYb5NESgoS
234
234
  dissect/target/plugins/os/unix/linux/modules.py,sha256=-LThb5mcKtngVfIICpdOGLtgJPc99WQ8Qufwddt8YgQ,2500
235
235
  dissect/target/plugins/os/unix/linux/netstat.py,sha256=EBpbK4BD3pZ0fKCR3ZMmVip4eQ0f6x_9yumA8vsUKPw,1691
236
236
  dissect/target/plugins/os/unix/linux/network.py,sha256=KfGfYhtrzpHHefaHjTpdbGSLu6IN4anweYt3V02D9zU,14392
237
- dissect/target/plugins/os/unix/linux/network_managers.py,sha256=nr0gA3hBqsvP9k6xAYmRYwGRB1kMtXB1k0pe78jWdFI,25768
237
+ dissect/target/plugins/os/unix/linux/network_managers.py,sha256=atvcHPXFHVeCD5ipygqpR8pOgSexCGKIvVZz3Z8ITLA,25770
238
238
  dissect/target/plugins/os/unix/linux/proc.py,sha256=jm35fAasnNbObN2tpflwQuCfVYLDkTP2EDrzYG42ZSk,23354
239
239
  dissect/target/plugins/os/unix/linux/processes.py,sha256=xAJswf06HZsY8JhQ11xfJw1OLTZ1q9XZbu7_a7k2UpY,2019
240
240
  dissect/target/plugins/os/unix/linux/services.py,sha256=cZWmoVImbl7foKQfBpiKjeC2kjvfRUpM-ympFQorwHI,4128
@@ -270,10 +270,11 @@ dissect/target/plugins/os/unix/locate/plocate.py,sha256=0p7ibPPrDlQuJNjJbV4rU0fJ
270
270
  dissect/target/plugins/os/unix/log/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
271
271
  dissect/target/plugins/os/unix/log/atop.py,sha256=zjG5eKS-X0mpBXs-Sg2f7RfQvtjt0T8JcteNd9DB_ok,16361
272
272
  dissect/target/plugins/os/unix/log/audit.py,sha256=rZwxC90Q0FOB5BZxplTJwCTIp0hdVpaps1e3C1fRYaM,3754
273
- dissect/target/plugins/os/unix/log/auth.py,sha256=9NJvlo7Vbsp_ENJFpKd04PH_sUuOy6ueSBwQqY0MtKo,14546
273
+ dissect/target/plugins/os/unix/log/auth.py,sha256=MNfPoGo_pGFMizbF5ZyW6bi-QWCxuaB7OVAeIJAAC6M,13068
274
+ dissect/target/plugins/os/unix/log/helpers.py,sha256=3_UNw36isxlmIRs0EreU4Oe5UrKOPl-mApjvfRXmYtQ,1775
274
275
  dissect/target/plugins/os/unix/log/journal.py,sha256=hhsvKs78BPv0vJN360fKVHqyBCdLUWxdv6ZUa4tqpD8,17795
275
276
  dissect/target/plugins/os/unix/log/lastlog.py,sha256=Wr3-2n1-GwckN9mSx-yM55N6_L0PQyx6TGHoEvuc6c0,2515
276
- dissect/target/plugins/os/unix/log/messages.py,sha256=XtjZ0a2budgQm_K5JT3fMf7JcjuD0AelcD3zOFN2xpI,5732
277
+ dissect/target/plugins/os/unix/log/messages.py,sha256=GjHqbbyoqXxIlD6cxK552Gv00LK399dU3u9NISGIVno,5787
277
278
  dissect/target/plugins/os/unix/log/utmp.py,sha256=k2A69s2qUT2JunJrH8GO6nQ0zMDotXMTaj8OzQ7ljj8,7336
278
279
  dissect/target/plugins/os/windows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
279
280
  dissect/target/plugins/os/windows/_os.py,sha256=SUTfCPEVi2ADfjsQQJad6dEsnKUzRtsKJXOlEuiT9Xk,12462
@@ -338,7 +339,7 @@ dissect/target/plugins/os/windows/regf/applications.py,sha256=AZwaLXsVmqMjoZYI3d
338
339
  dissect/target/plugins/os/windows/regf/appxdebugkeys.py,sha256=X8MYLcD76pIZoIWwS_DgUp6q6pi2WO7jhZeoc4uGLak,3966
339
340
  dissect/target/plugins/os/windows/regf/auditpol.py,sha256=vTqWw0_vu9p_emWC8FuYcYQpOXhEFQQDLV0K6-18i9c,5208
340
341
  dissect/target/plugins/os/windows/regf/bam.py,sha256=jJ0i-82uteBU0hPgs81f8NV8NCeRtIklK82Me2S_ro0,2131
341
- dissect/target/plugins/os/windows/regf/cit.py,sha256=rvaQzOVi-OHTdJzmF5l32Bx9pTJm11JfYXx-5N0cL28,38517
342
+ dissect/target/plugins/os/windows/regf/cit.py,sha256=WYuwzTJKSR8Ki0582zpTpRUApx_J3OIYFWivKgqH-Is,39178
342
343
  dissect/target/plugins/os/windows/regf/clsid.py,sha256=ellokL8H7TR8XkGqqWraJ3bL0qP5RJrjNsp4JeBLU7A,3810
343
344
  dissect/target/plugins/os/windows/regf/firewall.py,sha256=86JvlBc418nHB5l3IkbEnTw6zr-H5pEGEoZ8fBhmeLE,3231
344
345
  dissect/target/plugins/os/windows/regf/mru.py,sha256=JzjwaV3Pbza2oOVILrnqcmPKCq2rGIGFwRpJW8Yc1p0,13840
@@ -381,10 +382,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
381
382
  dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
382
383
  dissect/target/volumes/md.py,sha256=7ShPtusuLGaIv27SvEETtgsuoQyAa4iAAeOR1NEaajI,1689
383
384
  dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
384
- dissect.target-3.21.dev7.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
385
- dissect.target-3.21.dev7.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
386
- dissect.target-3.21.dev7.dist-info/METADATA,sha256=gVyNSrgCeZcrEN3najdfE0aOsB5Ib-7wop_X6pCnw5M,13186
387
- dissect.target-3.21.dev7.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
388
- dissect.target-3.21.dev7.dist-info/entry_points.txt,sha256=BWuxAb_6AvUAQpIQOQU0IMTlaF6TDht2AIZK8bHd-zE,492
389
- dissect.target-3.21.dev7.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
390
- dissect.target-3.21.dev7.dist-info/RECORD,,
385
+ dissect.target-3.21.dev9.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
386
+ dissect.target-3.21.dev9.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
387
+ dissect.target-3.21.dev9.dist-info/METADATA,sha256=KoXhIy7PkSoTr-n6q7z0pgLwcQeGhaLAqfazXNkFQrs,13186
388
+ dissect.target-3.21.dev9.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
389
+ dissect.target-3.21.dev9.dist-info/entry_points.txt,sha256=BWuxAb_6AvUAQpIQOQU0IMTlaF6TDht2AIZK8bHd-zE,492
390
+ dissect.target-3.21.dev9.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
391
+ dissect.target-3.21.dev9.dist-info/RECORD,,