-
Notifications
You must be signed in to change notification settings - Fork 3
Configuration
The telemetry EventHorizon collects is determined by the config.json stored in its application folder (typically C:\Program Files\EventHorizon\). As the file extension suggests, the configuration is in JSON format, and allows you to configure the ETW providers and event names that EventHorizon provides to the detection engine. Below is the general layout of config.json, but as a general note the provider field is not required, as EventHorizon uses the provider_guid to subscribe to providers.
[
{
"provider": "PROVIDER COMMON NAME",
"provider_guid": "{PROVIDER GUID}",
"event_names": [
"EVENT_TASK_NAME",
"OTHER_EVENT_TASK_NAME",
...
],
"enabled": true|false
},
{
"provider": "OTHER PROVIDER COMMON NAME",
"provider_guid": "{OTHER PROVIDER GUID}",
"event_names": [
"EVENT_TASK_NAME",
"OTHER_EVENT_TASK_NAME",
...
],
"enabled": true|false
},
...
]Rules are placed in a Rules directory within the application folder, so it'll typically be C:\Program Files\EventHorizon\Rules. Simply put your rule(s) (they should be .yaml files) in that directory and when the detection engine starts, it should load your rules. Additionally, if you update or add rules while the detection engine is running, you may run the following command to refresh the detection rules.
& "C:\Program Files\EventHorizon\EventHorizonHelper.exe" reloadEventHorizon's rule syntax is meant to closely mimic that of Sigma rules so as to increase ease of use as well as the ability to migrate rules from Sigma to EventHorizon.
title: RULE TITLE HERE
description: DESCRIPTIVE DESCRIPTION HERE
logsource:
provider: ETW PROVIDER COMMON NAME HERE
event_name: EVENT TASK NAME HERE
detection:
{search-identifier} [optional]
{field|condition: value} [optional]
condition: BOOLEAN CONDITION HERE
response: SOME_RESPONSIVE_CAPABILITY(SOME PARAMTER(S)) [optional]Log sources in EventHorizon are made up of two fields: provider and event_name. These fields allow EventHorizon to filter through events in order to feed them to your detection logic and fire an alert should the event match.
The provider field consists of the common name of the provider (not the GUID). For example, the provider could be something like Microsoft-Windows-Sysmon or Microsoft-Windows-Kernel-Process.
The event_name field is the ETW event's task name. There are a few ways to find the event's task name, but perhaps the easiest way is to look at the ETW provider's manifest. Below are a few resources for looking at provider manifests:
- EventHorizon's ETW manifest folder (Static files)
- repnz's ETW Provider Docs (Static files)
- ETW Explorer (Dynamically extracts manifests from system)
Below is a snippet taken from Microsoft-Windows-Kernel-Process
<events>
<event value="1" symbol="ProcessStart" version="0" task="ProcessStart" opcode="win:Start" level="win:Informational" keywords="WINEVENT_KEYWORD_PROCESS" template="ProcessStartArgs" />
<event value="1" symbol="ProcessStart_V1" version="1" task="ProcessStart" opcode="win:Start" level="win:Informational" keywords="WINEVENT_KEYWORD_PROCESS" template="ProcessStartArgs_V1" />
<event value="1" symbol="ProcessStart_V2" version="2" task="ProcessStart" opcode="win:Start" level="win:Informational" keywords="WINEVENT_KEYWORD_PROCESS" template="ProcessStartArgs_V2" />
<event value="1" symbol="ProcessStart_V3" version="3" task="ProcessStart" opcode="win:Start" level="win:Informational" keywords="WINEVENT_KEYWORD_PROCESS" template="ProcessRundownArgs_V1" />
<event value="1" symbol="ProcessStart_V4" version="4" task="ProcessStart" opcode="win:Start" level="win:Informational" keywords="WINEVENT_KEYWORD_PROCESS" template="ProcessStartArgs_V4" />
...
</events>If you wanted to write a rule on process creation events, then you would look at the <events> in the provider XML, find the event that corresponds to that, and use the task field in your rule. So, in this example, ProcessStart would be the correct event name in the rule.
As an example, a rule that alerts on instances of cmd.exe being launched would look like:
title: CMD Launched
description: Detects when cmd.exe is launched
logsource:
provider: Microsoft-Windows-Kernel-Process
event_name: ProcessStart
detection:
selection:
ImageName|endswith: "cmd.exe"
condition: selectionEventHorizon allows you to specify an action to take when a rule is matched. These actions include:
- Process termination
- Process suspension
- Process memory dumping (regional or entire process memory)
The process termination response takes exactly one parameter in the form of a process id, and is not hard coded. In the detection rule, you may pass any of the event's fields (so long as it's a process id) to be terminated. As an example of the flexibility of this rule, you may pass the ParentProcessId from the event to be terminated:
terminate_process(ParentProcessId)
Similar to the process termination response is the process suspension response. It also takes exactly one parameter from the detection-triggering event that contains a process id then suspends the process
suspend_process(ProcessId)
The process memory dump response dumps either an entire process or a region of a process's memory based off of the parameters given to it (see below sections for more). It will then write the dumped memory onto a file in a specified directory on the system.
Something to keep in mind is that the memory dumping functionality isn't implemented in the same place. Full process memory dumps are done in usermode inside the detection engine while regional dumps are done in kernel mode. The reason for this is due to the complexity of implementing full process memory dumps from the kernel driver. Regional process memory dumps in testing were only seen as a result of ETWTI telemetry and thus provided kernel mode virtual addresses which was convenient for a kernel driver. However, when trying to just dump all of a process's memory it became quickly apparent that it would be more trouble to fit it into the kernel driver.
To dump all of a process's memory, simply pass the process id and a directory path on disk to dump the memory to.
dump_process(TargetProcessId, \\??\\C:\\)
To dump a specific region of a process's memory you need to pass in 4 things:
- Process ID
- Base address
- Region size
- Dump directory
Regional memory dumps at the moment are done from the ELAM kernel driver and thus require memory addresses that kernel virtual addresses. While this seems confusing on the surface, regional memory dumps are more frequently used with something like ETWTI, which emits events containing kernel virtual addresses. If there's a reason you have an ETW provider emitting relative virtual addresses for a usermode process and need to dump a memory region, please open an issue.
dump_process(TargetProcessId, BaseAddress, RegionSize, \\??\\C:\\)