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

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,,