Windows.Forensics.PersistenceSniper

PersistenceSniper is a Powershell module that can be used by Blue Teams, Incident Responders and System Administrators to hunt persistences implanted in Windows machines. It is also available on Powershell Gallery and it is digitally signed with a valid code signing certificate. The tool is under active development with new releases coming out regularly, so make sure to use the up-to-date version. https://github.com/last-byte/PersistenceSniper

NOTE: the Rapid7 team has observed this artifact fail with some EDR/EPP tools deployed with Powershell prevention capabilities. Please ensure the Velociraptor binary (and child powershell) are excluded in these tools. Now DiffCSVUrl is downloaded during generation of the collector, not during execution.


name: Windows.Forensics.PersistenceSniper
description: |
  PersistenceSniper is a Powershell module that can be used by Blue Teams, Incident
  Responders and System Administrators to hunt persistences implanted in Windows machines.
  It is also available on Powershell Gallery and it is digitally signed with a valid code
  signing certificate. The tool is under active development with new releases coming out
  regularly, so make sure to use the up-to-date version.
  https://github.com/last-byte/PersistenceSniper

  NOTE: the Rapid7 team has observed this artifact fail with some EDR/EPP tools deployed
  with Powershell prevention capabilities. Please ensure the Velociraptor binary (and
  child powershell) are excluded in these tools.
  Now DiffCSVUrl is downloaded during generation of the 
  collector, not during execution.

author: Chris Jones - CPIRT | FabFaeb | Antonio Blescia (TheThMando) | 0xdeadcell

parameters:
  - name: IncludeHighFalsePositivesChecks
    default: true
    type: bool
  - name: UploadHits
    type: bool
    default: false

tools:
  - name: PSniper
    url: https://github.com/last-byte/PersistenceSniper/releases/download/v1.16.1/PersistenceSniper.zip
  - name: DiffCSVUrl
    url: https://raw.githubusercontent.com/ablescia/Windows.PersistenceSniper/main/false_positives.csv


type: Client

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

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

       LET Toolzip <= SELECT FullPath
         FROM Artifact.Generic.Utils.FetchBinary(ToolName="PSniper",
                                                 IsExecutable=FALSE)
       
       LET CSVPath <= SELECT FullPath
         FROM Artifact.Generic.Utils.FetchBinary(ToolName="DiffCSVUrl",
                                                 IsExecutable=FALSE)

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

       LET PSniperLocation = path_join(
           components=[TmpDir, 'PersistenceSniper', 'PersistenceSniper.psm1'],
           path_type='windows')

       LET FalsePositivesFile <= path_join(
           components=[TmpDir, '\\false_positives.csv'],
           path_type='windows')

       LET CSVFile <= path_join(
           components=[TmpDir + '\\psniper_results.csv'],
           path_type='windows')
       LET csvpath = '"' + CSVFile.Path + '"'

       LET arg_diffcsv <= if(
           condition=CSVFile != "",
           then="-DiffCSV " + '"' + FalsePositivesFile.Path + '"',
           else="")

       LET arg_includehighfalsepositiveschecks <= if(
           condition=IncludeHighFalsePositivesChecks,
           then="-IncludeHighFalsePositivesChecks",
           else="")

       LET cmdline <= join(
           array=['import-module', '"' + PSniperLocation.Path + '";', 'Find-AllPersistence', arg_includehighfalsepositiveschecks, arg_diffcsv, '| ConvertTo-CSV -NoTypeInformation | Out-File -encoding ASCII',csvpath],
           sep=' ')

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

       LET hits = SELECT *
         FROM parse_csv(filename=CSVFile)

       -- upload files if selected
       LET upload_hits = SELECT *, upload(file=CSVFile) AS Upload
                         FROM hits

       -- return rows
       SELECT *
       FROM if(
         condition=UploadHits,
         then=upload_hits,
         else=hits)