From 9f569fd5c6e21fb6297ed9406268c4c1609e8b29 Mon Sep 17 00:00:00 2001
From: Dominik Phillips <153827241+x86phil@users.noreply.github.com>
Date: Wed, 10 Apr 2024 13:48:44 +0200
Subject: [PATCH 01/15] update: folder names
---
bluekrabs/bluekrabs.sln | 4 ++--
examples/ManagedExamples/ManagedExamples.csproj | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/bluekrabs/bluekrabs.sln b/bluekrabs/bluekrabs.sln
index 3228316..c173def 100644
--- a/bluekrabs/bluekrabs.sln
+++ b/bluekrabs/bluekrabs.sln
@@ -20,12 +20,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
MTA.testsettings = MTA.testsettings
EndProjectSection
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "krabs headers", "krabs headers", "{1FD19105-D67C-492B-B98F-53E00A324269}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bluekrabs headers", "bluekrabs headers", "{1FD19105-D67C-492B-B98F-53E00A324269}"
ProjectSection(SolutionItems) = preProject
krabs.hpp = krabs.hpp
EndProjectSection
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "krabs", "krabs", "{371361C8-96EC-4D6D-B80B-2E47E3453264}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bluekrabs", "bluekrabs", "{371361C8-96EC-4D6D-B80B-2E47E3453264}"
ProjectSection(SolutionItems) = preProject
krabs\client.hpp = krabs\client.hpp
krabs\collection_view.hpp = krabs\collection_view.hpp
diff --git a/examples/ManagedExamples/ManagedExamples.csproj b/examples/ManagedExamples/ManagedExamples.csproj
index ee8666e..4c222ab 100644
--- a/examples/ManagedExamples/ManagedExamples.csproj
+++ b/examples/ManagedExamples/ManagedExamples.csproj
@@ -86,7 +86,7 @@
{ed4e6027-541f-440a-a5ee-15dbb7b89423}
- Microsoft.O365.Security.Native.ETW
+ Threathunters.BlueKrabsetw.Native.ETW
From c1387e4153420f447c8b7a143ffa75bfcb5047ac Mon Sep 17 00:00:00 2001
From: Dominik Phillips <153827241+x86phil@users.noreply.github.com>
Date: Thu, 2 May 2024 09:17:18 +0200
Subject: [PATCH 02/15] include: - update provider config during runtime -
disable provider
---
bluekrabs/krabs/etw.hpp | 89 +++++-
bluekrabs/krabs/filter_descriptor.hpp | 111 +++++++
.../krabs/filtering/direct_event_filter.hpp | 280 +++++++++++++++++-
bluekrabs/krabs/kt.hpp | 31 +-
bluekrabs/krabs/provider.hpp | 29 +-
bluekrabs/krabs/schema_locator.hpp | 12 +-
bluekrabs/krabs/trace.hpp | 132 ++++++++-
bluekrabs/krabs/ut.hpp | 275 ++++++++++++++---
.../NativeExamples/NativeExamples.vcxproj | 2 +
.../NativeExamples.vcxproj.filters | 6 +
examples/NativeExamples/examples.h | 12 +
examples/NativeExamples/main.cpp | 5 +-
examples/NativeExamples/user_trace_004.cpp | 49 ++-
.../NativeExamples/user_trace_007_rundown.cpp | 207 +++++++++++++
.../user_trace_009_from_file.cpp | 225 ++++++++++++++
.../user_trace_010_direct_filter.cpp | 11 +-
.../user_trace_012_open_trace.cpp | 34 ++-
.../user_trace_014_transition_trace.cpp | 25 ++
.../user_trace_015_update_provider.cpp | 62 ++++
test.nuspec | 36 +++
20 files changed, 1561 insertions(+), 72 deletions(-)
create mode 100644 bluekrabs/krabs/filter_descriptor.hpp
create mode 100644 examples/NativeExamples/user_trace_014_transition_trace.cpp
create mode 100644 examples/NativeExamples/user_trace_015_update_provider.cpp
create mode 100644 test.nuspec
diff --git a/bluekrabs/krabs/etw.hpp b/bluekrabs/krabs/etw.hpp
index 3bccca7..b980be3 100644
--- a/bluekrabs/krabs/etw.hpp
+++ b/bluekrabs/krabs/etw.hpp
@@ -85,12 +85,24 @@ namespace krabs { namespace details {
*/
void process();
+
+
+ ///**
+ //*
+ //* Starts processing the ETW trace identified by the info in the trace type.
+ //* open() needs to called for this to work first.
+ //*
+ //*/
+ void disable(const typename T::trace_type::provider_type& p);
+
+ void update(const typename T::trace_type::provider_type& p);
+
/**
*
* Queries the ETW trace identified by the info in the trace type.
*
*/
- EVENT_TRACE_PROPERTIES query();
+ trace_info query();
/**
*
@@ -127,15 +139,18 @@ namespace krabs { namespace details {
private:
trace_info fill_trace_info();
trace_info_v2 fill_trace_info_v2();
- EVENT_TRACE_LOGFILE fill_logfile();
- void close_trace();
+ EVENT_TRACE_LOGFILE fill_logfile();
void register_trace();
- EVENT_TRACE_PROPERTIES query_trace();
- EVENT_TRACE_PROPERTIES_V2 query_trace_v2();
void stop_trace();
EVENT_TRACE_LOGFILE open_trace();
+ void close_trace();
+ void update_trace();
+ trace_info query_trace();
+ EVENT_TRACE_PROPERTIES_V2 query_trace_v2();
void process_trace();
void enable_providers();
+ void disable_provider(const typename T::trace_type::provider_type& p);
+ void update_provider(const typename T::trace_type::provider_type& p);
private:
T &trace_;
@@ -215,7 +230,27 @@ namespace krabs { namespace details {
}
template
- EVENT_TRACE_PROPERTIES trace_manager::query()
+ void trace_manager::update(const typename T::trace_type::provider_type& p)
+ {
+ if (trace_.sessionHandle_ == INVALID_PROCESSTRACE_HANDLE) {
+ throw open_trace_failure();
+ }
+
+ update_provider(p);
+ }
+
+ template
+ void trace_manager::disable(const typename T::trace_type::provider_type& p)
+ {
+ if (trace_.sessionHandle_ == INVALID_PROCESSTRACE_HANDLE) {
+ throw open_trace_failure();
+ }
+
+ disable_provider(p);
+ }
+
+ template
+ trace_info trace_manager::query()
{
return query_trace();
}
@@ -354,9 +389,26 @@ namespace krabs { namespace details {
}
template
- EVENT_TRACE_PROPERTIES trace_manager::query_trace()
+ void trace_manager::update_trace()
{
trace_info info = fill_trace_info();
+ ULONG status = ControlTrace(
+ NULL,
+ trace_.name_.c_str(),
+ &info.properties,
+ EVENT_TRACE_CONTROL_UPDATE);
+
+ if (status != ERROR_WMI_INSTANCE_NOT_FOUND) {
+ error_check_common_conditions(status);
+ }
+ }
+
+ template
+ trace_info trace_manager::query_trace()
+ {
+ //trace_info info = fill_trace_info();
+ trace_info info = {};
+ info.properties.Wnode.BufferSize = sizeof(trace_info);
ULONG status = ControlTrace(
NULL,
@@ -368,7 +420,8 @@ namespace krabs { namespace details {
if (status != ERROR_WMI_INSTANCE_NOT_FOUND) {
error_check_common_conditions(status);
- return info.properties;
+ //return info.properties;
+ return info;
}
return { };
@@ -507,4 +560,24 @@ namespace krabs { namespace details {
{
T::trace_type::enable_providers(trace_);
}
+
+ template
+ void trace_manager::disable_provider(const typename T::trace_type::provider_type& p)
+ {
+ T::trace_type::disable_provider(trace_, p);
+ }
+
+ template
+ void trace_manager::update_provider(const typename T::trace_type::provider_type& p)
+ {
+ if (trace_.registrationHandle_ == INVALID_PROCESSTRACE_HANDLE) {
+ trace_.properties_ = query_trace().properties;
+ trace_.registrationHandle_ = trace_.properties_.Wnode.HistoricalContext;
+ }
+
+ if (trace_.registrationHandle_ != INVALID_PROCESSTRACE_HANDLE) {
+ T::trace_type::update_provider(trace_, p);
+ }
+ }
+
} /* namespace details */ } /* namespace krabs */
diff --git a/bluekrabs/krabs/filter_descriptor.hpp b/bluekrabs/krabs/filter_descriptor.hpp
new file mode 100644
index 0000000..007ed4e
--- /dev/null
+++ b/bluekrabs/krabs/filter_descriptor.hpp
@@ -0,0 +1,111 @@
+
+#pragma once
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#include
+#include
+//#include
+
+#include
+
+#include "filtering/direct_event_filter.hpp"
+
+
+#pragma comment(lib, "tdh.lib")
+
+namespace krabs { namespace details {
+
+ template
+ class filter_descriptor {
+ public:
+ filter_descriptor(T& trace);
+
+ void set_event_payload();
+ void set_event_id(const event_id_event_filter& direct_filter);
+ void set_event_pid();
+ void set_event_name();
+ void set_system_flags(const system_flags_event_filter& direct_filter);
+
+ private:
+ ULONG filter_descriptor_count_ = 0;
+ EVENT_FILTER_DESCRIPTOR filter_desc_[MAX_EVENT_FILTERS_COUNT] = { 0 };
+ std::unique_ptr id_cache_;
+ std::unique_ptr pid_cache_;
+ std::unique_ptr exe_name_cache_;
+ std::unique_ptr event_name_cache_;
+ unsigned int pids_cache_[MAX_EVENT_FILTER_PID_COUNT] = { 0 };
+ PAYLOAD_FILTER_PREDICATE predicates_cache_[MAX_PAYLOAD_PREDICATES] = { 0 };
+
+ private:
+ //T& trace_;
+
+ private:
+ template
+ friend class krabs::trace;
+ };
+
+
+ // Implementation
+ // ------------------------------------------------------------------------
+
+ template
+ filter_descriptor::filter_descriptor(T& trace)
+ : trace_(trace)
+ {}
+
+ template
+ void filter_descriptor::set_event_payload() {
+
+ }
+
+ template
+ void filter_descriptor::set_event_id(const event_id_event_filter& direct_filter)
+ {
+ /*typedef struct _EVENT_FILTER_EVENT_ID {
+ BOOLEAN FilterIn;
+ UCHAR Reserved;
+ USHORT Count;
+ USHORT Events[ANYSIZE_ARRAY];
+ } EVENT_FILTER_EVENT_ID, * PEVENT_FILTER_EVENT_ID;*/
+
+ auto& filter_desc = filter_desc_[filter_descriptor_count_++];
+ auto count = direct_filter.get_data().size();
+ if (count > 0) {
+ auto cache_size = FIELD_OFFSET(EVENT_FILTER_EVENT_ID, Events[count]);
+ id_cache_ = std::make_unique(cache_size);
+ auto event_id_desc = reinterpret_cast(id_cache_.get());
+ event_id_desc->FilterIn = TRUE;
+ event_id_desc->Count = static_cast(event_ids_count);
+
+ auto i = 0;
+ for (auto event_id : direct_filter.get_data()) {
+ event_id_desc->Events[i++] = event_id;
+ }
+
+ filter_desc.Type = EVENT_FILTER_TYPE_EVENT_ID;
+ filter_desc.Ptr = reinterpret_cast(event_id_desc);
+ filter_desc.Size = cache_size;
+ }
+ }
+
+ template
+ void filter_descriptor::set_event_pid() {
+
+ }
+ template
+ void filter_descriptor::set_event_name() {
+
+ }
+
+ template
+ void filter_descriptor::set_system_flags(const system_flags_event_filter& direct_filter)
+ {
+ auto& filter_desc = filter_desc_[filter_descriptor_count_++];
+ filter_desc.Ptr = direct_filter.get_value();
+ filter_desc.Size = direct_filter.get_size();
+ filter_desc.Type = EVENT_FILTER_TYPE_SYSTEM_FLAGS;
+ }
+} /* namespace details */ } /* namespace krabs */
\ No newline at end of file
diff --git a/bluekrabs/krabs/filtering/direct_event_filter.hpp b/bluekrabs/krabs/filtering/direct_event_filter.hpp
index 5b6c361..26906b6 100644
--- a/bluekrabs/krabs/filtering/direct_event_filter.hpp
+++ b/bluekrabs/krabs/filtering/direct_event_filter.hpp
@@ -1,6 +1,6 @@
#include
#include
-
+#include
namespace krabs {
@@ -63,6 +63,283 @@ namespace krabs {
unsigned int type_;
unsigned long size_;
};*/
+
+ struct base_descriptor {
+ base_descriptor(unsigned int a1)
+ : type_(a1)
+ {}
+
+ virtual EVENT_FILTER_DESCRIPTOR operator()() const = 0;
+
+ unsigned int type_;
+ };
+
+ struct system_flags_descriptor : base_descriptor {
+ system_flags_descriptor(unsigned long long a1, unsigned long a2)
+ : base_descriptor(EVENT_FILTER_TYPE_SYSTEM_FLAGS)
+ , descriptor_({ 0 })
+ , data_(a1)
+ , size_(a2)
+ {}
+
+ EVENT_FILTER_DESCRIPTOR operator()() const override
+ {
+ descriptor_.Ptr = reinterpret_cast(&data_);
+ descriptor_.Size = size_;
+ descriptor_.Type = type_;
+
+ return descriptor_;
+ }
+
+ private:
+ mutable unsigned long long data_;
+ unsigned long size_;
+ mutable EVENT_FILTER_DESCRIPTOR descriptor_;
+ };
+
+ struct event_id_descriptor : base_descriptor {
+ event_id_descriptor(std::set a1, bool a2)
+ : base_descriptor(EVENT_FILTER_TYPE_EVENT_ID)
+ , descriptor_({ 0 })
+ , data_(a1)
+ , filter_in_(a2)
+ {}
+
+ EVENT_FILTER_DESCRIPTOR operator()() const override
+ {
+ /*typedef struct _EVENT_FILTER_EVENT_ID {
+ BOOLEAN FilterIn;
+ UCHAR Reserved;
+ USHORT Count;
+ USHORT Events[ANYSIZE_ARRAY];
+ } EVENT_FILTER_EVENT_ID, * PEVENT_FILTER_EVENT_ID;*/
+
+ auto count = data_.size();
+ if (count > 0) {
+ auto cache_size = FIELD_OFFSET(EVENT_FILTER_EVENT_ID, Events[count]);
+ cache_ = std::make_unique(cache_size);
+ auto tmp = reinterpret_cast(cache_.get());
+ tmp->FilterIn = filter_in_;
+ tmp->Count = static_cast(count);
+ int i = 0;
+ for (auto item : data_) {
+ tmp->Events[i++] = item;
+ }
+ descriptor_.Ptr = reinterpret_cast(cache_.get());
+ descriptor_.Size = cache_size;
+ descriptor_.Type = type_;
+ }
+
+ return descriptor_;
+ }
+
+ private:
+ std::set data_;
+ bool filter_in_;
+ mutable EVENT_FILTER_DESCRIPTOR descriptor_;
+ mutable std::unique_ptr cache_;
+ };
+
+ struct pid_descriptor : base_descriptor {
+ pid_descriptor(std::set a1)
+ : base_descriptor(EVENT_FILTER_TYPE_PID)
+ , descriptor_({ 0 })
+ , data_(a1)
+ {}
+
+ EVENT_FILTER_DESCRIPTOR operator()() const override
+ {
+ /*typedef struct _EVENT_FILTER_EVENT_ID {
+ BOOLEAN FilterIn;
+ UCHAR Reserved;
+ USHORT Count;
+ USHORT Events[ANYSIZE_ARRAY];
+ } EVENT_FILTER_EVENT_ID, * PEVENT_FILTER_EVENT_ID;*/
+
+ auto count = data_.size();
+ if (count > 0) {
+ int i = 0;
+ for (auto item : data_) {
+ if (i < MAX_EVENT_FILTER_PID_COUNT) {
+ cache_[i++] = item;
+ }
+ }
+ descriptor_.Ptr = reinterpret_cast(cache_);
+ descriptor_.Size = sizeof(unsigned int) * i;
+ descriptor_.Type = type_;
+ }
+
+ return descriptor_;
+ }
+
+ private:
+ std::set data_;
+ mutable EVENT_FILTER_DESCRIPTOR descriptor_;
+ mutable unsigned int cache_[MAX_EVENT_FILTER_PID_COUNT] = { 0 };
+ };
+
+ struct event_name_descriptor : base_descriptor {
+ event_name_descriptor(std::set a1, bool a2)
+ : base_descriptor(EVENT_FILTER_TYPE_EVENT_NAME)
+ , descriptor_({ 0 })
+ , data_(a1)
+ , filter_in_(a2)
+ {}
+
+ EVENT_FILTER_DESCRIPTOR operator()() const override
+ {
+ /*typedef struct _EVENT_FILTER_EVENT_NAME {
+ ULONGLONG MatchAnyKeyword;
+ ULONGLONG MatchAllKeyword;
+ UCHAR Level;
+ BOOLEAN FilterIn;
+ USHORT NameCount;
+ UCHAR Names[ANYSIZE_ARRAY];
+ } EVENT_FILTER_EVENT_NAME, * PEVENT_FILTER_EVENT_NAME;*/
+
+ auto count = data_.size();
+ if (count > 0) {
+ auto cache_size = FIELD_OFFSET(EVENT_FILTER_EVENT_NAME, Names[count]);
+ cache_ = std::make_unique(cache_size);
+ auto tmp = reinterpret_cast(cache_.get());
+ tmp->FilterIn = filter_in_;
+ tmp->Level = 0;
+ tmp->MatchAnyKeyword = 0;
+ tmp->MatchAllKeyword = 0;
+ tmp->NameCount = static_cast(count);
+ // The Names field should be a series of
+ // NameCount null terminated utf-8
+ // event names.
+ auto i = 0;
+ for (auto item1 : data_) {
+ item1.push_back('\0');
+ for (auto& item2 : item1) {
+ tmp->Names[i++] = item2;
+ }
+ }
+
+ descriptor_.Ptr = reinterpret_cast(cache_.get());
+ descriptor_.Size = cache_size;
+ descriptor_.Type = type_;
+ }
+
+ return descriptor_;
+ }
+
+ private:
+ std::set data_;
+ bool filter_in_;
+ mutable EVENT_FILTER_DESCRIPTOR descriptor_;
+ mutable std::unique_ptr cache_;
+ };
+
+ struct payload_descriptor : base_descriptor {
+ payload_descriptor(std::set a1, bool a2)
+ : base_descriptor(EVENT_FILTER_TYPE_PAYLOAD)
+ , descriptor_({ 0 })
+ , data_(a1)
+ , filter_in_(a2)
+ {}
+
+ EVENT_FILTER_DESCRIPTOR operator()() const override
+ {
+ /*typedef struct _PAYLOAD_FILTER_PREDICATE {
+ LPWSTR FieldName;
+ USHORT CompareOp;
+ LPWSTR Value;
+ } PAYLOAD_FILTER_PREDICATE, *PPAYLOAD_FILTER_PREDICATE;*/
+
+
+
+ return descriptor_;
+ }
+
+ private:
+ std::set data_;
+ bool filter_in_;
+ mutable EVENT_FILTER_DESCRIPTOR descriptor_;
+ mutable PAYLOAD_FILTER_PREDICATE cache_[MAX_PAYLOAD_PREDICATES] = { 0 };
+ //mutable std::unique_ptr cache_;
+ };
+
+ struct descriptor_info {
+ unsigned long count;
+ EVENT_FILTER_DESCRIPTOR descriptor[MAX_EVENT_FILTERS_COUNT];
+ };
+
+ /**
+ *
+ * Accepts an event if any of the predicates in the vector matches
+ *
+ */
+ struct direct_event_filters1 {
+ direct_event_filters1(std::vector list)
+ : list_(list)
+ , descriptor_({0})
+ , count_(0)
+ {}
+
+ descriptor_info operator()() const
+ {
+ auto& count = descriptor_.count;
+ if (count == 0) {
+ for (auto& item : list_) {
+ switch (item->type_) {
+ case EVENT_FILTER_TYPE_SYSTEM_FLAGS: {
+ auto tmp = static_cast(const_cast(item));
+ if (tmp) {
+ descriptor_.descriptor[count++] = (*tmp)();
+ }
+ break;
+ }
+ case EVENT_FILTER_TYPE_EVENT_ID: {
+ auto tmp = static_cast(const_cast(item));
+ if (tmp) {
+ descriptor_.descriptor[count++] = (*tmp)();
+ }
+ break;
+ }
+ case EVENT_FILTER_TYPE_EVENT_NAME: {
+ auto tmp = static_cast(const_cast(item));
+ if (tmp) {
+ descriptor_.descriptor[count++] = (*tmp)();
+ }
+ break;
+ }
+ case EVENT_FILTER_TYPE_PAYLOAD: {
+ auto tmp = static_cast(const_cast(item));
+ if (tmp) {
+ descriptor_.descriptor[count++] = (*tmp)();
+ }
+ break;
+ }
+ case EVENT_FILTER_TYPE_PID: {
+ auto tmp = static_cast(const_cast(item));
+ if (tmp) {
+ descriptor_.descriptor[count++] = (*tmp)();
+ }
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ }
+ }
+
+ return descriptor_;
+ }
+ private:
+ mutable unsigned long count_;
+ mutable descriptor_info descriptor_;
+ std::vector list_;
+ };
+
+
+
+
+
+
struct system_flags_event_filter : direct_event_filter_base {
system_flags_event_filter(unsigned long long flags, unsigned long size)
: flags_(flags),
@@ -188,7 +465,6 @@ namespace krabs {
unsigned long size_;
};
-
/*
typedef struct _PAYLOAD_FILTER_PREDICATE {
LPWSTR FieldName;
diff --git a/bluekrabs/krabs/kt.hpp b/bluekrabs/krabs/kt.hpp
index 512b694..2c99bcd 100644
--- a/bluekrabs/krabs/kt.hpp
+++ b/bluekrabs/krabs/kt.hpp
@@ -59,6 +59,15 @@ namespace krabs { namespace details {
static void enable_providers(
const krabs::trace &trace);
+ /**
+ *
+ * Enables the providers that are attached to the given trace.
+ *
+ */
+ static void update_provider(
+ krabs::trace& trace,
+ const krabs::details::kt::provider_type& p);
+
/**
*
* Enables the configured kernel rundown flags.
@@ -112,7 +121,7 @@ namespace krabs { namespace details {
const krabs::trace &trace)
{
unsigned long flags = 0;
- for (auto &provider : trace.providers_) {
+ for (auto &provider : trace.enabled_providers_) {
flags |= provider.get().flags();
}
@@ -131,7 +140,7 @@ namespace krabs { namespace details {
error_check_common_conditions(status);
auto group_mask_set = false;
- for (auto& provider : trace.providers_) {
+ for (auto& provider : trace.enabled_providers_) {
auto group = provider.get().group_mask();
PERFINFO_OR_GROUP_WITH_GROUPMASK(group, &(gmi.EventTraceGroupMasks));
group_mask_set |= (group != 0);
@@ -146,12 +155,26 @@ namespace krabs { namespace details {
return;
}
+ inline void kt::update_provider(
+ krabs::trace& trace,
+ const krabs::details::kt::provider_type& p)
+ {
+ if (trace.registrationHandle_ == INVALID_PROCESSTRACE_HANDLE)
+ return;
+ GUID g;
+ if (g == p.guid()) {
+
+ }
+ error_check_common_conditions(ERROR_NOT_FOUND);
+ return;
+ }
+
inline void kt::enable_rundown(
const krabs::trace& trace)
{
bool rundown_enabled = false;
ULONG rundown_flags = 0;
- for (auto& provider : trace.providers_) {
+ for (auto& provider : trace.enabled_providers_) {
rundown_enabled |= provider.get().rundown_enabled();
rundown_flags |= provider.get().rundown_flags();
}
@@ -174,7 +197,7 @@ namespace krabs { namespace details {
const EVENT_RECORD &record,
const krabs::trace &trace)
{
- for (auto &provider : trace.providers_) {
+ for (auto &provider : trace.enabled_providers_) {
if (provider.get().id() == record.EventHeader.ProviderId) {
provider.get().on_event(record, trace.context_);
return;
diff --git a/bluekrabs/krabs/provider.hpp b/bluekrabs/krabs/provider.hpp
index fb8c164..5b99bbb 100644
--- a/bluekrabs/krabs/provider.hpp
+++ b/bluekrabs/krabs/provider.hpp
@@ -45,7 +45,6 @@ namespace krabs {
typedef std::function provider_error_callback;
namespace details {
-
/**
*
* Serves as a base for providers and kernel_providers. Handles event
@@ -275,6 +274,13 @@ namespace krabs {
*/
void enable_rundown_events();
+ /**
+ *
+ * Retrieves the GUID associated with this provider.
+ *
+ */
+ const GUID guid() const;
+
/**
*
* Turns a strongly typed provider to provider<> (useful for
@@ -353,11 +359,18 @@ namespace krabs {
/**
*
- * Retrieves the GUID associated with this provider.
+ * Retrieves the krabs::guid associated with this provider.
*
*/
const krabs::guid &id() const;
+ /**
+ *
+ * Retrieves the GUID associated with this provider.
+ *
+ */
+ const GUID guid() const;
+
/**
*
* Sets flags to be enabled for the kernel rundown GUID.
@@ -608,6 +621,7 @@ namespace krabs {
}
guid_ = providerGuid;
+ //guid2_ = krabs::guid(providerGuid);
any_ = 0;
all_ = 0;
level_ = 5;
@@ -667,9 +681,20 @@ namespace krabs {
return tmp;
}
+ template
+ inline const GUID provider::guid() const
+ {
+ return guid_;
+ }
+
inline const krabs::guid &kernel_provider::id() const
{
return id_;
}
+ inline const GUID kernel_provider::guid() const
+ {
+ return id_.operator GUID();
+ }
+
}
diff --git a/bluekrabs/krabs/schema_locator.hpp b/bluekrabs/krabs/schema_locator.hpp
index e3ec591..7ad8c41 100644
--- a/bluekrabs/krabs/schema_locator.hpp
+++ b/bluekrabs/krabs/schema_locator.hpp
@@ -149,15 +149,17 @@ namespace krabs {
// allocate and fill the schema from TDH
auto buffer = std::unique_ptr(new char[bufferSize]);
- error_check_common_conditions(
- TdhGetEventInformation(
+ status = TdhGetEventInformation(
(PEVENT_RECORD)&record,
0,
NULL,
(PTRACE_EVENT_INFO)buffer.get(),
- &bufferSize),
- record);
-
+ &bufferSize);
+
+ if (status != ERROR_SUCCESS) {
+ error_check_common_conditions(status, record);
+ }
+
return buffer;
}
}
diff --git a/bluekrabs/krabs/trace.hpp b/bluekrabs/krabs/trace.hpp
index ffed74f..a78c885 100644
--- a/bluekrabs/krabs/trace.hpp
+++ b/bluekrabs/krabs/trace.hpp
@@ -4,6 +4,8 @@
#pragma once
#include
+#include
diff --git a/examples/NativeExamples/NativeExamples.vcxproj.filters b/examples/NativeExamples/NativeExamples.vcxproj.filters
index 98bb548..d7645ab 100644
--- a/examples/NativeExamples/NativeExamples.vcxproj.filters
+++ b/examples/NativeExamples/NativeExamples.vcxproj.filters
@@ -70,6 +70,12 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
diff --git a/examples/NativeExamples/examples.h b/examples/NativeExamples/examples.h
index 96b0b0d..27ca68e 100644
--- a/examples/NativeExamples/examples.h
+++ b/examples/NativeExamples/examples.h
@@ -66,6 +66,7 @@ struct user_trace_006_predicate_vectors
struct user_trace_007_rundown
{
static void start();
+ static void start2();
};
struct user_trace_008_stacktrace
@@ -76,6 +77,7 @@ struct user_trace_008_stacktrace
struct user_trace_009_from_file
{
static void start();
+ static void start2();
};
struct user_trace_010_direct_filter
@@ -94,6 +96,16 @@ struct user_trace_012_open_trace
};
struct user_trace_013_pktmon
+{
+ static void start();
+};
+
+struct user_trace_014_transition_trace
+{
+ static void start();
+};
+
+struct user_trace_015_update_provider
{
static void start();
};
\ No newline at end of file
diff --git a/examples/NativeExamples/main.cpp b/examples/NativeExamples/main.cpp
index a9f66f1..cbac172 100644
--- a/examples/NativeExamples/main.cpp
+++ b/examples/NativeExamples/main.cpp
@@ -19,10 +19,13 @@ int main(void)
//user_trace_005::start();
//user_trace_006_predicate_vectors::start();
//user_trace_007_rundown::start();
+ //user_trace_007_rundown::start2();
//user_trace_008_stacktrace::start();
//user_trace_009_from_file::start();
+ //user_trace_009_from_file::start2();
//user_trace_010_direct_filter::start();
//user_trace_011_search_wevt::start();
//user_trace_012_open_trace::start();
- user_trace_013_pktmon::start();
+ //user_trace_013_pktmon::start();
+ user_trace_014_transition_trace::start();
}
\ No newline at end of file
diff --git a/examples/NativeExamples/user_trace_004.cpp b/examples/NativeExamples/user_trace_004.cpp
index 457e559..d1df719 100644
--- a/examples/NativeExamples/user_trace_004.cpp
+++ b/examples/NativeExamples/user_trace_004.cpp
@@ -8,6 +8,8 @@
#include
#include
+#include
+#include
#include "..\..\bluekrabs\krabs.hpp"
#include "examples.h"
@@ -39,12 +41,33 @@ void user_trace_004::start()
auto cb = [](const EVENT_RECORD &record, const krabs::trace_context &trace_context) {
krabs::schema schema(record, trace_context.schema_locator);
- assert(schema.event_id() == 11);
- assert(schema.process_id() == 4);
+ /* assert(schema.event_id() == 11);
+ assert(schema.process_id() == 4);*/
std::wcout << L"Event " +
std::to_wstring(schema.event_id()) +
L" received for pid " +
std::to_wstring(schema.process_id()) << std::endl;
+ auto extended_data_count = record.ExtendedDataCount;
+ for (USHORT i = 0; i < extended_data_count; i++)
+ {
+ auto& extended_data = record.ExtendedData[i];
+
+ if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_TS_ID)
+ {
+ auto result = (reinterpret_cast<_EVENT_EXTENDED_ITEM_TS_ID*>(extended_data.DataPtr))->SessionId;
+ std::wcout << L"(" << "EVENT_EXTENDED_ITEM_TS_ID" << L") received." << result << std::endl;
+ }
+ if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_SID)
+ {
+
+ }
+ if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY)
+ {
+ auto result = (reinterpret_cast<_EVENT_EXTENDED_ITEM_PROCESS_START_KEY*>(extended_data.DataPtr))->ProcessStartKey;
+ std::wcout << L"(" << "EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY" << L") received." << result << std::endl;
+ }
+ }
+
};
filter.add_on_event_callback(cb);
@@ -54,5 +77,25 @@ void user_trace_004::start()
// provider directly will be called for all events that are fired by the ETW producer.
provider.add_filter(filter);
trace.enable(provider);
- trace.start();
+
+ std::thread workerThread([&]() {
+ trace.start();
+ });
+
+ //const int durationInSeconds = 5;
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+ //trace.stop();
+
+ /*workerThread.join();*/
+
+ provider.enable_property(provider.enable_property() | EVENT_ENABLE_PROPERTY_PROCESS_START_KEY | EVENT_ENABLE_PROPERTY_SID | EVENT_ENABLE_PROPERTY_TS_ID);
+ //trace.open();
+ trace.enable(provider);
+ std::this_thread::sleep_for(std::chrono::seconds(10));
+ trace.stop();
+ workerThread.join();
+ //trace.start();
+
+
+
}
diff --git a/examples/NativeExamples/user_trace_007_rundown.cpp b/examples/NativeExamples/user_trace_007_rundown.cpp
index 5725448..83d0e46 100644
--- a/examples/NativeExamples/user_trace_007_rundown.cpp
+++ b/examples/NativeExamples/user_trace_007_rundown.cpp
@@ -84,4 +84,211 @@ void user_trace_007_rundown::start()
trace.enable(dotnet_rundown_provider);
trace.start();
+}
+
+
+void user_trace_007_rundown::start2()
+{
+ krabs::user_trace trace(L"user_trace_007");
+
+
+ krabs::provider<> provider1(L"Microsoft-Windows-DotNETRuntimeRundown");
+ krabs::provider<> provider2(L"Microsoft-Windows-Kernel-Power");
+ krabs::provider<> provider3(L"Microsoft-Windows-DotNETRuntime");
+ krabs::provider<> provider4(L"Microsoft-JScript");
+ krabs::provider<> provider5(L"Microsoft-Windows-Win32k");
+ krabs::provider<> provider6(L"Microsoft-Windows-UserModePowerService");
+ krabs::provider<> provider7(L"Microsoft-Windows-Networking-Correlation");
+ krabs::provider<> provider8(L"Microsoft-Windows-Kernel-Processor-Power");
+ krabs::provider<> provider9(L"Microsoft-Windows-RPC");
+ krabs::provider<> provider10(L"Microsoft-Windows-Kernel-EventTracing");
+ krabs::provider<> provider11(L"Microsoft-Antimalware-Engine");
+ krabs::provider<> provider12(L"Microsoft-Windows-Search-Core");
+ krabs::provider<> provider13(L"Microsoft-Antimalware-AMFilter");
+ krabs::provider<> provider14(L"Microsoft-Windows-Performance-Recorder-Control");
+ krabs::provider<> provider20(krabs::guid(L"{e13c0d23-ccbc-4e12-931b-d9cc2eee27e4}"));
+ krabs::provider<> provider15(L"Microsoft-Windows-Kernel-StoreMgr");
+ krabs::provider<> provider16(L"Microsoft-Antimalware-RTP");
+ krabs::provider<> provider17(L"Microsoft-Antimalware-Service");
+ krabs::provider<> provider18(L"Microsoft-Windows-ProcessStateManager");
+ krabs::provider<> provider19(L"Microsoft-Windows-ReadyBoostDriver");
+ krabs::provider<> provider21(L"Microsoft-Windows-COMRuntime");
+
+
+ // user_trace providers typically have any and all flags, whose meanings are
+ // unique to the specific providers that are being invoked. To understand these
+ // flags, you'll need to look to the ETW event producer.
+ //provider.any(0xf0010000000003ff);
+
+ // providers should be wired up with functions (or functors) that are called when
+ // events from that provider are fired.
+ provider1.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider2.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider3.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider4.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider5.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider6.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider7.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider8.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider9.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider10.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider11.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider12.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider13.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider14.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider15.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider16.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider17.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider18.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider19.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider20.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider21.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ //std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ /* provider22.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+
+ });
+ provider23.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+
+ });
+ provider24.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+
+ });*/
+
+
+
+ // the user_trace needs to know about the provider that we've set up.
+ trace.enable(provider1);
+ trace.enable(provider2);
+ trace.enable(provider3);
+ trace.enable(provider4);
+ trace.enable(provider5);
+ trace.enable(provider6);
+ trace.enable(provider7);
+ trace.enable(provider8);
+ trace.enable(provider10);
+ trace.enable(provider11);
+ trace.enable(provider12);
+ trace.enable(provider13);
+ trace.enable(provider14);
+ trace.enable(provider15);
+ trace.enable(provider16);
+ trace.enable(provider17);
+ trace.enable(provider18);
+ trace.enable(provider19);
+ trace.enable(provider20);
+ trace.enable(provider21);
+ /* trace.enable(provider22);
+ trace.enable(provider23);
+ trace.enable(provider24);*/
+ // specify a filename to read from, will disable realtime and source from file instead
+
+
+ // begin listening for events. This call blocks until the end of file is reached, so if
+ // you want to do other things while this runs, you'll need to call this on another thread.
+ trace.start();
+
}
\ No newline at end of file
diff --git a/examples/NativeExamples/user_trace_009_from_file.cpp b/examples/NativeExamples/user_trace_009_from_file.cpp
index e00f8d9..5690c15 100644
--- a/examples/NativeExamples/user_trace_009_from_file.cpp
+++ b/examples/NativeExamples/user_trace_009_from_file.cpp
@@ -65,3 +65,228 @@ void user_trace_009_from_file::start()
// stop the trace and close the trace file
trace.stop();
}
+
+void user_trace_009_from_file::start2()
+{
+ // user_trace instances should be used for any non-kernel traces that are defined
+// by components or programs in Windows.
+ krabs::user_trace trace;
+
+ // A trace can have any number of providers, which are identified by GUID. These
+ // GUIDs are defined by the components that emit events, and their GUIDs can
+ // usually be found with various ETW tools (like wevutil).
+ krabs::provider<> provider1(L"Microsoft-Windows-DotNETRuntimeRundown");
+ krabs::provider<> provider2(L"Microsoft-Windows-Kernel-Power");
+ krabs::provider<> provider3(L"Microsoft-Windows-DotNETRuntime");
+ krabs::provider<> provider4(L"Microsoft-JScript");
+ krabs::provider<> provider5(L"Microsoft-Windows-Win32k");
+ krabs::provider<> provider6(L"Microsoft-Windows-UserModePowerService");
+ krabs::provider<> provider7(L"Microsoft-Windows-Networking-Correlation");
+ krabs::provider<> provider8(L"Microsoft-Windows-Kernel-Processor-Power");
+ krabs::provider<> provider9(L"Microsoft-Windows-RPC");
+ krabs::provider<> provider10(L"Microsoft-Windows-Kernel-EventTracing");
+ krabs::provider<> provider11(L"Microsoft-Antimalware-Engine");
+ krabs::provider<> provider12(L"Microsoft-Windows-Search-Core");
+ krabs::provider<> provider13(L"Microsoft-Antimalware-AMFilter");
+ krabs::provider<> provider14(L"Microsoft-Windows-Performance-Recorder-Control");
+ krabs::provider<> provider20(krabs::guid(L"{e13c0d23-ccbc-4e12-931b-d9cc2eee27e4}"));
+ krabs::provider<> provider30(krabs::guid(L"{9B79EE91-B5FD-41C0-A243-4248E266E9D0}"));
+ krabs::provider<> provider15(L"Microsoft-Windows-Kernel-StoreMgr");
+ krabs::provider<> provider16(L"Microsoft-Antimalware-RTP");
+ krabs::provider<> provider17(L"Microsoft-Antimalware-Service");
+ krabs::provider<> provider18(L"Microsoft-Windows-ProcessStateManager");
+ krabs::provider<> provider19(L"Microsoft-Windows-ReadyBoostDriver");
+ krabs::provider<> provider21(L"Microsoft-Windows-COMRuntime");
+
+
+ // user_trace providers typically have any and all flags, whose meanings are
+ // unique to the specific providers that are being invoked. To understand these
+ // flags, you'll need to look to the ETW event producer.
+ //provider.any(0xf0010000000003ff);
+
+ // providers should be wired up with functions (or functors) that are called when
+ // events from that provider are fired.
+ provider1.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider2.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider3.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider4.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider5.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider6.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider7.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider8.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider9.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider10.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider11.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider12.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider13.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider14.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider15.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider16.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider17.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider18.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider19.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider20.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider21.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ provider30.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+ std::wcout << L"Event " << schema.event_id() << std::endl;
+ if (schema.event_id() == schema.event_id())
+ return;
+ });
+ /* provider22.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+
+ });
+ provider23.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+
+ });
+ provider24.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+
+ });*/
+
+
+
+ // the user_trace needs to know about the provider that we've set up.
+ trace.enable(provider1);
+ trace.enable(provider2);
+ trace.enable(provider3);
+ trace.enable(provider4);
+ trace.enable(provider5);
+ trace.enable(provider6);
+ trace.enable(provider7);
+ trace.enable(provider8);
+ trace.enable(provider9);
+ trace.enable(provider10);
+ trace.enable(provider11);
+ trace.enable(provider12);
+ trace.enable(provider13);
+ trace.enable(provider14);
+ trace.enable(provider15);
+ trace.enable(provider16);
+ trace.enable(provider17);
+ trace.enable(provider18);
+ trace.enable(provider19);
+ trace.enable(provider20);
+ trace.enable(provider21);
+ trace.enable(provider30);
+ /* trace.enable(provider22);
+ trace.enable(provider23);
+ trace.enable(provider24);*/
+ // specify a filename to read from, will disable realtime and source from file instead
+ trace.set_trace_filename(L"C:\\Users\\root\\Documents\\WPR Files\\DESKTOP-L5HRUTP.02-08-2024.15-05-28.etl");
+
+ // begin listening for events. This call blocks until the end of file is reached, so if
+ // you want to do other things while this runs, you'll need to call this on another thread.
+ trace.open();
+ trace.process();
+ /* std::thread workerThread([&]() {
+ trace.process();
+ });*/
+
+ // stop the trace and close the trace file
+ //trace.stop();
+}
diff --git a/examples/NativeExamples/user_trace_010_direct_filter.cpp b/examples/NativeExamples/user_trace_010_direct_filter.cpp
index 529c058..808c3dc 100644
--- a/examples/NativeExamples/user_trace_010_direct_filter.cpp
+++ b/examples/NativeExamples/user_trace_010_direct_filter.cpp
@@ -48,6 +48,15 @@ void user_trace_010_direct_filter::start()
auto eventname = std::make_shared(std::set{ "name1", "name2" }, true);
//auto eventid = krabs::event_id_type_filter({ 5 }, true);
auto payload_filter = std::make_shared(L"DesiredAccess", (unsigned short)PAYLOADFIELD_GE, L"12288");
+
+ auto sy = krabs::system_flags_descriptor(0xFFFFFFFFFFFF, 4);
+ auto id = krabs::event_id_descriptor(std::set{ 5, 12, 31, 131, 133 }, true);
+
+ auto d1 = sy();
+ auto d2 = id();
+
+ krabs::direct_event_filters1 direct_filter1({&sy,&id});
+ auto a = direct_filter1();
krabs::direct_event_filters direct_filter({
eventid,
payload_filter,
@@ -87,7 +96,7 @@ void user_trace_010_direct_filter::start()
std::wcout << L" ValueName=" << parser.parse(L"ValueName") << std::endl;
std::wcout << L" CapturedDataSize=" << parser.parse(L"CapturedDataSize") << std::endl;
std::wcout << L" PreviousDataCapturedSize=" << parser.parse(L"PreviousDataCapturedSize") << std::endl;*/
-
+
diff --git a/examples/NativeExamples/user_trace_012_open_trace.cpp b/examples/NativeExamples/user_trace_012_open_trace.cpp
index 534e3b5..5c6fb86 100644
--- a/examples/NativeExamples/user_trace_012_open_trace.cpp
+++ b/examples/NativeExamples/user_trace_012_open_trace.cpp
@@ -3,6 +3,8 @@
// This example shows how to use a user_trace with an ETL file
#include
+#include
+#include
#include "..\..\bluekrabs\krabs.hpp"
#include "examples.h"
@@ -12,21 +14,51 @@ void user_trace_012_open_trace::start()
krabs::user_trace trace(L"test_sense");
krabs::provider<> provider(krabs::guid(L"{16c6501a-ff2d-46ea-868d-8f96cb0cb52d}"));
+ //provider.enable_property(provider.enable_property() | EVENT_ENABLE_PROPERTY_PROCESS_START_KEY | EVENT_ENABLE_PROPERTY_SID | EVENT_ENABLE_PROPERTY_TS_ID);
+
provider.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
// Once an event is received, if we want krabs to help us analyze it, we need
// to snap in a schema to ask it for information.
krabs::schema schema(record, trace_context.schema_locator);
+
// We then have the ability to ask a few questions of the event.
std::wcout << L"Event " << schema.event_id();
std::wcout << L"(" << schema.event_name() << L") received." << std::endl;
krabs::parser parser(schema);
+ /*auto extended_data_count = record.ExtendedDataCount;
+ for (USHORT i = 0; i < extended_data_count; i++)
+ {
+ auto& extended_data = record.ExtendedData[i];
+
+ if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_TS_ID)
+ {
+ auto result = (reinterpret_cast<_EVENT_EXTENDED_ITEM_TS_ID*>(extended_data.DataPtr))->SessionId;
+ std::wcout << L"(" << "EVENT_EXTENDED_ITEM_TS_ID" << L") received." << result << std::endl;
+ }
+ if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_SID)
+ {
+
+ }
+ if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY)
+ {
+ auto result = (reinterpret_cast<_EVENT_EXTENDED_ITEM_PROCESS_START_KEY*>(extended_data.DataPtr))->ProcessStartKey;
+ std::wcout << L"(" << "EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY" << L") received." << result << std::endl;
+ }
+ }*/
+
});
trace.enable(provider);
trace.open();
- trace.process();
+ std::thread workerThread([&]() {
+ trace.process();
+ });
+
+ trace.stop();
+ //trace.update(provider);
+
}
\ No newline at end of file
diff --git a/examples/NativeExamples/user_trace_014_transition_trace.cpp b/examples/NativeExamples/user_trace_014_transition_trace.cpp
new file mode 100644
index 0000000..5a63d4b
--- /dev/null
+++ b/examples/NativeExamples/user_trace_014_transition_trace.cpp
@@ -0,0 +1,25 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+// This example shows how to use a user_trace with an ETL file
+#pragma once
+
+#include
+#include
+#include
+
+#include "..\..\bluekrabs\krabs.hpp"
+#include "examples.h"
+
+
+
+void user_trace_014_transition_trace::start()
+{
+
+ krabs::user_trace trace(L"test_sense");
+
+
+ auto config = trace.query_config();
+
+ std::wcout << L"config" << std::endl;
+}
\ No newline at end of file
diff --git a/examples/NativeExamples/user_trace_015_update_provider.cpp b/examples/NativeExamples/user_trace_015_update_provider.cpp
new file mode 100644
index 0000000..62a131c
--- /dev/null
+++ b/examples/NativeExamples/user_trace_015_update_provider.cpp
@@ -0,0 +1,62 @@
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+// This example shows how to use a user_trace with an ETL file
+#pragma once
+
+#include
+#include
+#include
+
+#include "..\..\bluekrabs\krabs.hpp"
+#include "examples.h"
+
+
+
+void user_trace_015_update_provider::start()
+{
+
+ krabs::user_trace trace(L"test_sense");
+
+ krabs::provider<> provider(krabs::guid(L"{16c6501a-ff2d-46ea-868d-8f96cb0cb52d}"));
+
+ provider.enable_property(provider.enable_property() | EVENT_ENABLE_PROPERTY_PROCESS_START_KEY | EVENT_ENABLE_PROPERTY_SID | EVENT_ENABLE_PROPERTY_TS_ID);
+
+ provider.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+
+ // Once an event is received, if we want krabs to help us analyze it, we need
+ // to snap in a schema to ask it for information.
+ krabs::schema schema(record, trace_context.schema_locator);
+
+
+ // We then have the ability to ask a few questions of the event.
+ std::wcout << L"Event " << schema.event_id();
+ std::wcout << L"(" << schema.event_name() << L") received." << std::endl;
+ krabs::parser parser(schema);
+
+ auto extended_data_count = record.ExtendedDataCount;
+ for (USHORT i = 0; i < extended_data_count; i++)
+ {
+ auto& extended_data = record.ExtendedData[i];
+
+ if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_TS_ID)
+ {
+ auto result = (reinterpret_cast<_EVENT_EXTENDED_ITEM_TS_ID*>(extended_data.DataPtr))->SessionId;
+ std::wcout << L"(" << "EVENT_EXTENDED_ITEM_TS_ID" << L") received." << result << std::endl;
+ }
+ if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_SID)
+ {
+
+ }
+ if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY)
+ {
+ auto result = (reinterpret_cast<_EVENT_EXTENDED_ITEM_PROCESS_START_KEY*>(extended_data.DataPtr))->ProcessStartKey;
+ std::wcout << L"(" << "EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY" << L") received." << result << std::endl;
+ }
+ }
+
+ });
+
+
+
+
+}
\ No newline at end of file
diff --git a/test.nuspec b/test.nuspec
new file mode 100644
index 0000000..f406a28
--- /dev/null
+++ b/test.nuspec
@@ -0,0 +1,36 @@
+
+
+
+ first_test_nuget
+ 4.3.7
+ BlueKrabsetw.Native.ETW - managed wrappers for BlueKrabsetw
+ non
+ non
+ MIT
+ https://github.com/threathunters-io/bluekrabsetw
+ false
+ BlueKrabsetw.Native.ETW is a managed wrapper around the BlueKrabsetw ETW library.
+ BlueKrabsetw.Native.ETW is a managed wrapper around the BlueKrabsetw ETW library. It originates from the Microsoft.O365.Security.Native.ETW library and seeks to improve and include capabilities that have not yet been included in the former library.
+
+ Version 4.3.7:
+ - Downgrade to .NET version 4.7.2
+
+ non
+
+ ETW krabs managed cppcli
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
From b200d0eefb986bdfaa0ad7c44174698ee62d7c34 Mon Sep 17 00:00:00 2001
From: Dominik Phillips <153827241+x86phil@users.noreply.github.com>
Date: Mon, 6 May 2024 15:52:24 +0200
Subject: [PATCH 03/15] include: update trace session
---
bluekrabs/krabs/etw.hpp | 117 ++++++++++++++----
bluekrabs/krabs/trace.hpp | 59 ++++++---
.../NativeExamples/NativeExamples.vcxproj | 2 +-
.../NativeExamples.vcxproj.filters | 2 +-
examples/NativeExamples/examples.h | 5 +-
examples/NativeExamples/main.cpp | 3 +-
...provider.cpp => user_trace_015_update.cpp} | 39 +++++-
7 files changed, 180 insertions(+), 47 deletions(-)
rename examples/NativeExamples/{user_trace_015_update_provider.cpp => user_trace_015_update.cpp} (66%)
diff --git a/bluekrabs/krabs/etw.hpp b/bluekrabs/krabs/etw.hpp
index b980be3..00290f7 100644
--- a/bluekrabs/krabs/etw.hpp
+++ b/bluekrabs/krabs/etw.hpp
@@ -95,6 +95,8 @@ namespace krabs { namespace details {
//*/
void disable(const typename T::trace_type::provider_type& p);
+ void update();
+
void update(const typename T::trace_type::provider_type& p);
/**
@@ -109,7 +111,7 @@ namespace krabs { namespace details {
* Queries the ETW trace identified by the info in the trace type v2.
*
*/
- EVENT_TRACE_PROPERTIES_V2 query_v2();
+ trace_info_v2 query_v2();
/**
*
@@ -137,6 +139,7 @@ namespace krabs { namespace details {
void on_event(const EVENT_RECORD &record);
private:
+ trace_info fill_trace_update_info();
trace_info fill_trace_info();
trace_info_v2 fill_trace_info_v2();
EVENT_TRACE_LOGFILE fill_logfile();
@@ -146,7 +149,7 @@ namespace krabs { namespace details {
void close_trace();
void update_trace();
trace_info query_trace();
- EVENT_TRACE_PROPERTIES_V2 query_trace_v2();
+ trace_info_v2 query_trace_v2();
void process_trace();
void enable_providers();
void disable_provider(const typename T::trace_type::provider_type& p);
@@ -171,7 +174,8 @@ namespace krabs { namespace details {
*
*/
template
- static void __stdcall trace_callback_thunk(EVENT_RECORD *pRecord)
+ static void __stdcall trace_callback_thunk(
+ EVENT_RECORD *pRecord)
{
auto *pUserTrace = (T*)(pRecord->UserContext);
trace_manager trace(*pUserTrace);
@@ -191,7 +195,8 @@ namespace krabs { namespace details {
*
*/
template
- static ULONG __stdcall trace_buffer_callback(EVENT_TRACE_LOGFILE *pLogFile)
+ static ULONG __stdcall trace_buffer_callback(
+ EVENT_TRACE_LOGFILE *pLogFile)
{
auto *pTrace = (T*)(pLogFile->Context);
trace_manager trace(*pTrace);
@@ -230,7 +235,18 @@ namespace krabs { namespace details {
}
template
- void trace_manager::update(const typename T::trace_type::provider_type& p)
+ void trace_manager::update()
+ {
+ if (trace_.sessionHandle_ == INVALID_PROCESSTRACE_HANDLE) {
+ throw open_trace_failure();
+ }
+
+ update_trace();
+ }
+
+ template
+ void trace_manager::update(
+ const typename T::trace_type::provider_type& p)
{
if (trace_.sessionHandle_ == INVALID_PROCESSTRACE_HANDLE) {
throw open_trace_failure();
@@ -240,7 +256,8 @@ namespace krabs { namespace details {
}
template
- void trace_manager::disable(const typename T::trace_type::provider_type& p)
+ void trace_manager::disable(
+ const typename T::trace_type::provider_type& p)
{
if (trace_.sessionHandle_ == INVALID_PROCESSTRACE_HANDLE) {
throw open_trace_failure();
@@ -256,7 +273,7 @@ namespace krabs { namespace details {
}
template
- EVENT_TRACE_PROPERTIES_V2 trace_manager::query_v2()
+ trace_info_v2 trace_manager::query_v2()
{
return query_trace();
}
@@ -388,10 +405,59 @@ namespace krabs { namespace details {
}
}
+ template
+ trace_info trace_manager::fill_trace_update_info()
+ {
+ trace_info info = query_trace();
+
+ /*
+ EnableFlags: Set this member to 0 to disable all kernel providers.
+ Otherwise, you must specify the kernel providers that you want to
+ enable or keep enabled. Applies only to system logger sessions.
+
+ FlushTimer: Set this member if you want to change the time to wait
+ before flushing buffers. If this member is 0, the member is not
+ updated.
+
+ LogFileNameOffset: Set this member if you want to switch to another
+ log file. If this member is 0, the file name is not updated. If the
+ offset is not zero and you do not change the log file name, the
+ function returns an error.
+
+ LogFileMode: Set this member if you want to turn
+ EVENT_TRACE_REAL_TIME_MODE on and off. To turn real time consuming
+ off, set this member to 0. To turn real time consuming on, set
+ this member to EVENT_TRACE_REAL_TIME_MODE and it will be OR'd with
+ the current modes.
+
+ MaximumBuffers: Set this member if you want to change the maximum
+ number of buffers that ETW uses. If this member is 0, the member
+ is not updated.
+ */
+ if (auto enable_flags = T::trace_type::construct_enable_flags(trace_)) {
+ info.properties.EnableFlags = enable_flags;
+ }
+
+ if (trace_.properties_.FlushTimer) {
+ info.properties.FlushTimer = trace_.properties_.FlushTimer;
+ }
+
+ if (trace_.properties_.LogFileMode) {
+ info.properties.LogFileMode = trace_.properties_.LogFileMode;
+ }
+
+ if (trace_.properties_.MaximumBuffers) {
+ info.properties.MaximumBuffers = trace_.properties_.MaximumBuffers;
+ }
+
+ return info;
+ }
+
template
void trace_manager::update_trace()
{
- trace_info info = fill_trace_info();
+ auto info = fill_trace_update_info();
+
ULONG status = ControlTrace(
NULL,
trace_.name_.c_str(),
@@ -407,7 +473,7 @@ namespace krabs { namespace details {
trace_info trace_manager::query_trace()
{
//trace_info info = fill_trace_info();
- trace_info info = {};
+ trace_info info = {};
info.properties.Wnode.BufferSize = sizeof(trace_info);
ULONG status = ControlTrace(
@@ -419,7 +485,6 @@ namespace krabs { namespace details {
if (status != ERROR_WMI_INSTANCE_NOT_FOUND) {
error_check_common_conditions(status);
-
//return info.properties;
return info;
}
@@ -428,7 +493,7 @@ namespace krabs { namespace details {
}
template
- EVENT_TRACE_PROPERTIES_V2 trace_manager::query_trace_v2()
+ trace_info_v2 trace_manager::query_trace_v2()
{
if (IsWindowsVersionOrGreater(10, 0, 15063)) {
error_check_common_conditions(ERROR_NOT_SUPPORTED);
@@ -436,20 +501,20 @@ namespace krabs { namespace details {
return { };
}
- trace_info_v2 info = fill_trace_info_v2();
-
- ULONG status = ControlTrace(
- NULL,
- trace_.name_.c_str(),
- //info,
- &info.properties,
- EVENT_TRACE_CONTROL_QUERY);
+ trace_info_v2 info = {};
- if (status != ERROR_WMI_INSTANCE_NOT_FOUND) {
- error_check_common_conditions(status);
+ //ULONG status = ControlTrace(
+ // NULL,
+ // trace_.name_.c_str(),
+ // //info,
+ // &info.properties,
+ // EVENT_TRACE_CONTROL_QUERY);
- return info.properties;
- }
+ //if (status != ERROR_WMI_INSTANCE_NOT_FOUND) {
+ // error_check_common_conditions(status);
+ // //return info.properties;
+ // return info;
+ //}
return { };
}
@@ -562,13 +627,15 @@ namespace krabs { namespace details {
}
template
- void trace_manager::disable_provider(const typename T::trace_type::provider_type& p)
+ void trace_manager::disable_provider(
+ const typename T::trace_type::provider_type& p)
{
T::trace_type::disable_provider(trace_, p);
}
template
- void trace_manager::update_provider(const typename T::trace_type::provider_type& p)
+ void trace_manager::update_provider(
+ const typename T::trace_type::provider_type& p)
{
if (trace_.registrationHandle_ == INVALID_PROCESSTRACE_HANDLE) {
trace_.properties_ = query_trace().properties;
diff --git a/bluekrabs/krabs/trace.hpp b/bluekrabs/krabs/trace.hpp
index a78c885..5a6e6c6 100644
--- a/bluekrabs/krabs/trace.hpp
+++ b/bluekrabs/krabs/trace.hpp
@@ -33,8 +33,7 @@ namespace krabs {
* Selected statistics about an ETW trace
*
*/
- class trace_stats
- {
+ class trace_stats {
public:
const uint32_t buffersCount;
const uint32_t buffersFree;
@@ -60,25 +59,31 @@ namespace krabs {
* Selected statistics about an ETW trace
*
*/
- class trace_config
- {
+ class trace_config {
public:
- const uint64_t log_file_mode;
- const uint64_t flush_timer;
- const uint64_t enable_flags;
+ const uint32_t buffer_size;
+ const uint32_t minimum_buffers;
+ const uint32_t maximum_buffers;
+ const uint32_t maximum_file_size;
+ const uint32_t log_file_mode;
+ const uint32_t flush_timer;
+ const uint32_t enable_flags;
const std::wstring log_file_name;
const std::wstring logger_name;
-
-
+ const uint32_t flush_threshold;
+
trace_config(const details::trace_info& props)
- : log_file_mode(props.properties.LogFileMode)
+ : buffer_size(props.properties.BufferSize)
+ , minimum_buffers(props.properties.MinimumBuffers)
+ , maximum_buffers(props.properties.MaximumBuffers)
+ , maximum_file_size(props.properties.MaximumFileSize)
+ , log_file_mode(props.properties.LogFileMode)
, flush_timer(props.properties.FlushTimer)
, enable_flags(props.properties.EnableFlags)
+ , flush_threshold(props.properties.FlushThreshold)
, logger_name(props.traceName)
, log_file_name(props.logfileName)
- {
-
- }
+ { }
};
@@ -193,6 +198,20 @@ namespace krabs {
*/
void set_trace_filename(const std::wstring& filename);
+ /**
+ *
+ * Update the session configuration so that the session receives
+ * the requested events from the provider.
+ *
+ *
+ * krabs::trace trace;
+ * krabs::guid id(L"{A0C1853B-5C40-4B15-8766-3CF1C58F985A}");
+ * provider<> powershell(id);
+ * trace.enable(powershell);
+ *
+ */
+ void update();
+
/**
*
* Update the session configuration so that the session receives
@@ -361,7 +380,7 @@ namespace krabs {
// * todo
// *
// */
- void update(const typename T::provider_type& p);
+ void update_provider(const typename T::provider_type& p);
private:
std::wstring name_;
@@ -434,6 +453,7 @@ namespace krabs {
template
void trace::set_trace_properties(const PEVENT_TRACE_PROPERTIES properties)
{
+ properties_ = {};
properties_.BufferSize = properties->BufferSize;
properties_.MinimumBuffers = properties->MinimumBuffers;
properties_.MaximumBuffers = properties->MaximumBuffers;
@@ -486,7 +506,7 @@ namespace krabs {
}
}
- update(p);
+ update_provider(p);
}
template
@@ -498,7 +518,7 @@ namespace krabs {
}
template
- void trace::update(const typename T::provider_type& p)
+ void trace::update_provider(const typename T::provider_type& p)
{
details::trace_manager manager(*this);
manager.update(p);
@@ -544,6 +564,13 @@ namespace krabs {
manager.process();
}
+ template
+ void trace::update()
+ {
+ details::trace_manager manager(*this);
+ manager.update();
+ }
+
template
trace_stats trace::query_stats()
{
diff --git a/examples/NativeExamples/NativeExamples.vcxproj b/examples/NativeExamples/NativeExamples.vcxproj
index 56a8c98..de25fc7 100644
--- a/examples/NativeExamples/NativeExamples.vcxproj
+++ b/examples/NativeExamples/NativeExamples.vcxproj
@@ -173,7 +173,7 @@
-
+
diff --git a/examples/NativeExamples/NativeExamples.vcxproj.filters b/examples/NativeExamples/NativeExamples.vcxproj.filters
index d7645ab..e4a7240 100644
--- a/examples/NativeExamples/NativeExamples.vcxproj.filters
+++ b/examples/NativeExamples/NativeExamples.vcxproj.filters
@@ -73,7 +73,7 @@
Source Files
-
+
Source Files
diff --git a/examples/NativeExamples/examples.h b/examples/NativeExamples/examples.h
index 27ca68e..ec1eb6b 100644
--- a/examples/NativeExamples/examples.h
+++ b/examples/NativeExamples/examples.h
@@ -105,7 +105,8 @@ struct user_trace_014_transition_trace
static void start();
};
-struct user_trace_015_update_provider
+struct user_trace_015_update
{
- static void start();
+ static void start1();
+ static void start2();
};
\ No newline at end of file
diff --git a/examples/NativeExamples/main.cpp b/examples/NativeExamples/main.cpp
index cbac172..d27aca3 100644
--- a/examples/NativeExamples/main.cpp
+++ b/examples/NativeExamples/main.cpp
@@ -27,5 +27,6 @@ int main(void)
//user_trace_011_search_wevt::start();
//user_trace_012_open_trace::start();
//user_trace_013_pktmon::start();
- user_trace_014_transition_trace::start();
+ //user_trace_014_transition_trace::start();
+ user_trace_015_update::start2();
}
\ No newline at end of file
diff --git a/examples/NativeExamples/user_trace_015_update_provider.cpp b/examples/NativeExamples/user_trace_015_update.cpp
similarity index 66%
rename from examples/NativeExamples/user_trace_015_update_provider.cpp
rename to examples/NativeExamples/user_trace_015_update.cpp
index 62a131c..0dcbfd6 100644
--- a/examples/NativeExamples/user_trace_015_update_provider.cpp
+++ b/examples/NativeExamples/user_trace_015_update.cpp
@@ -12,13 +12,16 @@
-void user_trace_015_update_provider::start()
+void user_trace_015_update::start1()
{
krabs::user_trace trace(L"test_sense");
krabs::provider<> provider(krabs::guid(L"{16c6501a-ff2d-46ea-868d-8f96cb0cb52d}"));
+
+
+
provider.enable_property(provider.enable_property() | EVENT_ENABLE_PROPERTY_PROCESS_START_KEY | EVENT_ENABLE_PROPERTY_SID | EVENT_ENABLE_PROPERTY_TS_ID);
provider.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
@@ -59,4 +62,38 @@ void user_trace_015_update_provider::start()
+}
+
+void user_trace_015_update::start2()
+{
+
+ krabs::user_trace trace(L"test_sense");
+ /*std::thread workerThread([&]() {
+ trace.start();
+ });*/
+ //Sleep(1000);
+ auto tmp = trace.query_config();
+ std::cout << "current config:" << std::endl;
+ std::cout << "min buffer:" << tmp.minimum_buffers << std::endl;
+ std::cout << "max buffer:" << tmp.maximum_buffers << std::endl;
+ std::cout << "max flush:" << tmp.flush_timer << std::endl;
+ Sleep(1000);
+
+
+ trace.open();
+
+ EVENT_TRACE_PROPERTIES etp = {};
+ //etp.MinimumBuffers = 32;
+ etp.MaximumBuffers = 128;
+ etp.FlushTimer = 10;
+ trace.set_trace_properties(&etp);
+ trace.update();
+ auto tmp2 = trace.query_config();
+
+ std::cout << "new config:" << std::endl;
+ std::cout << "min buffer:" << tmp2.minimum_buffers << std::endl;
+ std::cout << "max buffer:" << tmp2.maximum_buffers << std::endl;
+ std::cout << "max flush:" << tmp2.flush_timer << std::endl;
+ //trace.stop();
+ //workerThread.join();
}
\ No newline at end of file
From fe9ffc5da59d924e18d627a6ac3ace9ea14f9f01 Mon Sep 17 00:00:00 2001
From: Dominik Phillips <153827241+x86phil@users.noreply.github.com>
Date: Tue, 7 May 2024 09:36:02 +0200
Subject: [PATCH 04/15] include: decouple stop and close session
---
bluekrabs/krabs/etw.hpp | 13 ++++
bluekrabs/krabs/trace.hpp | 35 +++++++++--
examples/NativeExamples/main.cpp | 4 +-
.../user_trace_012_open_trace.cpp | 10 +++-
.../NativeExamples/user_trace_015_update.cpp | 60 +++++++++++++++++--
5 files changed, 109 insertions(+), 13 deletions(-)
diff --git a/bluekrabs/krabs/etw.hpp b/bluekrabs/krabs/etw.hpp
index 00290f7..a5e6a51 100644
--- a/bluekrabs/krabs/etw.hpp
+++ b/bluekrabs/krabs/etw.hpp
@@ -70,6 +70,13 @@ namespace krabs { namespace details {
*/
void stop();
+ /**
+ *
+ * Stops the ETW trace identified by the info in the trace type.
+ *
+ */
+ void close();
+
/**
*
* Opens the ETW trace identified by the info in the trace type.
@@ -300,6 +307,12 @@ namespace krabs { namespace details {
close_trace();
}
+ template
+ void trace_manager::close()
+ {
+ close_trace();
+ }
+
template
void trace_manager::set_buffers_processed(size_t processed)
{
diff --git a/bluekrabs/krabs/trace.hpp b/bluekrabs/krabs/trace.hpp
index 5a6e6c6..081a3d2 100644
--- a/bluekrabs/krabs/trace.hpp
+++ b/bluekrabs/krabs/trace.hpp
@@ -269,9 +269,22 @@ namespace krabs {
* trace.stop();
*
*/
- void stop();
+ void stop(bool force = false);
-
+ /**
+ *
+ * Closes a trace session.
+ *
+ *
+ * krabs::trace trace;
+ * krabs::guid id(L"{A0C1853B-5C40-4B15-8766-3CF1C58F985A}");
+ * provider<> powershell(id);
+ * trace.enable(powershell);
+ * trace.start();
+ * trace.stop();
+ *
+ */
+ void close();
/**
*
@@ -448,6 +461,9 @@ namespace krabs {
if (!non_stoppable_) {
stop();
}
+ else {
+ close();
+ }
}
template
@@ -500,7 +516,7 @@ namespace krabs {
- if (it != enabled_providers_.end()) {
+ if (it == enabled_providers_.end()) {
enabled_providers_.push_back(std::ref(p));
return;
}
@@ -534,10 +550,19 @@ namespace krabs {
}
template
- void trace::stop()
+ void trace::stop(bool force)
+ {
+ if (!non_stoppable_ || force) {
+ details::trace_manager manager(*this);
+ manager.stop();
+ }
+ }
+
+ template
+ void trace::close()
{
details::trace_manager manager(*this);
- manager.stop();
+ manager.close();
}
template
diff --git a/examples/NativeExamples/main.cpp b/examples/NativeExamples/main.cpp
index d27aca3..20c9da2 100644
--- a/examples/NativeExamples/main.cpp
+++ b/examples/NativeExamples/main.cpp
@@ -25,8 +25,8 @@ int main(void)
//user_trace_009_from_file::start2();
//user_trace_010_direct_filter::start();
//user_trace_011_search_wevt::start();
- //user_trace_012_open_trace::start();
+ user_trace_012_open_trace::start();
//user_trace_013_pktmon::start();
//user_trace_014_transition_trace::start();
- user_trace_015_update::start2();
+ //user_trace_015_update::start2();
}
\ No newline at end of file
diff --git a/examples/NativeExamples/user_trace_012_open_trace.cpp b/examples/NativeExamples/user_trace_012_open_trace.cpp
index 5c6fb86..64b1910 100644
--- a/examples/NativeExamples/user_trace_012_open_trace.cpp
+++ b/examples/NativeExamples/user_trace_012_open_trace.cpp
@@ -54,11 +54,19 @@ void user_trace_012_open_trace::start()
trace.enable(provider);
trace.open();
+ //trace.process();
std::thread workerThread([&]() {
trace.process();
});
- trace.stop();
+ const int durationInSeconds = 30;
+ std::this_thread::sleep_for(std::chrono::seconds(durationInSeconds));
+ trace.close();
+
+ workerThread.join();
+
+ //workerThread.join();
+
//trace.update(provider);
}
\ No newline at end of file
diff --git a/examples/NativeExamples/user_trace_015_update.cpp b/examples/NativeExamples/user_trace_015_update.cpp
index 0dcbfd6..374dd5e 100644
--- a/examples/NativeExamples/user_trace_015_update.cpp
+++ b/examples/NativeExamples/user_trace_015_update.cpp
@@ -68,6 +68,49 @@ void user_trace_015_update::start2()
{
krabs::user_trace trace(L"test_sense");
+
+ krabs::provider<> provider(krabs::guid(L"{16c6501a-ff2d-46ea-868d-8f96cb0cb52d}"));
+
+ //provider.enable_property(provider.enable_property() | EVENT_ENABLE_PROPERTY_PROCESS_START_KEY | EVENT_ENABLE_PROPERTY_SID | EVENT_ENABLE_PROPERTY_TS_ID);
+
+ provider.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+
+ // Once an event is received, if we want krabs to help us analyze it, we need
+ // to snap in a schema to ask it for information.
+ krabs::schema schema(record, trace_context.schema_locator);
+
+
+ // We then have the ability to ask a few questions of the event.
+ std::wcout << L"Event " << schema.event_id();
+ std::wcout << L"(" << schema.event_name() << L") received." << std::endl;
+ krabs::parser parser(schema);
+
+ /*auto extended_data_count = record.ExtendedDataCount;
+ for (USHORT i = 0; i < extended_data_count; i++)
+ {
+ auto& extended_data = record.ExtendedData[i];
+
+ if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_TS_ID)
+ {
+ auto result = (reinterpret_cast<_EVENT_EXTENDED_ITEM_TS_ID*>(extended_data.DataPtr))->SessionId;
+ std::wcout << L"(" << "EVENT_EXTENDED_ITEM_TS_ID" << L") received." << result << std::endl;
+ }
+ if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_SID)
+ {
+
+ }
+ if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY)
+ {
+ auto result = (reinterpret_cast<_EVENT_EXTENDED_ITEM_PROCESS_START_KEY*>(extended_data.DataPtr))->ProcessStartKey;
+ std::wcout << L"(" << "EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY" << L") received." << result << std::endl;
+ }
+ }*/
+
+
+ });
+
+ trace.enable(provider);
+
/*std::thread workerThread([&]() {
trace.start();
});*/
@@ -77,7 +120,7 @@ void user_trace_015_update::start2()
std::cout << "min buffer:" << tmp.minimum_buffers << std::endl;
std::cout << "max buffer:" << tmp.maximum_buffers << std::endl;
std::cout << "max flush:" << tmp.flush_timer << std::endl;
- Sleep(1000);
+
trace.open();
@@ -87,13 +130,20 @@ void user_trace_015_update::start2()
etp.MaximumBuffers = 128;
etp.FlushTimer = 10;
trace.set_trace_properties(&etp);
- trace.update();
+ //trace.update();
auto tmp2 = trace.query_config();
-
+ std::thread workerThread([&]() {
+ trace.process();
+ });
std::cout << "new config:" << std::endl;
std::cout << "min buffer:" << tmp2.minimum_buffers << std::endl;
std::cout << "max buffer:" << tmp2.maximum_buffers << std::endl;
std::cout << "max flush:" << tmp2.flush_timer << std::endl;
- //trace.stop();
- //workerThread.join();
+
+ const int durationInSeconds = 30;
+ std::this_thread::sleep_for(std::chrono::seconds(durationInSeconds));
+ trace.enable(provider);
+ trace.stop();
+
+ workerThread.join();
}
\ No newline at end of file
From a6ff52786efc44db449547acbbb8b34bd96a99dd Mon Sep 17 00:00:00 2001
From: Dominik Phillips <153827241+x86phil@users.noreply.github.com>
Date: Fri, 24 May 2024 14:42:52 +0200
Subject: [PATCH 05/15] update: close
---
bluekrabs/krabs/etw.hpp | 30 +++++++++++++++++++++---------
1 file changed, 21 insertions(+), 9 deletions(-)
diff --git a/bluekrabs/krabs/etw.hpp b/bluekrabs/krabs/etw.hpp
index a5e6a51..4346d20 100644
--- a/bluekrabs/krabs/etw.hpp
+++ b/bluekrabs/krabs/etw.hpp
@@ -72,7 +72,9 @@ namespace krabs { namespace details {
/**
*
- * Stops the ETW trace identified by the info in the trace type.
+ * Close the ETW trace identified by the info in the trace type.
+ * In conjunction with stopping, closing detaches a consumer
+ * from an active trace session but does not terminate the session.
*
*/
void close();
@@ -92,18 +94,28 @@ namespace krabs { namespace details {
*/
void process();
-
-
- ///**
- //*
- //* Starts processing the ETW trace identified by the info in the trace type.
- //* open() needs to called for this to work first.
- //*
- //*/
+ /**
+ *
+ * Starts processing the ETW trace identified by the info in the trace type.
+ * open() needs to called for this to work first.
+ *
+ */
void disable(const typename T::trace_type::provider_type& p);
+ /**
+ *
+ * Starts processing the ETW trace identified by the info in the trace type.
+ * open() needs to called for this to work first.
+ *
+ */
void update();
+ /**
+ *
+ * Starts processing the ETW trace identified by the info in the trace type.
+ * open() needs to called for this to work first.
+ *
+ */
void update(const typename T::trace_type::provider_type& p);
/**
From 2420d21fc7efc1a277354b796082f0fcf0f67234 Mon Sep 17 00:00:00 2001
From: Dominik Phillips <153827241+x86phil@users.noreply.github.com>
Date: Thu, 4 Jul 2024 15:20:25 +0200
Subject: [PATCH 06/15] new example added
---
.../user_trace_012_open_trace.cpp | 110 +++++++++++-------
1 file changed, 69 insertions(+), 41 deletions(-)
diff --git a/examples/NativeExamples/user_trace_012_open_trace.cpp b/examples/NativeExamples/user_trace_012_open_trace.cpp
index 64b1910..8e66b14 100644
--- a/examples/NativeExamples/user_trace_012_open_trace.cpp
+++ b/examples/NativeExamples/user_trace_012_open_trace.cpp
@@ -8,65 +8,93 @@
#include "..\..\bluekrabs\krabs.hpp"
#include "examples.h"
+//
+//void user_trace_012_open_trace::start()
+//{
+// krabs::user_trace trace(L"test_sense");
+// krabs::provider<> provider(krabs::guid(L"{16c6501a-ff2d-46ea-868d-8f96cb0cb52d}"));
+//
+// //provider.enable_property(provider.enable_property() | EVENT_ENABLE_PROPERTY_PROCESS_START_KEY | EVENT_ENABLE_PROPERTY_SID | EVENT_ENABLE_PROPERTY_TS_ID);
+//
+// provider.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+//
+// // Once an event is received, if we want krabs to help us analyze it, we need
+// // to snap in a schema to ask it for information.
+// krabs::schema schema(record, trace_context.schema_locator);
+//
+//
+// // We then have the ability to ask a few questions of the event.
+// std::wcout << L"Event " << schema.event_id();
+// std::wcout << L"(" << schema.event_name() << L") received." << std::endl;
+// krabs::parser parser(schema);
+//
+// /*auto extended_data_count = record.ExtendedDataCount;
+// for (USHORT i = 0; i < extended_data_count; i++)
+// {
+// auto& extended_data = record.ExtendedData[i];
+//
+// if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_TS_ID)
+// {
+// auto result = (reinterpret_cast<_EVENT_EXTENDED_ITEM_TS_ID*>(extended_data.DataPtr))->SessionId;
+// std::wcout << L"(" << "EVENT_EXTENDED_ITEM_TS_ID" << L") received." << result << std::endl;
+// }
+// if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_SID)
+// {
+//
+// }
+// if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY)
+// {
+// auto result = (reinterpret_cast<_EVENT_EXTENDED_ITEM_PROCESS_START_KEY*>(extended_data.DataPtr))->ProcessStartKey;
+// std::wcout << L"(" << "EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY" << L") received." << result << std::endl;
+// }
+// }*/
+//
+//
+// });
+//
+// trace.enable(provider);
+// trace.open();
+// //trace.process();
+// std::thread workerThread([&]() {
+// trace.process();
+// });
+//
+// const int durationInSeconds = 30;
+// std::this_thread::sleep_for(std::chrono::seconds(durationInSeconds));
+// trace.close();
+//
+// workerThread.join();
+//
+// //workerThread.join();
+//
+// //trace.update(provider);
+//
+//}
void user_trace_012_open_trace::start()
{
- krabs::user_trace trace(L"test_sense");
- krabs::provider<> provider(krabs::guid(L"{16c6501a-ff2d-46ea-868d-8f96cb0cb52d}"));
-
- //provider.enable_property(provider.enable_property() | EVENT_ENABLE_PROPERTY_PROCESS_START_KEY | EVENT_ENABLE_PROPERTY_SID | EVENT_ENABLE_PROPERTY_TS_ID);
+ krabs::user_trace trace(L"DefenderApiLogger");
+ krabs::provider<> provider(krabs::guid(L"{f4e1897c-bb5d-5668-f1d8-040f4d8dd344}"));
provider.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
// Once an event is received, if we want krabs to help us analyze it, we need
// to snap in a schema to ask it for information.
krabs::schema schema(record, trace_context.schema_locator);
-
-
// We then have the ability to ask a few questions of the event.
- std::wcout << L"Event " << schema.event_id();
- std::wcout << L"(" << schema.event_name() << L") received." << std::endl;
- krabs::parser parser(schema);
-
- /*auto extended_data_count = record.ExtendedDataCount;
- for (USHORT i = 0; i < extended_data_count; i++)
- {
- auto& extended_data = record.ExtendedData[i];
-
- if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_TS_ID)
- {
- auto result = (reinterpret_cast<_EVENT_EXTENDED_ITEM_TS_ID*>(extended_data.DataPtr))->SessionId;
- std::wcout << L"(" << "EVENT_EXTENDED_ITEM_TS_ID" << L") received." << result << std::endl;
- }
- if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_SID)
- {
-
- }
- if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY)
- {
- auto result = (reinterpret_cast<_EVENT_EXTENDED_ITEM_PROCESS_START_KEY*>(extended_data.DataPtr))->ProcessStartKey;
- std::wcout << L"(" << "EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY" << L") received." << result << std::endl;
- }
- }*/
-
-
- });
+ std::wcout << L"ProviderName " << schema.provider_name() << std::endl;
+ std::wcout << L"EventId" << schema.event_id() << std::endl;
+ });
trace.enable(provider);
trace.open();
- //trace.process();
+
std::thread workerThread([&]() {
trace.process();
});
-
+
const int durationInSeconds = 30;
std::this_thread::sleep_for(std::chrono::seconds(durationInSeconds));
trace.close();
-
workerThread.join();
-
- //workerThread.join();
-
- //trace.update(provider);
-
}
\ No newline at end of file
From 20aa898793d4fb021b5f9aaf4ac31356a67012f9 Mon Sep 17 00:00:00 2001
From: Dominik Phillips
Date: Thu, 4 Jul 2024 15:49:44 +0200
Subject: [PATCH 07/15] update sln file
---
bluekrabs/bluekrabs.sln | 70 ++++++++++++++++++++---------------------
1 file changed, 35 insertions(+), 35 deletions(-)
diff --git a/bluekrabs/bluekrabs.sln b/bluekrabs/bluekrabs.sln
index c173def..7bb39f1 100644
--- a/bluekrabs/bluekrabs.sln
+++ b/bluekrabs/bluekrabs.sln
@@ -20,12 +20,27 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
MTA.testsettings = MTA.testsettings
EndProjectSection
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bluekrabs headers", "bluekrabs headers", "{1FD19105-D67C-492B-B98F-53E00A324269}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EtwTestsCS", "..\tests\ManagedETWTests\EtwTestsCS.csproj", "{600CFE03-FD84-4323-9439-839D81C31972}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{C4AB7F5F-2FB3-4C16-A1F3-F6700C655B02}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{2E00634C-7E8B-4656-9505-78FF2F5D0EDD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ManagedExamples", "..\examples\ManagedExamples\ManagedExamples.csproj", "{32E71DD0-D11A-44DE-8CA8-572995AF2373}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NativeExamples", "..\examples\NativeExamples\NativeExamples.vcxproj", "{D31B1A4B-8282-4AED-99FC-9AA5974B9134}"
+ ProjectSection(ProjectDependencies) = postProject
+ {ED4E6027-541F-440A-A5EE-15DBB7B89423} = {ED4E6027-541F-440A-A5EE-15DBB7B89423}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Threathunters.BlueKrabsetw.Native.ETW.NetCore", "..\Threathunters.BlueKrabsetw.Native.ETW.NetCore\Microsoft.O365.Security.Native.ETW.NetCore.vcxproj", "{9DE6788C-5759-4A75-B484-ABA4C7EF5F08}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bluekrabs headers", "bluekrabs headers", "{60104949-C1E9-45B1-A37A-2A0EE5F94E1B}"
ProjectSection(SolutionItems) = preProject
krabs.hpp = krabs.hpp
EndProjectSection
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bluekrabs", "bluekrabs", "{371361C8-96EC-4D6D-B80B-2E47E3453264}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bluekrabs", "bluekrabs", "{6345EFAF-43BD-42DE-9B8D-8D955E0C1FDC}"
ProjectSection(SolutionItems) = preProject
krabs\client.hpp = krabs\client.hpp
krabs\collection_view.hpp = krabs\collection_view.hpp
@@ -53,7 +68,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bluekrabs", "bluekrabs", "{
krabs\wstring_convert.hpp = krabs\wstring_convert.hpp
EndProjectSection
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "filtering", "filtering", "{96FA58B5-A1F6-4107-9FB4-226290F9D696}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "filtering", "filtering", "{DE5DA5AA-BA9F-4D07-AF37-E1CE1487217C}"
ProjectSection(SolutionItems) = preProject
krabs\filtering\comparers.hpp = krabs\filtering\comparers.hpp
krabs\filtering\direct_event_filter.hpp = krabs\filtering\direct_event_filter.hpp
@@ -62,7 +77,18 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "filtering", "filtering", "{
krabs\filtering\view_adapters.hpp = krabs\filtering\view_adapters.hpp
EndProjectSection
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testing", "testing", "{9ED1AE76-2EAA-4CCF-8F01-458BDC8BCD53}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "helping", "helping", "{531AF202-7C02-4203-9463-F10DE8A996AD}"
+ProjectSection(SolutionItems) = preProject
+ krabs\helping\file_mapping.hpp = krabs\helping\file_mapping.hpp
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "searching", "searching", "{2C63BA17-1E15-4B5B-B979-A00C3A331678}"
+ProjectSection(SolutionItems) = preProject
+ discover.hpp = discover.hpp
+ krabs\searching\wevt.hpp = krabs\searching\wevt.hpp
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testing", "testing", "{9EBF97B2-137A-42F1-830F-E644C9590C33}"
ProjectSection(SolutionItems) = preProject
krabs\testing\event_filter_proxy.hpp = krabs\testing\event_filter_proxy.hpp
krabs\testing\extended_data_builder.hpp = krabs\testing\extended_data_builder.hpp
@@ -73,32 +99,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testing", "testing", "{9ED1
krabs\testing\synth_record.hpp = krabs\testing\synth_record.hpp
EndProjectSection
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EtwTestsCS", "..\tests\ManagedETWTests\EtwTestsCS.csproj", "{600CFE03-FD84-4323-9439-839D81C31972}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{C4AB7F5F-2FB3-4C16-A1F3-F6700C655B02}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{2E00634C-7E8B-4656-9505-78FF2F5D0EDD}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ManagedExamples", "..\examples\ManagedExamples\ManagedExamples.csproj", "{32E71DD0-D11A-44DE-8CA8-572995AF2373}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NativeExamples", "..\examples\NativeExamples\NativeExamples.vcxproj", "{D31B1A4B-8282-4AED-99FC-9AA5974B9134}"
- ProjectSection(ProjectDependencies) = postProject
- {ED4E6027-541F-440A-A5EE-15DBB7B89423} = {ED4E6027-541F-440A-A5EE-15DBB7B89423}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Threathunters.BlueKrabsetw.Native.ETW.NetCore", "..\Threathunters.BlueKrabsetw.Native.ETW.NetCore\Microsoft.O365.Security.Native.ETW.NetCore.vcxproj", "{9DE6788C-5759-4A75-B484-ABA4C7EF5F08}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "searching", "searching", "{03BCA2C2-F363-45B0-8745-E193BFBD54C5}"
- ProjectSection(SolutionItems) = preProject
- discover.hpp = discover.hpp
- krabs\searching\wevt.hpp = krabs\searching\wevt.hpp
- EndProjectSection
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "helping", "helping", "{40378D85-BA5E-4FA1-A450-44BFA680B203}"
- ProjectSection(SolutionItems) = preProject
- krabs\helping\file_mapping.hpp = krabs\helping\file_mapping.hpp
- EndProjectSection
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -161,14 +161,14 @@ Global
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{880977B8-15CA-421B-BF48-D01626A530A2} = {C4AB7F5F-2FB3-4C16-A1F3-F6700C655B02}
- {371361C8-96EC-4D6D-B80B-2E47E3453264} = {1FD19105-D67C-492B-B98F-53E00A324269}
- {96FA58B5-A1F6-4107-9FB4-226290F9D696} = {371361C8-96EC-4D6D-B80B-2E47E3453264}
- {9ED1AE76-2EAA-4CCF-8F01-458BDC8BCD53} = {371361C8-96EC-4D6D-B80B-2E47E3453264}
{600CFE03-FD84-4323-9439-839D81C31972} = {C4AB7F5F-2FB3-4C16-A1F3-F6700C655B02}
{32E71DD0-D11A-44DE-8CA8-572995AF2373} = {2E00634C-7E8B-4656-9505-78FF2F5D0EDD}
{D31B1A4B-8282-4AED-99FC-9AA5974B9134} = {2E00634C-7E8B-4656-9505-78FF2F5D0EDD}
- {03BCA2C2-F363-45B0-8745-E193BFBD54C5} = {371361C8-96EC-4D6D-B80B-2E47E3453264}
- {40378D85-BA5E-4FA1-A450-44BFA680B203} = {371361C8-96EC-4D6D-B80B-2E47E3453264}
+ {6345EFAF-43BD-42DE-9B8D-8D955E0C1FDC} = {60104949-C1E9-45B1-A37A-2A0EE5F94E1B}
+ {DE5DA5AA-BA9F-4D07-AF37-E1CE1487217C} = {6345EFAF-43BD-42DE-9B8D-8D955E0C1FDC}
+ {531AF202-7C02-4203-9463-F10DE8A996AD} = {6345EFAF-43BD-42DE-9B8D-8D955E0C1FDC}
+ {2C63BA17-1E15-4B5B-B979-A00C3A331678} = {6345EFAF-43BD-42DE-9B8D-8D955E0C1FDC}
+ {9EBF97B2-137A-42F1-830F-E644C9590C33} = {6345EFAF-43BD-42DE-9B8D-8D955E0C1FDC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {82BAA012-2EF9-4303-A429-CDA3655D5009}
From 22c23bb45f6a159e0922f440663ba9cf6d595dbf Mon Sep 17 00:00:00 2001
From: Dominik Phillips
Date: Wed, 17 Jul 2024 17:17:20 +0200
Subject: [PATCH 08/15] includes: provider add, remove, and update capabilities
propagated some of the functionality to the managed layer
---
...t.O365.Security.Native.ETW.NetCore.vcxproj | 1 +
.../Filtering/PreEventfilter.hpp | 171 ++++++
.../ITrace.hpp | 22 +
.../KernelTrace.hpp | 17 +
...Microsoft.O365.Security.Native.ETW.vcxproj | 1 +
...t.O365.Security.Native.ETW.vcxproj.filters | 3 +
.../Provider.hpp | 15 +-
.../UserTrace.hpp | 50 ++
bluekrabs/bluekrabs.sln | 7 +-
bluekrabs/krabs.hpp | 3 +-
bluekrabs/krabs/etw.hpp | 16 +-
.../krabs/filtering/direct_event_filter.hpp | 20 +-
.../krabs/filtering/post_event_filter.hpp | 0
.../krabs/filtering/pre_event_filter.hpp | 254 +++++++++
bluekrabs/krabs/kt.hpp | 6 +-
bluekrabs/krabs/provider.hpp | 19 +-
bluekrabs/krabs/trace.hpp | 86 +--
bluekrabs/krabs/ut.hpp | 509 +++---------------
examples/ManagedExamples/Program.cs | 4 +-
.../UserTrace008_DirecFilter.cs | 36 +-
.../NativeExamples/NativeExamples.vcxproj | 3 +-
.../NativeExamples.vcxproj.filters | 5 +-
examples/NativeExamples/examples.h | 7 +-
examples/NativeExamples/main.cpp | 4 +-
.../NativeExamples/user_trace_007_rundown.cpp | 207 -------
.../user_trace_010_direct_filter.cpp | 112 +---
.../user_trace_012_open_trace.cpp | 5 +
...te.cpp => user_trace_015_update_trace.cpp} | 19 +-
.../user_trace_016_update_provider.cpp | 60 +++
29 files changed, 846 insertions(+), 816 deletions(-)
create mode 100644 Threathunters.BlueKrabsetw.Native.ETW/Filtering/PreEventfilter.hpp
create mode 100644 bluekrabs/krabs/filtering/post_event_filter.hpp
create mode 100644 bluekrabs/krabs/filtering/pre_event_filter.hpp
rename examples/NativeExamples/{user_trace_015_update.cpp => user_trace_015_update_trace.cpp} (96%)
create mode 100644 examples/NativeExamples/user_trace_016_update_provider.cpp
diff --git a/Threathunters.BlueKrabsetw.Native.ETW.NetCore/Microsoft.O365.Security.Native.ETW.NetCore.vcxproj b/Threathunters.BlueKrabsetw.Native.ETW.NetCore/Microsoft.O365.Security.Native.ETW.NetCore.vcxproj
index c3ea46a..c86f54e 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW.NetCore/Microsoft.O365.Security.Native.ETW.NetCore.vcxproj
+++ b/Threathunters.BlueKrabsetw.Native.ETW.NetCore/Microsoft.O365.Security.Native.ETW.NetCore.vcxproj
@@ -216,6 +216,7 @@
+
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/Filtering/PreEventfilter.hpp b/Threathunters.BlueKrabsetw.Native.ETW/Filtering/PreEventfilter.hpp
new file mode 100644
index 0000000..9779ba5
--- /dev/null
+++ b/Threathunters.BlueKrabsetw.Native.ETW/Filtering/PreEventfilter.hpp
@@ -0,0 +1,171 @@
+#pragma once
+
+#include "../Conversions.hpp"
+#include "../EventRecordError.hpp"
+#include "../EventRecord.hpp"
+#include "../EventRecordMetadata.hpp"
+#include "../Guid.hpp"
+#include "../IEventRecord.hpp"
+#include "../IEventRecordError.hpp"
+#include "../NativePtr.hpp"
+#include "Predicate.hpp"
+
+using namespace System;
+using namespace System::Collections::Generic;
+using namespace System::Runtime::InteropServices;
+
+namespace Microsoft {
+ namespace O365 {
+ namespace Security {
+ namespace ETW {
+
+ public interface class IPrePredicate
+ {
+ public:
+ virtual EVENT_FILTER_DESCRIPTOR operator()();
+ };
+
+ public ref class SystemFlags : public IPrePredicate
+ {
+ public:
+ SystemFlags(unsigned long long a1, unsigned long a2)
+ : data_(a1)
+ , size_(a2)
+ {}
+
+ virtual EVENT_FILTER_DESCRIPTOR operator()()
+ {
+ auto native_filter = new krabs::system_flags(data_, size_);
+
+ return native_filter->operator()();
+ }
+
+ private:
+ unsigned long long data_;
+ unsigned long size_;
+ };
+
+ public ref class EventIds : IPrePredicate
+ {
+ public:
+ EventIds(IEnumerable^ a1)
+ : data_(gcnew List(a1))
+ , filter_in_(true)
+ {}
+
+ /*EventIds(... array^ a1)
+ : data_(gcnew List(a1))
+ , filter_in_(true)
+ {}*/
+
+ virtual EVENT_FILTER_DESCRIPTOR operator()()
+ {
+ std::set x;
+ for each (auto y in data_)
+ {
+ x.insert(static_cast(y));
+ }
+
+ auto native_filter = new krabs::event_ids(x, filter_in_);
+
+ return native_filter->operator()();
+ }
+
+ private:
+ List^ data_;
+ bool filter_in_;
+ };
+
+ public ref class ProcessIds : IPrePredicate
+ {
+ public:
+ ProcessIds(IEnumerable^ a1)
+ : data_(gcnew List(a1))
+ {}
+
+ ProcessIds(... array^ a1)
+ : data_(gcnew List(a1))
+ {}
+
+ virtual EVENT_FILTER_DESCRIPTOR operator()()
+ {
+ std::set x;
+ for each (auto y in data_)
+ {
+ x.insert(static_cast(y));
+ }
+
+ auto native_filter = new krabs::event_ids(x, 0);
+
+ return native_filter->operator()();
+ }
+
+ private:
+ List^ data_;
+ };
+
+ public ref class EventNames : IPrePredicate
+ {
+ public:
+ EventNames(bool a2, IEnumerable^ a1)
+ : data_(gcnew List(a1))
+ , filter_in_(a2)
+ {}
+
+ EventNames(bool a2, ... array^ a1)
+ : data_(gcnew List(a1))
+ , filter_in_(a2)
+ {}
+
+ virtual EVENT_FILTER_DESCRIPTOR operator()()
+ {
+ std::set x;
+ for each (auto y in data_)
+ {
+ x.insert(msclr::interop::marshal_as(y));
+ }
+
+ auto native_filter = new krabs::event_names(x, filter_in_);
+
+ return native_filter->operator()();
+ }
+
+ private:
+ List^ data_;
+ bool filter_in_;
+ };
+
+ public ref class PreEventFilter
+ {
+ public:
+ PreEventFilter(IEnumerable^ filters)
+ : directFilterList_(gcnew List(filters)),
+ filter_(new krabs::pre_event_filter())
+ {}
+
+ PreEventFilter(... array^ filters)
+ : directFilterList_(gcnew List(filters)),
+ filter_(new krabs::pre_event_filter())
+ {}
+
+ internal:
+ operator krabs::pre_event_filter& ()
+ {
+ auto count = 0;
+ for each (auto filter in directFilterList_)
+ {
+ filter_->descriptor_.descriptor[count++] = filter->operator()();
+ }
+
+ filter_->descriptor_.count = count;
+ return *filter_;
+ }
+
+ NativePtr filter_;
+ List^ directFilterList_;
+ };
+ }
+ }
+ }
+}
+
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/ITrace.hpp b/Threathunters.BlueKrabsetw.Native.ETW/ITrace.hpp
index bdf3a9b..b504b0c 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW/ITrace.hpp
+++ b/Threathunters.BlueKrabsetw.Native.ETW/ITrace.hpp
@@ -23,6 +23,11 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
///
void SetTraceProperties(EventTraceProperties^ properties);
+ ///
+ /// Starts listening for events from the enabled providers.
+ ///
+ void Open();
+
///
/// Starts listening for events from the enabled providers.
///
@@ -33,6 +38,11 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
///
void Stop();
+ ///
+ /// Stops listening for events.
+ ///
+ void Close();
+
///
/// Get stats about events handled by this trace.
///
@@ -57,6 +67,18 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
///
/// The to enable.
void Enable(RawProvider^ provider);
+
+ ///
+ /// Enables a provider for the given user trace.
+ ///
+ /// The to enable.
+ void Disable(Provider^ provider);
+
+ ///
+ /// Enables a raw provider for the given user trace.
+ ///
+ /// The to enable.
+ void Disable(RawProvider^ provider);
};
///
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/KernelTrace.hpp b/Threathunters.BlueKrabsetw.Native.ETW/KernelTrace.hpp
index 9b19cfe..e04d2d9 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW/KernelTrace.hpp
+++ b/Threathunters.BlueKrabsetw.Native.ETW/KernelTrace.hpp
@@ -152,6 +152,18 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
///
virtual void Stop();
+ ///
+ /// Stops listening for events.
+ ///
+ ///
+ /// KernelTrace trace = new KernelTrace();
+ /// // ...
+ /// trace.Start();
+ /// trace.Stop();
+ ///
+ virtual void Close();
+
+
///
/// Get stats about events handled by this trace
///
@@ -250,6 +262,11 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
ExecuteAndConvertExceptions(return trace_->stop());
}
+ inline void KernelTrace::Close ()
+ {
+ ExecuteAndConvertExceptions(return trace_->close());
+ }
+
inline TraceStats KernelTrace::QueryStats()
{
ExecuteAndConvertExceptions(return TraceStats(trace_->query_stats()));
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/Microsoft.O365.Security.Native.ETW.vcxproj b/Threathunters.BlueKrabsetw.Native.ETW/Microsoft.O365.Security.Native.ETW.vcxproj
index 7993801..5205690 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW/Microsoft.O365.Security.Native.ETW.vcxproj
+++ b/Threathunters.BlueKrabsetw.Native.ETW/Microsoft.O365.Security.Native.ETW.vcxproj
@@ -211,6 +211,7 @@
+
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/Microsoft.O365.Security.Native.ETW.vcxproj.filters b/Threathunters.BlueKrabsetw.Native.ETW/Microsoft.O365.Security.Native.ETW.vcxproj.filters
index 54467e7..9e49ece 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW/Microsoft.O365.Security.Native.ETW.vcxproj.filters
+++ b/Threathunters.BlueKrabsetw.Native.ETW/Microsoft.O365.Security.Native.ETW.vcxproj.filters
@@ -125,6 +125,9 @@
Header Files\Filtering
+
+ Header Files\Filtering
+
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/Provider.hpp b/Threathunters.BlueKrabsetw.Native.ETW/Provider.hpp
index 29ea463..daaa5bd 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW/Provider.hpp
+++ b/Threathunters.BlueKrabsetw.Native.ETW/Provider.hpp
@@ -11,6 +11,7 @@
#include "NativePtr.hpp"
#include "Filtering/EventFilter.hpp"
#include "Filtering/DirectEventFilter.hpp"
+#include "Filtering/PreEventfilter.hpp"
using namespace System;
using namespace System::Runtime::InteropServices;
@@ -18,7 +19,7 @@ using namespace System::Runtime::InteropServices;
namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
ref class UserTrace;
-
+
// Flags as documented here:
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd392306(v=vs.85).aspx
public enum class TraceFlags
@@ -181,6 +182,18 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
provider_->add_filter(filter);
}
+ void AddFilter(O365::Security::ETW::PreEventFilter^ filter) {
+ provider_->add_filter(filter);
+ }
+
+ ///
+ /// Adds a new EventFilter to the provider.
+ ///
+ /// the to add
+ /*void AddFilter(O365::Security::ETW::PreEventFilter^ filter) {
+ provider_->add_filter(filter);
+ }*/
+
///
/// An event that is invoked when an ETW event is fired in this
/// provider.
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/UserTrace.hpp b/Threathunters.BlueKrabsetw.Native.ETW/UserTrace.hpp
index 82a8d8f..a4eac41 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW/UserTrace.hpp
+++ b/Threathunters.BlueKrabsetw.Native.ETW/UserTrace.hpp
@@ -73,6 +73,30 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
///
virtual void Enable(O365::Security::ETW::RawProvider ^provider);
+ ///
+ /// Enables a provider for the given user trace.
+ ///
+ /// the to enable on the trace
+ ///
+ /// UserTrace trace = new UserTrace();
+ /// System.Guid powershell = System.Guid.Parse("{...}")
+ /// Provider provider = new Provider(powershell);
+ /// trace.Enable(provider);
+ ///
+ virtual void Disable(O365::Security::ETW::Provider^ provider);
+
+ ///
+ /// Enables a raw provider for the given user trace.
+ ///
+ /// the to enable on the trace
+ ///
+ /// UserTrace trace = new UserTrace();
+ /// System.Guid powershell = System.Guid.Parse("{...}")
+ /// Provider provider = new RawProvider(powershell);
+ /// trace.Enable(provider);
+ ///
+ virtual void Disable(O365::Security::ETW::RawProvider^ provider);
+
///
/// Sets the trace properties for a session.
/// Must be called before Open()/Start().
@@ -160,6 +184,17 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
///
virtual void Stop();
+ ///
+ /// Stops listening for events.
+ ///
+ ///
+ /// UserTrace trace = new UserTrace();
+ /// // ...
+ /// trace.Start();
+ /// trace.Stop();
+ ///
+ virtual void Close();
+
///
/// Get stats about events handled by this trace
///
@@ -206,6 +241,16 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
return trace_->enable(*provider->provider_);
}
+ inline void UserTrace::Disable(O365::Security::ETW::Provider^ provider)
+ {
+ return trace_->disable(*provider->provider_);
+ }
+
+ inline void UserTrace::Disable(O365::Security::ETW::RawProvider^ provider)
+ {
+ return trace_->disable(*provider->provider_);
+ }
+
inline void UserTrace::SetTraceProperties(EventTraceProperties ^properties)
{
EVENT_TRACE_PROPERTIES _properties;
@@ -237,6 +282,11 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
ExecuteAndConvertExceptions(return trace_->stop());
}
+ inline void UserTrace::Close()
+ {
+ ExecuteAndConvertExceptions(return trace_->close());
+ }
+
inline TraceStats UserTrace::QueryStats()
{
ExecuteAndConvertExceptions(return TraceStats(trace_->query_stats()));
diff --git a/bluekrabs/bluekrabs.sln b/bluekrabs/bluekrabs.sln
index 7bb39f1..1743510 100644
--- a/bluekrabs/bluekrabs.sln
+++ b/bluekrabs/bluekrabs.sln
@@ -47,7 +47,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bluekrabs", "bluekrabs", "{
krabs\compiler_check.hpp = krabs\compiler_check.hpp
krabs\errors.hpp = krabs\errors.hpp
krabs\etw.hpp = krabs\etw.hpp
- krabs\helping\file_mapping.hpp = krabs\helping\file_mapping.hpp
krabs\guid.hpp = krabs\guid.hpp
krabs\kernel_guids.hpp = krabs\kernel_guids.hpp
krabs\kernel_providers.hpp = krabs\kernel_providers.hpp
@@ -73,17 +72,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "filtering", "filtering", "{
krabs\filtering\comparers.hpp = krabs\filtering\comparers.hpp
krabs\filtering\direct_event_filter.hpp = krabs\filtering\direct_event_filter.hpp
krabs\filtering\event_filter.hpp = krabs\filtering\event_filter.hpp
+ krabs\filtering\post_event_filter.hpp = krabs\filtering\post_event_filter.hpp
krabs\filtering\predicates.hpp = krabs\filtering\predicates.hpp
+ krabs\filtering\pre_event_filter.hpp = krabs\filtering\pre_event_filter.hpp
krabs\filtering\view_adapters.hpp = krabs\filtering\view_adapters.hpp
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "helping", "helping", "{531AF202-7C02-4203-9463-F10DE8A996AD}"
-ProjectSection(SolutionItems) = preProject
+ ProjectSection(SolutionItems) = preProject
krabs\helping\file_mapping.hpp = krabs\helping\file_mapping.hpp
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "searching", "searching", "{2C63BA17-1E15-4B5B-B979-A00C3A331678}"
-ProjectSection(SolutionItems) = preProject
+ ProjectSection(SolutionItems) = preProject
discover.hpp = discover.hpp
krabs\searching\wevt.hpp = krabs\searching\wevt.hpp
EndProjectSection
diff --git a/bluekrabs/krabs.hpp b/bluekrabs/krabs.hpp
index 1e1ae51..c8db64b 100644
--- a/bluekrabs/krabs.hpp
+++ b/bluekrabs/krabs.hpp
@@ -57,5 +57,6 @@
#include "krabs/filtering/comparers.hpp"
#include "krabs/filtering/predicates.hpp"
#include "krabs/filtering/event_filter.hpp"
+//#include "krabs/filtering/pre_event_filter.hpp"
-#pragma warning(pop)
+#pragma warning(pop)
\ No newline at end of file
diff --git a/bluekrabs/krabs/etw.hpp b/bluekrabs/krabs/etw.hpp
index 4346d20..46960d4 100644
--- a/bluekrabs/krabs/etw.hpp
+++ b/bluekrabs/krabs/etw.hpp
@@ -108,7 +108,7 @@ namespace krabs { namespace details {
* open() needs to called for this to work first.
*
*/
- void update();
+ void enable(const typename T::trace_type::provider_type& p);
/**
*
@@ -116,8 +116,8 @@ namespace krabs { namespace details {
* open() needs to called for this to work first.
*
*/
- void update(const typename T::trace_type::provider_type& p);
-
+ void update();
+
/**
*
* Queries the ETW trace identified by the info in the trace type.
@@ -172,7 +172,7 @@ namespace krabs { namespace details {
void process_trace();
void enable_providers();
void disable_provider(const typename T::trace_type::provider_type& p);
- void update_provider(const typename T::trace_type::provider_type& p);
+ void enable_provider(const typename T::trace_type::provider_type& p);
private:
T &trace_;
@@ -264,14 +264,14 @@ namespace krabs { namespace details {
}
template
- void trace_manager::update(
+ void trace_manager::enable(
const typename T::trace_type::provider_type& p)
{
if (trace_.sessionHandle_ == INVALID_PROCESSTRACE_HANDLE) {
throw open_trace_failure();
}
- update_provider(p);
+ enable_provider(p);
}
template
@@ -659,7 +659,7 @@ namespace krabs { namespace details {
}
template
- void trace_manager::update_provider(
+ void trace_manager::enable_provider(
const typename T::trace_type::provider_type& p)
{
if (trace_.registrationHandle_ == INVALID_PROCESSTRACE_HANDLE) {
@@ -668,7 +668,7 @@ namespace krabs { namespace details {
}
if (trace_.registrationHandle_ != INVALID_PROCESSTRACE_HANDLE) {
- T::trace_type::update_provider(trace_, p);
+ T::trace_type::enable_provider(trace_, p);
}
}
diff --git a/bluekrabs/krabs/filtering/direct_event_filter.hpp b/bluekrabs/krabs/filtering/direct_event_filter.hpp
index 26906b6..ec6cd3c 100644
--- a/bluekrabs/krabs/filtering/direct_event_filter.hpp
+++ b/bluekrabs/krabs/filtering/direct_event_filter.hpp
@@ -283,11 +283,16 @@ namespace krabs {
{
auto& count = descriptor_.count;
if (count == 0) {
- for (auto& item : list_) {
- switch (item->type_) {
- case EVENT_FILTER_TYPE_SYSTEM_FLAGS: {
+ for (auto& item : list_)
+ {
+ descriptor_.descriptor[count++] = item->operator()();
+ /*switch (item->type_)
+ {
+ case EVENT_FILTER_TYPE_SYSTEM_FLAGS:
+ {
auto tmp = static_cast(const_cast(item));
- if (tmp) {
+ if (tmp)
+ {
descriptor_.descriptor[count++] = (*tmp)();
}
break;
@@ -323,7 +328,7 @@ namespace krabs {
default: {
break;
}
- }
+ }*/
}
}
@@ -335,11 +340,6 @@ namespace krabs {
std::vector list_;
};
-
-
-
-
-
struct system_flags_event_filter : direct_event_filter_base {
system_flags_event_filter(unsigned long long flags, unsigned long size)
: flags_(flags),
diff --git a/bluekrabs/krabs/filtering/post_event_filter.hpp b/bluekrabs/krabs/filtering/post_event_filter.hpp
new file mode 100644
index 0000000..e69de29
diff --git a/bluekrabs/krabs/filtering/pre_event_filter.hpp b/bluekrabs/krabs/filtering/pre_event_filter.hpp
new file mode 100644
index 0000000..4eb1980
--- /dev/null
+++ b/bluekrabs/krabs/filtering/pre_event_filter.hpp
@@ -0,0 +1,254 @@
+#include
+#include
+#include
+
+namespace krabs {
+
+ //
+ // EVENT_FILTER_TYPE values for the Type field of EVENT_FILTER_DESCRIPTOR.
+ // * /
+ //#define EVENT_FILTER_TYPE_NONE (0x00000000)
+ //#define EVENT_FILTER_TYPE_SCHEMATIZED (0x80000000) // Provider-side.
+ //#define EVENT_FILTER_TYPE_SYSTEM_FLAGS (0x80000001) // Internal use only.
+ //#define EVENT_FILTER_TYPE_TRACEHANDLE (0x80000002) // Initiate rundown.
+ //#define EVENT_FILTER_TYPE_PID (0x80000004) // Process ID.
+ //#define EVENT_FILTER_TYPE_EXECUTABLE_NAME (0x80000008) // EXE file name.
+ //#define EVENT_FILTER_TYPE_PACKAGE_ID (0x80000010) // Package ID.
+ //#define EVENT_FILTER_TYPE_PACKAGE_APP_ID (0x80000020) // Package Relative App Id (PRAID).
+ //#define EVENT_FILTER_TYPE_PAYLOAD (0x80000100) // TDH payload filter.
+ //#define EVENT_FILTER_TYPE_EVENT_ID (0x80000200) // Event IDs.
+ //#define EVENT_FILTER_TYPE_EVENT_NAME (0x80000400) // Event name (TraceLogging only).
+ //#define EVENT_FILTER_TYPE_STACKWALK (0x80001000) // Event IDs for stack.
+ //#define EVENT_FILTER_TYPE_STACKWALK_NAME (0x80002000) // Event name for stack (TraceLogging only).
+ //#define EVENT_FILTER_TYPE_STACKWALK_LEVEL_KW (0x80004000) // Filter stack collection by level and keyword.
+ //#define EVENT_FILTER_TYPE_CONTAINER (0x80008000) // Filter by Container ID.
+
+ struct pre_predicate_base {
+ pre_predicate_base() {}
+
+ virtual EVENT_FILTER_DESCRIPTOR operator()() const = 0;
+ };
+
+ struct filter_descriptor {
+ unsigned long count = 0;
+ EVENT_FILTER_DESCRIPTOR descriptor[MAX_EVENT_FILTERS_COUNT];
+ };
+
+ struct system_flags : pre_predicate_base {
+ system_flags(unsigned long long a1, unsigned long a2)
+ : descriptor_({ 0 })
+ , data_(a1)
+ , size_(a2)
+ {}
+
+ EVENT_FILTER_DESCRIPTOR operator()() const override
+ {
+ descriptor_.Ptr = reinterpret_cast(&data_);
+ descriptor_.Size = size_;
+ descriptor_.Type = EVENT_FILTER_TYPE_SYSTEM_FLAGS;
+
+ return descriptor_;
+ }
+
+ private:
+ mutable unsigned long long data_;
+ unsigned long size_;
+ mutable EVENT_FILTER_DESCRIPTOR descriptor_;
+ };
+
+ struct event_ids : pre_predicate_base {
+ event_ids(std::set a1, bool a2)
+ : descriptor_({ 0 })
+ , data_(a1)
+ , filter_in_(a2)
+ {}
+
+ EVENT_FILTER_DESCRIPTOR operator()() const override
+ {
+ /*typedef struct _EVENT_FILTER_EVENT_ID {
+ BOOLEAN FilterIn;
+ UCHAR Reserved;
+ USHORT Count;
+ USHORT Events[ANYSIZE_ARRAY];
+ } EVENT_FILTER_EVENT_ID, * PEVENT_FILTER_EVENT_ID;*/
+
+ auto count = data_.size();
+ if (count > 0) {
+ auto cache_size = FIELD_OFFSET(EVENT_FILTER_EVENT_ID, Events[count]);
+ cache_ = std::make_unique(cache_size);
+ auto tmp = reinterpret_cast(cache_.get());
+ tmp->FilterIn = filter_in_;
+ tmp->Count = static_cast(count);
+ int i = 0;
+ for (auto item : data_) {
+ tmp->Events[i++] = item;
+ }
+ descriptor_.Ptr = reinterpret_cast(cache_.get());
+ descriptor_.Size = cache_size;
+ descriptor_.Type = EVENT_FILTER_TYPE_EVENT_ID;
+ }
+
+ return descriptor_;
+ }
+
+ private:
+ std::set data_;
+ bool filter_in_; // When this member is TRUE, filtering is enabled for the specified event IDs. When this member is FALSE, filtering is disabled for the event IDs.
+ mutable EVENT_FILTER_DESCRIPTOR descriptor_;
+ mutable std::unique_ptr cache_;
+ };
+
+ struct process_pids : pre_predicate_base {
+ process_pids(std::set a1)
+ : descriptor_({ 0 })
+ , data_(a1)
+ {}
+
+ EVENT_FILTER_DESCRIPTOR operator()() const override
+ {
+ /*typedef struct _EVENT_FILTER_EVENT_ID {
+ BOOLEAN FilterIn;
+ UCHAR Reserved;
+ USHORT Count;
+ USHORT Events[ANYSIZE_ARRAY];
+ } EVENT_FILTER_EVENT_ID, * PEVENT_FILTER_EVENT_ID;*/
+
+ auto count = data_.size();
+ if (count > 0) {
+ int i = 0;
+ for (auto item : data_) {
+ if (i < MAX_EVENT_FILTER_PID_COUNT) {
+ cache_[i++] = item;
+ }
+ }
+ descriptor_.Ptr = reinterpret_cast(cache_);
+ descriptor_.Size = sizeof(unsigned int) * i;
+ descriptor_.Type = EVENT_FILTER_TYPE_PID;
+ }
+
+ return descriptor_;
+ }
+
+ private:
+ std::set data_;
+ mutable EVENT_FILTER_DESCRIPTOR descriptor_;
+ mutable unsigned int cache_[MAX_EVENT_FILTER_PID_COUNT] = { 0 };
+ };
+
+ struct event_names : pre_predicate_base {
+ event_names(std::set a1, bool a2)
+ : descriptor_({ 0 })
+ , data_(a1)
+ , filter_in_(a2)
+ {}
+
+ EVENT_FILTER_DESCRIPTOR operator()() const override
+ {
+ /*typedef struct _EVENT_FILTER_EVENT_NAME {
+ ULONGLONG MatchAnyKeyword;
+ ULONGLONG MatchAllKeyword;
+ UCHAR Level;
+ BOOLEAN FilterIn;
+ USHORT NameCount;
+ UCHAR Names[ANYSIZE_ARRAY];
+ } EVENT_FILTER_EVENT_NAME, * PEVENT_FILTER_EVENT_NAME;*/
+
+ auto count = data_.size();
+ if (count > 0) {
+ auto cache_size = FIELD_OFFSET(EVENT_FILTER_EVENT_NAME, Names[count]);
+ cache_ = std::make_unique(cache_size);
+ auto tmp = reinterpret_cast(cache_.get());
+ tmp->FilterIn = filter_in_;
+ tmp->Level = 0;
+ tmp->MatchAnyKeyword = 0;
+ tmp->MatchAllKeyword = 0;
+ tmp->NameCount = static_cast(count);
+ // The Names field should be a series of
+ // NameCount null terminated utf-8
+ // event names.
+ auto i = 0;
+ for (auto item1 : data_) {
+ item1.push_back('\0');
+ for (auto& item2 : item1) {
+ tmp->Names[i++] = item2;
+ }
+ }
+
+ descriptor_.Ptr = reinterpret_cast(cache_.get());
+ descriptor_.Size = cache_size;
+ descriptor_.Type = EVENT_FILTER_TYPE_EVENT_NAME;
+ }
+
+ return descriptor_;
+ }
+
+ private:
+ std::set data_;
+ bool filter_in_;
+ mutable EVENT_FILTER_DESCRIPTOR descriptor_;
+ mutable std::unique_ptr cache_;
+ };
+
+ struct event_payloads : pre_predicate_base {
+ event_payloads(std::set a1, bool a2)
+ : descriptor_({ 0 })
+ , data_(a1)
+ , filter_in_(a2)
+ {}
+
+ EVENT_FILTER_DESCRIPTOR operator()() const override
+ {
+ /*typedef struct _PAYLOAD_FILTER_PREDICATE {
+ LPWSTR FieldName;
+ USHORT CompareOp;
+ LPWSTR Value;
+ } PAYLOAD_FILTER_PREDICATE, *PPAYLOAD_FILTER_PREDICATE;
+
+ EVENT_FILTER_TYPE_PAYLOAD
+
+ */
+
+
+
+ return descriptor_;
+ }
+
+ private:
+ std::set data_;
+ bool filter_in_;
+ mutable EVENT_FILTER_DESCRIPTOR descriptor_;
+ mutable PAYLOAD_FILTER_PREDICATE cache_[MAX_PAYLOAD_PREDICATES] = { 0 };
+ //mutable std::unique_ptr cache_;
+ };
+
+
+ /**
+ *
+ *
+ *
+ */
+ struct pre_event_filter {
+ pre_event_filter() {}
+ pre_event_filter(std::vector> list)
+ : descriptor_({ 0 })
+ , list_(list)
+ {}
+
+ filter_descriptor operator()() const
+ {
+ auto& count = descriptor_.count;
+ if (count == 0) {
+ for (auto& item : list_)
+ {
+ descriptor_.descriptor[count++] = item->operator()();
+ }
+ }
+
+ return descriptor_;
+ }
+
+ std::vector> list_;
+ mutable filter_descriptor descriptor_;
+
+ };
+} /* namespace krabs */
\ No newline at end of file
diff --git a/bluekrabs/krabs/kt.hpp b/bluekrabs/krabs/kt.hpp
index 2c99bcd..623094d 100644
--- a/bluekrabs/krabs/kt.hpp
+++ b/bluekrabs/krabs/kt.hpp
@@ -25,7 +25,7 @@ namespace krabs { namespace details {
struct kt {
typedef krabs::kernel_provider provider_type;
-
+ typedef int provider_enable_info;
/**
*
* Used to assign a name to the trace instance that is being
@@ -64,7 +64,7 @@ namespace krabs { namespace details {
* Enables the providers that are attached to the given trace.
*
*/
- static void update_provider(
+ static void enable_provider(
krabs::trace& trace,
const krabs::details::kt::provider_type& p);
@@ -155,7 +155,7 @@ namespace krabs { namespace details {
return;
}
- inline void kt::update_provider(
+ inline void kt::enable_provider(
krabs::trace& trace,
const krabs::details::kt::provider_type& p)
{
diff --git a/bluekrabs/krabs/provider.hpp b/bluekrabs/krabs/provider.hpp
index 5b99bbb..af8d394 100644
--- a/bluekrabs/krabs/provider.hpp
+++ b/bluekrabs/krabs/provider.hpp
@@ -11,6 +11,7 @@
#include "compiler_check.hpp"
#include "filtering/event_filter.hpp"
#include "filtering/direct_event_filter.hpp"
+#include "filtering/pre_event_filter.hpp"
#include "perfinfo_groupmask.hpp"
#include "trace_context.hpp"
#include "wstring_convert.hpp"
@@ -113,6 +114,8 @@ namespace krabs {
void add_filter(const event_filter &f);
void add_filter(const direct_event_filters& f);
+
+ void add_filter(const pre_event_filter& f);
protected:
/**
@@ -127,7 +130,7 @@ namespace krabs {
std::deque error_callbacks_;
std::deque filters_;
std::deque direct_filters_;
-
+ filter_descriptor pre_filter_;
private:
template
friend class details::trace_manager;
@@ -302,7 +305,7 @@ namespace krabs {
T level_;
T enable_property_;
bool rundown_enabled_;
-
+
private:
template
friend class details::trace_manager;
@@ -503,12 +506,19 @@ namespace krabs {
direct_filters_.push_back(f);
}
+ template
+ void base_provider::add_filter(const pre_event_filter& f)
+ {
+ pre_filter_ = f();
+ }
+
template
void base_provider::on_event(const EVENT_RECORD &record, const krabs::trace_context &trace_context) const
{
try
{
- for (auto& callback : callbacks_) {
+ for (auto& callback : callbacks_)
+ {
callback(record, trace_context);
}
@@ -518,7 +528,8 @@ namespace krabs {
}
catch (krabs::could_not_find_schema& ex)
{
- for (auto& error_callback : error_callbacks_) {
+ for (auto& error_callback : error_callbacks_)
+ {
error_callback(record, ex.what());
}
}
diff --git a/bluekrabs/krabs/trace.hpp b/bluekrabs/krabs/trace.hpp
index 081a3d2..e41b49d 100644
--- a/bluekrabs/krabs/trace.hpp
+++ b/bluekrabs/krabs/trace.hpp
@@ -240,8 +240,6 @@ namespace krabs {
*/
void disable(const typename T::provider_type& p);
-
-
/**
*
* Starts a trace session.
@@ -385,24 +383,27 @@ namespace krabs {
*/
void on_event(const EVENT_RECORD &);
- ///**
- // *
- // * Updates a trace session.
- // *
- // *
- // * todo
- // *
- // */
- void update_provider(const typename T::provider_type& p);
+ /////**
+ //// *
+ //// * Updates a trace session.
+ //// *
+ //// *
+ //// * todo
+ //// *
+ //// */
+ //void update_provider(const typename T::provider_type& p);
private:
std::wstring name_;
std::wstring logFilename_;
bool non_stoppable_;
std::deque> enabled_providers_;
- std::deque> disabled_providers_;
+ // This essentially takes the union of all the provider flags
+ // for a given provider. This comes about when multiple providers
+ // for the same XX are provided and request different provider flags.
+ // TODO: Only forward the calls that are requested to each provider.
+ typename T::provider_enable_info provider_enable_info_;
std::mutex providers_mutex_;
- //std::map provider_pos_;
TRACEHANDLE registrationHandle_;
TRACEHANDLE sessionHandle_;
@@ -497,54 +498,57 @@ namespace krabs {
void trace::on_event(const EVENT_RECORD &record)
{
++eventsHandled_;
+ std::lock_guard lock(providers_mutex_);
T::forward_events(record, *this);
}
template
void trace::enable(const typename T::provider_type& p)
- {
- {
- std::lock_guard lock(providers_mutex_);
- auto& guid = p.guid();
-
- auto it = std::find_if(
- enabled_providers_.begin(),
- enabled_providers_.end(),
- [&guid](const auto& x) {
- return x.get().guid() == guid;
+ {
+ auto insert_unique = [&](const auto& _p) {
+ auto it = std::find_if(enabled_providers_.begin(), enabled_providers_.end(), [&_p](const auto& x) {
+ return x.get().guid() == _p.guid();
});
-
-
-
if (it == enabled_providers_.end()) {
- enabled_providers_.push_back(std::ref(p));
- return;
+ enabled_providers_.push_back(std::ref(_p));
}
- }
+ else {
+ *it = std::ref(_p);
+ }
+ };
- update_provider(p);
+ if (registrationHandle_ == INVALID_PROCESSTRACE_HANDLE) {
+ insert_unique(p);
+ }
+ else {
+ std::lock_guard lock(providers_mutex_);
+ details::trace_manager manager(*this);
+ manager.enable(p);
+ insert_unique(p);
+ }
}
template
void trace::disable(const typename T::provider_type& p)
- {
- details::trace_manager manager(*this);
- manager.remove(p);
- //disabled_providers_.push_back(std::ref(p));
- }
+ {
+ if (registrationHandle_ == INVALID_PROCESSTRACE_HANDLE) {
+ auto it = std::find_if(enabled_providers_.begin(), enabled_providers_.end(), [&p](const auto& x) {
+ return x.get().guid() == p.guid();
+ });
- template
- void trace::update_provider(const typename T::provider_type& p)
- {
- details::trace_manager manager(*this);
- manager.update(p);
+ if (it != enabled_providers_.end()) {
+ std::lock_guard lock(providers_mutex_);
+ details::trace_manager manager(*this);
+ manager.disable(p);
+ enabled_providers_.erase(it);
+ }
+ }
}
template
void trace::start()
{
eventsHandled_ = 0;
-
details::trace_manager manager(*this);
manager.start();
}
diff --git a/bluekrabs/krabs/ut.hpp b/bluekrabs/krabs/ut.hpp
index 4c19dea..6d5d9fb 100644
--- a/bluekrabs/krabs/ut.hpp
+++ b/bluekrabs/krabs/ut.hpp
@@ -22,29 +22,9 @@ namespace krabs { namespace details {
* code.
*
*/
- struct ut {
- struct filter_flags {
- ULONG filter_type_;
- std::set event_ids_;
- std::set event_names_;
- ULONGLONG custom_value_;
- ULONG custom_size_;
- std::wstring field_name_;
- unsigned short compare_op_;
- std::wstring value_;
- };
-
- struct event_filter_buffers {
- std::vector event_id_buffer;
- std::vector event_pid_buffer;
- std::vector event_exe_name_buffer;
- std::vector event_name_buffer;
- unsigned int pids[MAX_EVENT_FILTER_PID_COUNT] = { 0 };
- EVENT_FILTER_DESCRIPTOR filter_desc[15] = { 0 };
- PAYLOAD_FILTER_PREDICATE predicates[MAX_PAYLOAD_PREDICATES] = { 0 };
- };
+ struct ut {
//ENABLE_TRACE_PARAMETERS
- struct provider_enable_info {
+ struct enable_trace_info {
GUID guid;
ENABLE_TRACE_PARAMETERS parameters;
bool rundown_enabled = false;
@@ -52,13 +32,11 @@ namespace krabs { namespace details {
ULONGLONG any;
ULONGLONG all;
ULONG enable_property;
-
- event_filter_buffers event_buffer;
+ EVENT_FILTER_DESCRIPTOR filter_desc[15] = { 0 };
};
typedef krabs::provider<> provider_type;
- typedef std::map provider_enable_info_container;
-
+ typedef std::map provider_enable_info;
/**
*
* Used to assign a name to the trace instance that is being
@@ -88,42 +66,9 @@ namespace krabs { namespace details {
* todo.
*
*/
- static ULONG populate_system_flags_filter_desc(ut::provider_enable_info& info, const system_flags_event_filter* system_flags);
-
- /**
- *
- * todo.
- *
- */
- static ULONG populate_event_id_filter_desc(ut::provider_enable_info& info, const event_id_event_filter* system_flags);
-
- /**
- *
- * todo.
- *
- */
- static ULONG populate_event_pid_filter_desc(ut::provider_enable_info& info, const event_pid_event_filter* system_flags);
-
- /**
- *
- * todo.
- *
- */
- static ULONG populate_event_name_filter_desc(ut::provider_enable_info& info, const event_name_event_filter* event_names);
-
- /**
- *
- * todo.
- *
- */
- static ULONG populate_event_payload_filter_desc(ut::provider_enable_info& info, const event_payload_event_filter* event_names);
-
- /**
- *
- * todo.
- *
- */
- static void populate_provider_enable_info(const ut::provider_type& provider, ut::provider_enable_info& info);
+ static void set_provider_enable_info(
+ const ut::provider_type& provider,
+ ut::enable_trace_info& info);
/**
*
@@ -133,6 +78,15 @@ namespace krabs { namespace details {
static void enable_providers(
krabs::trace &trace);
+ ///**
+ // *
+ // * Enables the providers that are attached to the given trace.
+ // *
+ // */
+ static void enable_provider(
+ krabs::trace& trace,
+ const krabs::details::ut::provider_type& p);
+
/**
*
* Enables the providers that are attached to the given trace.
@@ -142,15 +96,6 @@ namespace krabs { namespace details {
krabs::trace& trace,
const krabs::details::ut::provider_type& p);
- ///**
- // *
- // * Enables the providers that are attached to the given trace.
- // *
- // */
- static void update_provider(
- krabs::trace& trace,
- const krabs::details::ut::provider_type& p);
-
/**
*
* Enables the configured rundown events for each provider.
@@ -213,193 +158,9 @@ namespace krabs { namespace details {
return 0;
}
- inline ULONG ut::populate_system_flags_filter_desc(
- ut::provider_enable_info& info,
- const system_flags_event_filter* system_flags)
- {
- auto& filter_desc = info.parameters.EnableFilterDesc[info.parameters.FilterDescCount];
- filter_desc.Ptr = reinterpret_cast(&system_flags->get_value());
- filter_desc.Size = system_flags->get_size();
- filter_desc.Type = EVENT_FILTER_TYPE_SYSTEM_FLAGS;
-
- return 1;
- }
-
- inline ULONG ut::populate_event_id_filter_desc(
- ut::provider_enable_info& info,
- const event_id_event_filter* event_ids)
- {
- /*typedef struct _EVENT_FILTER_EVENT_ID {
- BOOLEAN FilterIn;
- UCHAR Reserved;
- USHORT Count;
- USHORT Events[ANYSIZE_ARRAY];
- } EVENT_FILTER_EVENT_ID, * PEVENT_FILTER_EVENT_ID;*/
- auto& filter_desc = info.parameters.EnableFilterDesc[info.parameters.FilterDescCount];
- auto& buffer = info.event_buffer.event_id_buffer;
- auto event_ids_count = event_ids->get_data().size();
- auto buffer_size = FIELD_OFFSET(EVENT_FILTER_EVENT_ID, Events[event_ids_count]);
- if (event_ids_count > 0) {
- filter_desc.Type = EVENT_FILTER_TYPE_EVENT_ID;
- buffer.resize(buffer_size, 0);
- auto event_ids_desc = reinterpret_cast(&buffer[0]);
- event_ids_desc->FilterIn = TRUE;
- event_ids_desc->Count = static_cast(event_ids_count);
- auto index = 0;
- for (auto id : event_ids->get_data()) {
- event_ids_desc->Events[index] = id;
- index++;
- }
- filter_desc.Ptr = reinterpret_cast(event_ids_desc);
- filter_desc.Size = buffer_size;
-
- return 1;
- }
-
- return 0;
- }
-
- inline ULONG ut::populate_event_pid_filter_desc(
- ut::provider_enable_info& info,
- const event_pid_event_filter* event_ids)
- {
- /*typedef struct _EVENT_FILTER_EVENT_ID {
- BOOLEAN FilterIn;
- UCHAR Reserved;
- USHORT Count;
- USHORT Events[ANYSIZE_ARRAY];
- } EVENT_FILTER_EVENT_ID, * PEVENT_FILTER_EVENT_ID;*/
- auto& filter_desc = info.parameters.EnableFilterDesc[info.parameters.FilterDescCount];
- auto& buffer = info.event_buffer.pids;
- auto event_ids_count = event_ids->get_data().size();
- //auto buffer_size = FIELD_OFFSET(EVENT_FILTER_EVENT_ID, Events[event_ids_count]);
- if (event_ids_count > 0) {
- /*filter_desc.Type = EVENT_FILTER_TYPE_PID;
- buffer.resize(buffer_size, 0);
- auto event_ids_desc = reinterpret_cast(&buffer[0]);
- event_ids_desc->FilterIn = TRUE;
- event_ids_desc->Count = static_cast(event_ids_count);
- auto index = 0;
- for (auto id : event_ids->get_data()) {
- event_ids_desc->Events[index] = id;
- index++;
- }*/
- auto index = 0;
- for (auto id : event_ids->get_data()) {
- buffer[index] = id;
- index++;
- }
-
- auto size = sizeof(unsigned int) * index;
- filter_desc.Type = EVENT_FILTER_TYPE_PID;
- filter_desc.Ptr = reinterpret_cast(buffer);
- filter_desc.Size = (ULONG)size;
-
- return 1;
- }
-
- return 0;
- }
-
- inline ULONG ut::populate_event_name_filter_desc(
- ut::provider_enable_info& info,
- const event_name_event_filter* event_names)
- {
- /*typedef struct _EVENT_FILTER_EVENT_NAME {
- ULONGLONG MatchAnyKeyword;
- ULONGLONG MatchAllKeyword;
- UCHAR Level;
- BOOLEAN FilterIn;
- USHORT NameCount;
- UCHAR Names[ANYSIZE_ARRAY];
- } EVENT_FILTER_EVENT_NAME, * PEVENT_FILTER_EVENT_NAME;*/
- auto& filter_desc = info.parameters.EnableFilterDesc[info.parameters.FilterDescCount]; //todo check if slot set
- auto& buffer = info.event_buffer.event_id_buffer;
- auto names_count = event_names->get_data().size();
- auto buffer_size = FIELD_OFFSET(EVENT_FILTER_EVENT_ID, Events[names_count]);
- if (names_count > 0) {
- filter_desc.Type = EVENT_FILTER_TYPE_EVENT_NAME;
- buffer.resize(buffer_size, 0);
- auto event_name_desc = reinterpret_cast(&buffer[0]);
- event_name_desc->FilterIn = TRUE;
- event_name_desc->Level = info.level;
- event_name_desc->MatchAnyKeyword = info.any;
- event_name_desc->MatchAllKeyword = info.all;
-
- // The Names field should be a series of
- // NameCount null terminated utf-8
- // event names.
- auto index = 0;
- for (auto name : event_names->get_data()) {
- name.push_back('\0');
- for (auto& s : name) {
- event_name_desc->Names[index] = s;
- index++;
- }
- event_name_desc->NameCount = static_cast(names_count);
- }
- filter_desc.Ptr = reinterpret_cast(event_name_desc);
- filter_desc.Size = buffer_size;
-
- return 1;
- }
-
- return 0;
- }
-
- inline ULONG ut::populate_event_payload_filter_desc(
- ut::provider_enable_info& info,
- const event_payload_event_filter* event_payload)
- {
- /*typedef struct _PAYLOAD_FILTER_PREDICATE {
- LPWSTR FieldName;
- USHORT CompareOp;
- LPWSTR Value;
- } PAYLOAD_FILTER_PREDICATE, *PPAYLOAD_FILTER_PREDICATE;*/
- auto& filter_desc = info.parameters.EnableFilterDesc[info.parameters.FilterDescCount];
- auto& predicates = info.event_buffer.predicates;
- ULONG predicates_count = 0;
- EVENT_DESCRIPTOR ed = { 0 };
- PVOID event_filter[MAX_EVENT_FILTERS_COUNT] = { 0 };
- std::wstring mans{ L"C:\\data\\microsoft-windows-system-events.dll" };
- ULONG Status = TdhLoadManifestFromBinary((PWSTR)mans.c_str());
- if (Status != ERROR_SUCCESS) {
- printf("TdhCreatePayloadFilter() failed with %lu\n", Status);
- }
- //0. check if manifest provider
- //1. load find eval and load manifest
- //2. polpulate first payload filter
- predicates[predicates_count].CompareOp = event_payload->get_compare_op();
- predicates[predicates_count].FieldName = static_cast(const_cast(event_payload->get_field_name().c_str()));
- predicates[predicates_count].Value = static_cast(const_cast(event_payload->get_value().c_str()));
- predicates_count++;
- ed.Id = 5;
- //TdhCreatePayloadFilter();
- Status = TdhCreatePayloadFilter(
- &info.guid,
- &ed,
- TRUE, // TRUE Match any predicates (OR); FALSE Match all predicates (AND)
- 1,
- predicates,
- &event_filter[0]);
- if (Status != ERROR_SUCCESS) {
- printf("TdhCreatePayloadFilter() failed with %lu\n", Status);
- }
- Status = TdhAggregatePayloadFilters(
- 1,
- event_filter,
- NULL,
- &filter_desc);
- if (Status != ERROR_SUCCESS) {
- printf("TdhAggregatePayloadFilters() failed with %lu\n", Status);
- }
-
- return 1;
- }
-
- inline void ut::populate_provider_enable_info(
+ inline void ut::set_provider_enable_info(
const ut::provider_type& provider,
- ut::provider_enable_info& info)
+ ut::enable_trace_info& info)
{
info.parameters.ControlFlags = 0;
info.parameters.Version = ENABLE_TRACE_PARAMETERS_VERSION_2;
@@ -411,117 +172,97 @@ namespace krabs { namespace details {
info.rundown_enabled |= provider.rundown_enabled_;
info.parameters.EnableProperty |= provider.enable_property_;
- info.parameters.FilterDescCount = 0;
- info.parameters.EnableFilterDesc = &info.event_buffer.filter_desc[0];
+
// There can only be one descriptor for each filter
// type as specified by the Type member of the
// EVENT_FILTER_DESCRIPTOR structure.
- for (const auto& direct_filters : provider.direct_filters_) {
- for (const auto& direct_filter : direct_filters.list_) {
- switch (direct_filter->get_type()) {
- case EVENT_FILTER_TYPE_SYSTEM_FLAGS: {
- auto system_flags = reinterpret_cast(direct_filter.get());
- if (ULONG count = populate_system_flags_filter_desc(info, system_flags))
- {
- info.parameters.FilterDescCount += count;
- }
- break;
- }
- case EVENT_FILTER_TYPE_EVENT_ID: {
- auto event_ids = reinterpret_cast(direct_filter.get());
- if (ULONG count = populate_event_id_filter_desc(info, event_ids))
- {
- info.parameters.FilterDescCount += count;
- }
- break;
- }
- case EVENT_FILTER_TYPE_EVENT_NAME: {
- auto event_names = reinterpret_cast(direct_filter.get());
- if (ULONG count = populate_event_name_filter_desc(info, event_names))
- {
- info.parameters.FilterDescCount += count;
- }
- break;
- }
- case EVENT_FILTER_TYPE_PAYLOAD: {
- auto event_payload = dynamic_cast(direct_filter.get());
- if (ULONG count = populate_event_payload_filter_desc(info, event_payload))
- {
- info.parameters.FilterDescCount += count;
- }
- break;
- }
- case EVENT_FILTER_TYPE_PID: {
- auto event_pids = reinterpret_cast(direct_filter.get());
- if (ULONG count = populate_event_pid_filter_desc(info, event_pids))
- {
- info.parameters.FilterDescCount += count;
- }
- break;
- }
- default: {
- break;
- }
- }
- }
+ if (provider.pre_filter_.count == 0)
+ {
+ info.parameters.FilterDescCount = 0;
+ info.parameters.EnableFilterDesc = &info.filter_desc[0];
}
-
- //return enable_trace_parameters{ 0 };
+ else
+ {
+ info.parameters.FilterDescCount = provider.pre_filter_.count;
+ info.parameters.EnableFilterDesc = const_cast(&provider.pre_filter_.descriptor[0]);
+ }
}
+
inline void ut::enable_providers(
krabs::trace& trace)
{
if (trace.registrationHandle_ == INVALID_PROCESSTRACE_HANDLE) {
return;
}
-
- std::lock_guard lock(trace.providers_mutex_);
- provider_enable_info_container providers_enable_info;
+
+ for (auto& provider : trace.enabled_providers_) {
+ auto& _provider = provider.get();
+ enable_provider(trace, _provider);
+ }
+ }
- // This function essentially takes the union of all the provider flags
+ inline void ut::enable_provider(
+ krabs::trace& trace,
+ const krabs::details::ut::provider_type& provider)
+ {
+ if (trace.registrationHandle_ == INVALID_PROCESSTRACE_HANDLE) {
+ return;
+ }
+
+ // This essentially takes the union of all the provider flags
// for a given provider GUID. This comes about when multiple providers
- // for the same GUID are provided and request different provider flags.
+ // for the same GUID are provided and request different provider flags.
+ auto& provider_enable_info = trace.provider_enable_info_[provider.guid_];
+ provider_enable_info.parameters.ControlFlags = 0;
+ provider_enable_info.parameters.Version = ENABLE_TRACE_PARAMETERS_VERSION_2;
+ provider_enable_info.guid = provider.guid_;
// TODO: Only forward the calls that are requested to each provider.
- for (auto& provider : trace.enabled_providers_) {
- auto& _provider = provider.get();
- auto& enable_info = providers_enable_info[_provider.guid_];
- populate_provider_enable_info(provider, enable_info);
-
- ULONG status = EnableTraceEx2(trace.registrationHandle_,
- &_provider.guid_,
- EVENT_CONTROL_CODE_ENABLE_PROVIDER,
- enable_info.level,
- enable_info.any,
- enable_info.all,
- 0,
- &enable_info.parameters);
+ provider_enable_info.level |= provider.level_;
+ provider_enable_info.any |= provider.any_;
+ provider_enable_info.all |= provider.all_;
+ provider_enable_info.rundown_enabled |= provider.rundown_enabled_;
+ provider_enable_info.parameters.EnableProperty |= provider.enable_property_;
- error_check_common_conditions(status);
+ // There can only be one descriptor for each filter
+ // type as specified by the Type member of the
+ // EVENT_FILTER_DESCRIPTOR structure.
+ if (provider.pre_filter_.count == 0)
+ {
+ provider_enable_info.parameters.FilterDescCount = 0;
+ provider_enable_info.parameters.EnableFilterDesc = &provider_enable_info.filter_desc[0];
}
+ else
+ {
+ provider_enable_info.parameters.FilterDescCount = provider.pre_filter_.count;
+ provider_enable_info.parameters.EnableFilterDesc = const_cast(&provider.pre_filter_.descriptor[0]);
+ }
+
+ ULONG status = EnableTraceEx2(trace.registrationHandle_,
+ &provider.guid_,
+ EVENT_CONTROL_CODE_ENABLE_PROVIDER,
+ provider_enable_info.level,
+ provider_enable_info.any,
+ provider_enable_info.all,
+ 0,
+ &provider_enable_info.parameters);
+
+ error_check_common_conditions(status);
}
+
inline void ut::disable_provider(
krabs::trace& trace,
- const krabs::details::ut::provider_type& p)
+ const krabs::details::ut::provider_type& provider)
{
if (trace.registrationHandle_ == INVALID_PROCESSTRACE_HANDLE) {
return;
}
-
- std::lock_guard lock(trace.providers_mutex_);
- auto& guid = p.guid_;
- auto it = std::find_if(
- trace.enabled_providers_.begin(),
- trace.enabled_providers_.end(),
- [&guid](const auto& x) {
- return krabs::guid(x.get().guid_) == guid;
- });
-
- if (it != trace.enabled_providers_.end()) {
+ auto it = trace.provider_enable_info_.find(provider.guid_);
+ if (it != trace.provider_enable_info_.end()) {
ULONG status = EnableTraceEx2(trace.registrationHandle_,
- &guid,
+ &provider.guid_,
EVENT_CONTROL_CODE_DISABLE_PROVIDER,
0,
0,
@@ -530,87 +271,13 @@ namespace krabs { namespace details {
NULL);
error_check_common_conditions(status);
- if (status == ERROR_SUCCESS) {
- trace.enabled_providers_.erase(it);
+ if (status == ERROR_SUCCESS) {
+ trace.provider_enable_info_.erase(it);
}
}
-
-
- /*while (!trace.disabled_providers_.empty()) {
- {
- auto& provider = trace.disabled_providers_.front();
- auto& _provider = provider.get();
- auto& guid = _provider.guid_;
-
- auto it = std::find_if(
- trace.enabled_providers_.begin(),
- trace.enabled_providers_.end(),
- [&guid](const auto& x) {
- return krabs::guid(x.get().guid_) == guid;
- });
-
- if (it == trace.enabled_providers_.end()) {
- ENABLE_TRACE_PARAMETERS parameters = { };
- ULONG status = EnableTraceEx2(trace.registrationHandle_,
- &guid,
- EVENT_CONTROL_CODE_DISABLE_PROVIDER,
- 0,
- 0,
- 0,
- 0,
- ¶meters);
-
- error_check_common_conditions(status);
- if (status == ERROR_SUCCESS) {
- trace.enabled_providers_.erase(it);
- }
- }
- }
-
- trace.disabled_providers_.pop_front();
- }*/
}
- inline void ut::update_provider(
- krabs::trace& trace,
- const krabs::details::ut::provider_type& p)
- {
- if (trace.registrationHandle_ == INVALID_PROCESSTRACE_HANDLE) {
- return;
- }
-
- {
- std::lock_guard lock(trace.providers_mutex_);
-
- auto& guid = p.guid();
- auto it = std::find_if(
- trace.enabled_providers_.begin(),
- trace.enabled_providers_.end(),
- [&guid](const auto& x) {
- return krabs::guid(x.get().guid()) == guid;
- });
-
- if (it != trace.enabled_providers_.end()) {
- ULONG status = EnableTraceEx2(trace.registrationHandle_,
- &guid,
- EVENT_CONTROL_CODE_DISABLE_PROVIDER,
- 0,
- 0,
- 0,
- 0,
- NULL);
-
- error_check_common_conditions(status);
-
- if (status == ERROR_SUCCESS) {
- return;
- }
- }
- }
-
-
-
- }
+
inline void ut::enable_rundown(
krabs::trace& trace)
@@ -618,8 +285,6 @@ namespace krabs { namespace details {
if (trace.registrationHandle_ == INVALID_PROCESSTRACE_HANDLE)
return;
- std::lock_guard lock(trace.providers_mutex_);
-
for (auto& provider : trace.enabled_providers_) {
if (!provider.get().rundown_enabled_)
continue;
@@ -643,9 +308,6 @@ namespace krabs { namespace details {
if (trace.registrationHandle_ == INVALID_PROCESSTRACE_HANDLE) {
return;
}
-
-
-
}
@@ -680,7 +342,6 @@ namespace krabs { namespace details {
const EVENT_RECORD &record,
krabs::trace &trace)
{
- std::lock_guard lock(trace.providers_mutex_);
// for manifest providers, EventHeader.ProviderId is the Provider GUID
for (auto& provider : trace.enabled_providers_) {
if (record.EventHeader.ProviderId == provider.get().guid_) {
diff --git a/examples/ManagedExamples/Program.cs b/examples/ManagedExamples/Program.cs
index f05064e..5f7547c 100644
--- a/examples/ManagedExamples/Program.cs
+++ b/examples/ManagedExamples/Program.cs
@@ -19,8 +19,8 @@ static void Main(string[] args)
//UserTrace007_StackTrace.Start();
//FakingEvents001.Start();
//WppTrace001.Start();
- //UserTrace008_DirectFilter.Start();
- UserTrace009_OpenTrace.Start();
+ UserTrace008_DirectFilter.Start();
+ //UserTrace009_OpenTrace.Start();
//UserTrace010_ExtendedData.Start();
}
}
diff --git a/examples/ManagedExamples/UserTrace008_DirecFilter.cs b/examples/ManagedExamples/UserTrace008_DirecFilter.cs
index 2329982..da13719 100644
--- a/examples/ManagedExamples/UserTrace008_DirecFilter.cs
+++ b/examples/ManagedExamples/UserTrace008_DirecFilter.cs
@@ -22,29 +22,35 @@ public static void Start()
// This is what EnableRundownEvents() does.
//provider.EnableRundownEvents();
List tt = new List();
- List ips = new List();
- for (int i = 5; i <= 7; i++)
- {
-
- ips.Add(i);
- }
- var f1 = new EventIdFilter(ips);
+
if (true)
{
var f2 = new SystemFlagsEventFilter(0xFFFFFFFFFFFF, 4);
tt.Add(f2);
}
+
+
+ var f4 = new SystemFlags(0xFFFFFFFFFFFF, 4);
+ List ids = new List();
+ ids.Add(5);
+ var f5 = new EventIds(ids);
+
//var filter3 = new EventIdFilter(5);
+ var pre = new PreEventFilter(
+ f4,
+ f5
+ );
//var directFilter = new DirectEventFilters(filter2, filter3);
- var processFilter = new EventFilter(Filter.EventIdIs(5)); // ProcessStart
- var directFilter = new DirectEventFilters(tt);
+ //var processFilter = new EventFilter(Filter.EventIdIs(5)); // ProcessStart
+ //var directFilter = new DirectEventFilters(tt);
+
//processFilter.OnEvent += ProcessEventHandler;
//provider.AddFilter(tt);
- provider.AddFilter(processFilter);
- provider.AddFilter(directFilter);
-
+ //provider.AddFilter(processFilter);
+ //provider.AddFilter(directFilter);
+ provider.AddFilter(pre);
// process rundown events - i.e. running processes
//var processRundownFilter = new EventFilter(Filter.EventIdIs(15)); // ProcessRundown
provider.OnEvent += ProcessEventHandler;
@@ -56,8 +62,8 @@ public static void Start()
private static void ProcessEventHandler(IEventRecord record)
{
- if(record.Id == 5)
- {
+ //if(record.Id == 5)
+ //{
//var pid = record.GetUInt32("ProcessID");
var keyName = record.GetUnicodeString("KeyName");
var valueName = record.GetUnicodeString("ValueName");
@@ -68,7 +74,7 @@ private static void ProcessEventHandler(IEventRecord record)
Console.WriteLine($"ValueName={valueName}");
Console.WriteLine($"CapturedDataSize={capturedDataSize}");
Console.WriteLine($"PreviousDataCapturedSize={previousDataCapturedSize}");
- }
+ //}
}
}
diff --git a/examples/NativeExamples/NativeExamples.vcxproj b/examples/NativeExamples/NativeExamples.vcxproj
index de25fc7..6ab1586 100644
--- a/examples/NativeExamples/NativeExamples.vcxproj
+++ b/examples/NativeExamples/NativeExamples.vcxproj
@@ -154,6 +154,7 @@
+
@@ -173,7 +174,7 @@
-
+
diff --git a/examples/NativeExamples/NativeExamples.vcxproj.filters b/examples/NativeExamples/NativeExamples.vcxproj.filters
index e4a7240..85ffd53 100644
--- a/examples/NativeExamples/NativeExamples.vcxproj.filters
+++ b/examples/NativeExamples/NativeExamples.vcxproj.filters
@@ -73,7 +73,10 @@
Source Files
-
+
+ Source Files
+
+
Source Files
diff --git a/examples/NativeExamples/examples.h b/examples/NativeExamples/examples.h
index ec1eb6b..5f90be6 100644
--- a/examples/NativeExamples/examples.h
+++ b/examples/NativeExamples/examples.h
@@ -105,8 +105,13 @@ struct user_trace_014_transition_trace
static void start();
};
-struct user_trace_015_update
+struct user_trace_015_update_trace
{
static void start1();
static void start2();
+};
+
+struct user_trace_016_update_provider
+{
+ static void start();
};
\ No newline at end of file
diff --git a/examples/NativeExamples/main.cpp b/examples/NativeExamples/main.cpp
index 20c9da2..0412074 100644
--- a/examples/NativeExamples/main.cpp
+++ b/examples/NativeExamples/main.cpp
@@ -23,9 +23,9 @@ int main(void)
//user_trace_008_stacktrace::start();
//user_trace_009_from_file::start();
//user_trace_009_from_file::start2();
- //user_trace_010_direct_filter::start();
+ user_trace_010_direct_filter::start();
//user_trace_011_search_wevt::start();
- user_trace_012_open_trace::start();
+ //user_trace_012_open_trace::start();
//user_trace_013_pktmon::start();
//user_trace_014_transition_trace::start();
//user_trace_015_update::start2();
diff --git a/examples/NativeExamples/user_trace_007_rundown.cpp b/examples/NativeExamples/user_trace_007_rundown.cpp
index 83d0e46..5725448 100644
--- a/examples/NativeExamples/user_trace_007_rundown.cpp
+++ b/examples/NativeExamples/user_trace_007_rundown.cpp
@@ -84,211 +84,4 @@ void user_trace_007_rundown::start()
trace.enable(dotnet_rundown_provider);
trace.start();
-}
-
-
-void user_trace_007_rundown::start2()
-{
- krabs::user_trace trace(L"user_trace_007");
-
-
- krabs::provider<> provider1(L"Microsoft-Windows-DotNETRuntimeRundown");
- krabs::provider<> provider2(L"Microsoft-Windows-Kernel-Power");
- krabs::provider<> provider3(L"Microsoft-Windows-DotNETRuntime");
- krabs::provider<> provider4(L"Microsoft-JScript");
- krabs::provider<> provider5(L"Microsoft-Windows-Win32k");
- krabs::provider<> provider6(L"Microsoft-Windows-UserModePowerService");
- krabs::provider<> provider7(L"Microsoft-Windows-Networking-Correlation");
- krabs::provider<> provider8(L"Microsoft-Windows-Kernel-Processor-Power");
- krabs::provider<> provider9(L"Microsoft-Windows-RPC");
- krabs::provider<> provider10(L"Microsoft-Windows-Kernel-EventTracing");
- krabs::provider<> provider11(L"Microsoft-Antimalware-Engine");
- krabs::provider<> provider12(L"Microsoft-Windows-Search-Core");
- krabs::provider<> provider13(L"Microsoft-Antimalware-AMFilter");
- krabs::provider<> provider14(L"Microsoft-Windows-Performance-Recorder-Control");
- krabs::provider<> provider20(krabs::guid(L"{e13c0d23-ccbc-4e12-931b-d9cc2eee27e4}"));
- krabs::provider<> provider15(L"Microsoft-Windows-Kernel-StoreMgr");
- krabs::provider<> provider16(L"Microsoft-Antimalware-RTP");
- krabs::provider<> provider17(L"Microsoft-Antimalware-Service");
- krabs::provider<> provider18(L"Microsoft-Windows-ProcessStateManager");
- krabs::provider<> provider19(L"Microsoft-Windows-ReadyBoostDriver");
- krabs::provider<> provider21(L"Microsoft-Windows-COMRuntime");
-
-
- // user_trace providers typically have any and all flags, whose meanings are
- // unique to the specific providers that are being invoked. To understand these
- // flags, you'll need to look to the ETW event producer.
- //provider.any(0xf0010000000003ff);
-
- // providers should be wired up with functions (or functors) that are called when
- // events from that provider are fired.
- provider1.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider2.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider3.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider4.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider5.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider6.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider7.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider8.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider9.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider10.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider11.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider12.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider13.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider14.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider15.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider16.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider17.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider18.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider19.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider20.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- provider21.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
- krabs::schema schema(record, trace_context.schema_locator);
- //std::wcout << L"Event " << schema.event_id() << std::endl;
- if (schema.event_id() == schema.event_id())
- return;
- });
- /* provider22.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
-
- });
- provider23.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
-
- });
- provider24.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
-
- });*/
-
-
-
- // the user_trace needs to know about the provider that we've set up.
- trace.enable(provider1);
- trace.enable(provider2);
- trace.enable(provider3);
- trace.enable(provider4);
- trace.enable(provider5);
- trace.enable(provider6);
- trace.enable(provider7);
- trace.enable(provider8);
- trace.enable(provider10);
- trace.enable(provider11);
- trace.enable(provider12);
- trace.enable(provider13);
- trace.enable(provider14);
- trace.enable(provider15);
- trace.enable(provider16);
- trace.enable(provider17);
- trace.enable(provider18);
- trace.enable(provider19);
- trace.enable(provider20);
- trace.enable(provider21);
- /* trace.enable(provider22);
- trace.enable(provider23);
- trace.enable(provider24);*/
- // specify a filename to read from, will disable realtime and source from file instead
-
-
- // begin listening for events. This call blocks until the end of file is reached, so if
- // you want to do other things while this runs, you'll need to call this on another thread.
- trace.start();
-
}
\ No newline at end of file
diff --git a/examples/NativeExamples/user_trace_010_direct_filter.cpp b/examples/NativeExamples/user_trace_010_direct_filter.cpp
index 808c3dc..531219c 100644
--- a/examples/NativeExamples/user_trace_010_direct_filter.cpp
+++ b/examples/NativeExamples/user_trace_010_direct_filter.cpp
@@ -15,107 +15,43 @@ void user_trace_010_direct_filter::start()
{
krabs::user_trace trace(L"My Named Trace");
krabs::provider<> provider(L"Microsoft-Windows-Kernel-Audit-API-Calls");
- //krabs::provider<> provider(L"Microsoft-Windows-PowerShell");
- krabs::predicates::id_is eventid_is_5 = krabs::predicates::id_is(5);
- /*
-
- -
-
- 53504
- 1
- 4
- 111
- 10
- 0x0
-
- 31
-
-
- Microsoft-Windows-PowerShell/Operational
- DESKTOP-L5HRUTP
-
-
--
- 17916
- DefaultAppDomain
- */
-
- auto custom_filter = std::make_shared(0xFFFFFFFFFFFF, 4);// krabs::none_type_filter((unsigned long long)0xFFFFFFFFFFFF, 4);
- auto eventid = std::make_shared(std::set{ 5 }, true);
- auto pid = std::make_shared(std::set{ 4 }, true);
-
- auto eventname = std::make_shared(std::set{ "name1", "name2" }, true);
+ //auto custom_filter = std::make_shared(0xFFFFFFFFFFFF, 4);// krabs::none_type_filter((unsigned long long)0xFFFFFFFFFFFF, 4);
+ //auto eventid = std::make_shared(std::set{ 5 }, true);
+ //auto pid = std::make_shared(std::set{ 4 }, true);
+ //auto eventname = std::make_shared(std::set{ "name1", "name2" }, true);
//auto eventid = krabs::event_id_type_filter({ 5 }, true);
- auto payload_filter = std::make_shared(L"DesiredAccess", (unsigned short)PAYLOADFIELD_GE, L"12288");
-
- auto sy = krabs::system_flags_descriptor(0xFFFFFFFFFFFF, 4);
- auto id = krabs::event_id_descriptor(std::set{ 5, 12, 31, 131, 133 }, true);
+ //auto payload_filter = std::make_shared(L"DesiredAccess", (unsigned short)PAYLOADFIELD_GE, L"12288");
+ //auto sy = krabs::system_flags_descriptor(0xFFFFFFFFFFFF, 4);
+ //auto id = krabs::event_id_descriptor(std::set{ 5, 12, 31, 131, 133 }, true);
+ //auto d1 = sy();
+ //auto d2 = id();
+ //krabs::direct_event_filters1 direct_filter1({ &sy,&id });
+ //auto a = direct_filter1();
+ //krabs::direct_event_filters direct_filter({
+ // eventid,
+ // payload_filter,
+ // custom_filter,
+ // pid
+ //eventname
+ // });
- auto d1 = sy();
- auto d2 = id();
+ auto a1 = std::make_shared(0xFFFFFFFFFFFF, 4);
+ auto a2 = std::make_shared(std::set{ 5, 12, 31, 131, 133 }, true);
+ krabs::pre_event_filter pre_filter({ a1,a2 });
- krabs::direct_event_filters1 direct_filter1({&sy,&id});
- auto a = direct_filter1();
- krabs::direct_event_filters direct_filter({
- eventid,
- payload_filter,
- custom_filter,
- pid
- //eventname
- });
- krabs::event_filter filter(
- krabs::predicates::any_of({
- &eventid_is_5
- })
- );
- /*
- filter.add_custom_filter(0xFFFFFFFFFFFF, 4);*/
provider.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
krabs::schema schema(record, trace_context.schema_locator);
assert(schema.event_id() == 5);
krabs::parser parser(schema);
- std::wcout << L" PID=" << schema.process_id() << std::endl;
+ std::wcout << L" ProviderID=" << schema.provider_name() << std::endl;
std::wcout << L" EventID=" << schema.event_id() << std::endl;
- std::wcout << L" TargetProcessId=" << parser.parse(L"TargetProcessId");
- std::wcout << L" DesiredAccess=" << parser.parse(L"DesiredAccess");
- std::wcout << L" ReturnCode=" << parser.parse(L"ReturnCode");
- /*
- std::wcout << L" ContextInfo=" << parser.parse(L"ContextInfo") << std::endl;
- std::wcout << L" UserData=" << parser.parse(L"UserData") << std::endl;
- std::wcout << L" Payload=" << parser.parse(L"Payload") << std::endl;*/
-
-
-
- /*auto t = parser.parse(L"CapturedData");
- std::wcout << L" EventID=" << schema.event_id() << std::endl;
- std::wcout << L" KeyName=" << parser.parse(L"KeyName") << std::endl;
- std::wcout << L" ValueName=" << parser.parse(L"ValueName") << std::endl;
- std::wcout << L" CapturedDataSize=" << parser.parse(L"CapturedDataSize") << std::endl;
- std::wcout << L" PreviousDataCapturedSize=" << parser.parse(L"PreviousDataCapturedSize") << std::endl;*/
-
-
-
-
});
- provider.add_filter(direct_filter);
- //provider.add_filter(filter);
+ provider.add_filter(pre_filter);
trace.enable(provider);
-
- std::thread workerThread([&]() {
- trace.start();
- });
-
- const int durationInSeconds = 30;
- std::this_thread::sleep_for(std::chrono::seconds(durationInSeconds));
- trace.stop();
-
- workerThread.join();
-
- //std::wcout << L" DirectFilter: Events in 30s =" << trace.query_stats().eventsTotal << std::endl;
- std::wcout << L" IndirectFilter: Events in 30s =" << trace.query_stats().eventsTotal << std::endl;
+ trace.start();
}
\ No newline at end of file
diff --git a/examples/NativeExamples/user_trace_012_open_trace.cpp b/examples/NativeExamples/user_trace_012_open_trace.cpp
index 8e66b14..4fe3b73 100644
--- a/examples/NativeExamples/user_trace_012_open_trace.cpp
+++ b/examples/NativeExamples/user_trace_012_open_trace.cpp
@@ -71,6 +71,11 @@
//
//}
+
+
+///
+/// Note: For existing sessions, pre-filtering capabilities cannot be used.
+///
void user_trace_012_open_trace::start()
{
krabs::user_trace trace(L"DefenderApiLogger");
diff --git a/examples/NativeExamples/user_trace_015_update.cpp b/examples/NativeExamples/user_trace_015_update_trace.cpp
similarity index 96%
rename from examples/NativeExamples/user_trace_015_update.cpp
rename to examples/NativeExamples/user_trace_015_update_trace.cpp
index 374dd5e..f22dc6f 100644
--- a/examples/NativeExamples/user_trace_015_update.cpp
+++ b/examples/NativeExamples/user_trace_015_update_trace.cpp
@@ -11,8 +11,10 @@
#include "examples.h"
-
-void user_trace_015_update::start1()
+///
+/// start session
+///
+void user_trace_015_update_trace::start1()
{
krabs::user_trace trace(L"test_sense");
@@ -64,7 +66,10 @@ void user_trace_015_update::start1()
}
-void user_trace_015_update::start2()
+///
+/// open session
+///
+void user_trace_015_update_trace::start2()
{
krabs::user_trace trace(L"test_sense");
@@ -146,4 +151,10 @@ void user_trace_015_update::start2()
trace.stop();
workerThread.join();
-}
\ No newline at end of file
+}
+
+
+
+
+
+
diff --git a/examples/NativeExamples/user_trace_016_update_provider.cpp b/examples/NativeExamples/user_trace_016_update_provider.cpp
new file mode 100644
index 0000000..f66b181
--- /dev/null
+++ b/examples/NativeExamples/user_trace_016_update_provider.cpp
@@ -0,0 +1,60 @@
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+// This example shows how to use a user_trace with an ETL file
+#pragma once
+
+#include
+#include
+#include
+
+#include "..\..\bluekrabs\krabs.hpp"
+#include "examples.h"
+
+
+///
+/// Note: This example demonstrates:
+/// 1. Enabling a provider and running for 10 seconds
+/// 2. Enabling an additional provider during runtime and run for another 10 seconds
+/// 3. Disabling a provider during runtime and running for another 10 seconds
+///
+void user_trace_016_update_provider::start()
+{
+ krabs::user_trace trace(L"update_provider");
+ krabs::provider<> provider_api(L"Microsoft-Windows-Kernel-Audit-API-Calls");
+ provider_api.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+
+ krabs::parser parser(schema);
+
+ std::wcout << L" ProviderID=" << schema.provider_name() << std::endl;
+ std::wcout << L" EventID=" << schema.event_id() << std::endl;
+
+ });
+
+ trace.enable(provider_api);
+ std::thread workerThread([&]() {
+ trace.start();
+ });
+
+ const int durationInSeconds = 10;
+ std::this_thread::sleep_for(std::chrono::seconds(durationInSeconds));
+
+ krabs::provider<> provider_power(L"Microsoft-Windows-PowerShell");
+ provider_power.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
+ krabs::schema schema(record, trace_context.schema_locator);
+
+ krabs::parser parser(schema);
+
+ std::wcout << L" ProviderID=" << schema.provider_name() << std::endl;
+ std::wcout << L" EventID=" << schema.event_id() << std::endl;
+
+ });
+
+ trace.enable(provider_power);
+ std::this_thread::sleep_for(std::chrono::seconds(durationInSeconds));
+ trace.disable(provider_power);
+ std::this_thread::sleep_for(std::chrono::seconds(durationInSeconds));
+ trace.stop();
+ workerThread.join();
+
+}
From b88ad004fade0eece53f0087d22f4307dc41f69e Mon Sep 17 00:00:00 2001
From: Dominik Phillips
Date: Wed, 17 Jul 2024 17:38:15 +0200
Subject: [PATCH 09/15] update: managed code e.g. removed directfilter
---
...t.O365.Security.Native.ETW.NetCore.vcxproj | 1 -
.../Filtering/DirectEventFilter.hpp | 157 ------------------
...Microsoft.O365.Security.Native.ETW.vcxproj | 1 -
...t.O365.Security.Native.ETW.vcxproj.filters | 3 -
.../Provider.hpp | 17 --
bluekrabs/bluekrabs.sln | 1 -
bluekrabs/krabs/provider.hpp | 10 --
.../UserTrace008_DirecFilter.cs | 8 +-
8 files changed, 1 insertion(+), 197 deletions(-)
delete mode 100644 Threathunters.BlueKrabsetw.Native.ETW/Filtering/DirectEventFilter.hpp
diff --git a/Threathunters.BlueKrabsetw.Native.ETW.NetCore/Microsoft.O365.Security.Native.ETW.NetCore.vcxproj b/Threathunters.BlueKrabsetw.Native.ETW.NetCore/Microsoft.O365.Security.Native.ETW.NetCore.vcxproj
index c86f54e..c6df4dc 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW.NetCore/Microsoft.O365.Security.Native.ETW.NetCore.vcxproj
+++ b/Threathunters.BlueKrabsetw.Native.ETW.NetCore/Microsoft.O365.Security.Native.ETW.NetCore.vcxproj
@@ -212,7 +212,6 @@
-
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/Filtering/DirectEventFilter.hpp b/Threathunters.BlueKrabsetw.Native.ETW/Filtering/DirectEventFilter.hpp
deleted file mode 100644
index b0e6313..0000000
--- a/Threathunters.BlueKrabsetw.Native.ETW/Filtering/DirectEventFilter.hpp
+++ /dev/null
@@ -1,157 +0,0 @@
-#pragma once
-
-#include "../Conversions.hpp"
-#include "../EventRecordError.hpp"
-#include "../EventRecord.hpp"
-#include "../EventRecordMetadata.hpp"
-#include "../Guid.hpp"
-#include "../IEventRecord.hpp"
-#include "../IEventRecordError.hpp"
-#include "../NativePtr.hpp"
-#include "Predicate.hpp"
-
-using namespace System;
-using namespace System::Collections::Generic;
-using namespace System::Runtime::InteropServices;
-
-namespace Microsoft {
- namespace O365 {
- namespace Security {
- namespace ETW {
-
- public interface class IDirectEventFilter
- {
- public:
- virtual unsigned int GetEventType();
- virtual unsigned long GetSize();
- };
-
- public ref class SystemFlagsEventFilter : IDirectEventFilter
- {
- public:
- SystemFlagsEventFilter(unsigned long long flags, unsigned long size)
- : flags_(flags),
- type_(EVENT_FILTER_TYPE_SYSTEM_FLAGS),
- size_(size)
- {
- }
-
- virtual unsigned int GetEventType()
- {
- return type_;
- }
-
- virtual unsigned long GetSize()
- {
- return size_;
- }
-
- unsigned long long GetFlag()
- {
- return flags_;
- }
-
-
- private:
- unsigned long long flags_;
- unsigned int type_;
- unsigned long size_;
- };
-
- public ref class EventIdFilter : IDirectEventFilter
- {
- public:
- EventIdFilter(IEnumerable^ ids)
- : ids_(gcnew List(ids)),
- type_(EVENT_FILTER_TYPE_EVENT_ID),
- size_(0)
- {
- }
-
- EventIdFilter(... array^ ids)
- : ids_(gcnew List(ids)),
- type_(EVENT_FILTER_TYPE_EVENT_ID),
- size_(0)
- {
- }
-
- virtual unsigned int GetEventType()
- {
- return type_;
- }
-
- virtual unsigned long GetSize()
- {
- return size_;
- }
-
- List^ GetList()
- {
- return ids_;
- }
-
- private:
- List^ ids_;
- unsigned int type_;
- unsigned long size_;
- };
-
-
- public ref class DirectEventFilters
- {
- public:
- DirectEventFilters(IEnumerable^ filters)
- : directFilterList_(gcnew List(filters)),
- filter_(new krabs::direct_event_filters())
- {
- }
-
- DirectEventFilters(... array^ filters)
- : directFilterList_(gcnew List(filters)),
- filter_(new krabs::direct_event_filters())
- {
- }
-
- internal:
- operator krabs::direct_event_filters& ()
- {
-
- for each (auto filter in directFilterList_)
- {
- switch (filter->GetEventType()) {
- case EVENT_FILTER_TYPE_SYSTEM_FLAGS: {
- if (auto typeFilter = dynamic_cast(filter))
- {
- auto p = std::make_shared(typeFilter->GetFlag(), typeFilter->GetSize());
- filter_->list_.emplace_back(p);
- }
- break;
- }
- case EVENT_FILTER_TYPE_EVENT_ID: {
- if (auto typeFilter = dynamic_cast(filter))
- {
- std::set tmp;
- for each (auto l in typeFilter->GetList())
- {
- tmp.insert(static_cast(l));
- }
- auto p = std::make_shared(tmp, TRUE);
- filter_->list_.emplace_back(p);
- }
- break;
- }
- default: {
-
- }
- }
- }
- return *filter_;
- }
-
- NativePtr filter_;
- List^ directFilterList_;
- };
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/Microsoft.O365.Security.Native.ETW.vcxproj b/Threathunters.BlueKrabsetw.Native.ETW/Microsoft.O365.Security.Native.ETW.vcxproj
index 5205690..123a5ce 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW/Microsoft.O365.Security.Native.ETW.vcxproj
+++ b/Threathunters.BlueKrabsetw.Native.ETW/Microsoft.O365.Security.Native.ETW.vcxproj
@@ -207,7 +207,6 @@
-
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/Microsoft.O365.Security.Native.ETW.vcxproj.filters b/Threathunters.BlueKrabsetw.Native.ETW/Microsoft.O365.Security.Native.ETW.vcxproj.filters
index 9e49ece..f1532d7 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW/Microsoft.O365.Security.Native.ETW.vcxproj.filters
+++ b/Threathunters.BlueKrabsetw.Native.ETW/Microsoft.O365.Security.Native.ETW.vcxproj.filters
@@ -122,9 +122,6 @@
Header Files
-
- Header Files\Filtering
-
Header Files\Filtering
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/Provider.hpp b/Threathunters.BlueKrabsetw.Native.ETW/Provider.hpp
index daaa5bd..f10437c 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW/Provider.hpp
+++ b/Threathunters.BlueKrabsetw.Native.ETW/Provider.hpp
@@ -10,7 +10,6 @@
#include "Guid.hpp"
#include "NativePtr.hpp"
#include "Filtering/EventFilter.hpp"
-#include "Filtering/DirectEventFilter.hpp"
#include "Filtering/PreEventfilter.hpp"
using namespace System;
@@ -174,26 +173,10 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
provider_->add_filter(filter);
}
- ///
- /// Adds a new EventFilter to the provider.
- ///
- /// the to add
- void AddFilter(O365::Security::ETW::DirectEventFilters^ filter) {
- provider_->add_filter(filter);
- }
-
void AddFilter(O365::Security::ETW::PreEventFilter^ filter) {
provider_->add_filter(filter);
}
- ///
- /// Adds a new EventFilter to the provider.
- ///
- /// the to add
- /*void AddFilter(O365::Security::ETW::PreEventFilter^ filter) {
- provider_->add_filter(filter);
- }*/
-
///
/// An event that is invoked when an ETW event is fired in this
/// provider.
diff --git a/bluekrabs/bluekrabs.sln b/bluekrabs/bluekrabs.sln
index 1743510..c260f0b 100644
--- a/bluekrabs/bluekrabs.sln
+++ b/bluekrabs/bluekrabs.sln
@@ -70,7 +70,6 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "filtering", "filtering", "{DE5DA5AA-BA9F-4D07-AF37-E1CE1487217C}"
ProjectSection(SolutionItems) = preProject
krabs\filtering\comparers.hpp = krabs\filtering\comparers.hpp
- krabs\filtering\direct_event_filter.hpp = krabs\filtering\direct_event_filter.hpp
krabs\filtering\event_filter.hpp = krabs\filtering\event_filter.hpp
krabs\filtering\post_event_filter.hpp = krabs\filtering\post_event_filter.hpp
krabs\filtering\predicates.hpp = krabs\filtering\predicates.hpp
diff --git a/bluekrabs/krabs/provider.hpp b/bluekrabs/krabs/provider.hpp
index af8d394..a61efff 100644
--- a/bluekrabs/krabs/provider.hpp
+++ b/bluekrabs/krabs/provider.hpp
@@ -10,7 +10,6 @@
#include "compiler_check.hpp"
#include "filtering/event_filter.hpp"
-#include "filtering/direct_event_filter.hpp"
#include "filtering/pre_event_filter.hpp"
#include "perfinfo_groupmask.hpp"
#include "trace_context.hpp"
@@ -113,8 +112,6 @@ namespace krabs {
*/
void add_filter(const event_filter &f);
- void add_filter(const direct_event_filters& f);
-
void add_filter(const pre_event_filter& f);
protected:
@@ -129,7 +126,6 @@ namespace krabs {
std::deque callbacks_;
std::deque error_callbacks_;
std::deque filters_;
- std::deque direct_filters_;
filter_descriptor pre_filter_;
private:
template
@@ -500,12 +496,6 @@ namespace krabs {
filters_.push_back(f);
}
- template
- void base_provider::add_filter(const direct_event_filters& f)
- {
- direct_filters_.push_back(f);
- }
-
template
void base_provider::add_filter(const pre_event_filter& f)
{
diff --git a/examples/ManagedExamples/UserTrace008_DirecFilter.cs b/examples/ManagedExamples/UserTrace008_DirecFilter.cs
index da13719..aed49f6 100644
--- a/examples/ManagedExamples/UserTrace008_DirecFilter.cs
+++ b/examples/ManagedExamples/UserTrace008_DirecFilter.cs
@@ -21,13 +21,7 @@ public static void Start()
// The trace needs to be sent EVENT_CONTROL_CODE_CAPTURE_STATE.
// This is what EnableRundownEvents() does.
//provider.EnableRundownEvents();
- List tt = new List();
-
- if (true)
- {
- var f2 = new SystemFlagsEventFilter(0xFFFFFFFFFFFF, 4);
- tt.Add(f2);
- }
+
var f4 = new SystemFlags(0xFFFFFFFFFFFF, 4);
From cf0162a8788fefd662087f9fb00fedb86d796535 Mon Sep 17 00:00:00 2001
From: Dominik Phillips <153827241+x86phil@users.noreply.github.com>
Date: Wed, 17 Jul 2024 17:56:55 +0200
Subject: [PATCH 10/15] Update README.md
---
README.md | 33 ++++++++++++++++++++++++---------
1 file changed, 24 insertions(+), 9 deletions(-)
diff --git a/README.md b/README.md
index ca7761d..ad78a69 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,31 @@
Overview
-========
-
+==============
**bluekrabsetw** is a C++ library that simplifies interacting with ETW. It allows for any number of traces and providers to be enabled and for client code to register for event notifications from these traces. **bluekrabsetw** originates from the **krabsetw** c++ library and seeks to improve and include capabilities that have not yet been included in the former library.
-**bluekrabsetw** also provides code to simplify parsing generic event data into strongly typed data types.
+**bluekrabsetw** also provides code to simplify parsing generic event data into strongly typed data types.
-**Microsoft.O365.Security.Native.ETW** is a C++ CLI (.NET) wrapper around **krabsetw**. It provides the same functionality as **krabsetw** to .NET applications and is used in production by the Office 365 Security team. It's affectionately referred to as **Lobsters**.
+**Threathunters.BlueKrabsetw.Native.ETW** is a C++ CLI (.NET) wrapper around **bluekrabsetw**. It provides the same functionality as bluekrabsetw to .NET applications.
-Examples & Documentation
-========
+Additional Capabilities
+==============
+The following capabilities have been integrated into the solution alongside the original krabsetw C++ library:
+- **Provider Enhanced Runtime Capabilities**:
+ - Supports enabling and disabling providers dynamically to adapt to changing requirements. This includes: Provider Addition, Removal, and Update Functionality
+
+- **Session Enhanced Runtime Capabilities**:
+ - todo
+
+- **Decoupling of Functionality to Allow Better Control of Sessions**:
+ - Provides improved modularity and flexibility, making it easier to manage and control Sessions.
+- **Improved Pre-Filtering Mechanisms**:
+ - Optimizes data processing by allowing more efficient filtering before data is collected.
+
+These enhancements extend the core features of the original krabsetw C++ library, providing a more robust and flexible solution.
+
+Examples & Documentation
+==============
* An [ETW Primer](docs/EtwPrimer.md).
* Simple examples can be found in the `examples` folder.
* Please refer to [KrabsExample.md](docs/KrabsExample.md) and [LobstersExample.md](docs/LobstersExample.md) for detailed examples.
@@ -19,12 +34,12 @@ Examples & Documentation
Important Notes
==============
-* `krabsetw` and `Microsoft.O365.Security.Native.ETW` only support x64. No effort has been made to support x86.
-* `krabsetw` and `Microsoft.O365.Security.Native.ETW` are only supported on Windows 7 or Windows 2008R2 machines and above.
+* `bluekrabsetw` and `Threathunters.BlueKrabsetw.Native.ETW` only support x64. No effort has been made to support x86.
+* `bluekrabsetw` and `Threathunters.BlueKrabsetw.Native.ETW` are only supported on Windows 7 or Windows 2008R2 machines and above.
* Throwing exceptions in the event handler callback or krabsetw or Microsoft.O365.Security.Native.ETW will cause the trace to stop processing events.
* The call to "start" on the trace object is blocking so thread management may be necessary.
* The Visual Studio solution is krabs\krabs.sln.
-* When building a native code binary using the `krabsetw` package, please refer to the [compilation readme](krabs/README.md) for notes about the `TYPEASSERT` and `NDEBUG` compilation flags.
+* When building a native code binary using the `bluekrabsetw` package, please refer to the [compilation readme](krabs/README.md) for notes about the `TYPEASSERT` and `NDEBUG` compilation flags.
NuGet Packages
==============
From 9a90fc97035a7df25cd59ee8d7fb157f1daf3bf2 Mon Sep 17 00:00:00 2001
From: Dominik Phillips <153827241+x86phil@users.noreply.github.com>
Date: Wed, 17 Jul 2024 18:02:28 +0200
Subject: [PATCH 11/15] Update README.md
---
README.md | 31 +++++++++++++++----------------
1 file changed, 15 insertions(+), 16 deletions(-)
diff --git a/README.md b/README.md
index ad78a69..a68dfd7 100644
--- a/README.md
+++ b/README.md
@@ -7,22 +7,21 @@ Overview
**Threathunters.BlueKrabsetw.Native.ETW** is a C++ CLI (.NET) wrapper around **bluekrabsetw**. It provides the same functionality as bluekrabsetw to .NET applications.
-Additional Capabilities
-==============
-The following capabilities have been integrated into the solution alongside the original krabsetw C++ library:
-- **Provider Enhanced Runtime Capabilities**:
- - Supports enabling and disabling providers dynamically to adapt to changing requirements. This includes: Provider Addition, Removal, and Update Functionality
-
-- **Session Enhanced Runtime Capabilities**:
- - todo
-
-- **Decoupling of Functionality to Allow Better Control of Sessions**:
- - Provides improved modularity and flexibility, making it easier to manage and control Sessions.
-
-- **Improved Pre-Filtering Mechanisms**:
- - Optimizes data processing by allowing more efficient filtering before data is collected.
-
-These enhancements extend the core features of the original krabsetw C++ library, providing a more robust and flexible solution.
+> ### Additional Capabilities
+> The following capabilities have been integrated into the solution alongside the original krabsetw C++ library:
+> * **Provider Enhanced Runtime Capabilities**:
+> * Supports enabling and disabling providers dynamically to adapt to changing requirements. This includes: Provider Addition, Removal, and Update Functionality
+>
+> * **Session Enhanced Runtime Capabilities**:
+> * todo
+>
+> * **Decoupling of Functionality to Allow Better Control of Sessions**:
+> * Provides improved modularity and flexibility, making it easier to manage and control Sessions.
+>
+> * **Improved Pre-Filtering Mechanisms**:
+> * Optimizes data processing by allowing more efficient filtering before data is collected.
+>
+> These enhancements extend the core features of the original krabsetw C++ library, providing a more robust and flexible solution.
Examples & Documentation
==============
From 38e00c0a1a366650fb69bfc42f73c495dbc0a146 Mon Sep 17 00:00:00 2001
From: Dominik Phillips
Date: Thu, 18 Jul 2024 13:13:43 +0200
Subject: [PATCH 12/15] update: query_stats struct to include config info
---
.../ITrace.hpp | 5 +
.../KernelTrace.hpp | 15 ++
.../TraceStats.hpp | 14 +-
.../UserTrace.hpp | 16 ++
bluekrabs/krabs/trace.hpp | 63 +++-----
bluekrabs/krabs/ut.hpp | 89 +----------
examples/NativeExamples/examples.h | 3 +-
examples/NativeExamples/main.cpp | 4 +-
.../user_trace_015_update_trace.cpp | 150 +++---------------
9 files changed, 88 insertions(+), 271 deletions(-)
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/ITrace.hpp b/Threathunters.BlueKrabsetw.Native.ETW/ITrace.hpp
index b504b0c..ab710ef 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW/ITrace.hpp
+++ b/Threathunters.BlueKrabsetw.Native.ETW/ITrace.hpp
@@ -43,6 +43,11 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
///
void Close();
+ ///
+ /// Stops listening for events.
+ ///
+ void Update();
+
///
/// Get stats about events handled by this trace.
///
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/KernelTrace.hpp b/Threathunters.BlueKrabsetw.Native.ETW/KernelTrace.hpp
index e04d2d9..46180d8 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW/KernelTrace.hpp
+++ b/Threathunters.BlueKrabsetw.Native.ETW/KernelTrace.hpp
@@ -163,6 +163,16 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
///
virtual void Close();
+ ///
+ /// Stops listening for events.
+ ///
+ ///
+ /// KernelTrace trace = new KernelTrace();
+ /// // ...
+ /// trace.Start();
+ /// trace.Stop();
+ ///
+ virtual void Update();
///
/// Get stats about events handled by this trace
@@ -267,6 +277,11 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
ExecuteAndConvertExceptions(return trace_->close());
}
+ inline void KernelTrace::Close()
+ {
+ ExecuteAndConvertExceptions(return trace_->update());
+ }
+
inline TraceStats KernelTrace::QueryStats()
{
ExecuteAndConvertExceptions(return TraceStats(trace_->query_stats()));
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/TraceStats.hpp b/Threathunters.BlueKrabsetw.Native.ETW/TraceStats.hpp
index 7178676..eded92e 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW/TraceStats.hpp
+++ b/Threathunters.BlueKrabsetw.Native.ETW/TraceStats.hpp
@@ -36,13 +36,13 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
internal:
TraceStats(const krabs::trace_stats& stats)
- : BuffersCount(stats.buffersCount)
- , BuffersFree(stats.buffersFree)
- , BuffersWritten(stats.buffersWritten)
- , BuffersLost(stats.buffersLost)
- , EventsTotal(stats.eventsTotal)
- , EventsHandled(stats.eventsHandled)
- , EventsLost(stats.eventsLost)
+ : BuffersCount(stats.buffers_count)
+ , BuffersFree(stats.buffers_free)
+ , BuffersWritten(stats.buffers_written)
+ , BuffersLost(stats.buffers_lost)
+ , EventsTotal(stats.events_total)
+ , EventsHandled(stats.events_handled)
+ , EventsLost(stats.events_lost)
{ }
};
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/UserTrace.hpp b/Threathunters.BlueKrabsetw.Native.ETW/UserTrace.hpp
index a4eac41..b4994a0 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW/UserTrace.hpp
+++ b/Threathunters.BlueKrabsetw.Native.ETW/UserTrace.hpp
@@ -195,6 +195,17 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
///
virtual void Close();
+ ///
+ /// Stops listening for events.
+ ///
+ ///
+ /// UserTrace trace = new UserTrace();
+ /// // ...
+ /// trace.Start();
+ /// trace.Stop();
+ ///
+ virtual void Update();
+
///
/// Get stats about events handled by this trace
///
@@ -287,6 +298,11 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
ExecuteAndConvertExceptions(return trace_->close());
}
+ inline void UserTrace::Update()
+ {
+ ExecuteAndConvertExceptions(return trace_->close());
+ }
+
inline TraceStats UserTrace::QueryStats()
{
ExecuteAndConvertExceptions(return TraceStats(trace_->query_stats()));
diff --git a/bluekrabs/krabs/trace.hpp b/bluekrabs/krabs/trace.hpp
index e41b49d..51c9d83 100644
--- a/bluekrabs/krabs/trace.hpp
+++ b/bluekrabs/krabs/trace.hpp
@@ -35,32 +35,13 @@ namespace krabs {
*/
class trace_stats {
public:
- const uint32_t buffersCount;
- const uint32_t buffersFree;
- const uint32_t buffersWritten;
- const uint32_t buffersLost;
- const uint64_t eventsTotal;
- const uint64_t eventsHandled;
- const uint32_t eventsLost;
-
- trace_stats(uint64_t eventsHandled, const EVENT_TRACE_PROPERTIES& props)
- : buffersCount(props.NumberOfBuffers)
- , buffersFree(props.FreeBuffers)
- , buffersWritten(props.BuffersWritten)
- , buffersLost(props.RealTimeBuffersLost)
- , eventsTotal(eventsHandled + props.EventsLost)
- , eventsHandled(eventsHandled)
- , eventsLost(props.EventsLost)
- { }
- };
-
- /**
- *
- * Selected statistics about an ETW trace
- *
- */
- class trace_config {
- public:
+ const uint32_t buffers_count;
+ const uint32_t buffers_free;
+ const uint32_t buffers_written;
+ const uint32_t buffers_lost;
+ const uint64_t events_total;
+ const uint64_t events_handled;
+ const uint32_t events_lost;
const uint32_t buffer_size;
const uint32_t minimum_buffers;
const uint32_t maximum_buffers;
@@ -71,9 +52,16 @@ namespace krabs {
const std::wstring log_file_name;
const std::wstring logger_name;
const uint32_t flush_threshold;
-
- trace_config(const details::trace_info& props)
- : buffer_size(props.properties.BufferSize)
+
+ trace_stats(uint64_t eventsHandled, details::trace_info& props)
+ : buffers_count(props.properties.NumberOfBuffers)
+ , buffers_free(props.properties.FreeBuffers)
+ , buffers_written(props.properties.BuffersWritten)
+ , buffers_lost(props.properties.RealTimeBuffersLost)
+ , events_total(eventsHandled + props.properties.EventsLost)
+ , events_handled(eventsHandled)
+ , events_lost(props.properties.EventsLost)
+ , buffer_size(props.properties.BufferSize)
, minimum_buffers(props.properties.MinimumBuffers)
, maximum_buffers(props.properties.MaximumBuffers)
, maximum_file_size(props.properties.MaximumFileSize)
@@ -86,7 +74,6 @@ namespace krabs {
{ }
};
-
/**
*
* Represents a single trace session that can have multiple
@@ -330,13 +317,6 @@ namespace krabs {
*/
trace_stats query_stats();
- /**
- *
- * Queries the trace session to get the configuration.
- *
- */
- trace_config query_config();
-
/**
*
* Returns the number of buffers that were processed.
@@ -604,14 +584,7 @@ namespace krabs {
trace_stats trace::query_stats()
{
details::trace_manager manager(*this);
- return { eventsHandled_, manager.query().properties };
- }
-
- template
- trace_config trace::query_config()
- {
- details::trace_manager manager(*this);
- return { manager.query() };
+ return { eventsHandled_, manager.query() };
}
template
diff --git a/bluekrabs/krabs/ut.hpp b/bluekrabs/krabs/ut.hpp
index 6d5d9fb..11d410e 100644
--- a/bluekrabs/krabs/ut.hpp
+++ b/bluekrabs/krabs/ut.hpp
@@ -61,15 +61,6 @@ namespace krabs { namespace details {
static const unsigned long construct_enable_flags(
const krabs::trace &trace);
- /**
- *
- * todo.
- *
- */
- static void set_provider_enable_info(
- const ut::provider_type& provider,
- ut::enable_trace_info& info);
-
/**
*
* Enables the providers that are attached to the given trace.
@@ -104,16 +95,7 @@ namespace krabs { namespace details {
*/
static void enable_rundown(
krabs::trace& trace);
-
- /**
- *
- * Enables the providers that are attached to the given trace.
- *
- */
- static void enable_trace(
- krabs::trace& trace
- /*const krabs::details::ut::provider_type& p*/);
-
+
/**
*
* Decides to forward an event to any of the providers in the trace.
@@ -157,37 +139,6 @@ namespace krabs { namespace details {
{
return 0;
}
-
- inline void ut::set_provider_enable_info(
- const ut::provider_type& provider,
- ut::enable_trace_info& info)
- {
- info.parameters.ControlFlags = 0;
- info.parameters.Version = ENABLE_TRACE_PARAMETERS_VERSION_2;
- info.guid = provider.guid_;
-
- info.level |= provider.level_;
- info.any |= provider.any_;
- info.all |= provider.all_;
- info.rundown_enabled |= provider.rundown_enabled_;
-
- info.parameters.EnableProperty |= provider.enable_property_;
-
- // There can only be one descriptor for each filter
- // type as specified by the Type member of the
- // EVENT_FILTER_DESCRIPTOR structure.
- if (provider.pre_filter_.count == 0)
- {
- info.parameters.FilterDescCount = 0;
- info.parameters.EnableFilterDesc = &info.filter_desc[0];
- }
- else
- {
- info.parameters.FilterDescCount = provider.pre_filter_.count;
- info.parameters.EnableFilterDesc = const_cast(&provider.pre_filter_.descriptor[0]);
- }
- }
-
inline void ut::enable_providers(
krabs::trace& trace)
@@ -250,7 +201,6 @@ namespace krabs { namespace details {
error_check_common_conditions(status);
}
-
inline void ut::disable_provider(
krabs::trace& trace,
const krabs::details::ut::provider_type& provider)
@@ -301,43 +251,6 @@ namespace krabs { namespace details {
}
}
- inline void ut::enable_trace(
- krabs::trace& trace
- /*const krabs::details::ut::provider_type& p*/)
- {
- if (trace.registrationHandle_ == INVALID_PROCESSTRACE_HANDLE) {
- return;
- }
- }
-
-
- //inline void ut::forward_events(
- // const EVENT_RECORD& record,
- // krabs::trace& trace)
- //{
- // krabs::guid guid = record.EventHeader.ProviderId;
- // auto& pos = trace.provider_pos_[guid];
- // auto& provider = trace.providers_[pos];
- // // for manifest providers, EventHeader.ProviderId is the Provider GUID
- // if (record.EventHeader.ProviderId == provider.get().guid_) {
- // provider.get().on_event(record, trace.context_);
- // return;
- // }
-
- // // for MOF providers, EventHeader.Provider is the *Message* GUID
- // // we need to ask TDH for event information in order to determine the
- // // correct provider to pass this event to
- // auto schema = get_event_schema_from_tdh(record);
- // auto eventInfo = reinterpret_cast(schema.get());
- // if (eventInfo->ProviderGuid == provider.get().guid_) {
- // provider.get().on_event(record, trace.context_);
- // return;
- // }
- //
- // if (trace.default_callback_ != nullptr)
- // trace.default_callback_(record, trace.context_);
- //}
-
inline void ut::forward_events(
const EVENT_RECORD &record,
krabs::trace &trace)
diff --git a/examples/NativeExamples/examples.h b/examples/NativeExamples/examples.h
index 5f90be6..fd33b55 100644
--- a/examples/NativeExamples/examples.h
+++ b/examples/NativeExamples/examples.h
@@ -107,8 +107,7 @@ struct user_trace_014_transition_trace
struct user_trace_015_update_trace
{
- static void start1();
- static void start2();
+ static void start();
};
struct user_trace_016_update_provider
diff --git a/examples/NativeExamples/main.cpp b/examples/NativeExamples/main.cpp
index 0412074..a1e165a 100644
--- a/examples/NativeExamples/main.cpp
+++ b/examples/NativeExamples/main.cpp
@@ -23,10 +23,10 @@ int main(void)
//user_trace_008_stacktrace::start();
//user_trace_009_from_file::start();
//user_trace_009_from_file::start2();
- user_trace_010_direct_filter::start();
+ //user_trace_010_direct_filter::start();
//user_trace_011_search_wevt::start();
//user_trace_012_open_trace::start();
//user_trace_013_pktmon::start();
//user_trace_014_transition_trace::start();
- //user_trace_015_update::start2();
+ user_trace_015_update_trace::start();
}
\ No newline at end of file
diff --git a/examples/NativeExamples/user_trace_015_update_trace.cpp b/examples/NativeExamples/user_trace_015_update_trace.cpp
index f22dc6f..fee39c4 100644
--- a/examples/NativeExamples/user_trace_015_update_trace.cpp
+++ b/examples/NativeExamples/user_trace_015_update_trace.cpp
@@ -14,147 +14,43 @@
///
/// start session
///
-void user_trace_015_update_trace::start1()
+void user_trace_015_update_trace::start()
{
-
- krabs::user_trace trace(L"test_sense");
-
- krabs::provider<> provider(krabs::guid(L"{16c6501a-ff2d-46ea-868d-8f96cb0cb52d}"));
-
-
-
-
- provider.enable_property(provider.enable_property() | EVENT_ENABLE_PROPERTY_PROCESS_START_KEY | EVENT_ENABLE_PROPERTY_SID | EVENT_ENABLE_PROPERTY_TS_ID);
-
- provider.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
-
- // Once an event is received, if we want krabs to help us analyze it, we need
- // to snap in a schema to ask it for information.
- krabs::schema schema(record, trace_context.schema_locator);
-
-
- // We then have the ability to ask a few questions of the event.
- std::wcout << L"Event " << schema.event_id();
- std::wcout << L"(" << schema.event_name() << L") received." << std::endl;
- krabs::parser parser(schema);
-
- auto extended_data_count = record.ExtendedDataCount;
- for (USHORT i = 0; i < extended_data_count; i++)
- {
- auto& extended_data = record.ExtendedData[i];
-
- if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_TS_ID)
- {
- auto result = (reinterpret_cast<_EVENT_EXTENDED_ITEM_TS_ID*>(extended_data.DataPtr))->SessionId;
- std::wcout << L"(" << "EVENT_EXTENDED_ITEM_TS_ID" << L") received." << result << std::endl;
- }
- if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_SID)
- {
-
- }
- if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY)
- {
- auto result = (reinterpret_cast<_EVENT_EXTENDED_ITEM_PROCESS_START_KEY*>(extended_data.DataPtr))->ProcessStartKey;
- std::wcout << L"(" << "EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY" << L") received." << result << std::endl;
- }
- }
-
- });
-
-
-
-
-}
-
-///
-/// open session
-///
-void user_trace_015_update_trace::start2()
-{
-
- krabs::user_trace trace(L"test_sense");
-
- krabs::provider<> provider(krabs::guid(L"{16c6501a-ff2d-46ea-868d-8f96cb0cb52d}"));
-
- //provider.enable_property(provider.enable_property() | EVENT_ENABLE_PROPERTY_PROCESS_START_KEY | EVENT_ENABLE_PROPERTY_SID | EVENT_ENABLE_PROPERTY_TS_ID);
+ krabs::user_trace trace(L"update_trace");
+ krabs::provider<> provider(L"Microsoft-Windows-Kernel-Audit-API-Calls");
provider.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
-
- // Once an event is received, if we want krabs to help us analyze it, we need
- // to snap in a schema to ask it for information.
krabs::schema schema(record, trace_context.schema_locator);
-
- // We then have the ability to ask a few questions of the event.
- std::wcout << L"Event " << schema.event_id();
- std::wcout << L"(" << schema.event_name() << L") received." << std::endl;
krabs::parser parser(schema);
- /*auto extended_data_count = record.ExtendedDataCount;
- for (USHORT i = 0; i < extended_data_count; i++)
- {
- auto& extended_data = record.ExtendedData[i];
+ //std::wcout << L" ProviderID=" << schema.provider_name() << std::endl;
+ //std::wcout << L" EventID=" << schema.event_id() << std::endl;
- if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_TS_ID)
- {
- auto result = (reinterpret_cast<_EVENT_EXTENDED_ITEM_TS_ID*>(extended_data.DataPtr))->SessionId;
- std::wcout << L"(" << "EVENT_EXTENDED_ITEM_TS_ID" << L") received." << result << std::endl;
- }
- if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_SID)
- {
+ });
- }
- if (extended_data.ExtType == EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY)
- {
- auto result = (reinterpret_cast<_EVENT_EXTENDED_ITEM_PROCESS_START_KEY*>(extended_data.DataPtr))->ProcessStartKey;
- std::wcout << L"(" << "EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY" << L") received." << result << std::endl;
- }
- }*/
+ auto show_config = [&trace]() {
+ auto config = trace.query_stats();
+ std::cout << "current config:" << std::endl;
+ std::cout << "min buffer:" << config.minimum_buffers << std::endl;
+ std::cout << "max buffer:" << config.maximum_buffers << std::endl;
+ std::cout << "max flush:" << config.flush_timer << std::endl;
+ };
-
- });
-
- trace.enable(provider);
-
- /*std::thread workerThread([&]() {
+ trace.enable(provider);
+ std::thread workerThread([&]() {
trace.start();
- });*/
- //Sleep(1000);
- auto tmp = trace.query_config();
- std::cout << "current config:" << std::endl;
- std::cout << "min buffer:" << tmp.minimum_buffers << std::endl;
- std::cout << "max buffer:" << tmp.maximum_buffers << std::endl;
- std::cout << "max flush:" << tmp.flush_timer << std::endl;
-
-
-
- trace.open();
-
- EVENT_TRACE_PROPERTIES etp = {};
+ });
+ const int durationInSeconds = 10;
+ std::this_thread::sleep_for(std::chrono::seconds(durationInSeconds));
+ show_config();
+ EVENT_TRACE_PROPERTIES etp = { 0 };
//etp.MinimumBuffers = 32;
etp.MaximumBuffers = 128;
etp.FlushTimer = 10;
trace.set_trace_properties(&etp);
- //trace.update();
- auto tmp2 = trace.query_config();
- std::thread workerThread([&]() {
- trace.process();
- });
- std::cout << "new config:" << std::endl;
- std::cout << "min buffer:" << tmp2.minimum_buffers << std::endl;
- std::cout << "max buffer:" << tmp2.maximum_buffers << std::endl;
- std::cout << "max flush:" << tmp2.flush_timer << std::endl;
-
- const int durationInSeconds = 30;
- std::this_thread::sleep_for(std::chrono::seconds(durationInSeconds));
- trace.enable(provider);
+ trace.update();
+ show_config();
trace.stop();
-
workerThread.join();
-}
-
-
-
-
-
-
+}
\ No newline at end of file
From 315f31675ae0d1461d53604828f50eacceb945b3 Mon Sep 17 00:00:00 2001
From: Dominik Phillips
Date: Thu, 18 Jul 2024 13:42:59 +0200
Subject: [PATCH 13/15] Update: managed TraceStats including the new session
config values
---
.../KernelTrace.hpp | 2 +-
.../TraceStats.hpp | 40 +++++++++++++++++++
bluekrabs/krabs/trace.hpp | 2 +-
.../user_trace_014_transition_trace.cpp | 2 +-
tests/krabstests/test_user_providers.cpp | 4 +-
5 files changed, 45 insertions(+), 5 deletions(-)
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/KernelTrace.hpp b/Threathunters.BlueKrabsetw.Native.ETW/KernelTrace.hpp
index 46180d8..04183f0 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW/KernelTrace.hpp
+++ b/Threathunters.BlueKrabsetw.Native.ETW/KernelTrace.hpp
@@ -277,7 +277,7 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
ExecuteAndConvertExceptions(return trace_->close());
}
- inline void KernelTrace::Close()
+ inline void KernelTrace::Update()
{
ExecuteAndConvertExceptions(return trace_->update());
}
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/TraceStats.hpp b/Threathunters.BlueKrabsetw.Native.ETW/TraceStats.hpp
index eded92e..8feb60c 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW/TraceStats.hpp
+++ b/Threathunters.BlueKrabsetw.Native.ETW/TraceStats.hpp
@@ -34,6 +34,36 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
/// count of events lost
initonly uint32_t EventsLost;
+ /// count of trace buffers
+ initonly uint32_t BuffersSize;
+
+ /// count of free buffers
+ initonly uint32_t MinimumBuffers;
+
+ /// count of buffers written
+ initonly uint32_t MaximumBuffers;
+
+ /// count of buffers lost
+ initonly uint32_t MaximumFileSize;
+
+ /// count of total events
+ initonly uint32_t LogFileMode;
+
+ /// count of events handled
+ initonly uint32_t FlushTimer;
+
+ /// count of events lost
+ initonly uint32_t EnableFlags;
+
+ /// count of total events
+ initonly String^ LogFileName;
+
+ /// count of events handled
+ initonly String^ LoggerName;
+
+ /// count of events lost
+ initonly uint32_t FlushThreshold;
+
internal:
TraceStats(const krabs::trace_stats& stats)
: BuffersCount(stats.buffers_count)
@@ -43,6 +73,16 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
, EventsTotal(stats.events_total)
, EventsHandled(stats.events_handled)
, EventsLost(stats.events_lost)
+ , BuffersSize(stats.buffer_size)
+ , MinimumBuffers(stats.minimum_buffers)
+ , MaximumBuffers(stats.maximum_buffers)
+ , MaximumFileSize(stats.maximum_file_size)
+ , LogFileMode(stats.log_file_mode)
+ , FlushTimer(stats.flush_timer)
+ , EnableFlags(stats.enable_flags)
+ , LogFileName(msclr::interop::marshal_as(stats.log_file_name))
+ , LoggerName(msclr::interop::marshal_as(stats.logger_name))
+ , FlushThreshold(stats.flush_threshold)
{ }
};
diff --git a/bluekrabs/krabs/trace.hpp b/bluekrabs/krabs/trace.hpp
index 51c9d83..4dc42bd 100644
--- a/bluekrabs/krabs/trace.hpp
+++ b/bluekrabs/krabs/trace.hpp
@@ -53,7 +53,7 @@ namespace krabs {
const std::wstring logger_name;
const uint32_t flush_threshold;
- trace_stats(uint64_t eventsHandled, details::trace_info& props)
+ trace_stats(uint64_t eventsHandled, const details::trace_info& props)
: buffers_count(props.properties.NumberOfBuffers)
, buffers_free(props.properties.FreeBuffers)
, buffers_written(props.properties.BuffersWritten)
diff --git a/examples/NativeExamples/user_trace_014_transition_trace.cpp b/examples/NativeExamples/user_trace_014_transition_trace.cpp
index 5a63d4b..26d4439 100644
--- a/examples/NativeExamples/user_trace_014_transition_trace.cpp
+++ b/examples/NativeExamples/user_trace_014_transition_trace.cpp
@@ -19,7 +19,7 @@ void user_trace_014_transition_trace::start()
krabs::user_trace trace(L"test_sense");
- auto config = trace.query_config();
+ auto config = trace.query_stats();
std::wcout << L"config" << std::endl;
}
\ No newline at end of file
diff --git a/tests/krabstests/test_user_providers.cpp b/tests/krabstests/test_user_providers.cpp
index 9702cbb..d0c7ca1 100644
--- a/tests/krabstests/test_user_providers.cpp
+++ b/tests/krabstests/test_user_providers.cpp
@@ -98,7 +98,7 @@ namespace krabstests
// we can still query it to determine if a trace with a
// matching name is running
krabs::user_trace trace(TEST_TRACE_NAME);
- while (0 == trace.query_stats().buffersCount) {
+ while (0 == trace.query_stats().buffers_count) {
Sleep(500);
}
@@ -110,7 +110,7 @@ namespace krabstests
CloseHandle(my_thread);
// no buffers --> trace has stopped
- Assert::IsTrue(0 == trace.query_stats().buffersCount);
+ Assert::IsTrue(0 == trace.query_stats().buffers_count);
}
TEST_METHOD(should_get_same_trace_flags_as_set)
From e74b161f73b74987ed6dfdb3087d36fe4a10fdf8 Mon Sep 17 00:00:00 2001
From: Dominik Phillips
Date: Mon, 29 Jul 2024 13:42:05 +0200
Subject: [PATCH 14/15] update: direct filter example
---
.../ManagedExamples/UserTrace008_DirecFilter.cs | 15 ---------------
1 file changed, 15 deletions(-)
diff --git a/examples/ManagedExamples/UserTrace008_DirecFilter.cs b/examples/ManagedExamples/UserTrace008_DirecFilter.cs
index aed49f6..ff851a4 100644
--- a/examples/ManagedExamples/UserTrace008_DirecFilter.cs
+++ b/examples/ManagedExamples/UserTrace008_DirecFilter.cs
@@ -22,33 +22,18 @@ public static void Start()
// This is what EnableRundownEvents() does.
//provider.EnableRundownEvents();
-
-
var f4 = new SystemFlags(0xFFFFFFFFFFFF, 4);
List ids = new List();
ids.Add(5);
var f5 = new EventIds(ids);
-
- //var filter3 = new EventIdFilter(5);
var pre = new PreEventFilter(
f4,
f5
);
- //var directFilter = new DirectEventFilters(filter2, filter3);
- //var processFilter = new EventFilter(Filter.EventIdIs(5)); // ProcessStart
- //var directFilter = new DirectEventFilters(tt);
-
- //processFilter.OnEvent += ProcessEventHandler;
- //provider.AddFilter(tt);
- //provider.AddFilter(processFilter);
- //provider.AddFilter(directFilter);
provider.AddFilter(pre);
- // process rundown events - i.e. running processes
- //var processRundownFilter = new EventFilter(Filter.EventIdIs(15)); // ProcessRundown
provider.OnEvent += ProcessEventHandler;
- //provider.AddFilter(processRundownFilter);
trace.Enable(provider);
trace.Start();
From 71bb91b07898d993664105b79fac04e47b4127a0 Mon Sep 17 00:00:00 2001
From: Dominik Phillips
Date: Wed, 31 Jul 2024 14:12:02 +0200
Subject: [PATCH 15/15] Update: examples
---
.../ITrace.hpp | 5 ++
.../KernelTrace.hpp | 12 ++++
.../UserTrace.hpp | 14 ++++-
bluekrabs/bluekrabs.sln | 3 +
.../ManagedExamples/ManagedExamples.csproj | 32 +++++++++-
examples/ManagedExamples/Program.cs | 4 +-
.../ManagedExamples/UserTrace009_OpenTrace.cs | 15 +++--
.../UserTrace011_UpdateTrace.cs | 63 +++++++++++++++++++
.../UserTrace012_UpdateProvider.cs | 58 +++++++++++++++++
.../ManagedExamples/UserTrace013_FromFile.cs | 48 ++++++++++++++
.../user_trace_016_update_provider.cpp | 2 +-
11 files changed, 247 insertions(+), 9 deletions(-)
create mode 100644 examples/ManagedExamples/UserTrace011_UpdateTrace.cs
create mode 100644 examples/ManagedExamples/UserTrace012_UpdateProvider.cs
create mode 100644 examples/ManagedExamples/UserTrace013_FromFile.cs
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/ITrace.hpp b/Threathunters.BlueKrabsetw.Native.ETW/ITrace.hpp
index ab710ef..d2b3783 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW/ITrace.hpp
+++ b/Threathunters.BlueKrabsetw.Native.ETW/ITrace.hpp
@@ -23,6 +23,11 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
///
void SetTraceProperties(EventTraceProperties^ properties);
+ ///
+ /// TODO
+ ///
+ void SetTraceFilename(String^ filename);
+
///
/// Starts listening for events from the enabled providers.
///
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/KernelTrace.hpp b/Threathunters.BlueKrabsetw.Native.ETW/KernelTrace.hpp
index 04183f0..f97c296 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW/KernelTrace.hpp
+++ b/Threathunters.BlueKrabsetw.Native.ETW/KernelTrace.hpp
@@ -92,6 +92,12 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
///
virtual void SetTraceProperties(EventTraceProperties^ properties);
+ ///
+ ///
+ ///
+ ///
+ virtual void SetTraceFilename(String^ filename);
+
///
/// Opens a trace session.
///
@@ -252,6 +258,12 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
ExecuteAndConvertExceptions(return trace_->set_trace_properties(&_properties));
}
+ inline void KernelTrace::SetTraceFilename(String^ filename)
+ {
+ std::wstring nativeName = msclr::interop::marshal_as(filename);
+ ExecuteAndConvertExceptions(return trace_->set_trace_filename(nativeName));
+ }
+
inline void KernelTrace::Open()
{
ExecuteAndConvertExceptions((void)trace_->open());
diff --git a/Threathunters.BlueKrabsetw.Native.ETW/UserTrace.hpp b/Threathunters.BlueKrabsetw.Native.ETW/UserTrace.hpp
index b4994a0..213b747 100644
--- a/Threathunters.BlueKrabsetw.Native.ETW/UserTrace.hpp
+++ b/Threathunters.BlueKrabsetw.Native.ETW/UserTrace.hpp
@@ -124,6 +124,12 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
///
virtual void SetTraceProperties(EventTraceProperties ^properties);
+ ///
+ ///
+ ///
+ ///
+ virtual void SetTraceFilename(String^ filename);
+
///
/// Opens a trace session.
///
@@ -273,6 +279,12 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
ExecuteAndConvertExceptions(return trace_->set_trace_properties(&_properties));
}
+ inline void UserTrace::SetTraceFilename(String^ filename)
+ {
+ std::wstring nativeName = msclr::interop::marshal_as(filename);
+ ExecuteAndConvertExceptions(return trace_->set_trace_filename(nativeName));
+ }
+
inline void UserTrace::Open()
{
ExecuteAndConvertExceptions((void)trace_->open());
@@ -300,7 +312,7 @@ namespace Microsoft { namespace O365 { namespace Security { namespace ETW {
inline void UserTrace::Update()
{
- ExecuteAndConvertExceptions(return trace_->close());
+ ExecuteAndConvertExceptions(return trace_->update());
}
inline TraceStats UserTrace::QueryStats()
diff --git a/bluekrabs/bluekrabs.sln b/bluekrabs/bluekrabs.sln
index c260f0b..2982981 100644
--- a/bluekrabs/bluekrabs.sln
+++ b/bluekrabs/bluekrabs.sln
@@ -99,6 +99,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testing", "testing", "{9EBF
krabs\testing\synth_record.hpp = krabs\testing\synth_record.hpp
EndProjectSection
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "proxy", "proxy", "{E157A8E6-C44F-4D87-AA59-5D9F0A78820B}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -169,6 +171,7 @@ Global
{531AF202-7C02-4203-9463-F10DE8A996AD} = {6345EFAF-43BD-42DE-9B8D-8D955E0C1FDC}
{2C63BA17-1E15-4B5B-B979-A00C3A331678} = {6345EFAF-43BD-42DE-9B8D-8D955E0C1FDC}
{9EBF97B2-137A-42F1-830F-E644C9590C33} = {6345EFAF-43BD-42DE-9B8D-8D955E0C1FDC}
+ {E157A8E6-C44F-4D87-AA59-5D9F0A78820B} = {6345EFAF-43BD-42DE-9B8D-8D955E0C1FDC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {82BAA012-2EF9-4303-A429-CDA3655D5009}
diff --git a/examples/ManagedExamples/ManagedExamples.csproj b/examples/ManagedExamples/ManagedExamples.csproj
index 4c222ab..3055935 100644
--- a/examples/ManagedExamples/ManagedExamples.csproj
+++ b/examples/ManagedExamples/ManagedExamples.csproj
@@ -13,6 +13,21 @@
512
true
+ publish\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 0
+ 1.0.0.%2a
+ false
+ false
+ true
x64
@@ -22,7 +37,7 @@
bin\Debug\
DEBUG;TRACE
prompt
- 4
+ 5
false
@@ -78,6 +93,9 @@
+
+
+
@@ -92,6 +110,18 @@
+
+
+ False
+ Microsoft .NET Framework 4.7.2 %28x86 and x64%29
+ true
+
+
+ False
+ .NET Framework 3.5 SP1
+ false
+
+