Windows.Forensics.Trawler

Trawler [https://github.com/joeavanzato/Trawler] is a PowerShell script designed to help Incident Responders rapidly identify potential adversary persistence mechanisms on Windows. It is similar in nature to PersistenceSniper with additional targeted checks as well as the capability to operate against a ‘dead box’ (mounted drive). The output is simplified compared to PersistenceSniper, providing the user with the details needed to kick off an investigation into any identified mechanisms. Think of these tools as autoruns on steroids.

Please ensure the Velociraptor binary (and child powershell process) are excluded in any EDR/AV products.


name: Windows.Forensics.Trawler
description: |
  Trawler [https://github.com/joeavanzato/Trawler] is a PowerShell script designed to help Incident
  Responders rapidly identify potential adversary persistence mechanisms on Windows.  It is similar
  in nature to PersistenceSniper with additional targeted checks as well as the capability to operate
  against a 'dead box' (mounted drive). The output is simplified compared to PersistenceSniper, providing
  the user with the details needed to kick off an investigation into any identified mechanisms.
  Think of these tools as autoruns on steroids.

  Please ensure the Velociraptor binary (and child powershell process) are excluded in any EDR/AV products.

author: Joe Avanzato

parameters:
  - name: UploadResults
    type: bool
    default: true

tools:
  - name: Trawler
    url: https://github.com/joeavanzato/Trawler/releases/download/1_0_0/trawler_release_v1_0_0.zip
    expected_hash: efade9e0e6d228c118c4c28de2e45c37ae2fa4973283d5f851e6c62c7b72f53b

type: Client

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

sources:
    - query: |
       LET TmpDir <= tempdir(remove_last='Y')

       LET TrawlerZIP <= SELECT FullPath FROM Artifact.Generic.Utils.FetchBinary(ToolName="Trawler", IsExecutable=FALSE)

       LET _ <= SELECT * FROM unzip(filename=TrawlerZIP.FullPath, output_directory=TmpDir)

       LET TrawlerLocation = path_join(components=[TmpDir, 'trawler.ps1'], path_type='windows')

       LET TrawlerOutput <= path_join(components=[TmpDir + '\\detections.csv'], path_type='windows')
       LET TrawlerOutputPath = '"' + TrawlerOutput.Path + '"'

       LET cmdline <= join(
           array=[TrawlerLocation, '-outpath', TrawlerOutputPath],
           sep=' ')

       LET _ <= SELECT *
         FROM execve(
           argv=["powershell", "-ExecutionPolicy", "bypass", "-command", cmdline])

       LET LocalUploadTrawlerRecords = SELECT *
         FROM parse_csv(filename=TrawlerOutput)

       LET UploadTrawlerRecords = SELECT *, upload(file=TrawlerOutput) AS Upload
                         FROM LocalUploadTrawlerRecords

       SELECT *
       FROM if(
         condition=UploadResults,
         then=UploadTrawlerRecords,
         else=LocalUploadTrawlerRecords)