Sysmon Eventid 5 - Process Termination

This article pairs especially well with the Sysmon Process Creation blog post. We recommend you start there.

Overview

For this post we are going to be focusing on the Process Termination EventID (ID 5), and how we can combine results with the Process Creation EventID (ID 1) to create some interesting datapoints. Although process creation and termination are part of any process lifecycle, it’s worth paying attention to from a security perspective as malicious behavior can often exhibit telltale patterns. 

There’s not much to say about process creation and termination. Sysmon records include:

  • Image - process name (and path)
  • Computer - the computer the process was launched on
  • ProcessId - it’s process ID
  • ProcessGuid - the global identifier
  • UtcTime - and a timestamp 

Despite how little data we’re given, we can still make good use of these records by fusing process creation and termination together to get a bigger picture. Let’s view a sample event and then start with a simple example of putting this EventID to use.

Sample event

<?xml version="1.0" encoding="UTF-8"?>
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
   <System>
      <Provider Name="Microsoft-Windows-Sysmon" Guid="{5770385f-c22a-43e0-bf4c-06f5698ffbd9}" />
      <EventID>5</EventID>
      <Version>3</Version>
      <Level>4</Level>
      <Task>5</Task>
      <Opcode>0</Opcode>
      <Keywords>0x8000000000000000</Keywords>
      <TimeCreated SystemTime="2021-10-15T18:50:13.2842859Z" />
      <EventRecordID>2606475</EventRecordID>
      <Correlation />
      <Execution ProcessID="4432" ThreadID="5868" />
      <Channel>Microsoft-Windows-Sysmon/Operational</Channel>
      <Computer>RAHZOR</Computer>
      <Security UserID="S-1-5-18" />
   </System>
   <EventData>
      <Data Name="RuleName">-</Data>
      <Data Name="UtcTime">2021-10-15 18:50:13.283</Data>
      <Data Name="ProcessGuid">{e8a27be9-cd5f-6169-4413-000000002400}</Data>
      <Data Name="ProcessId">4280</Data>
      <Data Name="Image">C:\Users\shredder\AppData\Local\Microsoft\OneDrive\21.180.0905.0007\FileCoAuth.exe</Data>
   </EventData>
</Event>

Frequently terminating processes

Let's start by plotting the frequency of terminating processes over time. We have multiple processes, sometimes in temporary directories, across multiple computers, so we need to group things accordingly.

First we'll get all the fields we need:

tag=$SYSMON winlog Provider == "Microsoft-Windows-Sysmon" EventID == 5 Computer Image

Easy enough, but the Image name often includes temporary directories, such as "C:\Windows\Temp\1A92511E-A790-4A46-B3C6-8A7376B01C13\DismHost.exe". That's not terribly helpful as a key if we're really just looking for "DismHost.exe". We can extract the executable name using a regular expression:

regex -e Image "\\(?P<name>[^\\]*)$" 

The regular expression above grabs any characters at the end of the string up until a backslash is encountered -- in other words, the filename at the end of the given path.

The data we have is already organized temporally, so next we just need to count occurences, grouped by the filename (name) and the computer it was run on:

stats count by name Computer

Gravwell lets you key math operations (such as "count" here) by any number of other values. In this case, we group by unique combinations of "name" and "Computer". 

Finally, we chart our findings. We'll put the entire query here for reference:


tag=$SYSMON winlog Provider == "Microsoft-Windows-Sysmon" EventID == 5 Computer Image
| regex -e Image "\\(?P<name>[^\\]*)$" 
| stats count by name Computer
| chart count by name Computer

 

chart

Well well well, FileCoAuth.exe is a busy bee...

How long processes run

We can combine Process Creation (ID 1) and Termination (ID 5) to calculate how long a given process runs. We'll key by name and Computer as we did before, but this time we'll also key by the process ID, just in case a given process overlaps with itself. 

Let's start with a query to get a table of all started processes, along with their timestamps:


tag=$SYSMON winlog Provider == "Microsoft-Windows-Sysmon" EventID == 1 Computer ProcessID Image UtcTime
| regex -e Image "\\(?P[^\\]*)$""
| table Computer UtcTime name ProcessID

Just as before, we use a regular expression to get the process name. We pass the computerd, name, process ID, and the time the process was started to a table. Our goal is to get a table of each computer/name/process ID tuple, along with a start and end time, so we can calculate the runtime. Fortunately, Gravwell allows us to combine two or more queries, enriching data as you go, with compound queries.

Let's wrap our query in a compound query statement, and call is "start":


@start{
tag=$SYSMON winlog Provider == "Microsoft-Windows-Sysmon" EventID == 1 Computer ProcessID Image UtcTime
| regex -e Image "\\(?P<name>[^\\]*)$"
| table Computer UtcTime name ProcessID
};

From here, we can write a query that looks at process termination records, enrich it with the timestamp of a potentially matching start time (from the "start" query), and calculate the process runtime. 

Here's the entire query up front. We'll break it down from there.


@start{
tag=$SYSMON winlog Provider == "Microsoft-Windows-Sysmon" EventID == 1 Computer ProcessID Image UtcTime
| regex -e Image "\\(?P<name>[^\\]*)$" 
| table Computer UtcTime name ProcessID
};

tag=$SYSMON winlog Provider == "Microsoft-Windows-Sysmon" EventID == 5 Computer ProcessID Image UtcTime
| regex -e Image "\\(?P<name>[^\\]*)$"
| lookup -r @start [Computer ProcessID name] [Computer ProcessID name] UtcTime as StartTime
| require StartTime
| time UtcTime end StartTime start
| eval ( runtime = end-start )
| sort by runtime desc
| eval ( name != "FileCoAuth.exe" )
| table Computer name runtime

First, we have the "start" query as above. In the second query, we extract all the same fields as we did in the first, but instead extract records with EventID 5 (process termination). After extracting the process field, we use the lookup module to key on equivalent Computer/ProcessID/name tuples, enriching the process termination record with the timestamp from the matching process creation record and call it "StartTime".

From here we convert both timestamps to "time" types, subtract one from the other to get a runtime duration, sort, and table our results. We've filtered out "FileCoAuth.exe" as well in this example because it dominates the overall runtime. 

sysmon-5-table

Runtimes in the 100s of hours! How energy efficient of our test data machine!

Conclusion

Data is better together, especially when we can tell the source of the data.  You can use Gravwell’s automation system to automatically monitor process creation and termination patterns, and even pivot against many threat lists (both free and paid).

Sysmon is excellent for bringing all of that telemetry to you, while Gravwell is fantastic for making it human-readable. Having the processes available to you in one centralized location makes threat hunting, blocklisting, and security analysis easier.

Are you interested in adding Gravwell+Sysmon data to your Operations and Security arsenal? Get in touch with us for a free trial and demo to hear us geek out why Gravwell is the best tool for improving your organization’s security EDR.