Skip to content
Please update to the latest release 0.77.2 to address Multiple CVEs.
Windows.System.IsClrProcess

Windows.System.IsClrProcess

Identify running processes that host the .NET Common Language Runtime (CLR) and highlight suspicious processes where CLR visibility may be reduced, downgraded, or disabled.

Capabilities include:

  • CLR capable process discovery by finding mscoree.dll import
  • Brief CLR Rundown ETW collection to determine events active
  • Runs Mem2Disk targeting 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.


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.

  Capabilities include:
  - CLR capable process discovery by finding `mscoree.dll` import
  - Brief CLR Rundown ETW collection to determine events active
  - Runs Mem2Disk targeting 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