Skip to content
Please update to the latest release 0.77.2 to address Multiple CVEs.
Windows.Forensics.BulkExtractor

Windows.Forensics.BulkExtractor

Deploys the bulk_extractor binary onto the endpoint and runs it against selected drives or directories for data carving.

Executes bulk_extractor with record carving plugins from 4n6ist. Initially developed to carve EventLogs from physical disk and unallocated space, this may also be used for other bulk extractor capabilities. 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 ad-hoc 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.

Notes:

  1. Currently only supported for x64 machines.
  2. This artifact usually takes a long time. Ensure default timeout is high enough to allow for completion.
  3. This artifact is NOT recommended for hunting without careful consideration as bulk_extractor is a multithreaded tool and utilizes 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: |
  Deploys the bulk_extractor binary onto the endpoint and runs it
  against selected drives or directories for data carving.

  Executes bulk_extractor with record carving plugins from 4n6ist.
  Initially developed to carve EventLogs from physical disk and
  unallocated space, this may also be used for other bulk extractor
  capabilities. 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 ad-hoc 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.

  **Notes:**
  
  1. Currently only supported for x64 machines.
  2. This artifact usually takes a long time. Ensure default timeout is high
     enough to allow for completion.
  3. This artifact is NOT recommended for hunting without careful consideration as
     bulk_extractor is a multithreaded tool and utilizes 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

implied_permissions:
  - FILESYSTEM_WRITE

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