Windows.Forensics.BulkExtractor

This content will execute bulk_extractor with record carving plugins from 4n6ist. Initially developed to carve EventLogs from physical disk and unallocated space, this content may also be leveraged for other bulk extractor capability. Best use case is for remote targeted machine collection to remove the need for a disk image.

Settings Target - Can be \\.\PhysicalDrive[X], \\?\HarddiskVolumeShadowCopy[Y] or C:\Folder\Path" TargetAllPhysical - boolean option to include all attached physical disks TargetVSS - boolean option to target all VSC CarveEvtx - boolean option to include evtx carving FindRegex - regex to include for BulkExtractor find plugins

FreeCommand - supersedes evtx or find options and allows free form switch generation for adlib use cases. e.g ‘-E evtx, -e zip -S unzip_carve_mode=2’" Will add: command prefix: “-q 99999999999 -R’” and postfix: “-o [Outfolder] [Target]”. To make: bulk_extractor q 99999999999 -R -E evtx, -e zip -S unzip_carve_mode=2 -o [outfolder] [Target]

If FindRegex or “-f” has been used in FreeCommand the artifact will attempt to parse find.txt output.

Note

  1. Currently only supported for x64 bit machines.
  2. This artifact usually takes a long time. Ensure default timeout is high enough for completion.
  3. This content is NOT recommended for hunting without great consideration as bulk_extractor is a multithreaded tool and utilises all CPU available on the endpoint.
  4. The artifact copies carved data to the local disk prior to upload which is not ideal from a forensic viewpoint.

name: Windows.Forensics.BulkExtractor
description: |
    This content will execute bulk_extractor with record carving plugins from
    4n6ist. Initially developed to carve EventLogs from physical disk and
    unallocated space, this content may also be leveraged for other
    bulk extractor capability. Best use case is for remote targeted machine
    collection to remove the need for a disk image.

    **Settings**
    Target - Can be \\\\.\\PhysicalDrive[X], \\\\?\\HarddiskVolumeShadowCopy[Y]
    or C:\\Folder\\Path"
    TargetAllPhysical - boolean option to include all attached physical disks
    TargetVSS - boolean option to target all VSC
    CarveEvtx - boolean option to include evtx carving
    FindRegex - regex to include for BulkExtractor find plugins

    FreeCommand - supersedes evtx or find options and allows free form switch
    generation for adlib use cases.
    e.g '-E evtx, -e zip -S unzip_carve_mode=2'"
    Will add:
    command prefix: "-q 99999999999 -R'" and
    postfix: "-o [Outfolder] [Target]".
    To make: bulk_extractor q 99999999999 -R -E evtx, -e zip -S unzip_carve_mode=2 -o [outfolder] [Target]

    If FindRegex or "-f" has been used in FreeCommand the artifact will attempt
    to parse find.txt output.

    **Note**
    1. Currently only supported for x64 bit machines.
    2. This artifact usually takes a long time. Ensure default timeout is high
    enough for completion.
    3. This content is NOT recommended for hunting without great consideration as
    bulk_extractor is a multithreaded tool and utilises all CPU available on the
    endpoint.
    4. The artifact copies carved data to the local disk prior to upload which
    is not ideal from a forensic viewpoint.

reference:
  - http://www.kazamiya.net/en/bulk_extractor-rec
  - http://downloads.digitalcorpora.org/downloads/bulk_extractor/BEUsersManual.pdf
  - https://simson.net/clips/academic/2013.COSE.bulk_extractor.pdf

author: Matt Green - @mgreen27

required_permissions:
  - EXECVE

tools:
  - name: Bulk_Extractor_Binary
    url: https://github.com/Velocidex/Tools/raw/main/BulkExtractor/bulk_extractor.exe
    serve_locally: true

precondition: SELECT OS From info() where OS = 'windows'

