Detection rules › Kusto

Detect LolDriver drop or load from unknown or unsigned process

Author
Robbe Van den Daele
Source
github.com/HybridBrothers/Hunting-Queries-Detection-Rules

Adversaries may use LolDrivers to elevate their privileges on a system. Regularly, their drop their own LolDrivers from their beacon process when the LolDriver is not yet present on the system. This is a detection use case to detect an unknown process dropping these LolDrivers.

MITRE ATT&CK coverage

TacticTechniques
Privilege Escalation

References

Telemetry coverage

Rule body

let LOLDrivers = externaldata(Category:string, KnownVulnerableSamples:dynamic, Verified:string ) [h@"https://www.loldrivers.io/api/drivers.json"]
     with (
       format=multijson,
       ingestionMapping=@'[{"Column":"Category","Properties":{"Path":"$.Category"}},{"Column":"KnownVulnerableSamples","Properties":{"Path":"$.KnownVulnerableSamples"}},{"Column":"Verified","Properties":{"Path":"$.Verified"}}]'
     )
    | mv-expand KnownVulnerableSamples
    | extend SHA1 = tostring(KnownVulnerableSamples.SHA1), SHA256 = tostring(KnownVulnerableSamples.SHA256)
;
let SHA1List = toscalar(
    LOLDrivers
    | summarize make_set(SHA1)
);
let SHA256List = toscalar(
    LOLDrivers
    | summarize make_set(SHA256)
);
let device_events = (
    DeviceEvents
    | where Timestamp > ago(1h)
    | where ActionType == "DriverLoaded"
    | where SHA1 in ( SHA1List ) or SHA256 in ( SHA256List )
);
let device_file_events = (
    DeviceFileEvents
    | where Timestamp > ago(1h)
    | where ActionType == "FileCreated"
    | where SHA1 in ( SHA1List ) or SHA256 in ( SHA256List )
);
union device_events, device_file_events
| invoke FileProfile(InitiatingProcessSHA1)
| where GlobalPrevalence < 1000 or SignatureState =~ "Unsigned"

Stages and Predicates

Let binding: LOLDrivers

let LOLDrivers = externaldata(Category:string, KnownVulnerableSamples:dynamic, Verified:string ) [h@"https://www.loldrivers.io/api/drivers.json"]
     with (
       format=multijson,
       ingestionMapping=@'[{"Column":"Category","Properties":{"Path":"$.Category"}},{"Column":"KnownVulnerableSamples","Properties":{"Path":"$.KnownVulnerableSamples"}},{"Column":"Verified","Properties":{"Path":"$.Verified"}}]'
     )
    | mv-expand KnownVulnerableSamples
    | extend SHA1 = tostring(KnownVulnerableSamples.SHA1), SHA256 = tostring(KnownVulnerableSamples.SHA256);

Let binding: SHA1List

let SHA1List = toscalar(
    LOLDrivers
    | summarize make_set(SHA1)
);

Let binding: SHA256List

let SHA256List = toscalar(
    LOLDrivers
    | summarize make_set(SHA256)
);

union (2 sources)

Each leg below queries one source; the rule matches if any leg does. Sources: device_events, device_file_events

Leg 1: device_events

Leg 2: device_file_events

Applied to the combined result

| invoke FileProfile(InitiatingProcessSHA1) | where GlobalPrevalence < 1000 or SignatureState =~ "Unsigned"

Indicators

These rows show field, operator, and value matches.