Windows.ETW.DetectProcessSpoofing

Detects Process parent spoofing such as SelectMyParent.exe or Cobalt Strike select PPID.

NOTE: for short lasting processes it is expected to report NULL for CommandLine and Username fields as enrichment failed.


name: Windows.ETW.DetectProcessSpoofing
description: |
      Detects Process parent spoofing such as SelectMyParent.exe or
      Cobalt Strike select PPID.

      NOTE: for short lasting processes it is expected to report NULL
      for CommandLine and Username fields as enrichment failed.

reference:
  - https://blog.f-secure.com/detecting-parent-pid-spoofing/
  - https://www.youtube.com/watch?v=DOe7WTuJ1Ac

type: CLIENT_EVENT

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

    query: |
        LET RecentProcesses = SELECT * FROM fifo(query={
            SELECT System.TimeStamp AS CreateTime,
                   EventData.ImageName AS ImageName,
                   int(int=EventData.ProcessID) AS Pid,
                   EventData.MandatoryLabel AS MandatoryLabel,
                   EventData.ProcessTokenElevationType AS ProcessTokenElevationType,
                   EventData.ProcessTokenIsElevated AS TokenIsElevated
            FROM watch_etw(guid="{22fb2cd6-0e7b-422b-a0c7-2fad1fd0e716}", any=0x10)
            WHERE System.ID = 1
        }, max_rows=1000, max_age=60)

        -- Query it once to materialize the FIFO
        LET _ <= SELECT * FROM RecentProcesses

        LET GetProcessInfo(TargetPid) = SELECT * FROM switch(
        -- First try to get the pid directly
        a={
            SELECT
                Name, Pid, CreateTime,
                Exe as ImageName,
                CommandLine,
                Username,
                TokenIsElevated
            FROM pslist(pid=TargetPid)
        },
        -- Failing this look in the FIFO for a recently started process.
        b={
            SELECT
                basename(path=ImageName) as Name,
                Pid,
                CreateTime,
                ImageName,
                Null as CommandLine,
                Null as Username,
                if(condition= TokenIsElevated="0",
                    then= false,
                    else= true ) as TokenIsElevated
            FROM RecentProcesses
            WHERE Pid = TargetPid
            LIMIT 1
        })

        -- Resolve parent pid from the fifo - this allows us to catch fast terminating processes.
        SELECT System.TimeStamp AS EventTime,
            GetProcessInfo(TargetPid=int(int=EventData.ProcessID))[0] AS SuspiciousProcess,
            GetProcessInfo(TargetPid=System.ProcessID)[0] AS RealParent,
            GetProcessInfo(TargetPid=int(int=EventData.ParentProcessID))[0] AS ClaimedParent,
            System as _System, EventData as _EventData
        FROM watch_etw(guid="{22fb2cd6-0e7b-422b-a0c7-2fad1fd0e716}", any=0x10)
        WHERE System.ID = 1 AND str(str=System.ProcessID) != EventData.ParentProcessID