Created
December 19, 2019 08:06
-
-
Save jymcheong/cfddf6b2406d71fd6ecf5d325e8e7e4d to your computer and use it in GitHub Desktop.
C# ETW Example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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