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 +#include #include "compiler_check.hpp" #include "guid.hpp" @@ -53,6 +55,33 @@ namespace krabs { { } }; + /** + * + * Selected statistics about an ETW trace + * + */ + class trace_config + { + public: + const uint64_t log_file_mode; + const uint64_t flush_timer; + const uint64_t enable_flags; + const std::wstring log_file_name; + const std::wstring logger_name; + + + trace_config(const details::trace_info& props) + : log_file_mode(props.properties.LogFileMode) + , flush_timer(props.properties.FlushTimer) + , enable_flags(props.properties.EnableFlags) + , logger_name(props.traceName) + , log_file_name(props.logfileName) + { + + } + }; + + /** * * Represents a single trace session that can have multiple @@ -166,7 +195,8 @@ namespace krabs { /** * - * Enables the provider on the given user trace. + * Update the session configuration so that the session receives + * the requested events from the provider. * * * krabs::trace trace; @@ -177,6 +207,22 @@ namespace krabs { */ void enable(const typename T::provider_type &p); + /** + * + * Update the session configuration so that the session does not + * receive events from the provider. + * + * + * krabs::trace trace; + * krabs::guid id(L"{A0C1853B-5C40-4B15-8766-3CF1C58F985A}"); + * provider<> powershell(id); + * trace.disable(powershell); + * + */ + void disable(const typename T::provider_type& p); + + + /** * * Starts a trace session. @@ -206,6 +252,8 @@ namespace krabs { */ void stop(); + + /** * * Opens a trace session. @@ -222,6 +270,13 @@ namespace krabs { */ EVENT_TRACE_LOGFILE open(); + /** + * + * Transition the ETW trace from real-time to file or vice versa. + * + */ + void transition(); + /** * * Start processing events for an already opened session. @@ -245,6 +300,13 @@ 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. @@ -291,11 +353,24 @@ namespace krabs { */ void on_event(const EVENT_RECORD &); + ///** + // * + // * Updates a trace session. + // * + // * + // * todo + // * + // */ + void update(const typename T::provider_type& p); + private: std::wstring name_; std::wstring logFilename_; bool non_stoppable_; - std::deque> providers_; + std::deque> enabled_providers_; + std::deque> disabled_providers_; + std::mutex providers_mutex_; + //std::map provider_pos_; TRACEHANDLE registrationHandle_; TRACEHANDLE sessionHandle_; @@ -390,9 +465,43 @@ namespace krabs { } template - void trace::enable(const typename T::provider_type &p) + 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; + }); + + + + if (it != enabled_providers_.end()) { + enabled_providers_.push_back(std::ref(p)); + return; + } + } + + update(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)); + } + + template + void trace::update(const typename T::provider_type& p) { - providers_.push_back(std::ref(p)); + details::trace_manager manager(*this); + manager.update(p); } template @@ -420,6 +529,12 @@ namespace krabs { return manager.open(); } + template + void trace::transition() + { + return; + } + template void trace::process() { @@ -433,7 +548,14 @@ namespace krabs { trace_stats trace::query_stats() { details::trace_manager manager(*this); - return { eventsHandled_, manager.query() }; + return { eventsHandled_, manager.query().properties }; + } + + template + trace_config trace::query_config() + { + details::trace_manager manager(*this); + return { manager.query() }; } template diff --git a/bluekrabs/krabs/ut.hpp b/bluekrabs/krabs/ut.hpp index f27e52c..4c19dea 100644 --- a/bluekrabs/krabs/ut.hpp +++ b/bluekrabs/krabs/ut.hpp @@ -4,6 +4,8 @@ #pragma once #include +#include +#include #include "compiler_check.hpp" #include "trace.hpp" @@ -21,9 +23,6 @@ namespace krabs { namespace details { * */ struct ut { - - typedef krabs::provider<> provider_type; - struct filter_flags { ULONG filter_type_; std::set event_ids_; @@ -46,6 +45,7 @@ namespace krabs { namespace details { }; //ENABLE_TRACE_PARAMETERS struct provider_enable_info { + GUID guid; ENABLE_TRACE_PARAMETERS parameters; bool rundown_enabled = false; UCHAR level; @@ -56,10 +56,9 @@ namespace krabs { namespace details { event_filter_buffers event_buffer; }; + typedef krabs::provider<> provider_type; typedef std::map provider_enable_info_container; - - - + /** * * Used to assign a name to the trace instance that is being @@ -132,7 +131,25 @@ namespace krabs { namespace details { * */ static void enable_providers( - const krabs::trace &trace); + krabs::trace &trace); + + /** + * + * Enables the providers that are attached to the given trace. + * + */ + static void disable_provider( + 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); /** * @@ -141,7 +158,16 @@ namespace krabs { namespace details { * */ static void enable_rundown( - const krabs::trace& trace); + 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*/); /** * @@ -150,7 +176,7 @@ namespace krabs { namespace details { */ static void forward_events( const EVENT_RECORD &record, - const krabs::trace &trace); + krabs::trace &trace); /** * @@ -187,7 +213,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) + 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()); @@ -197,7 +225,9 @@ namespace krabs { namespace details { return 1; } - inline ULONG ut::populate_event_id_filter_desc(ut::provider_enable_info& info, const event_id_event_filter* event_ids) + 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; @@ -229,7 +259,9 @@ namespace krabs { namespace details { return 0; } - inline ULONG ut::populate_event_pid_filter_desc(ut::provider_enable_info& info, const event_pid_event_filter* event_ids) + 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; @@ -269,7 +301,9 @@ namespace krabs { namespace details { return 0; } - inline ULONG ut::populate_event_name_filter_desc(ut::provider_enable_info& info, const event_name_event_filter* event_names) + 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; @@ -313,7 +347,9 @@ namespace krabs { namespace details { return 0; } - inline ULONG ut::populate_event_payload_filter_desc(ut::provider_enable_info& info, const event_payload_event_filter* event_payload) + 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; @@ -336,20 +372,21 @@ namespace krabs { namespace details { 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.parameters.SourceId, + &info.guid, &ed, TRUE, // TRUE Match any predicates (OR); FALSE Match all predicates (AND) 1, predicates, - &event_filter[predicates_count++]); + &event_filter[0]); if (Status != ERROR_SUCCESS) { printf("TdhCreatePayloadFilter() failed with %lu\n", Status); } Status = TdhAggregatePayloadFilters( - predicates_count, + 1, event_filter, NULL, &filter_desc); @@ -360,11 +397,13 @@ namespace krabs { namespace details { return 1; } - inline void ut::populate_provider_enable_info(const ut::provider_type& provider, ut::provider_enable_info& info) + inline void ut::populate_provider_enable_info( + const ut::provider_type& provider, + ut::provider_enable_info& info) { info.parameters.ControlFlags = 0; info.parameters.Version = ENABLE_TRACE_PARAMETERS_VERSION_2; - info.parameters.SourceId = provider.guid_; + info.guid = provider.guid_; info.level |= provider.level_; info.any |= provider.any_; @@ -427,30 +466,30 @@ namespace krabs { namespace details { } } - - - //return enable_trace_parameters{ 0 }; } inline void ut::enable_providers( - const krabs::trace& trace) + krabs::trace& trace) { - if (trace.registrationHandle_ == INVALID_PROCESSTRACE_HANDLE) + if (trace.registrationHandle_ == INVALID_PROCESSTRACE_HANDLE) { return; - + } + + std::lock_guard lock(trace.providers_mutex_); provider_enable_info_container providers_enable_info; + // This function 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. // TODO: Only forward the calls that are requested to each provider. - for (auto& provider : trace.providers_) { - //auto& a = provider.get(); - auto& enable_info = providers_enable_info[provider.get().guid_]; + 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_, - &enable_info.parameters.SourceId, + &_provider.guid_, EVENT_CONTROL_CODE_ENABLE_PROVIDER, enable_info.level, enable_info.any, @@ -462,13 +501,126 @@ namespace krabs { namespace details { } } + inline void ut::disable_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) { + trace.enabled_providers_.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( - const krabs::trace& trace) + krabs::trace& trace) { if (trace.registrationHandle_ == INVALID_PROCESSTRACE_HANDLE) return; - for (auto& provider : trace.providers_) { + std::lock_guard lock(trace.providers_mutex_); + + for (auto& provider : trace.enabled_providers_) { if (!provider.get().rundown_enabled_) continue; @@ -484,12 +636,53 @@ 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, - const krabs::trace &trace) + krabs::trace &trace) { + std::lock_guard lock(trace.providers_mutex_); // for manifest providers, EventHeader.ProviderId is the Provider GUID - for (auto& provider : trace.providers_) { + for (auto& provider : trace.enabled_providers_) { if (record.EventHeader.ProviderId == provider.get().guid_) { provider.get().on_event(record, trace.context_); return; @@ -499,15 +692,17 @@ namespace krabs { namespace details { // 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()); - for (auto& provider : trace.providers_) { - if (eventInfo->ProviderGuid == provider.get().guid_) { - provider.get().on_event(record, trace.context_); - return; + if ((record.EventHeader.EventProperty & EVENT_HEADER_PROPERTY_LEGACY_EVENTLOG) == 1) { + auto schema = get_event_schema_from_tdh(record); + auto eventInfo = reinterpret_cast(schema.get()); + for (auto& provider : trace.enabled_providers_) { + 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_); } diff --git a/examples/NativeExamples/NativeExamples.vcxproj b/examples/NativeExamples/NativeExamples.vcxproj index 3f7d536..56a8c98 100644 --- a/examples/NativeExamples/NativeExamples.vcxproj +++ b/examples/NativeExamples/NativeExamples.vcxproj @@ -172,6 +172,8 @@ + + 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 + +