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

Fix multiple datetime parsing issues in teamviewer plugin #448

Merged
merged 3 commits into from
Nov 21, 2023
Merged
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
82 changes: 55 additions & 27 deletions dissect/target/plugins/apps/remoteaccess/teamviewer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import re
from datetime import datetime

from dissect.target.exceptions import UnsupportedPluginError
Expand All @@ -7,6 +8,8 @@
RemoteAccessRecord,
)

START_PATTERN = re.compile(r"^(\d{2}|\d{4})/")


class TeamviewerPlugin(RemoteAccessPlugin):
"""
Expand Down Expand Up @@ -54,30 +57,55 @@ def logs(self):
for logfile, user in self.logfiles:
logfile = self.target.fs.path(logfile)

for line in logfile.open("rt"):
line = line.strip()

# Skip empty lines
if not line:
continue

# Sometimes there are weird, mult-line/pretty print log messages.
try:
# should be year (%Y)
int(line[0])
except ValueError:
continue

ts_day, ts_time, description = line.split(" ", 2)
ts_time = ts_time.split(".")[0]

timestamp = datetime.strptime(f"{ts_day} {ts_time}", "%Y/%m/%d %H:%M:%S")

yield RemoteAccessRecord(
tool="teamviewer",
ts=timestamp,
logfile=str(logfile),
description=description,
_target=self.target,
_user=user,
)
start_date = None
with logfile.open("rt") as file:
while True:
try:
line = file.readline()
except UnicodeDecodeError:
continue

# End of file, quit while loop
if not line:
break

line = line.strip()

# Skip empty lines
if not line:
continue
# Older logs first mention the start time and then leave out the year
if line.startswith("Start:"):
start_date = datetime.strptime(line.split()[1], "%Y/%m/%d")

# Sometimes there are weird, mult-line/pretty print log messages.
# We only parse the start line which starts with year (%Y/) or month (%m/)
if not re.match(START_PATTERN, line):
continue

ts_day, ts_time, description = line.split(" ", 2)
ts_time = ts_time.split(".")[0]

# Correct for use of : as millisecond separator
if ts_time.count(":") > 2:
ts_time = ":".join(ts_time.split(":")[:3])
# Correct for missing year in date
if ts_day.count("/") == 1:
if not start_date:
self.target.log.debug("Missing year in log line, skipping line.")
continue
ts_day = f"{start_date.year}/{ts_day}"
# Correct for year if short notation for 2000 is used
if ts_day.count("/") == 2 and len(ts_day.split("/")[0]) == 2:
ts_day = "20" + ts_day

timestamp = datetime.strptime(f"{ts_day} {ts_time}", "%Y/%m/%d %H:%M:%S")

yield RemoteAccessRecord(
tool="teamviewer",
ts=timestamp,
logfile=str(logfile),
description=description,
_target=self.target,
_user=user,
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
# skip
# also skip as well as the blank line below

# "Start" is present in older logs, we can deduce the year from it
Start: 2021/11/11 12:34:56

2021/11/11 12:34:56 Strip the headers, trace the source!

# Here is where the "Start" year is used to fill in the year
11/11 12:35:55.465 Should be year 2021

2021/11/11 12:36:11:111 Should discard the milliseconds properly
21/11/11 12:37:00.000 Should be year 2021
30 changes: 28 additions & 2 deletions tests/plugins/apps/remoteaccess/test_teamviewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def test_teamviewer_plugin_global_log(target_win_users, fs_win):
tvp = TeamviewerPlugin(target_win_users)

records = list(tvp.logs())
assert len(records) == 1
assert len(records) == 4

record = records[0]
assert record.ts == datetime(2021, 11, 11, 12, 34, 56, tzinfo=timezone.utc)
Expand All @@ -36,7 +36,7 @@ def test_teamviewer_plugin_user_log(target_win_users, fs_win):
tvp = TeamviewerPlugin(target_win_users)

records = list(tvp.logs())
assert len(records) == 1
assert len(records) == 4

record = records[0]
assert record.ts == datetime(2021, 11, 11, 12, 34, 56, tzinfo=timezone.utc)
Expand All @@ -45,3 +45,29 @@ def test_teamviewer_plugin_user_log(target_win_users, fs_win):
assert record.username == user_details.user.name
assert record.user_id == user_details.user.sid
assert record.user_home == user_details.user.home


def test_teamviewer_plugin_special_date_parsing(target_win_users, fs_win):
teamviewer_logfile = absolute_path("_data/plugins/apps/remoteaccess/teamviewer/TestTeamviewer.log")
user_details = target_win_users.user_details.find(username="John")
target_logfile_name = f"{user_details.home_path}/appdata/roaming/teamviewer/teamviewer_TEST_logfile.log"

_, _, map_path = target_logfile_name.partition("C:/")
fs_win.map_file(map_path, teamviewer_logfile)

tvp = TeamviewerPlugin(target_win_users)

records = list(tvp.logs())
assert len(records) == 4

record_2 = records[1]
assert record_2.ts == datetime(2021, 11, 11, 12, 35, 55, tzinfo=timezone.utc)
assert record_2.description == "Should be year 2021"

record_3 = records[2]
assert record_3.ts == datetime(2021, 11, 11, 12, 36, 11, tzinfo=timezone.utc)
assert record_3.description == "Should discard the milliseconds properly"

record_4 = records[3]
assert record_4.ts == datetime(2021, 11, 11, 12, 37, 00, tzinfo=timezone.utc)
assert record_4.description == "Should be year 2021"