Windows.Detection.Termsrv

This artifact detects patched TerminalService / Remote Desktop (RDP) dynamic link library or ServiceDll - termsrv.dll.

ATT&CK T1505.005. Non Terminal Services Windows systems (e.g Windows 10 or 11) do not allow concurrent users to RDP into the machine at the same time. Typically a notice is displayed to the logged-on user requesting access and notifying of the impending log off. As a defence evasion technique threat actors have been known to patch termsrv.dll to evade detections.

The artifact collects 3 potential detection points:

  1. In memory - targeting termsrv.dll mapped file for the patch bytes
  2. On disk - targeting and file named termsrv.dll
  3. Services - targeting any unutual ServiceDll path or an untrusted authenticode ServiceDll

name: Windows.Detection.Termsrv
author: Matt Green - @mgreen27
description: |
    This artifact detects patched TerminalService / Remote Desktop (RDP) dynamic link library or ServiceDll - 
    termsrv.dll.
    
    ATT&CK T1505.005. Non Terminal Services Windows systems (e.g Windows 10 or 11) do not allow 
    concurrent users to RDP into the machine at the same time. Typically a notice 
    is displayed to the logged-on user requesting access and notifying of the 
    impending log off. As a defence evasion technique threat actors have been 
    known to patch termsrv.dll to evade detections.
    
    The artifact collects 3 potential detection points:
    
    1. In memory - targeting termsrv.dll mapped file for the patch bytes
    2. On disk - targeting and file named termsrv.dll
    3. Services - targeting any unutual ServiceDll path or an untrusted authenticode ServiceDll
    
reference:
  - https://attack.mitre.org/techniques/T1505/005/
  - https://www.mysysadmintips.com/windows/clients/545-multiple-rdp-remote-desktop-sessions-in-windows-10
  
type: CLIENT
  
parameters:
  - name: FileNameRegex
    description: Only file names that match this regular expression will be scanned.
    default: termsrv\.dll$
  - name: MappingRegex
    description: Only mapped sections that match this regular expression will be scanned.
    default: termsrv\.dll$
  - name: UploadHits
    type: bool
    description: If selected will upload any yara hits
  - name: YaraRule
    type: yara
    description: Patched RDP yara
    default: |
        rule termsrv_modified
        {
            meta:
                description = "Finds hex of termsrv.dll patch"
           strings:
                $patch = { B8 00 01 00 00 89 81 38 06 00 00 90 }
        
            condition:
                $patch
        }
  - name: ExpectedServiceDll
    description: Expected service dll location regex
    default: '''^C:\\Windows\\System32\\termsrv\.dll$'''
    
precondition: SELECT OS From info() where OS = 'windows'

sources:
  - name: VAD
    query: |
        SELECT ProcessCreateTime,Pid,Name,MappingName,AddressRange,State,Type,
            ProtectionMsg,Protection,SectionSize,YaraHit,HitContext,ProcessChain
        FROM Artifact.Windows.System.VAD(
                ProcessRegex='svchost\.exe',
                MappingNameRegex=MappingRegex,
                SuspiciousContent=YaraRule,
                UploadSection=UploadHits )

  - name: Yara.NTFS
    query: |
        SELECT OSPath,Size,ModTime,Rule,Meta,YaraString,HitOffset,HitContext
        FROM Artifact.Windows.Detection.Yara.NTFS(
                FileNameRegex=FileNameRegex,
                PathRegex=".",
                YaraRule=YaraRule,
                UploadHits=UploadHits,
                NumberOfHits=1 )
                
  - name: Services
    query: |
        SELECT State,Name,DisplayName,Status,Pid,ExitCode,StartMode,PathName,
            ServiceType,UserAccount,Created,FailureCommand,FailureActions,
            AbsoluteExePath, ServiceDll,
            HashServiceDll, CertinfoServiceDll,
            parse_pe(file=ServiceDll) as PEInfo
        FROM Artifact.Windows.System.Services(
                            DisplayNameRegex='Remote Desktop Services',
                            Calculate_hashes='Y',
                            CertificateInfo='Y')
        WHERE Name =~ 'TermService'
            AND ( NOT ServiceDll =~ ExpectedServiceDll OR CertinfoServiceDll.Trusted = 'untrusted' )
            
column_types:
  - name: HitContext
    type: preview_upload