Start using custom containers

This commit is contained in:
Maurice Heumann 2022-12-23 22:18:07 +01:00
parent dcab775bb9
commit 33b44f1dc1
8 changed files with 145 additions and 116 deletions

View File

@ -168,7 +168,7 @@ namespace vmx
} }
void ept::install_page_hook(void* destination, const void* source, const size_t length, void ept::install_page_hook(void* destination, const void* source, const size_t length,
ept_translation_hint* translation_hint) const ept_translation_hint* translation_hint)
{ {
auto* hook = this->get_or_create_ept_hook(destination, translation_hint); auto* hook = this->get_or_create_ept_hook(destination, translation_hint);
@ -194,7 +194,7 @@ namespace vmx
} }
void ept::install_hook(const void* destination, const void* source, const size_t length, void ept::install_hook(const void* destination, const void* source, const size_t length,
ept_translation_hint* translation_hint) const utils::list<ept_translation_hint>& hints)
{ {
auto current_destination = reinterpret_cast<uint64_t>(destination); auto current_destination = reinterpret_cast<uint64_t>(destination);
auto current_source = reinterpret_cast<uint64_t>(source); auto current_source = reinterpret_cast<uint64_t>(source);
@ -207,17 +207,16 @@ namespace vmx
const auto page_remaining = PAGE_SIZE - page_offset; const auto page_remaining = PAGE_SIZE - page_offset;
const auto data_to_write = min(page_remaining, current_length); const auto data_to_write = min(page_remaining, current_length);
ept_translation_hint* relevant_hint = nullptr;
ept_translation_hint* current_hint = translation_hint;
while (current_hint) const ept_translation_hint* relevant_hint = nullptr;
for(const auto& hint : hints)
{ {
if (current_hint->virtual_base_address == aligned_destination) if (hint.virtual_base_address == aligned_destination)
{ {
relevant_hint = current_hint; relevant_hint = &hint;
break; break;
} }
current_hint = current_hint->next_hint;
} }
this->install_page_hook(reinterpret_cast<void*>(current_destination), this->install_page_hook(reinterpret_cast<void*>(current_destination),
@ -539,7 +538,7 @@ namespace vmx
return nullptr; return nullptr;
} }
ept_hook* ept::get_or_create_ept_hook(void* destination, ept_translation_hint* translation_hint) ept_hook* ept::get_or_create_ept_hook(void* destination, const ept_translation_hint* translation_hint)
{ {
const auto virtual_target = PAGE_ALIGN(destination); const auto virtual_target = PAGE_ALIGN(destination);
@ -654,18 +653,13 @@ namespace vmx
target_entry->flags = new_pointer.flags; target_entry->flags = new_pointer.flags;
} }
ept_translation_hint* ept::generate_translation_hints(const void* destination, const size_t length) utils::list<ept_translation_hint> ept::generate_translation_hints(const void* destination, const size_t length)
{ {
utils::list<ept_translation_hint> hints{};
auto current_destination = reinterpret_cast<uint64_t>(destination); auto current_destination = reinterpret_cast<uint64_t>(destination);
auto current_length = length; auto current_length = length;
ept_translation_hint* current_hints = nullptr;
auto destructor = utils::finally([&current_hints]()
{
ept::free_translation_hints(current_hints);
});
while (current_length != 0) while (current_length != 0)
{ {
const auto aligned_destination = PAGE_ALIGN(current_destination); const auto aligned_destination = PAGE_ALIGN(current_destination);
@ -673,42 +667,25 @@ namespace vmx
const auto page_remaining = PAGE_SIZE - page_offset; const auto page_remaining = PAGE_SIZE - page_offset;
const auto data_to_write = min(page_remaining, current_length); const auto data_to_write = min(page_remaining, current_length);
auto* new_hint = memory::allocate_non_paged_object<ept_translation_hint>(); ept_translation_hint current_hint{};
if (!new_hint)
{
throw std::runtime_error("Failed to allocate hint");
}
new_hint->next_hint = current_hints; current_hint.virtual_base_address = aligned_destination;
current_hints = new_hint; current_hint.physical_base_address = memory::get_physical_address(aligned_destination);
current_hints->virtual_base_address = aligned_destination;
current_hints->physical_base_address = memory::get_physical_address(aligned_destination);
if (!current_hints->physical_base_address) if (!current_hint.physical_base_address)
{ {
throw std::runtime_error("Failed to resolve physical address"); throw std::runtime_error("Failed to resolve physical address");
} }
memcpy(&current_hints->page[0], aligned_destination, PAGE_SIZE); memcpy(&current_hint.page[0], aligned_destination, PAGE_SIZE);
hints.push_back(current_hint);
current_length -= data_to_write; current_length -= data_to_write;
current_destination += data_to_write; current_destination += data_to_write;
} }
destructor.cancel(); return hints;
return current_hints;
}
void ept::free_translation_hints(ept_translation_hint* hints)
{
auto* hint = hints;
while (hint)
{
auto* current_hint = hint;
hint = hint->next_hint;
memory::free_non_paged_object(current_hint);
}
} }
uint64_t* ept::get_access_records(size_t* count) uint64_t* ept::get_access_records(size_t* count)

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#define DECLSPEC_PAGE_ALIGN DECLSPEC_ALIGN(PAGE_SIZE) #define DECLSPEC_PAGE_ALIGN DECLSPEC_ALIGN(PAGE_SIZE)
#include "list.hpp"
namespace vmx namespace vmx
{ {
@ -55,8 +56,6 @@ namespace vmx
uint64_t physical_base_address{}; uint64_t physical_base_address{};
const void* virtual_base_address{}; const void* virtual_base_address{};
ept_translation_hint* next_hint{nullptr};
}; };
struct guest_context; struct guest_context;
@ -77,7 +76,7 @@ namespace vmx
void install_code_watch_point(uint64_t physical_page); void install_code_watch_point(uint64_t physical_page);
void install_hook(const void* destination, const void* source, size_t length, void install_hook(const void* destination, const void* source, size_t length,
ept_translation_hint* translation_hint = nullptr); const utils::list<ept_translation_hint>& hints = {});
void disable_all_hooks() const; void disable_all_hooks() const;
void handle_violation(guest_context& guest_context); void handle_violation(guest_context& guest_context);
@ -86,8 +85,7 @@ namespace vmx
ept_pointer get_ept_pointer() const; ept_pointer get_ept_pointer() const;
void invalidate() const; void invalidate() const;
static ept_translation_hint* generate_translation_hints(const void* destination, size_t length); static utils::list<ept_translation_hint> generate_translation_hints(const void* destination, size_t length);
static void free_translation_hints(ept_translation_hint* hints);
uint64_t* get_access_records(size_t* count); uint64_t* get_access_records(size_t* count);
@ -113,12 +111,12 @@ namespace vmx
ept_code_watch_point* allocate_ept_code_watch_point(); ept_code_watch_point* allocate_ept_code_watch_point();
ept_code_watch_point* find_ept_code_watch_point(uint64_t physical_address) const; ept_code_watch_point* find_ept_code_watch_point(uint64_t physical_address) const;
ept_hook* get_or_create_ept_hook(void* destination, ept_translation_hint* translation_hint = nullptr); ept_hook* get_or_create_ept_hook(void* destination, const ept_translation_hint* translation_hint = nullptr);
void split_large_page(uint64_t physical_address); void split_large_page(uint64_t physical_address);
void install_page_hook(void* destination, const void* source, size_t length, void install_page_hook(void* destination, const void* source, size_t length,
ept_translation_hint* translation_hint = nullptr); const ept_translation_hint* translation_hint = nullptr);
void record_access(uint64_t rip); void record_access(uint64_t rip);
}; };

