From 65417e3e7ae3dfe9c384614a35cb64e8b051c038 Mon Sep 17 00:00:00 2001 From: Maurice Heumann Date: Tue, 27 Dec 2022 09:36:46 +0100 Subject: [PATCH] Add non-threadsafe process callbacks --- src/driver/CMakeLists.txt | 4 ++ src/driver/driver_main.cpp | 24 ++++++++- src/driver/globals.cpp | 2 +- src/driver/list.hpp | 90 ++++++++++++++++++++++++++------- src/driver/process_callback.cpp | 65 ++++++++++++++++++++++++ src/driver/process_callback.hpp | 42 +++++++++++++++ 6 files changed, 206 insertions(+), 21 deletions(-) create mode 100644 src/driver/process_callback.cpp create mode 100644 src/driver/process_callback.hpp diff --git a/src/driver/CMakeLists.txt b/src/driver/CMakeLists.txt index 22d0367..a9b2a18 100644 --- a/src/driver/CMakeLists.txt +++ b/src/driver/CMakeLists.txt @@ -29,6 +29,10 @@ target_link_libraries(driver shared ) +target_compile_options(driver PRIVATE + "/Zc:threadSafeInit-" +) + target_link_options(driver PRIVATE "/IGNORE:4210" ) diff --git a/src/driver/driver_main.cpp b/src/driver/driver_main.cpp index e61380a..6853e2f 100644 --- a/src/driver/driver_main.cpp +++ b/src/driver/driver_main.cpp @@ -5,6 +5,7 @@ #include "exception.hpp" #include "hypervisor.hpp" #include "globals.hpp" +#include "process_callback.hpp" #define DOS_DEV_NAME L"\\DosDevices\\HelloDev" #define DEV_NAME L"\\Device\\HelloDev" @@ -16,8 +17,13 @@ public: : sleep_callback_([this](const sleep_callback::type type) { this->sleep_notification(type); - }) - , irp_(driver_object, DEV_NAME, DOS_DEV_NAME) + }), + process_callback_( + [this](const HANDLE parent_id, const HANDLE process_id, const process_callback::type type) + { + this->process_notification(parent_id, process_id, type); + }), + irp_(driver_object, DEV_NAME, DOS_DEV_NAME) { debug_log("Driver started\n"); } @@ -41,6 +47,7 @@ private: bool hypervisor_was_enabled_{false}; hypervisor hypervisor_{}; sleep_callback sleep_callback_{}; + process_callback::scoped_process_callback process_callback_{}; irp irp_{}; void sleep_notification(const sleep_callback::type type) @@ -58,6 +65,19 @@ private: this->hypervisor_.enable(); } } + + void process_notification(HANDLE /*parent_id*/, const HANDLE process_id, const process_callback::type type) + { + if (type == process_callback::type::create) + { + debug_log("Created process: %X\n", process_id); + } + + if (type == process_callback::type::destroy) + { + debug_log("Destroyed process: %X\n", process_id); + } + } }; global_driver* global_driver_instance{nullptr}; diff --git a/src/driver/globals.cpp b/src/driver/globals.cpp index bfccd3b..528ed47 100644 --- a/src/driver/globals.cpp +++ b/src/driver/globals.cpp @@ -115,7 +115,7 @@ int atexit(const globals::destructor destructor) try { - globals::destructors->push_back(destructor); + globals::destructors->push_front(destructor); } catch (const std::exception& e) { diff --git a/src/driver/list.hpp b/src/driver/list.hpp index 5f2573a..2e39f75 100644 --- a/src/driver/list.hpp +++ b/src/driver/list.hpp @@ -168,29 +168,45 @@ namespace utils T& push_back(const T& obj) { - auto& entry = this->add_uninitialized_entry(); - + auto& entry = this->add_uninitialized_entry_back(); new(&entry) T(obj); - return entry; } T& push_back(T&& obj) { - auto& entry = this->add_uninitialized_entry(); - + auto& entry = this->add_uninitialized_entry_back(); new(&entry) T(std::move(obj)); - return entry; } template T& emplace_back(Args&&... args) { - auto& entry = this->add_uninitialized_entry(); - + auto& entry = this->add_uninitialized_entry_back(); new(&entry) T(std::forward(args)...); + return entry; + } + T& push_front(const T& obj) + { + auto& entry = this->add_uninitialized_entry_front(); + new(&entry) T(obj); + return entry; + } + + T& push_front(T&& obj) + { + auto& entry = this->add_uninitialized_entry_front(); + new(&entry) T(std::move(obj)); + return entry; + } + + template + T& emplace_front(Args&&... args) + { + auto& entry = this->add_uninitialized_entry_front(); + new(&entry) T(std::forward(args)...); return entry; } @@ -271,6 +287,30 @@ namespace utils return {}; } + void erase(T& entry) + { + auto** insertion_point = &this->entries_; + while (*insertion_point) + { + if ((*insertion_point)->entry != &entry) + { + insertion_point = &(*insertion_point)->next; + continue; + } + + auto* list_entry = *insertion_point; + *insertion_point = list_entry->next; + + list_entry->entry->~T(); + this->object_allocator_.free(list_entry->entry_base); + this->list_allocator_.free(list_entry->this_base); + + return; + } + + throw std::runtime_error("Bad entry"); + } + iterator erase(iterator iterator) { auto* list_entry = iterator.get_entry(); @@ -350,19 +390,12 @@ namespace utils destructor.cancel(); } - - T& add_uninitialized_entry() + list_entry& create_uninitialized_list_entry() { void* list_base = {}; void* entry_base = {}; this->allocate_entry(list_base, entry_base); - auto** insertion_point = &this->entries_; - while (*insertion_point) - { - insertion_point = &(*insertion_point)->next; - } - auto* obj = align_pointer(entry_base); auto* entry = align_pointer(list_base); @@ -371,9 +404,30 @@ namespace utils entry->next = nullptr; entry->entry = obj; - *insertion_point = entry; + return *entry; + } - return *obj; + T& add_uninitialized_entry_back() + { + auto** insertion_point = &this->entries_; + while (*insertion_point) + { + insertion_point = &(*insertion_point)->next; + } + + auto& entry = this->create_uninitialized_list_entry(); + *insertion_point = &entry; + + return *entry.entry; + } + + T& add_uninitialized_entry_front() + { + auto& entry = this->create_uninitialized_list_entry(); + entry.next = this->entries_; + this->entries_ = &entry; + + return *entry.entry; } }; } diff --git a/src/driver/process_callback.cpp b/src/driver/process_callback.cpp new file mode 100644 index 0000000..0a00628 --- /dev/null +++ b/src/driver/process_callback.cpp @@ -0,0 +1,65 @@ +#include "std_include.hpp" +#include "process_callback.hpp" +#include "list.hpp" +#include "logging.hpp" + +namespace process_callback +{ + namespace + { + utils::list& get_callback_list() + { + static utils::list list{}; + return list; + } + + void process_notification_callback(const HANDLE parent_id, const HANDLE process_id, const BOOLEAN create) + { + const auto& list = get_callback_list(); + for (const auto& callback : list) + { + callback(parent_id, process_id, create == FALSE ? type::destroy : type::create); + } + } + + class process_notifier + { + public: + process_notifier() + : added_(PsSetCreateProcessNotifyRoutine(process_notification_callback, FALSE) == STATUS_SUCCESS) + { + get_callback_list(); + + if (!added_) + { + debug_log("Failed to register process notification callback\n"); + } + } + + ~process_notifier() + { + if (this->added_) + { + PsSetCreateProcessNotifyRoutine(process_notification_callback, TRUE); + } + } + + private: + bool added_{}; + }; + } + + void* add(callback_function callback) + { + static process_notifier _; + return &get_callback_list().push_back(std::move(callback)); + } + + void remove(void* handle) + { + if (handle) + { + get_callback_list().erase(*static_cast(handle)); + } + } +} diff --git a/src/driver/process_callback.hpp b/src/driver/process_callback.hpp new file mode 100644 index 0000000..737ccb1 --- /dev/null +++ b/src/driver/process_callback.hpp @@ -0,0 +1,42 @@ +#pragma once +#include "functional.hpp" + +namespace process_callback +{ + enum class type + { + create, + destroy, + }; + + using callback = void(HANDLE parent_id, HANDLE process_id, type type); + using callback_function = std::function; + + void* add(callback_function callback); + void remove(void* handle); + + class scoped_process_callback + { + public: + scoped_process_callback() = default; + + scoped_process_callback(callback_function function) + : handle_(add(std::move(function))) + { + } + + ~scoped_process_callback() + { + remove(this->handle_); + } + + scoped_process_callback(scoped_process_callback&& obj) noexcept = delete; + scoped_process_callback& operator=(scoped_process_callback&& obj) noexcept = delete; + + scoped_process_callback(const scoped_process_callback& obj) = delete; + scoped_process_callback& operator=(const scoped_process_callback& obj) = delete; + + private: + void* handle_{}; + }; +}