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
)