Skip to content

Commit cef6594

Browse files
author
Benjamin Cance
committed
Adds body file, timeline, l2t back. Closes Files not marked as deleted in bodyfile output #33 Data run calculations are wrong? #21 Investigate update sequence numbers #9 Datarun oddity #16 Additional rules #46
1 parent 2ee4d83 commit cef6594

File tree

2 files changed

+47
-3
lines changed

2 files changed

+47
-3
lines changed

src/analyzeMFT/cli.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import asyncio
2-
from optparse import OptionParser
2+
from optparse import OptionParser, OptionGroup
33
import sys
44
from .mft_analyzer import MftAnalyzer
55
from .constants import VERSION
@@ -21,6 +21,12 @@ async def main():
2121
help="Export as XML")
2222
export_group.add_option("--excel", action="store_const", const="excel", dest="export_format",
2323
help="Export as Excel")
24+
export_group.add_option("--body", action="store_const", const="body", dest="export_format",
25+
help="Export as body file (for mactime)")
26+
export_group.add_option("--timeline", action="store_const", const="timeline", dest="export_format",
27+
help="Export as TSK timeline")
28+
export_group.add_option("--l2t", action="store_const", const="l2t", dest="export_format",
29+
help="Export as log2timeline CSV")
2430
parser.add_option_group(export_group)
2531

2632
parser.add_option("-d", "--debug", action="store_true", dest="debug",
@@ -35,7 +41,7 @@ async def main():
3541
sys.exit(1)
3642

3743
if not options.export_format:
38-
options.export_format = "csv"
44+
options.export_format = "csv" # Default to CSV if no format specified
3945

4046
analyzer = MftAnalyzer(options.filename, options.output_file, options.debug, options.compute_hashes, options.export_format)
4147
await analyzer.analyze()

src/analyzeMFT/file_writers.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,42 @@ async def write_excel(records: List[MftRecord], output_file: str) -> None:
4747
for record in records:
4848
ws.append(record.to_csv())
4949
wb.save(output_file)
50-
await asyncio.sleep(0)
50+
await asyncio.sleep(0)
51+
52+
@staticmethod
53+
async def write_body(records: List[MftRecord], output_file: str) -> None:
54+
with open(output_file, 'w', encoding='utf-8') as bodyfile:
55+
for record in records:
56+
# Format: MD5|name|inode|mode_as_string|UID|GID|size|atime|mtime|ctime|crtime
57+
bodyfile.write(f"0|{record.filename}|{record.recordnum}|{record.flags:04o}|0|0|"
58+
f"{record.filesize}|{record.fn_times['atime'].unixtime}|"
59+
f"{record.fn_times['mtime'].unixtime}|{record.fn_times['ctime'].unixtime}|"
60+
f"{record.fn_times['crtime'].unixtime}\n")
61+
await asyncio.sleep(0)
62+
63+
@staticmethod
64+
async def write_timeline(records: List[MftRecord], output_file: str) -> None:
65+
with open(output_file, 'w', encoding='utf-8') as timeline:
66+
for record in records:
67+
# Format: Time|Source|Type|User|Host|Short|Desc|Version|Filename|Inode|Notes|Format|Extra
68+
timeline.write(f"{record.fn_times['crtime'].unixtime}|MFT|CREATE|||||{record.filename}|{record.recordnum}||||\n")
69+
timeline.write(f"{record.fn_times['mtime'].unixtime}|MFT|MODIFY|||||{record.filename}|{record.recordnum}||||\n")
70+
timeline.write(f"{record.fn_times['atime'].unixtime}|MFT|ACCESS|||||{record.filename}|{record.recordnum}||||\n")
71+
timeline.write(f"{record.fn_times['ctime'].unixtime}|MFT|CHANGE|||||{record.filename}|{record.recordnum}||||\n")
72+
await asyncio.sleep(0)
73+
74+
@staticmethod
75+
async def write_l2t(records: List[MftRecord], output_file: str) -> None:
76+
with open(output_file, 'w', newline='', encoding='utf-8') as l2tfile:
77+
writer = csv.writer(l2tfile)
78+
writer.writerow(['date', 'time', 'timezone', 'MACB', 'source', 'sourcetype', 'type', 'user', 'host', 'short', 'desc', 'version', 'filename', 'inode', 'notes', 'format', 'extra'])
79+
for record in records:
80+
for time_type, time_obj in record.fn_times.items():
81+
macb = 'M' if time_type == 'mtime' else 'A' if time_type == 'atime' else 'C' if time_type == 'ctime' else 'B'
82+
date_str = time_obj.dt.strftime('%m/%d/%Y') if time_obj.dt else ''
83+
time_str = time_obj.dt.strftime('%H:%M:%S') if time_obj.dt else ''
84+
writer.writerow([
85+
date_str, time_str, 'UTC', macb, 'MFT', 'FILESYSTEM', time_type, '', '', '',
86+
f"{record.filename} {time_type}", '', record.filename, record.recordnum, '', '', ''
87+
])
88+
await asyncio.sleep(0)

0 commit comments

Comments
 (0)