Skip to content

Commit

Permalink
Merge pull request #407 from target/exiftool-update
Browse files Browse the repository at this point in the history
Exiftool Output Modification (Remove Key Inclusion Requirements)
  • Loading branch information
phutelmyer authored Oct 25, 2023
2 parents 5dfe332 + ebe71b9 commit dd02a69
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 246 deletions.
2 changes: 1 addition & 1 deletion build/python/backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ ARG CONFIG_TESTS=false

ARG YARA_VERSION=4.3.1
ARG CAPA_VERSION=6.1.0
ARG EXIFTOOL_VERSION=12.52
ARG EXIFTOOL_VERSION=12.60

# Environment variables
ENV PYTHONDONTWRITEBYTECODE 1
Expand Down
58 changes: 0 additions & 58 deletions configs/python/backend/backend.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -154,62 +154,9 @@ scanners:
- 'application/msword'
- 'olecf_file'
- 'application/vnd.ms-excel'
priority: 5
options:
keys:
- 'Author'
- 'Characters'
- 'Company'
- 'CreateDate'
- 'LastModifiedBy'
- 'Lines'
- 'ModifyDate'
- 'Pages'
- 'Paragraphs'
- 'RevisionNumber'
- 'Software'
- 'Template'
- 'Title'
- 'TotalEditTime'
- 'Words'
tmp_directory: '/dev/shm/'
- positive:
flavors:
- 'application/pdf'
- 'pdf_file'
priority: 5
options:
keys:
- 'Author'
- 'CreateDate'
- 'Creator'
- 'CreatorTool'
- 'Linearized'
- 'ModifyDate'
- 'PageCount'
- 'PDFVersion'
- 'Producer'
- 'Title'
tmp_directory: '/dev/shm/'
- positive:
flavors:
- 'lnk_file'
priority: 5
options:
keys:
- 'CommandLineArguments'
- 'Description'
- 'FileAttributes'
- 'Flags'
- 'HotKey'
- 'IconFileName'
- 'IconIndex'
- 'RunWindow'
- 'TargetFileSize'
- 'WorkingDirectory'
tmp_directory: '/dev/shm/'
- positive:
flavors:
- 'image/gif'
- 'gif_file'
- 'image/jpeg'
Expand All @@ -227,11 +174,6 @@ scanners:
- 'image/heic'
- 'image/heif'
priority: 5
options:
keys:
- 'ImageHeight'
- 'ImageWidth'
tmp_directory: '/dev/shm/'
# 'ScanFloss':
# - positive:
# flavors:
Expand Down
66 changes: 33 additions & 33 deletions src/python/strelka/scanners/scan_exiftool.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import ast
import json
import subprocess
import tempfile
Expand All @@ -9,47 +8,48 @@
class ScanExiftool(strelka.Scanner):
"""Collects metadata parsed by Exiftool.
This scanner uses Exiftool to extract metadata from files and logs the
extracted key-value pairs.
Options:
keys: exiftool key values to log in the event.
Defaults to all.
tmp_directory: Location where tempfile writes temporary files.
Defaults to '/tmp/'.
"""

def scan(self, data, file, options, expire_at):
keys = options.get("keys", [])
tmp_directory = options.get("tmp_directory", "/tmp/")

# Use a temporary file to store the data for processing with Exiftool
with tempfile.NamedTemporaryFile(dir=tmp_directory) as tmp_data:
tmp_data.write(data)
tmp_data.flush()

(stdout, stderr) = subprocess.Popen(
["exiftool", "-d", '"%s"', "-j", tmp_data.name],
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
).communicate()

if stdout:
exiftool_dictionary = json.loads(stdout)[0]

self.event["keys"] = []
for k, v in exiftool_dictionary.items():
if keys and k not in keys:
continue

if isinstance(v, str):
v = v.strip()
v = v.strip("'\"")

try:
v = ast.literal_eval(v)
except (ValueError, SyntaxError):
pass

self.event["keys"].append(
{
"key": k,
"value": v,
}
)
try:
# Execute exiftool and retrieve JSON metadata output
(stdout, stderr) = subprocess.Popen(
["exiftool", "-j", tmp_data.name],
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
).communicate()

if stdout:
# Load metadata from stdout and update the event dictionary with it
# Converts fields with spaces to underscores to accommodate
# searchability (i.e., "File Name" to "file_name")
metadata = json.loads(stdout)[0]
for key, value in metadata.items():
formatted_key = key.replace(" ", "_").replace("/", "_").lower()

# Convert any lists to a comma-separated string
if isinstance(value, list):
value = ", ".join(map(str, value))

self.event[formatted_key] = value

# Handle potential errors from exiftool and JSON decoding
except subprocess.CalledProcessError as e:
self.flags.append(f"exiftool_error: Subprocess Error - {str(e)}")
except json.JSONDecodeError as e:
self.flags.append(f"exiftool_error: JSON Decode Error - {str(e)}")
except Exception as e:
self.flags.append(f"exiftool_error: General Error - {str(e)}")
Loading

0 comments on commit dd02a69

Please sign in to comment.