Skip to content

Instantly share code, notes, and snippets.

@jymcheong
Created December 19, 2019 08:06
Show Gist options
  • Save jymcheong/cfddf6b2406d71fd6ecf5d325e8e7e4d to your computer and use it in GitHub Desktop.
Save jymcheong/cfddf6b2406d71fd6ecf5d325e8e7e4d to your computer and use it in GitHub Desktop.
C# ETW Example
using System;
using System.Diagnostics;
using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.Session;
using Microsoft.Diagnostics.Tracing.Parsers;
using System.IO;
using System.Collections.Generic;
using System.Reflection;
using Newtonsoft.Json;
/* @ Package Manager Console:
PM> Install-Package Microsoft.Diagnostics.Tracing.TraceEvent
PM> Install-Package Newtonsoft.Json -Version 12.0.3
Need admin rights...
*/
namespace ConsoleETW
{
class Program
{
static string _hostname = Environment.MachineName;
static Dictionary<int, int> _spoof = new Dictionary<int, int>();
static string _assemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
static void Main(string[] args)
{
var sessionName = "MyTraceSession";
using (var session = new TraceEventSession(sessionName, null))
{
using (var source = new ETWTraceEventSource(sessionName, TraceEventSourceType.Session))
{
var registeredParser = new RegisteredTraceEventParser(source);
registeredParser.All += RegisteredParser_All;
session.EnableProvider("Microsoft-Windows-Sysmon");
session.EnableProvider("Microsoft-Windows-Kernel-Process");
source.Process();
}
}
}
private static void RegisteredParser_All(TraceEvent data)
{
string fullpath = "", user = "";
if (data.TaskName == "ProcessStart") //from Microsoft-Windows-Kernel-Process
{ // spoofed but wait for ProcessCreate since we want to use ProcessGuid field-value.
if ((int)data.ProcessID != (int)data.PayloadByName("ParentProcessID"))
_spoof.Add((int)data.PayloadByName("ProcessID"), (int)data.ProcessID);
return;
}
if (data.TaskName == "ProcessCreate(rule:ProcessCreate)")
{
fullpath = (string)data.PayloadByName("Image");
int trueParentPID = 0;
if (_spoof.TryGetValue((int)data.PayloadByName("ProcessId"), out trueParentPID))
{
ReportSpoof(trueParentPID, data);
_spoof.Remove((int)data.PayloadByName("ProcessId")); //PID can be reused, need to clean up
}
}
}
static void ReportSpoof(int trueParentPID, TraceEvent data)
{
Dictionary<string, object> log = new Dictionary<string, object>();
log.Add("Class", "SpoofParentProcessId");
log.Add("TrueParentProcessId", trueParentPID);
WriteLogFile(log, data.PayloadByName("ProcessGuid"));
}
static void WriteLogFile(Dictionary<string, object> log, object processguid)
{
// common fields
log.Add("SourceName", "PPIDSpoofChecker");
log.Add("Hostname", Environment.MachineName);
log.Add("ProcessGuid", "{" + processguid.ToString().ToUpper() + "}");
// ------------
long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; //used in filename
string filename = Environment.MachineName + "_" + "DFPM_rotated_" + milliseconds + ".txt";
Console.WriteLine(JsonConvert.SerializeObject(log));
if (!Directory.Exists(_assemblyPath + "\\logs")) return;
File.WriteAllText(_assemblyPath + "\\logs\\" + filename, JsonConvert.SerializeObject(log));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment