Detection rules › Kusto
Unsigned Windows System Binary
This query searches for invocations of a number of commonly used and signed Windows binaries. It then finds invocations of these binaries where they are not properly signed.
Known false positives
- In case a legitimate software package uses a file name that is the same as that of a known system binary, this rule may trigger.
MITRE ATT&CK coverage
References
Telemetry coverage
Rule body
let timeframe = 2*1h;
let default_global_prevalence = 0;
let signedSystemFiles = dynamic(["aitstatic.exe", "ApplicationFrameHost.exe", "ApplyTrustOffline.exe", "AppVClient.exe", "AppVDllSurrogate.exe", "AppVNice.exe", "AppVShNotify.exe", "audiodg.exe", "AuthHost.exe", "backgroundTaskHost.exe", "bcdedit.exe", "bdeunlock.exe", "BioIso.exe", "bootsect.exe", "browser_broker.exe", "CameraSettingsUIHost.exe", "CastSrv.exe", "CExecSvc.exe", "changepk.exe", "ClipRenew.exe", "ClipUp.exe", "CloudExperienceHostBroker.exe", "CloudNotifications.exe", "cmdiag.exe", "CompatTelRunner.exe", "consent.exe", "convertvhd.exe", "CredentialEnrollmentManager.exe", "CredentialUIBroker.exe", "csrss.exe", "DataExchangeHost.exe", "DeviceCensus.exe", "Dism.exe", "DisplaySwitch.exe", "dllhost.exe", "DTUHandler.exe", "easinvoker.exe", "ErgonomicKBNotificationService.exe", "fontdrvhost.exe", "FsIso.exe", "fsutil.exe", "GenValObj.exe", "hcsdiag.exe", "hvax64.exe", "hvc.exe", "hvix64.exe", "hvsievaluator.exe", "hvsimgr.exe", "hvsirdpclient.exe", "hvsirpcd.exe", "HvsiSettingsWorker.exe", "iotstartup.exe", "LicensingUI.exe", "LockAppHost.exe", "LockScreenContentServer.exe", "LsaIso.exe", "lsass.exe", "mavinject.exe", "mfpmp.exe", "MRT.exe", "MusNotifyIcon.exe", "NDKPing.exe", "NgcIso.exe", "nmbind.exe", "nmscrub.exe", "ntoskrnl.exe", "nvspinfo.exe", "OpenWith.exe", "PasswordOnWakeSettingFlyout.exe", "phoneactivate.exe", "PickerHost.exe", "PktMon.exe", "ProximityUxHost.exe", "prproc.exe", "ResetEngine.exe", "RuntimeBroker.exe", "ScriptRunner.exe", "securekernel.exe", "SecurityHealthHost.exe", "SecurityHealthService.exe", "services.exe", "sessionmsg.exe", "SettingSyncHost.exe", "SgrmBroker.exe", "SgrmLpac.exe", "SIHClient.exe", "SlideToShutDown.exe", "smss.exe", "SndVol.exe", "spaceman.exe", "sppsvc.exe", "svchost.exe", "SyncAppvPublishingServer.exe", "SysResetErr.exe", "systemreset.exe", "SystemSettingsAdminFlows.exe", "SystemSettingsBroker.exe", "SystemSettingsRemoveDevice.exe", "taskhostw.exe", "Taskmgr.exe", "tcblaunch.exe", "ttdinject.exe", "tttracer.exe", "ucsvc.exe", "upfc.exe", "UserAccountBroker.exe", "verifier.exe", "vmcompute.exe", "VmComputeAgent.exe", "vmms.exe", "vmplatformca.exe", "vmsp.exe", "vmwp.exe", "wcsetupagent.exe", "WerFault.exe", "WerFaultSecure.exe", "wermgr.exe", "wifitask.exe", "wimserv.exe", "wininit.exe", "winload.exe", "winresume.exe", "wkspbroker.exe", "wlrmdr.exe", "WpcMon.exe", "wuauclt.exe", "WUDFCompanionHost.exe", "WWAHost.exe", "AdtAgent.exe", "appverif.exe", "iaStorAfsNative.exe", "iaStorAfsService.exe", "MCU.exe", "microsoft.windows.softwarelogo.showdesktop.exe", "MpSigStub.exe", "RtkAudUService64.exe", "TsWpfWrp.exe"]);
let uniqueHashes = materialize(
DeviceProcessEvents
| where ingestion_time() >= ago(timeframe)
| where ActionType =~ "ProcessCreated"
| where FileName in~ (signedSystemFiles) and not(isempty(SHA1))
// Begin environment-specific filter.
// End environment-specific filter.
// FileProfile is case sensistive and works on lower-case hashes
| extend SHA1=tolower(SHA1)
| summarize MachineCount=dcount(DeviceId) by SHA1
);
let unsignedHashes = materialize(
uniqueHashes
// Take 1000 of the most unique hashes as files with high prevelance are very likely to be signed in a legit manner.
| top 1000 by MachineCount asc
// FileProfile is case-sensitive and works on lower-case hashes.
| extend SHA1=tolower(SHA1)
| invoke FileProfile(SHA1, 1000)
| where not(ProfileAvailability =~ "Error")
| where IsCertificateValid != 1 or (IsRootSignerMicrosoft != 1 and coalesce(GlobalPrevalence,default_global_prevalence) < 200)
| where not(SignatureState =~ "Unknown" and coalesce(GlobalPrevalence,default_global_prevalence) > 30000) // Workaround for a bug in MDE that reports some valid MS signed files as 'Unknown'.
);
DeviceProcessEvents
| where ingestion_time() >= ago(timeframe)
| where ActionType =~ "ProcessCreated"
| where SHA1 in~ ((unsignedHashes | project SHA1)) // This is for performance improvement.
| join kind=inner unsignedHashes on SHA1
| summarize arg_min(Timestamp, *) by DeviceId, FolderPath // Show only the first invocation per device.
Stages and Predicates
Parameters
let timeframe = 2*1h;
let default_global_prevalence = 0;
Let binding: signedSystemFiles
let signedSystemFiles = dynamic(["aitstatic.exe", "ApplicationFrameHost.exe", "ApplyTrustOffline.exe", "AppVClient.exe", "AppVDllSurrogate.exe", "AppVNice.exe", "AppVShNotify.exe", "audiodg.exe", "AuthHost.exe", "backgroundTaskHost.exe", "bcdedit.exe", "bdeunlock.exe", "BioIso.exe", "bootsect.exe", "browser_broker.exe", "CameraSettingsUIHost.exe", "CastSrv.exe", "CExecSvc.exe", "changepk.exe", "ClipRenew.exe", "ClipUp.exe", "CloudExperienceHostBroker.exe", "CloudNotifications.exe", "cmdiag.exe", "CompatTelRunner.exe", "consent.exe", "convertvhd.exe", "CredentialEnrollmentManager.exe", "CredentialUIBroker.exe", "csrss.exe", "DataExchangeHost.exe", "DeviceCensus.exe", "Dism.exe", "DisplaySwitch.exe", "dllhost.exe", "DTUHandler.exe", "easinvoker.exe", "ErgonomicKBNotificationService.exe", "fontdrvhost.exe", "FsIso.exe", "fsutil.exe", "GenValObj.exe", "hcsdiag.exe", "hvax64.exe", "hvc.exe", "hvix64.exe", "hvsievaluator.exe", "hvsimgr.exe", "hvsirdpclient.exe", "hvsirpcd.exe", "HvsiSettingsWorker.exe", "iotstartup.exe", "LicensingUI.exe", "LockAppHost.exe", "LockScreenContentServer.exe", "LsaIso.exe", "lsass.exe", "mavinject.exe", "mfpmp.exe", "MRT.exe", "MusNotifyIcon.exe", "NDKPing.exe", "NgcIso.exe", "nmbind.exe", "nmscrub.exe", "ntoskrnl.exe", "nvspinfo.exe", "OpenWith.exe", "PasswordOnWakeSettingFlyout.exe", "phoneactivate.exe", "PickerHost.exe", "PktMon.exe", "ProximityUxHost.exe", "prproc.exe", "ResetEngine.exe", "RuntimeBroker.exe", "ScriptRunner.exe", "securekernel.exe", "SecurityHealthHost.exe", "SecurityHealthService.exe", "services.exe", "sessionmsg.exe", "SettingSyncHost.exe", "SgrmBroker.exe", "SgrmLpac.exe", "SIHClient.exe", "SlideToShutDown.exe", "smss.exe", "SndVol.exe", "spaceman.exe", "sppsvc.exe", "svchost.exe", "SyncAppvPublishingServer.exe", "SysResetErr.exe", "systemreset.exe", "SystemSettingsAdminFlows.exe", "SystemSettingsBroker.exe", "SystemSettingsRemoveDevice.exe", "taskhostw.exe", "Taskmgr.exe", "tcblaunch.exe", "ttdinject.exe", "tttracer.exe", "ucsvc.exe", "upfc.exe", "UserAccountBroker.exe", "verifier.exe", "vmcompute.exe", "VmComputeAgent.exe", "vmms.exe", "vmplatformca.exe", "vmsp.exe", "vmwp.exe", "wcsetupagent.exe", "WerFault.exe", "WerFaultSecure.exe", "wermgr.exe", "wifitask.exe", "wimserv.exe", "wininit.exe", "winload.exe", "winresume.exe", "wkspbroker.exe", "wlrmdr.exe", "WpcMon.exe", "wuauclt.exe", "WUDFCompanionHost.exe", "WWAHost.exe", "AdtAgent.exe", "appverif.exe", "iaStorAfsNative.exe", "iaStorAfsService.exe", "MCU.exe", "microsoft.windows.softwarelogo.showdesktop.exe", "MpSigStub.exe", "RtkAudUService64.exe", "TsWpfWrp.exe"]);
Let binding: uniqueHashes
let uniqueHashes = materialize(
DeviceProcessEvents
| where ingestion_time() >= ago(timeframe)
| where ActionType =~ "ProcessCreated"
| where FileName in~ (signedSystemFiles) and not(isempty(SHA1))
| extend SHA1=tolower(SHA1)
| summarize MachineCount=dcount(DeviceId) by SHA1
);
Let binding: unsignedHashes
let unsignedHashes = materialize(
uniqueHashes
| top 1000 by MachineCount asc
| extend SHA1=tolower(SHA1)
| invoke FileProfile(SHA1, 1000)
| where not(ProfileAvailability =~ "Error")
| where IsCertificateValid != 1 or (IsRootSignerMicrosoft != 1 and coalesce(GlobalPrevalence,default_global_prevalence) < 200)
| where not(SignatureState =~ "Unknown" and coalesce(GlobalPrevalence,default_global_prevalence) > 30000)
);
Stage 1: source
let uniqueHashes
Stage 2: source
let unsignedHashes
Stage 3: source
DeviceProcessEvents
Stage 4: where
where ...
Stage 5: where
where ActionType =~ "ProcessCreated"
Stage 6: where
where /* macro: (SHA1 in~ <NestedQuery>) */
Stage 7: join
join kind=inner (unsignedHashes) on SHA1
Stage 8: summarize
summarize by DeviceId, FolderPath
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
GlobalPrevalence | gt | 30000 | excludes:GlobalPrevalence field:"GlobalPrevalence" value:"30000" |
SignatureState | eq | Unknown | excludes:SignatureState field:"SignatureState" value:"Unknown" |
ProfileAvailability | eq | Error | excludes:ProfileAvailability field:"ProfileAvailability" value:"Error" |
SHA1 | is_null | excludes:SHA1 |
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
ActionType | eq |
| field:"ActionType" kind:eq value:"ProcessCreated" |
FileName | in |
| field:"file_name" kind:in |
GlobalPrevalence | lt |
| field:"GlobalPrevalence" kind:lt value:"200" |
IsCertificateValid | ne |
| field:"IsCertificateValid" kind:ne value:"1" |
IsRootSignerMicrosoft | ne |
| field:"IsRootSignerMicrosoft" kind:ne value:"1" |
Output fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
DeviceId | summarize |
FolderPath | summarize |