pine.space
← Back to blog

2024-07-20

Detecting Windows persistence with Splunk

These notes combine two MITRE ATT&CK persistence techniques and their Splunk searches. They also explain how to prepare Linux auditd logs for Splunk.

Screensaver hijack (T1546.002)

Windows runs the configured .scr file when the screensaver starts. Changing the SCRNSAVE.EXE registry value can provide event-triggered execution. The useful records are a registry change (Sysmon EventCode 13), the reg add process that makes the change (EventCode 1), and the file being written to disk (EventCode 11).

index=sysmon (EventCode=13 Details="c:\\windows\\system32\\*.scr" TargetObject="*\\Control Panel\\Desktop\\SCRNSAVE.EXE" ) OR (EventCode=1 CommandLine="reg*\ add *\\Control Panel\\Desktop\" /v SCRNSAVE.EXE /t REG_SZ /d *C:\\WINDOWS\\System32\\*.scr*")
| rex field=CommandLine "/d\ \"(?<TargetFilename>\S+)\""
| eval TargetFilename=coalesce(TargetFilename, Details)
| eval TargetFilename=lower(TargetFilename)
| mvexpand User
| search NOT User="NOT_TRANSLATED"
| join TargetFilename [ search index=sysmon EventCode=11 TargetFilename="C:\\Windows\\System32*.scr" | eval TargetFilename=lower(TargetFilename) | fields TargetFilename Image ]
| table UtcTime EventCode Sid ProcessGuid ProcessId User ComputerName TargetFilename Image

Accessibility feature abuse (T1546.008)

The "sticky keys" technique replaces a Windows accessibility program, such as sethc.exe, utilman.exe, or osk.exe, with cmd.exe. This can open a SYSTEM command prompt from the login screen. T1546.008 can appear as writes to those filenames.

index=sysmon (EventCode=13 TargetObject IN (*osk.exe*, *sethc.exe*, *utilman.exe*, *magnify.exe*, *narrator.exe*, *DisplaySwitch.exe*, *atbroker.exe*)) OR (TargetFilename IN (*osk.exe*, *sethc.exe*) EventCode=11)
| eval TargetFile=coalesce(TargetObject, TargetFilename)
| mvexpand User
| search NOT User="NOT_TRANSLATED"
| table TargetFile UtcTime Sid ProcessGuid ProcessId User ComputerName

The original notes link each technique to its corresponding Atomic Red Team test: T1546.002 and T1546.008.

Getting auditd logs into Splunk

auditd records events on Linux systems so administrators and analysts can investigate security incidents. Rules control what it records. This example ruleset shows how rules are written, and Red Hat provides a guide to configuring auditd.

By default the logs land in /var/log/audit (changeable in auditd.conf) as ASCII key-value pairs. Some values, such as proctitle, are hex-encoded. ausearch -i decodes them at the command line, but importing into Splunk you have to decode them yourself.

The decoding evals I keep reaching for:

| rex field=msg "(?<unixtime>\d{10}\.\d{3})"
| rex field=msg ":(?<msg_id>\d{6})"
| eval readable_time = strftime(unixtime, "%Y-%m-%d %H:%M:%S.%Q")
| eval process_title = urldecode(replace(proctitle,"([0-9A-F]{2})","%\1"))
index=auditd
| search [
    index=auditd
    | search key=<key_name>
    | fields msg
    | format ]

Each auditd event spans multiple lines, so Splunk splits one event into several. Group them back together on the msg field with transaction or a subsearch before you analyze.

A detection depends on the telemetry underneath it. The logs must show what actually happened.