Identify running processes that host the .NET Common Language Runtime (CLR) and highlight suspicious processes where CLR visibility may be reduced, downgraded, or disabled.
Capablities include:
mscoree.dll importNOTE: for Mem2Disk capability, the artifact expects the imported name: Windows.Memory.Mem2Disk.
name: Windows.System.IsClrProcess
author: Matt Green - @mgreen27
description: |
Identify running processes that host the .NET Common Language Runtime (CLR) and
highlight suspicious processes where CLR visibility may be reduced, downgraded,
or disabled.
Capablities include:
- CLR capable process discovery by finding `mscoree.dll` import
- Brief CLR Rundown ETW collection to determine events active
- Runs Mem2Disk targetting commonly CLR patched DLLs
- Checks COMPlus_ETWEnabled environment variable
- Collects CLR.dll VersionInformation
- CommandLine visibility
NOTE: for Mem2Disk capability, the artifact expects the imported name: Windows.Memory.Mem2Disk.
parameters:
- name: ProcessRegex
default: .
type: regex
- name: PidRegex
default: .
type: regex
- name: ExePathRegex
default: .
type: regex
- name: CommandLineRegex
default: .
type: regex
- name: UsernameRegex
default: .
type: regex
- name: CheckForPatches
type: bool
- name: ModuleRegEx
default: \\(clr|amsi|ntdll|kernel32|Mp0av.dll|wldap32)\.dll$
type: regex
sources:
- precondition: SELECT OS From info() where OS = 'windows'
query: |
LET clr_processes <= SELECT Pid, Ppid, TokenIsElevated, Name, Exe, CommandLine,Username,
parse_pe(file=Exe) as PEInfo
FROM pslist()
WHERE Name =~ ProcessRegex
AND Pid =~ PidRegex
AND Exe =~ ExePathRegex
AND CommandLine =~ CommandLineRegex
AND Username =~ UsernameRegex
AND ( PEInfo.Imports =~ 'mscoree'
OR PEInfo.Directories.DotNet_Directory )
LET clr_details <= SELECT
System.ProcessID AS ProcessID,
dict(
ClrInstanceID=EventData.ClrInstanceID,
ClrVersion=format(
format='%s.%s.%s.%s',
args=[
EventData.VMMajorVersion,
EventData.VMMinorVersion,
EventData.VMBuildNumber,
EventData.VMQfeNumber]),
RuntimeDllPath=EventData.RuntimeDllPath
) as ClrDetails
FROM watch_etw(description="CLR Rundown Provider",
guid="{A669021C-C450-4609-A035-5AF59AF4DF18}",
any=0x40,
timeout=20 )
WHERE ProcessID =~ join(array=clr_processes.Pid,sep='|')
AND System.ID = 187
LET find_clr(pid) = SELECT * FROM clr_details WHERE ProcessID = pid
LET results <= SELECT *,
find_clr(pid=Pid).ClrDetails as ClrDetails
FROM clr_processes
LET find_dll(pid,modulename) = SELECT dict(ModulePath=ExePath) + parse_pe(file=ExePath).VersionInformation as VersionInformation
FROM modules(pid=Pid)
WHERE lowcase(string=ModuleName) = lowcase(string=modulename)
LET find_functions(pid) = SELECT regex_replace(
source=split(string=Functions,sep_string='+')[0],
re='''\!0x.+$''',
replace="!0xHexAddr"
) as Functions
FROM flatten(query={
SELECT Differences.Func As Functions
FROM Artifact.Windows.Memory.Mem2Disk(
PidFilter="^" + pid + "$",
ModuleRegEx=ModuleRegEx
)
})
GROUP BY Functions
LET find_modules(pid) = SELECT Path
FROM Artifact.Windows.Memory.Mem2Disk(
PidFilter="^" + pid + "$",
ModuleRegEx=ModuleRegEx
)
GROUP BY Path
LET check_complus(pid) = SELECT
if(condition = Env.COMPlus_ETWEnabled="0",
then = TRUE,
else = FALSE ) as EnvDisabled
FROM Artifact.Windows.Memory.ProcessInfo(PidRegex=pid)
SELECT
Pid, Ppid, Name, Exe, CommandLine,
Username, TokenIsElevated,
filter(list=PEInfo.Imports,regex='mscoree')[0] as MscoreeImport,
if(condition=ClrDetails,
then=ClrDetails[0],
else='ETW disabled or Potential downgraded CLR') as Functions,
find_dll(pid=Pid,modulename="clr.dll")[0].VersionInformation as CLRmodule,
if(condition= version(function="describe_address") != NULL,
then= find_functions(pid=str(str=Pid)).Functions,
else= find_modules(pid=str(str=Pid)).Path
) as PotentialPatches,
check_complus(pid=str(str=Pid))[0].EnvDisabled as EnvDisabled
FROM results