Saturday, February 15, 2020

Sifting Through ETW for Persistence in C#


Continuing my deep dive into how .NET can be used maliciously, this blog post will cover hunting for and detecting persistence created by a toolkit written in C#.

While persistence is considered what some refer to as "right of boom/breach", its importance cannot be understated for an attacker. If the attacker cannot maintain a hold on the system to move laterally and exfiltrate data, all is lost.


Today I will be looking at the SharPersist toolkit by Brett Hawkins ( There are a number of ways to establish persistence in Windows environments,  via the registry, services and startup folder. With multiple detection opportunities in place for PowerShell, it only seems right to start looking for alternate means of holding onto access.

SharPersist offers a number of options to create persistence, for this post we will focus on creating a service. On one side, detecting a new service should be relatively easy with logging in place, but without event tracing, visibility into .NET execution is severely limited.

What do All These Event Logs Mean?

While not ideal, all logging was conducted on the target Windows 10 system due to the amount of logs generated by event tracing. Our fictitious story begins after some log analysis identifies a new service installed on the system via Event ID 4697.

Figure 1

Okay, so the file name for service information is definitely interesting and will require some further digging. Since we are auditing the registry, we are able to identify when a value is set/modified. When there is a change to the registry, specifically the Services hive, this notifies the analyst that someone or something has attempted to modify the configuration of a service.

Figure 2

I think if I had to choose just one event ID from Sysmon, it would be EID 1. In the log for process creation, an analyst can note the image, the full command executed as well as the parent image for the process. As seen below in Figure 3, we can now identify the application responsible for this new service, as well as find out what application ran the executable.

Figure 3

Unfortunately, this is where information on SharPersist ends. To gain more visibility into what exactly this is tool doing and to start creating detections based on anomalous behavior, we turn to event tracing for the Microsoft Windows DotNet Runtime channel.

Tracing All The Things

After installing and setting up SilkETW to run as a service, I adjusted the configuration file to log all events to an event log which could be opened in Event Viewer. Event tracing provides a view into .NET that most may not be ready for. While there is a wealth of information to be pulled out of ETW, it takes almost as much time to filter out what really is important to the analyst and what strays away from "normal".

To wade through all the logs that event tracing provides, I want to focus on monitoring events  that should stand out from what we know as normal:

  - Image/Module & Assembly loading
  - Use of P/Invoke and follow on calls to Win32 API's
  - Loading of .NET DLL's that may be unusual (mscoree, mscorelib, clr, ...)
  - Processes loading .NET assemblies that do not usually load them

This list is by no means all inclusive, but is a good starting point to detect out of the ordinary behavior from .NET.

Figure 4
Above we can see the Assembly Loading for the SharPersist tool. As I stated earlier, we have to filter out the noise to get to the parts of the log that are important.

Figure 5
Again, we can view the command line for the created service, but if you look real hard you can see *clr.dll (.NET Common Language Runtime or CLR) has been loaded by the SharPersist process. Some processes may invoke CLR, whether the event is malicious or not requires further digging and knowing your environment.

Figure 6
The use of P/Invoke allows developers to call Windows API's (unmanaged) to interact with managed code. When discussing P/Invoke for offensive purposes, think of any Win32 API you may need and what you can do with it.

In Figure 6 we can also see a number of SharPersist libraries that are called, but more importantly references to the Service Control Manager. Putting all the pieces together, we can start to understand the purpose of the SharPersist tool that created the "FINDME" service.

Figure 7

To declare P/Invoke, we need to include the "using System.Runtime.InteropServices;" namespace. In addition to the numerous libraries for Service Control  called in Figure seven, the "CreateService" method should remove any more doubt we have as to what created the service.


Piecing the above events together and zeroing in on the suspicious calls to the Service Control Manager class and abused DLL's, we have enough information to initiate an incident response. While it is highly unlikely an attacker would drop the SharPersist tool on the system, I believe this was a successful exercise in using ETW to identify malicious indicators.

The SharPersist toolkit offers many paths to create persistence along with some interesting tradecraft options. Combined with the numerous tools being created for .NET exploitation, I plan to keep digging into ways to identify malicious use of the framework.

As I continue learning about C# tradecraft, I plan to focus more on creating solid detections and how the use of Dynamic Invoke over P/Invoke effects visibility. Below are some links to interesting articles if your interested.



JPCert's Log Analysis Training

6 Aug 2020 About a week or so ago, JPCert released their Log Analysis training slides and corresponding CSV files for each hands-on exercise...