parameters:
  - name: Target
    description: "Target. Can by physical drive, \\\\?\\HarddiskVolumeShadowCopy1 or C:\\Folder\\Path"
    default: \\.\PhysicalDrive0
  - name: TargetAllPhysical
    description: "Target all attached physical drives"
    type: bool
  - name: TargetVSS
    description: "Target all VSC. Note: Not targeted to folder. Velociraptor CAN collect from the Volume Shadow direct targeted to folder with ntfs accessor so there may be a better way."
    type: bool
  - name: CarveEvtx
    description: "Carve EVTX files"
    type: bool
  - name: FindRegex
    description: "Regex for Bulk_extractor find plugin"
  - name: FreeCommand
    description: "Bulk_extractor custom commands. .e.g '-E evtx, -e zip -S unzip_carve_mode=2'"

sources:
  - query: |
      LET bin <= SELECT *
        FROM Artifact.Generic.Utils.FetchBinary(ToolName="Bulk_Extractor_Binary")
      LET tempfolder <= tempdir()
      LET ExePath <= tempfile(extension=".exe")

      LET target = SELECT
            DeviceID,
            if(condition=DeviceID=~"^\\\\\\\\.\\\\",
                then=split(string=split(string=DeviceID,sep='\\\\\\\\.\\\\')[1],
                    sep='\\\\')[0],
                else="bulk_out") as base,
            _DeviceID
      FROM chain(
            a={
                SELECT
                    DeviceID,
                    upcase(string=DeviceID) as _DeviceID
                FROM Artifact.Windows.Sys.DiskInfo()
                WHERE TargetAllPhysical
            },
            b={
                SELECT
                    Target as DeviceID,
                    upcase(string=Target) as _DeviceID
                FROM scope()
                WHERE Target =~ '.'
            },
            c={
                SELECT
                    regex_replace(source=OSPath,
                        re="GLOBALROOT\\\\Device\\\\",replace="")AS DeviceID,
                    Data.ID AS ShadowCopyID,
                    upcase(string=regex_replace(source=OSPath,
                        re="GLOBALROOT\\\\Device\\\\",replace="")) as _DeviceID
                FROM glob(globs='/*', accessor='ntfs')
                WHERE ShadowCopyID AND TargetVSS
                ORDER by OSPath
            })
            GROUP BY _DeviceID

      LET cmdline = SELECT (bin[0].OSPath, '-q', '99999999999', '-R') +
                           CMD + '-o' as CMD FROM switch(
            a= {
                SELECT commandline_split(command=FreeCommand) AS CMD
                FROM scope()
                WHERE FreeCommand
            },
            b= {
                SELECT
                    ('-E','evtx','-e','find','-f',FindRegex) AS CMD
                FROM scope()
                WHERE CarveEvtx AND FindRegex
            },
            c= {
                SELECT ('-E','evtx') AS CMD
                FROM scope()
                WHERE CarveEvtx
            },
            d= {
                SELECT ('-E','find','-f',FindRegex) AS CMD
                FROM scope()
                WHERE FindRegex
            },
            e= {
                SELECT ('-h') AS CMD FROM scope()
            })

      SELECT * FROM foreach(
        row=target,
        query= {
            SELECT *
            FROM execve(
             argv=cmdline[0].CMD + (
                tempfolder + '\\' +
                  regex_replace(source=base, re='[^a-zA-Z]', replace='_'),
                  DeviceID),
             length=10000000, sep='\n')})

  - name: FindResults
    query: |
      SELECT * FROM foreach(
        row={  SELECT *
               FROM glob(globs='/*/find.txt', root=tempfolder)
        },
        query={
            SELECT *
            FROM split_records(filenames=OSPath,first_row_is_headers=false,
                columns=['Location','Match','Data'],regex='\t')
            WHERE NOT Location =~ '#'
        })
        WHERE FindRegex OR FreeCommand =~ '-f'

  - name: Upload
    query: |
      SELECT upload(file=OSPath,
                    name=strip(string=OSPath,prefix=tempfolder)) AS Upload
      FROM glob(globs="/**", root=tempfolder)
      WHERE Upload