Windows.Network.NetstatEnriched

NetstatEnhanced adds additional data points to the Netstat artifact and enables verbose search options.

Examples include: Process name and path, authenticode information or network connection details.

WARNING: KillProcess - attempts to use Taskill to kill the processes returned. DumpProcess - dumps the process as a sparse file for post processing.

Please only use these switches after scoping as there are no guardrails on shooting yourself in the foot.


name: Windows.Network.NetstatEnriched
author: "Matt Green - @mgreen27"
description: |
  NetstatEnhanced adds additional data points to the Netstat artifact and
  enables verbose search options.

  Examples include: Process name and path, authenticode information or
  network connection details.

  WARNING:
  KillProcess - attempts to use Taskill to kill the processes returned.
  DumpProcess - dumps the process as a sparse file for post processing.

  Please only use these switches after scoping as there are no guardrails on
  shooting yourself in the foot.

required_permissions:
  - EXECVE

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

parameters:
  - name: IPRegex
    description: "regex search over IP address fields."
    default:  .
    type: regex
  - name: PortRegex
    description: "regex search over port fields."
    default: .
    type: regex
  - name: Family
    description: "IP version family selection"
    type: choices
    default: ALL
    choices:
       - ALL
       - IPv4
       - IPv6
  - name: FamilyMap
    type: hidden
    default: |
      Choice,Regex
      ALL,"."
      IPv4,"^IPv4$"
      IPv6,"^IPv6$"

  - name: Type
    description: "Transport protocol type selection"
    type: choices
    default: ALL
    choices:
       - ALL
       - TCP
       - UDP
  - name: TypeMap
    type: hidden
    default: |
      Choice,Regex
      ALL,"."
      TCP,"^TCP$"
      UDP,"^UDP$"

  - name: Status
    description: "TCP status selection"
    type: choices
    default: ALL
    choices:
       - ALL
       - ESTABLISHED
       - LISTENING
       - OTHER
  - name: StatusMap
    type: hidden
    default: |
      Choice,Regex
      ALL,"."
      ESTABLISHED,"^ESTAB$"
      LISTENING,"^LISTEN$"
      OTHER,"CLOS|SENT|RCVD|LAST|WAIT|DELETE"

  - name: ProcessNameRegex
    description: "regex search over source process name"
    default: ^(malware\.exe|.*)$
    type: regex
  - name: ProcessPathRegex
    description: "regex search over source process path"
    default: .
    type: regex
  - name: CommandLineRegex
    description: "regex search over source process commandline"
    default: .
    type: regex
  - name: HashRegex
    description: "regex search over source process hash"
    default: .
    type: regex
  - name: UsernameRegex
    description: "regex search over source process user context"
    default: .
    type: regex
  - name: AuthenticodeSubjectRegex
    description: "regex search over source Authenticode Subject"
    default: .
    type: regex
  - name: AuthenticodeIssuerRegex
    description: "regex search over source Authenticode Issuer"
    default: .
    type: regex
  - name: AuthenticodeVerified
    description: "Authenticode signiture selection"
    type: choices
    default: ALL
    choices:
       - ALL
       - TRUSTED
       - UNSIGNED
       - NOT TRUSTED
  - name: AuthenticodeVerifiedMap
    type: hidden
    default: |
      Choice,Regex
      ALL,"."
      TRUSTED,"^trusted$"
      UNSIGNED,"^unsigned$"
      NOT TRUSTED,"unsigned|disallowed|untrusted|error"
  - name: DumpProcess
    description: "WARNING: If selected will attempt to dump process from all results."
    type: bool
  - name: KillProcess
    description: "WARNING: If selected will attempt to kill process from all results."
    type: bool
  - name: DISABLE_DANGEROUS_API_CALLS
    type: bool
    description: |
      Enable this to disable potentially flakey APIs which may cause
      crashes.

