Skip to content
This repository has been archived by the owner on Aug 5, 2024. It is now read-only.

Commit

Permalink
+SilkETW v0.5
Browse files Browse the repository at this point in the history
  • Loading branch information
FuzzySecurity committed Mar 25, 2019
1 parent 802952b commit dd11b70
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 11 deletions.
4 changes: 4 additions & 0 deletions Changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
-= SilkETW v0.5 =-

* Add support for writing results to the Windows event log.

-= SilkETW v0.4 =-

* Initial public release.
Binary file modified Images/help.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,5 +160,6 @@ For details on version specific changes, please refer to the [Changelog](Changel
### RoadMap

* Offer users the option to write trace data to disk as *.etl files.
* ~~Offer users the option to write trace data to the Windows event log.~~ **(v0.5)**
* Create a separate instance (SilkService) which can be deployed as a service with a configuration file.
* Suggestions welcome!
30 changes: 29 additions & 1 deletion SilkETW/ETWCollector.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics;
using System.IO;
using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.Session;
Expand Down Expand Up @@ -48,6 +49,10 @@ public static void StartTrace(CollectorType CollectorType, ulong TraceKeywords,
// Ctrl-c callback handler
SilkUtility.SetupCtrlCHandler(() =>
{
if (OutputType == OutputType.eventlog)
{
SilkUtility.WriteEventLogEntry("{\"Collector\":\"Stop\",\"Error\":false}", EventLogEntryType.SuccessAudit, EventIds.StopOk, Path);
}
TerminateCollector();
});

Expand Down Expand Up @@ -136,9 +141,17 @@ public static void StartTrace(CollectorType CollectorType, ulong TraceKeywords,
if (ProcessResult == 1)
{
SilkUtility.ReturnStatusMessage("[!] The collector failed to write to file", ConsoleColor.Red);
} else
} else if (ProcessResult == 2)
{
SilkUtility.ReturnStatusMessage("[!] The collector failed to POST the result", ConsoleColor.Red);
} else {
SilkUtility.ReturnStatusMessage("[!] The collector failed write to the eventlog", ConsoleColor.Red);
}

// Write status to eventlog if dictated by the output type
if (OutputType == OutputType.eventlog)
{
SilkUtility.WriteEventLogEntry($"{{\"Collector\":\"Stop\",\"Error\":true,\"ErrorCode\":{ProcessResult}}}", EventLogEntryType.Error, EventIds.StopError, Path);
}

// Shut down the collector
Expand All @@ -158,6 +171,21 @@ public static void StartTrace(CollectorType CollectorType, ulong TraceKeywords,
TraceSession.EnableProvider(ProviderName, (TraceEventLevel)UserTraceEventLevel, TraceKeywords);
}

// Write status to eventlog if dictated by the output type
if (OutputType == OutputType.eventlog)
{
String ConvertKeywords;
if (CollectorType == CollectorType.Kernel)
{
ConvertKeywords = Enum.GetName(typeof(KernelTraceEventParser.Keywords), TraceKeywords);
} else
{
ConvertKeywords = "0x" + String.Format("{0:X}", TraceKeywords);
}
String Message = $"{{\"Collector\":\"Start\",\"Data\":{{\"Type\":\"{CollectorType}\",\"Provider\":\"{ProviderName}\",\"Keywords\":\"{ConvertKeywords}\",\"FilterOption\":\"{FilterOption}\",\"FilterValue\":\"{FilterValue}\",\"YaraPath\":\"{YaraScan}\",\"YaraOption\":\"{YaraOptions}\"}}}}";
SilkUtility.WriteEventLogEntry(Message, EventLogEntryType.SuccessAudit, EventIds.Start, Path);
}

// Continuously process all new events in the data source
EventSource.Process();

Expand Down
8 changes: 6 additions & 2 deletions SilkETW/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class Silk
public OutputType OutputType { get; }

[Option("-p|--path", CommandOptionType.SingleValue)]
public String Path { get; } = String.Empty;
public String Path { get; set; } = String.Empty;

[Option("-pn|--providername", CommandOptionType.SingleValue)]
public String ProviderName { get; } = String.Empty;
Expand Down Expand Up @@ -172,7 +172,7 @@ private void OnExecute()
}
}
}
else
else if (OutputType == OutputType.url)
{
if (String.IsNullOrEmpty(Path))
{
Expand All @@ -190,6 +190,10 @@ private void OnExecute()
}
}
}
else if (OutputType == OutputType.eventlog)
{
Path = "SilkETW-Log";
}
}

// Validate filter options
Expand Down
79 changes: 71 additions & 8 deletions SilkETW/h_SilkETW.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Diagnostics;
using Microsoft.Diagnostics.Tracing;
using System.Collections;
using System.Security.AccessControl;
Expand All @@ -12,7 +13,7 @@