View File

@ -163,11 +163,11 @@ bool hypervisor::is_enabled() const
} }
bool hypervisor::install_ept_hook(const void* destination, const void* source, const size_t length, bool hypervisor::install_ept_hook(const void* destination, const void* source, const size_t length,
vmx::ept_translation_hint* translation_hint) const utils::list<vmx::ept_translation_hint>& hints)
{ {
try try
{ {
this->ept_->install_hook(destination, source, length, translation_hint); this->ept_->install_hook(destination, source, length, hints);
} }
catch (std::exception& e) catch (std::exception& e)
{ {
@ -183,7 +183,7 @@ bool hypervisor::install_ept_hook(const void* destination, const void* source, c
volatile long failures = 0; volatile long failures = 0;
thread::dispatch_on_all_cores([&] thread::dispatch_on_all_cores([&]
{ {
if (!this->try_install_ept_hook_on_core(destination, source, length, translation_hint)) if (!this->try_install_ept_hook_on_core(destination, source, length, hints))
{ {
InterlockedIncrement(&failures); InterlockedIncrement(&failures);
} }
@ -192,7 +192,7 @@ bool hypervisor::install_ept_hook(const void* destination, const void* source, c
return failures == 0; return failures == 0;
} }
bool hypervisor::install_ept_code_watch_point(const uint64_t physical_page, bool invalidate) const bool hypervisor::install_ept_code_watch_point(const uint64_t physical_page, const bool invalidate) const
{ {
try try
{ {
@ -826,11 +826,11 @@ void hypervisor::free_vm_states()
} }
bool hypervisor::try_install_ept_hook_on_core(const void* destination, const void* source, const size_t length, bool hypervisor::try_install_ept_hook_on_core(const void* destination, const void* source, const size_t length,
vmx::ept_translation_hint* translation_hint) const utils::list<vmx::ept_translation_hint>& hints)
{ {
try try
{ {
this->install_ept_hook_on_core(destination, source, length, translation_hint); this->install_ept_hook_on_core(destination, source, length, hints);
return true; return true;
} }
catch (std::exception& e) catch (std::exception& e)
@ -846,7 +846,7 @@ bool hypervisor::try_install_ept_hook_on_core(const void* destination, const voi
} }
void hypervisor::install_ept_hook_on_core(const void* destination, const void* source, const size_t length, void hypervisor::install_ept_hook_on_core(const void* destination, const void* source, const size_t length,
vmx::ept_translation_hint* translation_hint) const utils::list<vmx::ept_translation_hint>& hints)
{ {
auto* vm_state = this->get_current_vm_state(); auto* vm_state = this->get_current_vm_state();
if (!vm_state) if (!vm_state)
@ -857,8 +857,8 @@ void hypervisor::install_ept_hook_on_core(const void* destination, const void* s
(void)destination; (void)destination;
(void)source; (void)source;
(void)length; (void)length;
(void)translation_hint; (void)hints;
//vm_state->ept->install_hook(destination, source, length, translation_hint); //vm_state->ept->install_hook(destination, source, length, hints);
if (this->is_enabled()) if (this->is_enabled())
{ {

View File

@ -20,7 +20,7 @@ public:
bool is_enabled() const; bool is_enabled() const;
bool install_ept_hook(const void* destination, const void* source, size_t length, bool install_ept_hook(const void* destination, const void* source, size_t length,
vmx::ept_translation_hint* translation_hint = nullptr); const utils::list<vmx::ept_translation_hint>& hints = {});
bool install_ept_code_watch_point(uint64_t physical_page, bool invalidate = true) const; bool install_ept_code_watch_point(uint64_t physical_page, bool invalidate = true) const;
bool install_ept_code_watch_points(const uint64_t* physical_pages, size_t count) const; bool install_ept_code_watch_points(const uint64_t* physical_pages, size_t count) const;
@ -44,9 +44,9 @@ private:
void free_vm_states(); void free_vm_states();
bool try_install_ept_hook_on_core(const void* destination, const void* source, size_t length, bool try_install_ept_hook_on_core(const void* destination, const void* source, size_t length,
vmx::ept_translation_hint* translation_hint = nullptr); const utils::list<vmx::ept_translation_hint>& hints = {});
void install_ept_hook_on_core(const void* destination, const void* source, size_t length, void install_ept_hook_on_core(const void* destination, const void* source, size_t length,
vmx::ept_translation_hint* translation_hint = nullptr); const utils::list<vmx::ept_translation_hint>& hints = {});
vmx::state* get_current_vm_state() const; vmx::state* get_current_vm_state() const;
}; };

View File

@ -37,11 +37,12 @@ namespace
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
vmx::ept_translation_hint* generate_translation_hints(uint32_t process_id, const void* target_address, size_t size) utils::list<vmx::ept_translation_hint> generate_translation_hints(uint32_t process_id, const void* target_address,
size_t size)
{ {
vmx::ept_translation_hint* translation_hints{nullptr}; utils::list<vmx::ept_translation_hint> translation_hints{};
thread::kernel_thread t([&translation_hints, process_id, target_address, size] thread::kernel_thread([&translation_hints, process_id, target_address, size]
{ {
debug_log("Looking up process: %d\n", process_id); debug_log("Looking up process: %d\n", process_id);
@ -52,8 +53,7 @@ namespace
return; return;
} }
const auto name = process_handle.get_image_filename(); if (const auto name = process_handle.get_image_filename())
if (name)
{ {
debug_log("Attaching to %s\n", name); debug_log("Attaching to %s\n", name);
} }
@ -62,9 +62,7 @@ namespace
debug_log("Generating translation hints for address: %p\n", target_address); debug_log("Generating translation hints for address: %p\n", target_address);
translation_hints = vmx::ept::generate_translation_hints(target_address, size); translation_hints = vmx::ept::generate_translation_hints(target_address, size);
}); }).join();
t.join();
return translation_hints; return translation_hints;
} }
@ -83,17 +81,11 @@ namespace
throw std::runtime_error("Failed to copy buffer"); throw std::runtime_error("Failed to copy buffer");
} }
vmx::ept_translation_hint* translation_hints = nullptr;
auto destructor = utils::finally([&translation_hints]()
{
vmx::ept::free_translation_hints(translation_hints);
});
memcpy(buffer.get(), request.source_data, request.source_data_size); memcpy(buffer.get(), request.source_data, request.source_data_size);
translation_hints = generate_translation_hints(request.process_id, request.target_address, auto translation_hints = generate_translation_hints(request.process_id, request.target_address,
request.source_data_size); request.source_data_size);
if (!translation_hints) if (translation_hints.empty())
{ {
debug_log("Failed to generate tranlsation hints\n"); debug_log("Failed to generate tranlsation hints\n");
return; return;

View File

@ -31,14 +31,14 @@ namespace utils
{ {
} }
T* operator*() const T& operator*() const
{ {
return this->entry_->entry; return *this->entry_->entry;
} }
T* operator->() const T& operator->() const
{ {
return this->entry_->entry; return *this->entry_->entry;
} }
bool operator==(const iterator& i) const bool operator==(const iterator& i) const
@ -46,7 +46,7 @@ namespace utils
return this->entry_ == i.entry_; return this->entry_ == i.entry_;
} }
iterator operator++() const iterator operator++()
{ {
this->entry_ = this->entry_->next; this->entry_ = this->entry_->next;
return *this; return *this;
@ -89,14 +89,14 @@ namespace utils
{ {
} }
const T* operator*() const const T& operator*() const
{ {
return this->entry_->entry; return *this->entry_->entry;
} }
const T* operator->() const const T& operator->() const
{ {
return this->entry_->entry; return *this->entry_->entry;
} }
bool operator==(const const_iterator& i) const bool operator==(const const_iterator& i) const
@ -104,7 +104,7 @@ namespace utils
return this->entry_ == i.entry_; return this->entry_ == i.entry_;
} }
const_iterator operator++() const const_iterator operator++()
{ {
this->entry_ = this->entry_->next; this->entry_ = this->entry_->next;
return *this; return *this;
@ -166,30 +166,32 @@ namespace utils
return *this; return *this;
} }
T& push_back(T obj) T& push_back(const T& obj)
{ {
auto** inseration_point = &this->entries_; auto& entry = this->add_uninitialized_entry();
while (*inseration_point)
{ new(&entry) T(obj);
inseration_point = &(*inseration_point)->next;
return entry;
} }
auto* list_base = this->list_allocator_.allocate(sizeof(ListEntry) + alignof(ListEntry)); T& push_back(T&& obj)
auto* entry_base = this->object_allocator_.allocate(sizeof(T) + alignof(T)); {
auto& entry = this->add_uninitialized_entry();
auto* entry = align_pointer<T>(entry_base); new(&entry) T(std::move(obj));
auto* list_entry = align_pointer<ListEntry>(list_base);
list_entry->this_base = list_base; return entry;
list_entry->entry_base = entry_base; }
list_entry->next = nullptr;
list_entry->entry = entry;
*inseration_point = list_entry; template <typename... Args>
T& emplace_back(Args&&... args)
{
auto& entry = this->add_uninitialized_entry();
new(entry) T(std::move(obj)); new(&entry) T(std::forward<Args>(args)...);
return *entry; return entry;
} }
T& operator[](const size_t index) T& operator[](const size_t index)
@ -232,7 +234,7 @@ namespace utils
void clear() void clear()
{ {
while (this->entries_) while (!this->empty())
{ {
this->erase(this->begin()); this->erase(this->begin());
} }
@ -293,6 +295,11 @@ namespace utils
throw std::runtime_error("Bad iterator"); throw std::runtime_error("Bad iterator");
} }
bool empty() const
{
return this->entries_ == nullptr;
}
private: private:
friend iterator; friend iterator;
@ -309,5 +316,29 @@ namespace utils
return reinterpret_cast<U*>(ptr); return reinterpret_cast<U*>(ptr);
} }
T& add_uninitialized_entry()
{
auto** inseration_point = &this->entries_;
while (*inseration_point)
{
inseration_point = &(*inseration_point)->next;
}
auto* list_base = this->list_allocator_.allocate(sizeof(ListEntry) + alignof(ListEntry));
auto* entry_base = this->object_allocator_.allocate(sizeof(T) + alignof(T));
auto* entry = align_pointer<T>(entry_base);
auto* list_entry = align_pointer<ListEntry>(list_base);
list_entry->this_base = list_base;
list_entry->entry_base = entry_base;
list_entry->next = nullptr;
list_entry->entry = entry;
*inseration_point = list_entry;
return *entry;
}
}; };
} }

View File

@ -27,7 +27,7 @@ namespace std
}; };
template <typename T> template <typename T>
typename remove_reference<T>::type&& move(T&& arg) typename remove_reference<T>::type&& move(T&& arg) noexcept
{ {
return static_cast<typename remove_reference<T>::type&&>(arg); return static_cast<typename remove_reference<T>::type&&>(arg);
} }

View File

@ -91,17 +91,32 @@ namespace utils
} }
} }
T& push_back(T obj) T& push_back(const T& obj)
{ {
if (this->size_ + 1 > this->capacity_) auto& entry = this->add_uninitialized_entry();
{
this->reserve(max(this->capacity_, 5) * 2); new(&entry) T(obj);
return entry;
} }
auto* data = this->data() + this->size_++; T& push_back(T&& obj)
new(data) T(std::move(obj)); {
auto& entry = this->add_uninitialized_entry();
return *data; new(&entry) T(std::move(obj));
return entry;
}
template <typename... Args>
T& emplace_back(Args&&... args)
{
auto& entry = this->add_uninitialized_entry();
new(&entry) T(std::forward<Args>(args)...);
return entry;
} }
T& operator[](const size_t index) T& operator[](const size_t index)
@ -217,12 +232,28 @@ namespace utils
return iterator; return iterator;
} }
bool empty() const
{
return this->size_ == 0;
}
private: private:
Allocator allocator_{}; Allocator allocator_{};
void* storage_{nullptr}; void* storage_{nullptr};
size_t capacity_{0}; size_t capacity_{0};
size_t size_{0}; size_t size_{0};
T& add_uninitialized_entry()
{
if (this->size_ + 1 > this->capacity_)
{
this->reserve(max(this->capacity_, 5) * 2);
}
auto* data = this->data() + this->size_++;
return *data;
}
void* allocate_memory_for_capacity(const size_t capacity) void* allocate_memory_for_capacity(const size_t capacity)
{ {
constexpr auto alignment = alignof(T); constexpr auto alignment = alignof(T);