sources:
  - name: Netstat
    query: |
      LET VerifiedRegex <= SELECT Regex
            FROM parse_csv(filename=AuthenticodeVerifiedMap, accessor="data")
            WHERE Choice=AuthenticodeVerified LIMIT 1
      LET StatusRegex <= SELECT Regex
            FROM parse_csv(filename=StatusMap, accessor="data")
            WHERE Choice=Status LIMIT 1
      LET FamilyRegex <= SELECT Regex
            FROM parse_csv(filename=FamilyMap, accessor="data")
            WHERE Choice=Family LIMIT 1
      LET TypeRegex <= SELECT Regex
            FROM parse_csv(filename=TypeMap, accessor="data")
            WHERE Choice=Type LIMIT 1

      LET process <= SELECT Pid as PsId,
            Ppid,
            Name,
            CommandLine,
            Exe,
            Hash,
            Authenticode,
            Username
        FROM Artifact.Windows.System.Pslist(
            DISABLE_DANGEROUS_API_CALLS=DISABLE_DANGEROUS_API_CALLS)
        WHERE Name =~ ProcessNameRegex
            AND Exe =~ ProcessPathRegex
            AND CommandLine =~ CommandLineRegex

      LET results = SELECT Pid,
                { SELECT Ppid FROM process WHERE PsId = Pid } as Ppid,
                { SELECT Name FROM process WHERE PsId = Pid } as Name,
                { SELECT Exe FROM process WHERE PsId = Pid } as Path,
                { SELECT CommandLine FROM process WHERE PsId = Pid } as CommandLine,
                { SELECT Hash FROM process WHERE PsId = Pid } as Hash,
                { SELECT Username FROM process WHERE PsId = Pid } as Username,
                { SELECT Authenticode FROM process WHERE PsId = Pid } as Authenticode,
                FamilyString as Family,
                TypeString as Type,
                Status,
                Laddr.IP as Laddr,
                Laddr.Port as Lport,
                Raddr.IP as Raddr,
                Raddr.Port as Rport,
                Timestamp
            FROM netstat()
            WHERE
                Name =~ ProcessNameRegex
                AND Path =~ ProcessPathRegex
                and CommandLine =~ CommandLineRegex
                and Username =~ UsernameRegex
                and ( Hash.MD5 =~ HashRegex
                  or Hash.SHA1 =~ HashRegex
                  or Hash.SHA256 =~ HashRegex
                  or not Hash )
                and ( Authenticode.IssuerName =~ AuthenticodeIssuerRegex or not Authenticode )
                and ( Authenticode.SubjectName =~ AuthenticodeSubjectRegex or not Authenticode )
                and ( Authenticode.Trusted =~ VerifiedRegex.Regex[0] or not Authenticode )
                and Status =~ StatusRegex.Regex[0]
                and Family =~ FamilyRegex.Regex[0]
                and Type =~ TypeRegex.Regex[0]
                and ( format(format="%v", args=Laddr) =~ IPRegex
                    or format(format="%v", args=Raddr) =~ IPRegex )
                and ( format(format="%v", args=Lport) =~ PortRegex
                    or format(format="%v", args=Rport) =~ PortRegex )

      LET Regions(Pid) = SELECT dict(Offset=Address, Length=Size) AS Sparse
        FROM vad(pid=Pid)
        WHERE Protection =~ "r"
      LET dump = SELECT *,
            upload(accessor="sparse",
                    file=pathspec(
                    Path=serialize(item=Regions(Pid=Pid).Sparse),
                    DelegateAccessor="process",
                    DelegatePath=format(format="/%d", args=Pid)),
                     name=pathspec(Path=format(format="%d.dd", args=Pid))) AS ProcessMemory
        FROM results
      LET kill = SELECT *, pskill(pid=Pid) AS KillProcess
        FROM results
      LET dumpandkill = SELECT *, pskill(pid=Pid) AS KillProcess
        FROM dump

      SELECT * FROM switch(
            a = {
                SELECT *, if(condition= KillProcess=Null,then='Success',else=KillProcess) AS KillProcess
                FROM if(condition= DumpProcess AND KillProcess, then= dumpandkill )},
            b = { SELECT * FROM if(condition= DumpProcess, then= dump )},
            c = {
                SELECT *, if(condition= KillProcess=Null,then='Success',else=KillProcess) AS KillProcess
                FROM if(condition= KillProcess, then= kill)
            },
            catch = results
        )