namespace SilkETW
{
// Command line enums
// Enums
enum CollectorType
{
None = 0,
Expand All @@ -24,7 +25,8 @@ enum OutputType
{
None = 0,
url,
file
file,
eventlog
}

enum FilterOption
Expand All @@ -43,6 +45,14 @@ enum YaraOptions
Matches
}

enum EventIds
{
Start = 0,
StopOk,
StopError,
Event
}

enum KernelKeywords
{
//
Expand Down Expand Up @@ -277,7 +287,7 @@ public static void PrintLogo()
Console.WriteLine("███████║██║█████╗██║ ██╗███████╗ ██║ ╚███╔███╔╝ ");
Console.WriteLine("╚══════╝╚═╝╚════╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚══╝╚══╝ ");
Console.ResetColor();
Console.WriteLine(" [v0.4 - Ruben Boonen => @FuzzySec]\n");
Console.WriteLine(" [v0.5 - Ruben Boonen => @FuzzySec]\n");
}

// Print trivia ;)
Expand Down Expand Up @@ -310,10 +320,12 @@ public static void PrintHelp()
" ReferenceSet, PMCProfile, NonContainer\n" +
"-uk (--userkeyword) Define a mask of valid keywords, eg 0x2038 -> JitKeyword|InteropKeyword|\n" +
" LoaderKeyword|NGenKeyword\n" +
"-pn (--providername) User ETW provider name, eg \"Microsoft-Windows-DotNETRuntime\"\n" +
"-pn (--providername) User ETW provider name, eg \"Microsoft-Windows-DotNETRuntime\" or its\n" +
" corresponding GUID eg \"e13c0d23-ccbc-4e12-931b-d9cc2eee27e4\"\n" +
"-l (--level) Logging level: Always, Critical, Error, Warning, Informational, Verbose\n" +
"-ot (--outputtype) Output type; either POST to URL or write to file\n" +
"-p (--path) Either full output file path or URL\n" +
"-ot (--outputtype) Output type: POST to \"URL\", write to \"file\" or write to \"eventlog\"\n" +
"-p (--path) Full output file path or URL. Event logs are automatically written to\n" +
" \"Applications and Services Logs\\SilkETW-Log\"\n" +
"-f (--filter) Filter types: None, EventName, ProcessID, ProcessName, Opcode\n" +
"-fv (--filtervalue) Filter type capture value, eg \"svchost\" for ProcessName\n" +
"-y (--yara) Full path to folder containing Yara rules\n" +
Expand All @@ -330,7 +342,9 @@ public static void PrintHelp()
SilkUtility.ReturnStatusMessage("# Use a DNS User collector, specify log level, write to file", ConsoleColor.Green);
Console.WriteLine("SilkETW.exe -t user -pn Microsoft-Windows-DNS-Client -l Always -ot file -p C:\\Some\\Path\\out.json\n");
SilkUtility.ReturnStatusMessage("# Use an LDAP User collector, perform Yara matching, POST matches to Elasticsearch", ConsoleColor.Green);
Console.WriteLine("SilkETW.exe -t user -pn Microsoft-Windows-Ldap-Client -ot url -p https://some.elk:9200/ldap/_doc/ -y C:\\Some\\Yara\\Rule\\Folder -yo matches");
Console.WriteLine("SilkETW.exe -t user -pn Microsoft-Windows-Ldap-Client -ot url -p https://some.elk:9200/ldap/_doc/ -y C:\\Some\\Yara\\Rule\\Folder -yo matches\n");
SilkUtility.ReturnStatusMessage("# Specify \"Microsoft-Windows-COM-Perf\" by its GUID, write results to the event log", ConsoleColor.Green);
Console.WriteLine("SilkETW.exe -t user -pn b8d6861b-d20f-4eec-bbae-87e0dd80602b -ot eventlog");
}

// Print status message
Expand Down Expand Up @@ -400,6 +414,42 @@ public static bool DirectoryHasPermission(string DirectoryPath, FileSystemRights
return isInRoleWithAccess;
}

public static Boolean WriteEventLogEntry(String Message, EventLogEntryType Type, EventIds EventId, String Path)
{
//--[Event ID's]
// 0 == Collector start
// 1 == Collector terminated -> by user
// 2 == Collector terminated -> by error
// 3 == Event recorded
//--

try
{
// Event log properties
String Source = "ETW Collector";

// If the source doesn't exist we have to create it first
if (!EventLog.SourceExists(Source))
{
EventLog.CreateEventSource(Source, Path);
}

// Write event
using (EventLog Log = new EventLog(Path))
{
Log.Source = Source;
Log.MaximumKilobytes = 99968; // Max ~100mb size -> needs 64kb increments
Log.ModifyOverflowPolicy(OverflowAction.OverwriteAsNeeded, 10); // Always overwrite oldest
Log.WriteEntry(Message, Type, (int)EventId);
}
return true;
}
catch
{
return false;
}
}

public static int ProcessJSONEventData(String JSONData, OutputType OutputType, String Path, String YaraScan, YaraOptions YaraOptions)
{
// Yara options
Expand Down Expand Up @@ -432,6 +482,7 @@ public static int ProcessJSONEventData(String JSONData, OutputType OutputType, S
// 0 == OK
// 1 == File write failed
// 2 == URL POST request failed
// 3 == Eventlog write failed
//--

// Process JSON
Expand All @@ -456,7 +507,7 @@ public static int ProcessJSONEventData(String JSONData, OutputType OutputType, S
}

}
else
else if (OutputType == OutputType.url)
{
try
{
Expand Down Expand Up @@ -486,6 +537,18 @@ public static int ProcessJSONEventData(String JSONData, OutputType OutputType, S
}

}
else
{
Boolean WriteEvent = WriteEventLogEntry(JSONData, EventLogEntryType.Information, EventIds.Event, Path);
if (WriteEvent)
{
return 0;
} else
{
return 3;
}

}
} else
{
return 0;
Expand Down

0 comments on commit dd11b70

Please sign in to comment.