Skip to content

ScanExiftool

Collects metadata parsed by Exiftool.

This scanner uses Exiftool to extract metadata from files and logs the extracted key-value pairs.

Options

tmp_directory: Location where tempfile writes temporary files. Defaults to '/tmp/'.

Source code in strelka/src/python/strelka/scanners/scan_exiftool.py
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:
        tmp_directory: Location where tempfile writes temporary files.
            Defaults to '/tmp/'.
    """

    def scan(self, data, file, options, expire_at):
        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()

            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)}")

Features

The features of this scanner are detailed below. These features represent the capabilities and the type of analysis the scanner can perform. This may include support for Indicators of Compromise (IOC), the ability to emit files for further analysis, and the presence of extended documentation for complex analysis techniques.

Feature
Support
IOC Support
Emit Files
Extended Docs
Malware Scanner
Image Thumbnails

Tastes

Strelka's file distribution system assigns scanners to files based on 'flavors' and 'tastes'. Flavors describe the type of file, typically determined by MIME types from libmagic, matches from YARA rules, or characteristics of parent files. Tastes are the criteria used within Strelka to determine which scanners are applied to which files, with positive and negative tastes defining files to be included or excluded respectively.

Source Filetype
Include / Exclude
application/msword
application/pdf
application/vnd.ms-excel
application/x-shockwave-flash
bmp_file
fws_file
gif_file
image/avif
image/gif
image/heic
image/heif
image/jpeg
image/png
image/tiff
image/webp
image/x-ms-bmp
jpeg_file
lnk_file
olecf_file
pdf_file
png_file
type_is_tiff

Scanner Fields

This section provides a list of fields that are extracted from the files processed by this scanner. These fields include the data elements that the scanner extracts from each file, representing the analytical results produced by the scanner. If the test file is missing or cannot be parsed, this section will not contain any data.

Field Name
Field Type
appversion
float
author
str
bitspersample
int
bluematrixcolumn
str
bluetrc
str
characters
int
charcountwithspaces
int
cmmflags
str
codepage
str
colorcomponents
int
colorspacedata
str
comment
str
comments
str
company
str
compobjusertype
str
compobjusertypelen
int
connectionspaceilluminant
str
createdate
str
deviceattributes
str
devicemanufacturer
str
devicemfgdesc
str
devicemodel
str
devicemodeldesc
str
directory
str
docflags
str
elapsed
str
encodingprocess
str
exifbyteorder
str
exifimageheight
int
exifimagewidth
int
exiftoolversion
float
fileaccessdate
str
fileinodechangedate
str
filemodifydate
str
filename
str
filepermissions
str
filesize
str
filetype
str
filetypeextension
str
flags
list
gpslatitude
str
gpslatituderef
str
gpslongitude
str
gpslongituderef
str
gpsposition
str
greenmatrixcolumn
str
greentrc
str
headingpairs
str
hyperlinkschanged
str
identification
str
imageheight
int
imagesize
str
imagewidth
int
keywords
str
languagecode
str
lastmodifiedby
str
lastprinted
str
lines
int
linksuptodate
str
luminance
str
measurementbacking
str
measurementflare
str
measurementgeometry
str
measurementilluminant
str
measurementobserver
str
mediablackpoint
str
mediawhitepoint
str
megapixels
float
mimetype
str
modifydate
str
orientation
str
pages
int
paragraphs
int
primaryplatform
str
profileclass
str
profilecmmtype
str
profileconnectionspace
str
profilecopyright
str
profilecreator
str
profiledatetime
str
profiledescription
str
profilefilesignature
str
profileid
int
profileversion
str
redmatrixcolumn
str
redtrc
str
renderingintent
str
resolutionunit
str
revisionnumber
int
scalecrop
str
security
str
shareddoc
str
software
str
sourcefile
str
subject
str
subsecmodifydate
str
subsectime
int
system
str
technology
str
template
str
title
str
titleofparts
str
totaledittime
str
viewingconddesc
str
viewingcondilluminant
str
viewingcondilluminanttype
str
viewingcondsurround
str
word97
str
words
int
xmptoolkit
str
xresolution
int
ycbcrpositioning
str
ycbcrsubsampling
str
yresolution
int

Sample Event

Below is a sample event generated by this scanner, demonstrating the kind of output that can be expected when it processes a file. This sample is derived from a mock scan event configured in the scanner's test file. If no test file is available, this section will not display a sample event.

    test_scan_event = {
        "elapsed": 0.001,
        "flags": [],
        "sourcefile": 0.001,
        "exiftoolversion": 12.6,
        "filename": 0.001,
        "directory": "/tmp",
        "filesize": "51 kB",
        "filemodifydate": 0.001,
        "fileaccessdate": 0.001,
        "fileinodechangedate": 0.001,
        "filepermissions": "-rw-------",
        "filetype": "DOC",
        "filetypeextension": "doc",
        "mimetype": "application/msword",
        "identification": "Word 8.0",
        "languagecode": "English (US)",
        "docflags": "Has picture, 1Table, ExtChar",
        "system": "Windows",
        "word97": "No",
        "title": "",
        "subject": "",
        "author": "Ryan.OHoro",
        "keywords": "",
        "comments": "",
        "template": "Normal.dotm",
        "lastmodifiedby": "Ryan.OHoro",
        "software": "Microsoft Office Word",
        "createdate": "2022:12:16 19:48:00",
        "modifydate": "2022:12:16 19:48:00",
        "security": "None",
        "codepage": "Windows Latin 1 (Western European)",
        "company": "Target Corporation",
        "charcountwithspaces": 2877,
        "appversion": 16.0,
        "scalecrop": "No",
        "linksuptodate": "No",
        "shareddoc": "No",
        "hyperlinkschanged": "No",
        "titleofparts": "",
        "headingpairs": "Title, 1",
        "compobjusertypelen": 32,
        "compobjusertype": "Microsoft Word 97-2003 Document",
        "lastprinted": "0000:00:00 00:00:00",
        "revisionnumber": 2,
        "totaledittime": "1 minute",
        "words": 430,
        "characters": 2452,
        "pages": 1,
        "paragraphs": 5,
        "lines": 20,
    }