From e77359be93232965c672b38eb62b3bc5e6ec9ff0 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 15 May 2022 15:09:38 +0200 Subject: [PATCH 1/8] Prepare integrity analysis --- src/runner/main.cpp | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/runner/main.cpp b/src/runner/main.cpp index a35e478..095abba 100644 --- a/src/runner/main.cpp +++ b/src/runner/main.cpp @@ -78,21 +78,20 @@ std::filesystem::path extract_driver() void unsafe_main(const int /*argc*/, char* /*argv*/[]) { - //launcher().run(); - //return; - const auto driver_file = extract_driver(); driver driver{driver_file, "MomoLul"}; const driver_device driver_device{R"(\\.\HelloDev)"}; + //launcher().run(); + std::string pid_str{}; printf("Please enter the pid: "); std::getline(std::cin, pid_str); const auto pid = atoi(pid_str.data()); - + /* // IW5 insert_nop(driver_device, pid, 0x4488A8, 2); // Force calling CG_DrawFriendOrFoeTargetBoxes insert_nop(driver_device, pid, 0x47F6C7, 2); // Ignore blind-eye perks @@ -110,17 +109,19 @@ void unsafe_main(const int /*argc*/, char* /*argv*/[]) constexpr uint8_t data3[] = {0xEB}; patch_data(driver_device, pid, 0x443A2A, data3, sizeof(data3)); patch_data(driver_device, pid, 0x443978, data3, sizeof(data3)); + */ /* - insert_nop(driver_device, pid, 0x441D5A, 6); - insert_nop(driver_device, pid, 0x525104, 2); - insert_nop(driver_device, pid, 0x525121, 2); - - constexpr uint8_t data3[] = {0xEB}; - patch_data(driver_device, pid, 0x525087, data3, sizeof(data3)); - patch_data(driver_device, pid, 0x524E7F, data3, sizeof(data3)); - patch_data(driver_device, pid, 0x52512C, data3, sizeof(data3)); - */ + insert_nop(driver_device, pid, 0x441D5A, 6); + insert_nop(driver_device, pid, 0x525104, 2); + insert_nop(driver_device, pid, 0x525121, 2); + + constexpr uint8_t data3[] = {0xEB}; + patch_data(driver_device, pid, 0x525087, data3, sizeof(data3)); + patch_data(driver_device, pid, 0x524E7F, data3, sizeof(data3)); + patch_data(driver_device, pid, 0x52512C, data3, sizeof(data3)); + */ + printf("Press any key to disable all hooks!\n"); (void)_getch(); @@ -140,11 +141,13 @@ int main(const int argc, char* argv[]) catch (std::exception& e) { printf("Error: %s\n", e.what()); + _getch(); return 1; } catch (...) { printf("An unknown error occured!\n"); + _getch(); return 1; } } From 8510755ea4f470ccc02fcb290b621b029a36d678 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 15 May 2022 21:46:23 +0200 Subject: [PATCH 2/8] Remove experiments --- .../launcher/html/doc_host_ui_handler.cpp | 115 ---- .../launcher/html/doc_host_ui_handler.hpp | 47 -- src/runner/launcher/html/html_argument.cpp | 51 -- src/runner/launcher/html/html_argument.hpp | 20 - src/runner/launcher/html/html_dispatch.cpp | 67 -- src/runner/launcher/html/html_dispatch.hpp | 24 - src/runner/launcher/html/html_frame.cpp | 298 --------- src/runner/launcher/html/html_frame.hpp | 67 -- src/runner/launcher/html/html_window.cpp | 29 - src/runner/launcher/html/html_window.hpp | 15 - src/runner/launcher/html/ole_client_site.cpp | 77 --- src/runner/launcher/html/ole_client_site.hpp | 24 - .../launcher/html/ole_in_place_frame.cpp | 82 --- .../launcher/html/ole_in_place_frame.hpp | 30 - .../launcher/html/ole_in_place_site.cpp | 105 ---- .../launcher/html/ole_in_place_site.hpp | 32 - src/runner/launcher/launcher.cpp | 33 - src/runner/launcher/launcher.hpp | 15 - src/runner/launcher/window.cpp | 208 ------- src/runner/launcher/window.hpp | 44 -- src/runner/main.cpp | 2 - src/runner/resource.hpp | 1 - src/runner/resource.rc | 1 - src/runner/resources/main.html | 574 ------------------ src/runner/std_include.hpp | 3 - 25 files changed, 1964 deletions(-) delete mode 100644 src/runner/launcher/html/doc_host_ui_handler.cpp delete mode 100644 src/runner/launcher/html/doc_host_ui_handler.hpp delete mode 100644 src/runner/launcher/html/html_argument.cpp delete mode 100644 src/runner/launcher/html/html_argument.hpp delete mode 100644 src/runner/launcher/html/html_dispatch.cpp delete mode 100644 src/runner/launcher/html/html_dispatch.hpp delete mode 100644 src/runner/launcher/html/html_frame.cpp delete mode 100644 src/runner/launcher/html/html_frame.hpp delete mode 100644 src/runner/launcher/html/html_window.cpp delete mode 100644 src/runner/launcher/html/html_window.hpp delete mode 100644 src/runner/launcher/html/ole_client_site.cpp delete mode 100644 src/runner/launcher/html/ole_client_site.hpp delete mode 100644 src/runner/launcher/html/ole_in_place_frame.cpp delete mode 100644 src/runner/launcher/html/ole_in_place_frame.hpp delete mode 100644 src/runner/launcher/html/ole_in_place_site.cpp delete mode 100644 src/runner/launcher/html/ole_in_place_site.hpp delete mode 100644 src/runner/launcher/launcher.cpp delete mode 100644 src/runner/launcher/launcher.hpp delete mode 100644 src/runner/launcher/window.cpp delete mode 100644 src/runner/launcher/window.hpp delete mode 100644 src/runner/resources/main.html diff --git a/src/runner/launcher/html/doc_host_ui_handler.cpp b/src/runner/launcher/html/doc_host_ui_handler.cpp deleted file mode 100644 index 0c1cc86..0000000 --- a/src/runner/launcher/html/doc_host_ui_handler.cpp +++ /dev/null @@ -1,115 +0,0 @@ -#include "../../std_include.hpp" -#include "html_frame.hpp" - -doc_host_ui_handler::doc_host_ui_handler(html_frame* frame): frame_(frame) -{ -} - -HRESULT doc_host_ui_handler::QueryInterface(REFIID riid, LPVOID* ppvObj) -{ - auto client_site = this->frame_->get_client_site(); - if (client_site) - { - return client_site->QueryInterface(riid, ppvObj); - } - - return E_NOINTERFACE; -} - -ULONG doc_host_ui_handler::AddRef() -{ - return 1; -} - -ULONG doc_host_ui_handler::Release() -{ - return 1; -} - -HRESULT doc_host_ui_handler::ShowContextMenu(DWORD /*dwID*/, POINT* /*ppt*/, IUnknown* /*pcmdtReserved*/, - IDispatch* /*pdispReserved*/) -{ - return S_OK; -} - -HRESULT doc_host_ui_handler::ShowUI(DWORD /*dwID*/, IOleInPlaceActiveObject* /*pActiveObject*/, - IOleCommandTarget* /*pCommandTarget*/, - IOleInPlaceFrame* /*pFrame*/, IOleInPlaceUIWindow* /*pDoc*/) -{ - return S_OK; -} - -HRESULT doc_host_ui_handler::HideUI() -{ - return S_OK; -} - -HRESULT doc_host_ui_handler::UpdateUI() -{ - return S_OK; -} - -HRESULT doc_host_ui_handler::EnableModeless(BOOL /*fEnable*/) -{ - return S_OK; -} - -HRESULT doc_host_ui_handler::OnDocWindowActivate(BOOL /*fActivate*/) -{ - return S_OK; -} - -HRESULT doc_host_ui_handler::OnFrameWindowActivate(BOOL /*fActivate*/) -{ - return S_OK; -} - -HRESULT doc_host_ui_handler::ResizeBorder(LPCRECT /*prcBorder*/, IOleInPlaceUIWindow* /*pUIWindow*/, - BOOL /*fRameWindow*/) -{ - return S_OK; -} - -HRESULT doc_host_ui_handler::TranslateAcceleratorA(LPMSG /*lpMsg*/, const GUID* pguidCmdGroup, DWORD /*nCmdID*/) -{ - pguidCmdGroup = nullptr; - return S_FALSE; -} - -HRESULT doc_host_ui_handler::GetOptionKeyPath(LPOLESTR* /*pchKey*/, DWORD /*dw*/) -{ - return S_FALSE; -} - -HRESULT doc_host_ui_handler::GetDropTarget(IDropTarget* /*pDropTarget*/, IDropTarget** /*ppDropTarget*/) -{ - return S_FALSE; -} - -HRESULT doc_host_ui_handler::GetExternal(IDispatch** ppDispatch) -{ - *ppDispatch = this->frame_->get_html_dispatch(); - return (*ppDispatch) ? S_OK : S_FALSE; -} - -HRESULT doc_host_ui_handler::FilterDataObject(IDataObject* /*pDO*/, IDataObject** ppDORet) -{ - *ppDORet = nullptr; - return S_FALSE; -} - -HRESULT STDMETHODCALLTYPE doc_host_ui_handler::TranslateUrl(DWORD /*dwTranslate*/, OLECHAR __RPC_FAR* /*pchURLIn*/, - OLECHAR __RPC_FAR* __RPC_FAR* ppchURLOut) -{ - *ppchURLOut = nullptr; - return S_FALSE; -} - -HRESULT doc_host_ui_handler::GetHostInfo(DOCHOSTUIINFO __RPC_FAR * pInfo) -{ - pInfo->cbSize = sizeof(DOCHOSTUIINFO); - pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_DPI_AWARE /*| DOCHOSTUIFLAG_SCROLL_NO*/; - pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT; - - return S_OK; -} diff --git a/src/runner/launcher/html/doc_host_ui_handler.hpp b/src/runner/launcher/html/doc_host_ui_handler.hpp deleted file mode 100644 index 0b538b4..0000000 --- a/src/runner/launcher/html/doc_host_ui_handler.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -class html_frame; - -class doc_host_ui_handler final : public IDocHostUIHandler -{ -public: - doc_host_ui_handler(html_frame* frame); - virtual ~doc_host_ui_handler() = default; - -private: - html_frame* frame_; - -public: // IDocHostUIHandler interface - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppvObj) override; - ULONG STDMETHODCALLTYPE AddRef() override; - ULONG STDMETHODCALLTYPE Release() override; - HRESULT STDMETHODCALLTYPE ShowContextMenu( - DWORD dwID, - POINT __RPC_FAR * ppt, - IUnknown __RPC_FAR * pcmdtReserved, - IDispatch __RPC_FAR * pdispReserved) override; - HRESULT STDMETHODCALLTYPE ShowUI( - DWORD dwID, - IOleInPlaceActiveObject __RPC_FAR * pActiveObject, - IOleCommandTarget __RPC_FAR * pCommandTarget, - IOleInPlaceFrame __RPC_FAR * pFrame, - IOleInPlaceUIWindow __RPC_FAR * pDoc) override; - HRESULT STDMETHODCALLTYPE GetHostInfo(DOCHOSTUIINFO __RPC_FAR * pInfo) override; - HRESULT STDMETHODCALLTYPE HideUI() override; - HRESULT STDMETHODCALLTYPE UpdateUI() override; - HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable) override; - HRESULT STDMETHODCALLTYPE OnDocWindowActivate(BOOL fActivate) override; - HRESULT STDMETHODCALLTYPE OnFrameWindowActivate(BOOL fActivate) override; - HRESULT STDMETHODCALLTYPE ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow __RPC_FAR * pUIWindow, - BOOL fRameWindow) override; - HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpMsg, const GUID __RPC_FAR * pguidCmdGroup, DWORD nCmdID) - override; - HRESULT STDMETHODCALLTYPE GetOptionKeyPath(LPOLESTR __RPC_FAR * pchKey, DWORD dw) override; - HRESULT STDMETHODCALLTYPE GetDropTarget(IDropTarget __RPC_FAR * pDropTarget, - IDropTarget __RPC_FAR *__RPC_FAR * ppDropTarget) override; - HRESULT STDMETHODCALLTYPE GetExternal(IDispatch __RPC_FAR *__RPC_FAR * ppDispatch) override; - HRESULT STDMETHODCALLTYPE TranslateUrl(DWORD dwTranslate, OLECHAR __RPC_FAR * pchURLIn, - OLECHAR __RPC_FAR *__RPC_FAR * ppchURLOut) override; - HRESULT STDMETHODCALLTYPE FilterDataObject(IDataObject __RPC_FAR * pDO, IDataObject __RPC_FAR *__RPC_FAR * ppDORet) - override; -}; diff --git a/src/runner/launcher/html/html_argument.cpp b/src/runner/launcher/html/html_argument.cpp deleted file mode 100644 index 72798b8..0000000 --- a/src/runner/launcher/html/html_argument.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "../../std_include.hpp" -#include "html_argument.hpp" - -html_argument::html_argument(VARIANT* val) : value_(val) -{ -} - -bool html_argument::is_empty() const -{ - return this->value_ == nullptr || this->value_->vt == VT_EMPTY; -} - -bool html_argument::is_string() const -{ - if (this->is_empty()) return false; - return this->value_->vt == VT_BSTR; -} - -bool html_argument::is_number() const -{ - if (this->is_empty()) return false; - return this->value_->vt == VT_I4; -} - -bool html_argument::is_bool() const -{ - if (this->is_empty()) return false; - return this->value_->vt == VT_BOOL; -} - -std::string html_argument::get_string() const -{ - if (!this->is_string()) return {}; - std::wstring wide_string(this->value_->bstrVal); -#pragma warning(push) -#pragma warning(disable: 4244) - return std::string(wide_string.begin(), wide_string.end()); -#pragma warning(pop) -} - -int html_argument::get_number() const -{ - if (!this->is_number()) return 0; - return this->value_->intVal; -} - -bool html_argument::get_bool() const -{ - if (!this->is_bool()) return false; - return this->value_->boolVal != FALSE; -} diff --git a/src/runner/launcher/html/html_argument.hpp b/src/runner/launcher/html/html_argument.hpp deleted file mode 100644 index 6e460e2..0000000 --- a/src/runner/launcher/html/html_argument.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -class html_argument final -{ -public: - html_argument(VARIANT* val); - - bool is_empty() const; - - bool is_string() const; - bool is_number() const; - bool is_bool() const; - - std::string get_string() const; - int get_number() const; - bool get_bool() const; - -private: - VARIANT* value_; -}; diff --git a/src/runner/launcher/html/html_dispatch.cpp b/src/runner/launcher/html/html_dispatch.cpp deleted file mode 100644 index bbc008c..0000000 --- a/src/runner/launcher/html/html_dispatch.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "../../std_include.hpp" -#include "html_frame.hpp" - -html_dispatch::html_dispatch(html_frame* frame) : frame_(frame) -{ -} - -HRESULT html_dispatch::QueryInterface(const IID& riid, LPVOID* ppvObj) -{ - if (!memcmp(&riid, &IID_IUnknown, sizeof(GUID)) || - !memcmp(&riid, &IID_IDispatch, sizeof(GUID))) - { - *ppvObj = this; - this->AddRef(); - return S_OK; - } - - *ppvObj = nullptr; - return E_NOINTERFACE; -} - -ULONG html_dispatch::AddRef() -{ - return 1; -} - -ULONG html_dispatch::Release() -{ - return 1; -} - -HRESULT html_dispatch::GetTypeInfoCount(UINT* /*pctinfo*/) -{ - return S_FALSE; -} - -HRESULT html_dispatch::GetTypeInfo(UINT /*iTInfo*/, LCID /*lcid*/, ITypeInfo** /*ppTInfo*/) -{ - return S_FALSE; -} - -HRESULT html_dispatch::GetIDsOfNames(const IID& /*riid*/, LPOLESTR* rgszNames, UINT cNames, LCID /*lcid*/, - DISPID* rgDispId) -{ - for (unsigned int i = 0; i < cNames; ++i) - { - std::wstring wide_name(rgszNames[i]); -#pragma warning(push) -#pragma warning(disable: 4244) - std::string name(wide_name.begin(), wide_name.end()); -#pragma warning(pop) - - - rgDispId[i] = this->frame_->get_callback_id(name); - } - - return S_OK; -} - -HRESULT html_dispatch::Invoke(DISPID dispIdMember, const IID& /*riid*/, LCID /*lcid*/, WORD /*wFlags*/, - DISPPARAMS* pDispParams, - VARIANT* pVarResult, EXCEPINFO* /*pExcepInfo*/, UINT* /*puArgErr*/) -{ - html_frame::callback_params params(pDispParams, pVarResult); - this->frame_->invoke_callback(dispIdMember, ¶ms); - return S_OK; -} diff --git a/src/runner/launcher/html/html_dispatch.hpp b/src/runner/launcher/html/html_dispatch.hpp deleted file mode 100644 index 869af7a..0000000 --- a/src/runner/launcher/html/html_dispatch.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -class html_frame; - -class html_dispatch final : public IDispatch -{ -public: - html_dispatch(html_frame* frame); - virtual ~html_dispatch() = default; - -private: - html_frame* frame_; - -public: // IDispatch interface - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override; - ULONG STDMETHODCALLTYPE AddRef() override; - ULONG STDMETHODCALLTYPE Release() override; - HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pctinfo) override; - HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override; - HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) - override; - HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, - VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) override; -}; diff --git a/src/runner/launcher/html/html_frame.cpp b/src/runner/launcher/html/html_frame.cpp deleted file mode 100644 index 2588d09..0000000 --- a/src/runner/launcher/html/html_frame.cpp +++ /dev/null @@ -1,298 +0,0 @@ -#include "../../std_include.hpp" -#include "../../finally.hpp" - -#include "../../utils/nt.hpp" - -#include "html_frame.hpp" - - -std::atomic html_frame::frame_count_ = 0; - -html_frame::callback_params::callback_params(DISPPARAMS* params, VARIANT* res) : result(res) -{ - for (auto i = params->cArgs; i > 0; --i) - { - auto* param = ¶ms->rgvarg[i - 1]; - this->arguments.emplace_back(param); - } -} - -html_frame::html_frame() - : in_place_frame_(this) - , in_place_site_(this) - , ui_handler_(this) - , client_site_(this) - , html_dispatch_(this) -{ - if (frame_count_++ == 0 && OleInitialize(nullptr) != S_OK) - { - throw std::runtime_error("Unable to initialize the OLE library"); - } - - auto needs_restart = false; - needs_restart |= set_browser_feature("FEATURE_BROWSER_EMULATION", 11000); - needs_restart |= set_browser_feature("FEATURE_GPU_RENDERING", 1); - - if (needs_restart) - { - utils::nt::relaunch_self(); - utils::nt::terminate(0); - } -} - -html_frame::~html_frame() -{ - if (--frame_count_ <= 0) - { - frame_count_ = 0; - OleUninitialize(); - } -} - -void html_frame::object_deleter(IUnknown* object) -{ - if (object) - { - object->Release(); - } -} - -HWND html_frame::get_window() const -{ - return this->window_; -} - -std::shared_ptr html_frame::get_browser_object() const -{ - return this->browser_object_; -} - -ole_in_place_frame* html_frame::get_in_place_frame() -{ - return &this->in_place_frame_; -} - -ole_in_place_site* html_frame::get_in_place_site() -{ - return &this->in_place_site_; -} - -doc_host_ui_handler* html_frame::get_ui_handler() -{ - return &this->ui_handler_; -} - -ole_client_site* html_frame::get_client_site() -{ - return &this->client_site_; -} - -html_dispatch* html_frame::get_html_dispatch() -{ - return &this->html_dispatch_; -} - -std::shared_ptr html_frame::get_web_browser() const -{ - if (!this->browser_object_) return {}; - - IWebBrowser2* web_browser = nullptr; - if (FAILED(this->browser_object_->QueryInterface(IID_IWebBrowser2, reinterpret_cast(&web_browser))) - || !web_browser) - return {}; - - return std::shared_ptr(web_browser, object_deleter); -} - -std::shared_ptr html_frame::get_dispatch() const -{ - const auto web_browser = this->get_web_browser(); - if (!web_browser) return {}; - - IDispatch* dispatch = nullptr; - if (FAILED(web_browser->get_Document(&dispatch)) || !dispatch) return {}; - - return std::shared_ptr(dispatch, object_deleter); -} - -std::shared_ptr html_frame::get_document() const -{ - const auto dispatch = this->get_dispatch(); - if (!dispatch) return {}; - - IHTMLDocument2* document = nullptr; - if (FAILED(dispatch->QueryInterface(IID_IHTMLDocument2, reinterpret_cast(&document))) - || !document) - return {}; - - return std::shared_ptr(document, object_deleter); -} - -void html_frame::initialize(const HWND window) -{ - if (this->window_) return; - this->window_ = window; - - this->create_browser(); - this->initialize_browser(); -} - -void html_frame::create_browser() -{ - LPCLASSFACTORY class_factory = nullptr; - if (FAILED( - CoGetClassObject(CLSID_WebBrowser, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, nullptr, IID_IClassFactory, - reinterpret_cast(&class_factory))) || !class_factory) - { - throw std::runtime_error("Unable to get the class factory"); - } - - IOleObject* browser_object = nullptr; - class_factory->CreateInstance(nullptr, IID_IOleObject, reinterpret_cast(&browser_object)); - class_factory->Release(); - - if (!browser_object) - { - throw std::runtime_error("Unable to create browser object"); - } - - this->browser_object_ = std::shared_ptr(browser_object, [](IOleObject* browser_object) - { - if (browser_object) - { - browser_object->Close(OLECLOSE_NOSAVE); - object_deleter(browser_object); - } - }); -} - -void html_frame::initialize_browser() -{ - this->browser_object_->SetClientSite(this->get_client_site()); - this->browser_object_->SetHostNames(L"Hostname", nullptr); - - RECT rect; - GetClientRect(this->get_window(), &rect); - OleSetContainedObject(this->browser_object_.get(), TRUE); - - this->browser_object_->DoVerb(OLEIVERB_SHOW, nullptr, this->get_client_site(), -1, this->get_window(), &rect); - this->resize(rect.right, rect.bottom); -} - -bool html_frame::set_browser_feature(const std::string& feature, DWORD value) -{ - const auto registry_path = R"(SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\)" + feature; - - HKEY key = nullptr; - if (RegCreateKeyA(HKEY_CURRENT_USER, registry_path.data(), &key) == ERROR_SUCCESS) - { - RegCloseKey(key); - } - - key = nullptr; - if (RegOpenKeyExA( - HKEY_CURRENT_USER, registry_path.data(), 0, - KEY_ALL_ACCESS, &key) != ERROR_SUCCESS) - { - return false; // Error :( - } - - const utils::nt::library self; - const auto name = self.get_name(); - - DWORD type{}; - auto is_new = true; - if (RegQueryValueExA(key, name.data(), nullptr, &type, nullptr, nullptr) == ERROR_SUCCESS) - { - is_new = false; - } - - RegSetValueExA(key, name.data(), 0, REG_DWORD, reinterpret_cast(&value), sizeof(value)); - RegCloseKey(key); - - return is_new; -} - -void html_frame::resize(const DWORD width, const DWORD height) const -{ - auto web_browser = this->get_web_browser(); - if (web_browser) - { - web_browser->put_Left(0); - web_browser->put_Top(0); - web_browser->put_Width(width); - web_browser->put_Height(height); - } -} - -bool html_frame::load_url(const std::string& url) const -{ - auto web_browser = this->get_web_browser(); - if (!web_browser) return false; - - std::wstring wide_url(url.begin(), url.end()); - - VARIANT my_url; - VariantInit(&my_url); - my_url.vt = VT_BSTR; - my_url.bstrVal = SysAllocString(wide_url.data()); - - const auto _ = utils::finally([&my_url]() { VariantClear(&my_url); }); - if (!my_url.bstrVal) return false; - - return SUCCEEDED(web_browser->Navigate2(&my_url, nullptr, nullptr, nullptr, nullptr)); -} - -bool html_frame::load_html(const std::string& html) const -{ - if (!this->load_url("about:blank")) return false; - - const auto document = this->get_document(); - if (!document) return false; - - SAFEARRAYBOUND safe_array_bound = {1, 0}; - auto safe_array = SafeArrayCreate(VT_VARIANT, 1, &safe_array_bound); - if (!safe_array) return false; - - const auto _ = utils::finally([safe_array]() { SafeArrayDestroy(safe_array); }); - - VARIANT* variant = nullptr; - if (FAILED(SafeArrayAccessData(safe_array, reinterpret_cast(&variant))) || !variant) return false; - - std::wstring wide_html(html.begin(), html.end()); - - variant->vt = VT_BSTR; - variant->bstrVal = SysAllocString(wide_html.data()); - if (!variant->bstrVal) return false; - - document->write(safe_array); - document->close(); - - return true; -} - -int html_frame::get_callback_id(const std::string& name) -{ - for (auto i = 0u; i < this->callbacks_.size(); ++i) - { - if (this->callbacks_[i].first == name) - { - return i; - } - } - - return -1; -} - -void html_frame::invoke_callback(const int id, callback_params* params) -{ - if (id >= 0 && static_cast(id) < this->callbacks_.size()) - { - this->callbacks_[id].second(params); - } -} - -void html_frame::register_callback(const std::string& name, const std::function& callback) -{ - this->callbacks_.emplace_back(name, callback); -} diff --git a/src/runner/launcher/html/html_frame.hpp b/src/runner/launcher/html/html_frame.hpp deleted file mode 100644 index 04d8108..0000000 --- a/src/runner/launcher/html/html_frame.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once -#include "ole_in_place_frame.hpp" -#include "ole_in_place_site.hpp" -#include "doc_host_ui_handler.hpp" -#include "ole_client_site.hpp" -#include "html_dispatch.hpp" -#include "html_argument.hpp" - -class html_frame -{ -public: - class callback_params final - { - public: - callback_params(DISPPARAMS* params, VARIANT* res); - - std::vector arguments; - html_argument result; - }; - - html_frame(); - virtual ~html_frame(); - - void initialize(HWND window); - - void resize(DWORD width, DWORD height) const; - bool load_url(const std::string& url) const; - bool load_html(const std::string& html) const; - - HWND get_window() const; - - std::shared_ptr get_browser_object() const; - std::shared_ptr get_web_browser() const; - std::shared_ptr get_dispatch() const; - std::shared_ptr get_document() const; - - ole_in_place_frame* get_in_place_frame(); - ole_in_place_site* get_in_place_site(); - doc_host_ui_handler* get_ui_handler(); - ole_client_site* get_client_site(); - html_dispatch* get_html_dispatch(); - - int get_callback_id(const std::string& name); - void invoke_callback(int id, callback_params* params); - - void register_callback(const std::string& name, const std::function& callback); - -private: - HWND window_ = nullptr; - std::shared_ptr browser_object_; - - ole_in_place_frame in_place_frame_; - ole_in_place_site in_place_site_; - doc_host_ui_handler ui_handler_; - ole_client_site client_site_; - html_dispatch html_dispatch_; - - std::vector>> callbacks_; - - void create_browser(); - void initialize_browser(); - - static bool set_browser_feature(const std::string& feature, DWORD value); - static void object_deleter(IUnknown* object); - - static std::atomic frame_count_; -}; diff --git a/src/runner/launcher/html/html_window.cpp b/src/runner/launcher/html/html_window.cpp deleted file mode 100644 index ed6d4c2..0000000 --- a/src/runner/launcher/html/html_window.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "../../std_include.hpp" -#include "html_window.hpp" - -window* html_window::get_window() -{ - return this; -} - -html_frame* html_window::get_html_frame() -{ - return this; -} - -LRESULT html_window::processor(const UINT message, const WPARAM w_param, const LPARAM l_param) -{ - if (message == WM_SIZE) - { - this->resize(LOWORD(l_param), HIWORD(l_param)); - return 0; - } - - if (message == WM_CREATE) - { - this->initialize(*this); - return 0; - } - - return window::processor(message, w_param, l_param); -} diff --git a/src/runner/launcher/html/html_window.hpp b/src/runner/launcher/html/html_window.hpp deleted file mode 100644 index 5b9f25b..0000000 --- a/src/runner/launcher/html/html_window.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include "../window.hpp" -#include "html_frame.hpp" - -class html_window final : public window, public html_frame -{ -public: - ~html_window() = default; - - window* get_window(); - html_frame* get_html_frame(); - -private: - LRESULT processor(UINT message, WPARAM w_param, LPARAM l_param) override; -}; diff --git a/src/runner/launcher/html/ole_client_site.cpp b/src/runner/launcher/html/ole_client_site.cpp deleted file mode 100644 index 1a624de..0000000 --- a/src/runner/launcher/html/ole_client_site.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "../../std_include.hpp" -#include "html_frame.hpp" - -ole_client_site::ole_client_site(html_frame* frame): frame_(frame) -{ -} - -HRESULT ole_client_site::QueryInterface(REFIID riid, LPVOID* ppvObject) -{ - if (!memcmp(&riid, &IID_IUnknown, sizeof(GUID)) || - !memcmp(&riid, &IID_IOleClientSite, sizeof(GUID))) - { - *ppvObject = this; - this->AddRef(); - return S_OK; - } - - if (!memcmp(&riid, &IID_IOleInPlaceSite, sizeof(GUID))) - { - auto in_place_site = this->frame_->get_in_place_site(); - in_place_site->AddRef(); - *ppvObject = in_place_site; - return S_OK; - } - - if (!memcmp(&riid, &IID_IDocHostUIHandler, sizeof(GUID))) - { - auto ui_handler = this->frame_->get_ui_handler(); - ui_handler->AddRef(); - *ppvObject = ui_handler; - return S_OK; - } - - *ppvObject = nullptr; - return E_NOINTERFACE; -} - -ULONG ole_client_site::AddRef() -{ - return 1; -} - -ULONG ole_client_site::Release() -{ - return 1; -} - -HRESULT ole_client_site::SaveObject() -{ - return E_NOTIMPL; -} - -HRESULT ole_client_site::GetMoniker(DWORD /*dwAssign*/, DWORD /*dwWhichMoniker*/, IMoniker** /*ppmk*/) -{ - return E_NOTIMPL; -} - -HRESULT ole_client_site::GetContainer(LPOLECONTAINER* ppContainer) -{ - *ppContainer = nullptr; - return E_NOINTERFACE; -} - -HRESULT ole_client_site::ShowObject() -{ - return NOERROR; -} - -HRESULT ole_client_site::OnShowWindow(BOOL /*fShow*/) -{ - return E_NOTIMPL; -} - -HRESULT ole_client_site::RequestNewObjectLayout() -{ - return E_NOTIMPL; -} diff --git a/src/runner/launcher/html/ole_client_site.hpp b/src/runner/launcher/html/ole_client_site.hpp deleted file mode 100644 index d0adc80..0000000 --- a/src/runner/launcher/html/ole_client_site.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -class html_frame; - -class ole_client_site final : public IOleClientSite -{ -public: - ole_client_site(html_frame* frame); - virtual ~ole_client_site() = default; - -private: - html_frame* frame_; - -public: - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppvObject) override; - ULONG STDMETHODCALLTYPE AddRef() override; - ULONG STDMETHODCALLTYPE Release() override; - HRESULT STDMETHODCALLTYPE SaveObject() override; - HRESULT STDMETHODCALLTYPE GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk) override; - HRESULT STDMETHODCALLTYPE GetContainer(LPOLECONTAINER FAR* ppContainer) override; - HRESULT STDMETHODCALLTYPE ShowObject() override; - HRESULT STDMETHODCALLTYPE OnShowWindow(BOOL fShow) override; - HRESULT STDMETHODCALLTYPE RequestNewObjectLayout() override; -}; diff --git a/src/runner/launcher/html/ole_in_place_frame.cpp b/src/runner/launcher/html/ole_in_place_frame.cpp deleted file mode 100644 index aa71a01..0000000 --- a/src/runner/launcher/html/ole_in_place_frame.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "../../std_include.hpp" -#include "html_frame.hpp" - -ole_in_place_frame::ole_in_place_frame(html_frame* frame): frame_(frame) -{ -} - -HRESULT ole_in_place_frame::QueryInterface(REFIID /*riid*/, LPVOID* /*ppvObj*/) -{ - return E_NOTIMPL; -} - -ULONG ole_in_place_frame::AddRef() -{ - return 1; -} - -ULONG ole_in_place_frame::Release() -{ - return 1; -} - -HRESULT ole_in_place_frame::GetWindow(HWND* lphwnd) -{ - *lphwnd = this->frame_->get_window(); - return S_OK; -} - -HRESULT ole_in_place_frame::ContextSensitiveHelp(BOOL /*fEnterMode*/) -{ - return E_NOTIMPL; -} - -HRESULT ole_in_place_frame::GetBorder(LPRECT /*lprectBorder*/) -{ - return E_NOTIMPL; -} - -HRESULT ole_in_place_frame::RequestBorderSpace(LPCBORDERWIDTHS /*pborderwidths*/) -{ - return E_NOTIMPL; -} - -HRESULT ole_in_place_frame::SetBorderSpace(LPCBORDERWIDTHS /*pborderwidths*/) -{ - return E_NOTIMPL; -} - -HRESULT ole_in_place_frame::SetActiveObject(IOleInPlaceActiveObject* /*pActiveObject*/, LPCOLESTR /*pszObjName*/) -{ - return S_OK; -} - -HRESULT ole_in_place_frame::InsertMenus(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS /*lpMenuWidths*/) -{ - return E_NOTIMPL; -} - -HRESULT ole_in_place_frame::SetMenu(HMENU /*hmenuShared*/, HOLEMENU /*holemenu*/, HWND /*hwndActiveObject*/) -{ - return S_OK; -} - -HRESULT ole_in_place_frame::RemoveMenus(HMENU /*hmenuShared*/) -{ - return E_NOTIMPL; -} - -HRESULT ole_in_place_frame::SetStatusText(LPCOLESTR /*pszStatusText*/) -{ - return S_OK; -} - -HRESULT ole_in_place_frame::EnableModeless(BOOL /*fEnable*/) -{ - return S_OK; -} - -HRESULT ole_in_place_frame::TranslateAcceleratorA(LPMSG /*lpmsg*/, WORD /*wID*/) -{ - return E_NOTIMPL; -} diff --git a/src/runner/launcher/html/ole_in_place_frame.hpp b/src/runner/launcher/html/ole_in_place_frame.hpp deleted file mode 100644 index 4a39d7f..0000000 --- a/src/runner/launcher/html/ole_in_place_frame.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -class html_frame; - -class ole_in_place_frame final : public IOleInPlaceFrame -{ -public: - ole_in_place_frame(html_frame* frame); - virtual ~ole_in_place_frame() = default; - -private: - html_frame* frame_; - -public: // IOleInPlaceFrame interface - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override; - ULONG STDMETHODCALLTYPE AddRef() override; - ULONG STDMETHODCALLTYPE Release() override; - HRESULT STDMETHODCALLTYPE GetWindow(HWND FAR* lphwnd) override; - HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode) override; - HRESULT STDMETHODCALLTYPE GetBorder(LPRECT lprectBorder) override; - HRESULT STDMETHODCALLTYPE RequestBorderSpace(LPCBORDERWIDTHS pborderwidths) override; - HRESULT STDMETHODCALLTYPE SetBorderSpace(LPCBORDERWIDTHS pborderwidths) override; - HRESULT STDMETHODCALLTYPE SetActiveObject(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR pszObjName) override; - HRESULT STDMETHODCALLTYPE InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) override; - HRESULT STDMETHODCALLTYPE SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject) override; - HRESULT STDMETHODCALLTYPE RemoveMenus(HMENU hmenuShared) override; - HRESULT STDMETHODCALLTYPE SetStatusText(LPCOLESTR pszStatusText) override; - HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable) override; - HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpmsg, WORD wID) override; -}; diff --git a/src/runner/launcher/html/ole_in_place_site.cpp b/src/runner/launcher/html/ole_in_place_site.cpp deleted file mode 100644 index 8fc7ead..0000000 --- a/src/runner/launcher/html/ole_in_place_site.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include "../../std_include.hpp" -#include "html_frame.hpp" - -ole_in_place_site::ole_in_place_site(html_frame* frame) : frame_(frame) -{ -} - -HRESULT ole_in_place_site::QueryInterface(REFIID riid, LPVOID FAR* ppvObj) -{ - auto client_site = this->frame_->get_client_site(); - if (client_site) - { - return client_site->QueryInterface(riid, ppvObj); - } - - return E_NOINTERFACE; -} - -ULONG ole_in_place_site::AddRef() -{ - return 1; -} - -ULONG ole_in_place_site::Release() -{ - return 1; -} - -HRESULT ole_in_place_site::GetWindow(HWND* lphwnd) -{ - *lphwnd = this->frame_->get_window(); - return S_OK; -} - -HRESULT ole_in_place_site::ContextSensitiveHelp(BOOL /*fEnterMode*/) -{ - return E_NOTIMPL; -} - -HRESULT ole_in_place_site::CanInPlaceActivate() -{ - return S_OK; -} - -HRESULT ole_in_place_site::OnInPlaceActivate() -{ - return S_OK; -} - -HRESULT ole_in_place_site::OnUIActivate() -{ - return S_OK; -} - -HRESULT ole_in_place_site::GetWindowContext(LPOLEINPLACEFRAME* lplpFrame, LPOLEINPLACEUIWINDOW* lplpDoc, - LPRECT /*lprcPosRect*/, LPRECT /*lprcClipRect*/, - LPOLEINPLACEFRAMEINFO lpFrameInfo) -{ - *lplpFrame = this->frame_->get_in_place_frame(); - *lplpDoc = nullptr; - - lpFrameInfo->fMDIApp = FALSE; - lpFrameInfo->hwndFrame = this->frame_->get_window(); - lpFrameInfo->haccel = nullptr; - lpFrameInfo->cAccelEntries = 0; - - return S_OK; -} - -HRESULT ole_in_place_site::Scroll(SIZE /*scrollExtent*/) -{ - return E_NOTIMPL; -} - -HRESULT ole_in_place_site::OnUIDeactivate(BOOL /*fUndoable*/) -{ - return S_OK; -} - -HRESULT ole_in_place_site::OnInPlaceDeactivate() -{ - return S_OK; -} - -HRESULT ole_in_place_site::DiscardUndoState() -{ - return E_NOTIMPL; -} - -HRESULT ole_in_place_site::DeactivateAndUndo() -{ - return E_NOTIMPL; -} - -HRESULT ole_in_place_site::OnPosRectChange(LPCRECT lprcPosRect) -{ - IOleInPlaceObject* in_place = nullptr; - if (!this->frame_->get_browser_object()->QueryInterface(IID_IOleInPlaceObject, reinterpret_cast(&in_place))) - { - in_place->SetObjectRects(lprcPosRect, lprcPosRect); - in_place->Release(); - } - - return S_OK; -} diff --git a/src/runner/launcher/html/ole_in_place_site.hpp b/src/runner/launcher/html/ole_in_place_site.hpp deleted file mode 100644 index 3dad18c..0000000 --- a/src/runner/launcher/html/ole_in_place_site.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -class html_frame; - -class ole_in_place_site final : public IOleInPlaceSite -{ -public: - ole_in_place_site(html_frame* frame); - virtual ~ole_in_place_site() = default; - -private: - html_frame* frame_; - -public: // IOleInPlaceSite interface - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override; - ULONG STDMETHODCALLTYPE AddRef() override; - ULONG STDMETHODCALLTYPE Release() override; - HRESULT STDMETHODCALLTYPE GetWindow(HWND FAR* lphwnd) override; - HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode) override; - HRESULT STDMETHODCALLTYPE CanInPlaceActivate() override; - HRESULT STDMETHODCALLTYPE OnInPlaceActivate() override; - HRESULT STDMETHODCALLTYPE OnUIActivate() override; - HRESULT STDMETHODCALLTYPE GetWindowContext(LPOLEINPLACEFRAME FAR* lplpFrame, LPOLEINPLACEUIWINDOW FAR* lplpDoc, - LPRECT lprcPosRect, LPRECT lprcClipRect, - LPOLEINPLACEFRAMEINFO lpFrameInfo) override; - HRESULT STDMETHODCALLTYPE Scroll(SIZE scrollExtent) override; - HRESULT STDMETHODCALLTYPE OnUIDeactivate(BOOL fUndoable) override; - HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate() override; - HRESULT STDMETHODCALLTYPE DiscardUndoState() override; - HRESULT STDMETHODCALLTYPE DeactivateAndUndo() override; - HRESULT STDMETHODCALLTYPE OnPosRectChange(LPCRECT lprcPosRect) override; -}; diff --git a/src/runner/launcher/launcher.cpp b/src/runner/launcher/launcher.cpp deleted file mode 100644 index f00d830..0000000 --- a/src/runner/launcher/launcher.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "../std_include.hpp" -#include "../resource.hpp" -#include "launcher.hpp" - -#include "../utils/nt.hpp" - -launcher::launcher() -{ - this->create_main_menu(); -} - -void launcher::create_main_menu() -{ - this->main_window_.set_callback( - [](window* window, const UINT message, const WPARAM w_param, const LPARAM l_param) -> LRESULT - { - if (message == WM_CLOSE) - { - window::close_all(); - } - - return DefWindowProcA(*window, message, w_param, l_param); - }); - - this->main_window_.create("S1x", 750, 420); - this->main_window_.load_html(utils::nt::load_resource(MAIN_MENU)); - this->main_window_.show(); -} - -void launcher::run() const -{ - window::run(); -} diff --git a/src/runner/launcher/launcher.hpp b/src/runner/launcher/launcher.hpp deleted file mode 100644 index f1753c8..0000000 --- a/src/runner/launcher/launcher.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include "html/html_window.hpp" - -class launcher final -{ -public: - launcher(); - - void run() const; - -private: - html_window main_window_; - - void create_main_menu(); -}; diff --git a/src/runner/launcher/window.cpp b/src/runner/launcher/window.cpp deleted file mode 100644 index 76b1082..0000000 --- a/src/runner/launcher/window.cpp +++ /dev/null @@ -1,208 +0,0 @@ -#include "../std_include.hpp" -#include "window.hpp" - -#include "../utils/nt.hpp" - -std::mutex window::mutex_; -std::vector window::windows_; - -window::window() -{ - ZeroMemory(&this->wc_, sizeof(this->wc_)); - - this->classname_ = "window-base-" + std::to_string(time(nullptr)); - - this->wc_.cbSize = sizeof(this->wc_); - this->wc_.style = CS_HREDRAW | CS_VREDRAW; - this->wc_.lpfnWndProc = static_processor; - this->wc_.hInstance = GetModuleHandle(nullptr); - this->wc_.hCursor = LoadCursor(nullptr, IDC_ARROW); - this->wc_.hIcon = LoadIcon(this->wc_.hInstance, MAKEINTRESOURCE(102)); - this->wc_.hIconSm = this->wc_.hIcon; - this->wc_.hbrBackground = HBRUSH(COLOR_WINDOW); - this->wc_.lpszClassName = this->classname_.data(); - RegisterClassEx(&this->wc_); -} - -void window::create(const std::string& title, const int width, const int height, const long flags) -{ - { - std::lock_guard _(mutex_); - windows_.push_back(this); - } - - const auto x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2; - const auto y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2; - - this->handle_ = CreateWindowExA(NULL, this->wc_.lpszClassName, title.data(), flags, x, y, width, height, nullptr, - nullptr, this->wc_.hInstance, this); - - SendMessageA(this->handle_, WM_DPICHANGED, 0, 0); -} - -window::~window() -{ - this->close(); - UnregisterClass(this->wc_.lpszClassName, this->wc_.hInstance); -} - -void window::close() -{ - if (!this->handle_) return; - - SendMessageA(this->handle_, WM_KILL_WINDOW, NULL, NULL); - this->handle_ = nullptr; -} - -void window::run() -{ - MSG msg; - while (GetMessage(&msg, nullptr, 0, 0)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } -} - -void window::close_all() -{ - std::unique_lock lock(mutex_); - auto window_list = windows_; - lock.unlock(); - - const auto current_thread_id = GetCurrentThreadId(); - for (auto& window : window_list) - { - const auto thread_id = GetWindowThreadProcessId(*window, nullptr); - - if (thread_id == current_thread_id) - { - window->close(); - } - } -} - -void window::remove_window(const window* window) -{ - std::lock_guard _(mutex_); - - for (auto i = windows_.begin(); i != windows_.end(); ++i) - { - if (*i == window) - { - windows_.erase(i); - break; - } - } -} - -int window::get_window_count() -{ - std::lock_guard _(mutex_); - - auto count = 0; - const auto current_thread_id = GetCurrentThreadId(); - - for (const auto& window : windows_) - { - const auto thread_id = GetWindowThreadProcessId(*window, nullptr); - - if (thread_id == current_thread_id) - { - ++count; - } - } - - return count; -} - -void window::show() const -{ - ShowWindow(this->handle_, SW_SHOW); - UpdateWindow(this->handle_); -} - -void window::hide() const -{ - ShowWindow(this->handle_, SW_HIDE); - UpdateWindow(this->handle_); -} - -void window::set_callback(const std::function& callback) -{ - this->callback_ = callback; -} - -LRESULT window::processor(const UINT message, const WPARAM w_param, const LPARAM l_param) -{ - if (message == WM_DPICHANGED) - { - const utils::nt::library user32{"user32.dll"}; - const auto get_dpi = user32 ? user32.get_proc("GetDpiForWindow") : nullptr; - - if (get_dpi) - { - const auto dpi = get_dpi(*this); - if (dpi != this->last_dpi_) - { - RECT rect; - GetWindowRect(*this, &rect); - - const auto scale = dpi * 1.0 / this->last_dpi_; - this->last_dpi_ = dpi; - - const auto width = rect.right - rect.left; - const auto height = rect.bottom - rect.top; - - MoveWindow(*this, rect.left, rect.top, int(width * scale), int(height * scale), TRUE); - } - } - } - - if (message == WM_DESTROY) - { - remove_window(this); - - if (get_window_count() == 0) - { - PostQuitMessage(0); - } - - return TRUE; - } - - if (message == WM_KILL_WINDOW) - { - DestroyWindow(*this); - return 0; - } - - if (this->callback_) - { - return this->callback_(this, message, w_param, l_param); - } - - return DefWindowProc(*this, message, w_param, l_param); -} - -LRESULT CALLBACK window::static_processor(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param) -{ - if (message == WM_CREATE) - { - auto data = reinterpret_cast(l_param); - SetWindowLongPtrA(hwnd, GWLP_USERDATA, LONG_PTR(data->lpCreateParams)); - - static_cast(data->lpCreateParams)->handle_ = hwnd; - } - - const auto self = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); - if (self) return self->processor(message, w_param, l_param); - - return DefWindowProc(hwnd, message, w_param, l_param); -} - - -window::operator HWND() const -{ - return this->handle_; -} diff --git a/src/runner/launcher/window.hpp b/src/runner/launcher/window.hpp deleted file mode 100644 index 4dea45d..0000000 --- a/src/runner/launcher/window.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#define WM_KILL_WINDOW (WM_USER+0) - -class window -{ -public: - window(); - virtual ~window(); - - void create(const std::string& title, int width, int height, - long flags = (WS_OVERLAPPEDWINDOW & ~(WS_THICKFRAME | WS_MAXIMIZEBOX))); - - void close(); - - void show() const; - void hide() const; - - void set_callback(const std::function& callback); - - operator HWND() const; - - static void run(); - static void close_all(); - -protected: - virtual LRESULT processor(UINT message, WPARAM w_param, LPARAM l_param); - -private: - uint32_t last_dpi_ = 96; - - WNDCLASSEX wc_{}; - HWND handle_ = nullptr; - std::string classname_; - std::function callback_; - - static LRESULT CALLBACK static_processor(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param); - - static std::mutex mutex_; - static std::vector windows_; - - static void remove_window(const window* window); - static int get_window_count(); -}; diff --git a/src/runner/main.cpp b/src/runner/main.cpp index 095abba..b0f4ad9 100644 --- a/src/runner/main.cpp +++ b/src/runner/main.cpp @@ -11,8 +11,6 @@ #include "resource.hpp" -#include "launcher/launcher.hpp" - #pragma comment(lib, "Shlwapi.lib") void patch_data(const driver_device& driver_device, const uint32_t pid, const uint64_t addr, const uint8_t* buffer, diff --git a/src/runner/resource.hpp b/src/runner/resource.hpp index dde0c73..b08cce0 100644 --- a/src/runner/resource.hpp +++ b/src/runner/resource.hpp @@ -1,4 +1,3 @@ #pragma once #define DRIVER_BINARY 300 -#define MAIN_MENU 301 diff --git a/src/runner/resource.rc b/src/runner/resource.rc index 98eab2c..7145013 100644 --- a/src/runner/resource.rc +++ b/src/runner/resource.rc @@ -85,7 +85,6 @@ END 102 ICON "resources/icon.ico" DRIVER_BINARY RCDATA DRIVER_FILE -MAIN_MENU RCDATA "resources/main.html" diff --git a/src/runner/resources/main.html b/src/runner/resources/main.html deleted file mode 100644 index 54ef7dc..0000000 --- a/src/runner/resources/main.html +++ /dev/null @@ -1,574 +0,0 @@ - - - - - - - S1x - - - - - - -
-
- - - - -
-
- - - - - diff --git a/src/runner/std_include.hpp b/src/runner/std_include.hpp index b7af216..e682f6b 100644 --- a/src/runner/std_include.hpp +++ b/src/runner/std_include.hpp @@ -10,7 +10,4 @@ #include #include -#include -#include - #pragma comment(lib, "Shlwapi.lib") From 11effb4efac293e4cdfb690d5c283ecbd460d979 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 15 May 2022 21:47:08 +0200 Subject: [PATCH 3/8] Prepare code watching --- src/driver/ept.cpp | 138 +++++++++++++++++++++++++++++++++++-- src/driver/ept.hpp | 21 +++++- src/runner/CMakeLists.txt | 2 +- src/runner/main.cpp | 96 +++++++++++++++++++++++--- src/runner/process.cpp | 81 ++++++++++++++++++++++ src/runner/process.hpp | 9 +++ src/runner/std_include.hpp | 1 + src/runner/utils/io.cpp | 125 +++++++++++++++++++++++++++++++++ src/runner/utils/io.hpp | 21 ++++++ src/shared/irp_data.hpp | 15 ++++ 10 files changed, 495 insertions(+), 14 deletions(-) create mode 100644 src/runner/process.cpp create mode 100644 src/runner/process.hpp create mode 100644 src/runner/utils/io.cpp create mode 100644 src/runner/utils/io.hpp diff --git a/src/driver/ept.cpp b/src/driver/ept.cpp index 8af2564..1407a2f 100644 --- a/src/driver/ept.cpp +++ b/src/driver/ept.cpp @@ -77,7 +77,7 @@ namespace vmx void update_fake_page(ept_hook& hook) { - if(!hook.mapped_virtual_address) + if (!hook.mapped_virtual_address) { return; } @@ -85,9 +85,9 @@ namespace vmx uint8_t page_copy[PAGE_SIZE]; memcpy(page_copy, hook.mapped_virtual_address, PAGE_SIZE); - for(size_t i = 0; i < PAGE_SIZE; ++i) + for (size_t i = 0; i < PAGE_SIZE; ++i) { - if(hook.diff_page[i] != page_copy[i]) + if (hook.diff_page[i] != page_copy[i]) { hook.diff_page[i] = page_copy[i]; hook.fake_page[i] = page_copy[i]; @@ -121,6 +121,8 @@ namespace vmx memset(this->epml4, 0, sizeof(this->epml4)); memset(this->epdpt, 0, sizeof(this->epdpt)); memset(this->epde, 0, sizeof(this->epde)); + + memset(this->access_records, 0, sizeof(this->access_records)); } ept::~ept() @@ -140,6 +142,14 @@ namespace vmx hook = hook->next_hook; memory::free_aligned_object(current_hook); } + + auto* watch_point = this->ept_code_watch_points; + while (watch_point) + { + auto* current_watch_point = watch_point; + watch_point = watch_point->next_watch_point; + memory::free_aligned_object(current_watch_point); + } } void ept::install_page_hook(void* destination, const void* source, const size_t length, @@ -151,6 +161,33 @@ namespace vmx memcpy(hook->fake_page + page_offset, source, length); } + void ept::record_access(const uint64_t rip) + { + const auto _ = utils::finally([&] + { + InterlockedExchange(&this->access_records_barrier, 0); + }); + + // Aaaahhh, fuck that xD + while (InterlockedExchange(&this->access_records_barrier, 1)) + { + } + + for (unsigned long long& access_record : this->access_records) + { + if (access_record == 0) + { + access_record = rip; + return; + } + + if (access_record == rip) + { + return; + } + } + } + void ept::install_hook(const void* destination, const void* source, const size_t length, ept_translation_hint* translation_hint) { @@ -197,7 +234,7 @@ namespace vmx } } - void ept::handle_violation(guest_context& guest_context) const + void ept::handle_violation(guest_context& guest_context) { vmx_exit_qualification_ept_violation violation_qualification{}; violation_qualification.flags = guest_context.exit_qualification; @@ -208,6 +245,32 @@ namespace vmx } const auto physical_base_address = reinterpret_cast(PAGE_ALIGN(guest_context.guest_physical_address)); + + // watch-point stuff + + auto* watch_point = this->find_ept_code_watch_point(physical_base_address); + if (watch_point) + { + if (!violation_qualification.ept_executable && violation_qualification.execute_access) + { + watch_point->target_page->execute_access = 1; + watch_point->target_page->read_access = 0; + guest_context.increment_rip = false; + } + + if (violation_qualification.ept_executable && violation_qualification.read_access) + { + watch_point->target_page->execute_access = 0; + watch_point->target_page->read_access = 1; + guest_context.increment_rip = false; + this->record_access(guest_context.guest_rip); + } + + return; + } + + // ept-hooking stuff + auto* hook = this->find_ept_hook(physical_base_address); if (!hook) { @@ -283,6 +346,30 @@ namespace vmx } } + void ept::install_code_watch_point(const uint64_t physical_page) + { + const auto physical_base_address = reinterpret_cast(PAGE_ALIGN(physical_page)); + + if (this->find_ept_code_watch_point(physical_base_address)) + { + return; + } + + auto* watch_point = this->allocate_ept_code_watch_point(); + if (!watch_point) + { + throw std::runtime_error("Failed to allocate watch point"); + } + + this->split_large_page(physical_base_address); + + watch_point->target_page = this->get_pml1_entry(physical_base_address); + if (!watch_point->target_page) + { + throw std::runtime_error("Failed to get PML1 entry for target address"); + } + } + ept_pointer ept::get_ept_pointer() const { const auto ept_pml4_physical_address = memory::get_physical_address(const_cast(&this->epml4[0])); @@ -404,6 +491,36 @@ namespace vmx return nullptr; } + ept_code_watch_point* ept::allocate_ept_code_watch_point() + { + auto* watch_point = memory::allocate_aligned_object(); + if (!watch_point) + { + throw std::runtime_error("Failed to allocate ept watch point object"); + } + + watch_point->next_watch_point = this->ept_code_watch_points; + this->ept_code_watch_points = watch_point; + + return watch_point; + } + + ept_code_watch_point* ept::find_ept_code_watch_point(const uint64_t physical_address) const + { + auto* watch_point = this->ept_code_watch_points; + while (watch_point) + { + if (watch_point->physical_base_address == physical_address) + { + return watch_point; + } + + watch_point = watch_point->next_watch_point; + } + + return nullptr; + } + ept_hook* ept::get_or_create_ept_hook(void* destination, ept_translation_hint* translation_hint) { const auto virtual_target = PAGE_ALIGN(destination); @@ -575,4 +692,17 @@ namespace vmx memory::free_non_paged_object(current_hint); } } + + uint64_t* ept::get_access_records(size_t* count) + { + size_t i = 0; + for (const auto& record : this->access_records) + { + if (record == 0) break; + ++i; + } + + *count = i; + return this->access_records; + } } diff --git a/src/driver/ept.hpp b/src/driver/ept.hpp index ee49c35..a667c1b 100644 --- a/src/driver/ept.hpp +++ b/src/driver/ept.hpp @@ -23,6 +23,12 @@ namespace vmx ept_split* next_split{nullptr}; }; + struct ept_code_watch_point + { + uint64_t physical_base_address{}; + pml1* target_page{}; + ept_code_watch_point* next_watch_point{nullptr}; + }; struct ept_hook { @@ -68,11 +74,13 @@ namespace vmx void initialize(); + void install_code_watch_point(uint64_t physical_page); + void install_hook(const void* destination, const void* source, size_t length, ept_translation_hint* translation_hint = nullptr); void disable_all_hooks() const; - void handle_violation(guest_context& guest_context) const; + void handle_violation(guest_context& guest_context); void handle_misconfiguration(guest_context& guest_context) const; ept_pointer get_ept_pointer() const; @@ -81,13 +89,19 @@ namespace vmx static 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); + private: DECLSPEC_PAGE_ALIGN pml4 epml4[EPT_PML4E_ENTRY_COUNT]; DECLSPEC_PAGE_ALIGN pml3 epdpt[EPT_PDPTE_ENTRY_COUNT]; DECLSPEC_PAGE_ALIGN pml2 epde[EPT_PDPTE_ENTRY_COUNT][EPT_PDE_ENTRY_COUNT]; + uint64_t access_records[1024]; + volatile long access_records_barrier{0}; + ept_split* ept_splits{nullptr}; ept_hook* ept_hooks{nullptr}; + ept_code_watch_point* ept_code_watch_points{nullptr}; pml2* get_pml2_entry(uint64_t physical_address); pml1* get_pml1_entry(uint64_t physical_address); @@ -97,11 +111,16 @@ namespace vmx ept_hook* allocate_ept_hook(uint64_t physical_address); ept_hook* find_ept_hook(uint64_t physical_address) const; + ept_code_watch_point* allocate_ept_code_watch_point(); + 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); void split_large_page(uint64_t physical_address); void install_page_hook(void* destination, const void* source, size_t length, ept_translation_hint* translation_hint = nullptr); + + void record_access(uint64_t rip); }; } diff --git a/src/runner/CMakeLists.txt b/src/runner/CMakeLists.txt index 2ebea5f..fb9af94 100644 --- a/src/runner/CMakeLists.txt +++ b/src/runner/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB_RECURSE runner_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) file(GLOB_RECURSE runner_headers ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp) -add_executable(runner WIN32 +add_executable(runner #WIN32 ${runner_sources} ${runner_headers} ) diff --git a/src/runner/main.cpp b/src/runner/main.cpp index b0f4ad9..3b6413f 100644 --- a/src/runner/main.cpp +++ b/src/runner/main.cpp @@ -1,15 +1,20 @@ +#include "std_include.hpp" + #include #include #include #include -#include "std_include.hpp" + #include "driver.hpp" #include "driver_device.hpp" +#include "process.hpp" #include #include "resource.hpp" +#include "utils/io.hpp" +#include "utils/nt.hpp" #pragma comment(lib, "Shlwapi.lib") @@ -74,21 +79,96 @@ std::filesystem::path extract_driver() return driver_file; } +std::vector> find_executable_regions(const std::string& pe_file) +{ + std::string data{}; + if (!utils::io::read_file(pe_file, &data)) + { + return {}; + } + + const utils::nt::library library(reinterpret_cast(data.data())); + if (!library.is_valid()) + { + return {}; + } + + const auto section_headers = library.get_section_headers(); + + std::vector> regions{}; + for (const auto& section_header : section_headers) + { + if (section_header->Characteristics & IMAGE_SCN_MEM_EXECUTE) + { + regions.emplace_back(section_header->VirtualAddress, section_header->Misc.VirtualSize); + } + } + + return regions; +} + void unsafe_main(const int /*argc*/, char* /*argv*/[]) { - const auto driver_file = extract_driver(); - - driver driver{driver_file, "MomoLul"}; - const driver_device driver_device{R"(\\.\HelloDev)"}; - - //launcher().run(); - std::string pid_str{}; printf("Please enter the pid: "); std::getline(std::cin, pid_str); const auto pid = atoi(pid_str.data()); + printf("Opening process...\n"); + const auto proc = process::open(pid, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ); + if (!proc) + { + printf("Failed to open process...\n"); + return; + } + + printf("Reading modules...\n"); + const auto modules = process::get_modules(proc); + printf("Found %zu modules\n", modules.size()); + + std::vector module_files{}; + module_files.reserve(modules.size()); + + int i = 0; + for (const auto& module : modules) + { + auto name = process::get_module_filename(proc, module); + printf("(%i)\t%p: %s\n", i++, static_cast(module), name.data()); + module_files.emplace_back(std::move(name)); + } + + std::string module_str{}; + printf("\nPlease enter the module number: "); + std::getline(std::cin, module_str); + + const auto module_num = atoi(module_str.data()); + + if (module_num < 0 || static_cast(module_num) >= modules.size()) + { + printf("Invalid module num\n"); + _getch(); + return; + } + + const auto module_base = reinterpret_cast(modules[module_num]); + const auto& file = module_files[module_num]; + printf("Analyzing %s...\n", file.data()); + const auto regions = find_executable_regions(file); + + for (const auto& region : regions) + { + printf("%p - %zu\n", module_base + region.first, region.second); + } + + _getch(); + return; + + const auto driver_file = extract_driver(); + + driver driver{driver_file, "MomoLul"}; + const driver_device driver_device{R"(\\.\HelloDev)"}; + /* // IW5 insert_nop(driver_device, pid, 0x4488A8, 2); // Force calling CG_DrawFriendOrFoeTargetBoxes diff --git a/src/runner/process.cpp b/src/runner/process.cpp new file mode 100644 index 0000000..9c5d6da --- /dev/null +++ b/src/runner/process.cpp @@ -0,0 +1,81 @@ +#include "std_include.hpp" +#include "process.hpp" + +namespace process +{ + native_handle open(const uint32_t process_id, const DWORD access) + { + const auto handle = ::OpenProcess(access, FALSE, process_id); + if (handle) + { + return {handle}; + } + + return {}; + } + + std::vector get_modules(const native_handle& process) + { + if (!process) + { + return {}; + } + + DWORD needed = 1024; + std::vector result{}; + + do + { + result.resize(needed); + if (!EnumProcessModulesEx(process, result.data(), static_cast(result.size()), &needed, + LIST_MODULES_ALL)) + { + return {}; + } + } + while (needed > result.size()); + + result.resize(needed); + + // Remove duplicates + std::ranges::sort(result); + const auto last = std::ranges::unique(result).begin(); + result.erase(last, result.end()); + + // Remove nullptr + for (auto i = result.begin(); i != result.end();) + { + if (*i == nullptr) + { + i = result.erase(i); + break; + } + else + { + ++i; + } + } + + return result; + } + + std::string get_module_filename(const native_handle& process, const HMODULE module) + { + if (!process) + { + return {}; + } + + std::string buffer{}; + buffer.resize(1024); + + const auto length = GetModuleFileNameExA(process, module, &buffer[0], static_cast(buffer.size())); + if (length > 0) + { + buffer.resize(length); + return buffer; + } + + return {}; + } +} diff --git a/src/runner/process.hpp b/src/runner/process.hpp new file mode 100644 index 0000000..1e20452 --- /dev/null +++ b/src/runner/process.hpp @@ -0,0 +1,9 @@ +#pragma once +#include "native_handle.hpp" + +namespace process +{ + native_handle open(uint32_t process_id, DWORD access); + std::vector get_modules(const native_handle& process); + std::string get_module_filename(const native_handle& process, HMODULE module); +} diff --git a/src/runner/std_include.hpp b/src/runner/std_include.hpp index e682f6b..f9bd296 100644 --- a/src/runner/std_include.hpp +++ b/src/runner/std_include.hpp @@ -9,5 +9,6 @@ #include #include #include +#include #pragma comment(lib, "Shlwapi.lib") diff --git a/src/runner/utils/io.cpp b/src/runner/utils/io.cpp new file mode 100644 index 0000000..4968f44 --- /dev/null +++ b/src/runner/utils/io.cpp @@ -0,0 +1,125 @@ +#include "io.hpp" +#include "nt.hpp" +#include + +namespace utils::io +{ + bool remove_file(const std::string& file) + { + return DeleteFileA(file.data()) == TRUE; + } + + bool move_file(const std::string& src, const std::string& target) + { + return MoveFileA(src.data(), target.data()) == TRUE; + } + + bool file_exists(const std::string& file) + { + return std::ifstream(file).good(); + } + + bool write_file(const std::string& file, const std::string& data, const bool append) + { + const auto pos = file.find_last_of("/\\"); + if (pos != std::string::npos) + { + create_directory(file.substr(0, pos)); + } + + std::ofstream stream( + file, std::ios::binary | std::ofstream::out | (append ? std::ofstream::app : 0)); + + if (stream.is_open()) + { + stream.write(data.data(), data.size()); + stream.close(); + return true; + } + + return false; + } + + std::string read_file(const std::string& file) + { + std::string data; + read_file(file, &data); + return data; + } + + bool read_file(const std::string& file, std::string* data) + { + if (!data) return false; + data->clear(); + + if (file_exists(file)) + { + std::ifstream stream(file, std::ios::binary); + if (!stream.is_open()) return false; + + stream.seekg(0, std::ios::end); + const std::streamsize size = stream.tellg(); + stream.seekg(0, std::ios::beg); + + if (size > -1) + { + data->resize(static_cast(size)); + stream.read(const_cast(data->data()), size); + stream.close(); + return true; + } + } + + return false; + } + + size_t file_size(const std::string& file) + { + if (file_exists(file)) + { + std::ifstream stream(file, std::ios::binary); + + if (stream.good()) + { + stream.seekg(0, std::ios::end); + return static_cast(stream.tellg()); + } + } + + return 0; + } + + bool create_directory(const std::string& directory) + { + return std::filesystem::create_directories(directory); + } + + bool directory_exists(const std::string& directory) + { + return std::filesystem::is_directory(directory); + } + + bool directory_is_empty(const std::string& directory) + { + return std::filesystem::is_empty(directory); + } + + std::vector list_files(const std::string& directory) + { + std::vector files; + + for (auto& file : std::filesystem::directory_iterator(directory)) + { + files.push_back(file.path().generic_string()); + } + + return files; + } + + void copy_folder(const std::filesystem::path& src, const std::filesystem::path& target) + { + std::filesystem::copy(src, target, + std::filesystem::copy_options::overwrite_existing | + std::filesystem::copy_options::recursive); + } +} diff --git a/src/runner/utils/io.hpp b/src/runner/utils/io.hpp new file mode 100644 index 0000000..ab4ebaa --- /dev/null +++ b/src/runner/utils/io.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include +#include + +namespace utils::io +{ + bool remove_file(const std::string& file); + bool move_file(const std::string& src, const std::string& target); + bool file_exists(const std::string& file); + bool write_file(const std::string& file, const std::string& data, bool append = false); + bool read_file(const std::string& file, std::string* data); + std::string read_file(const std::string& file); + size_t file_size(const std::string& file); + bool create_directory(const std::string& directory); + bool directory_exists(const std::string& directory); + bool directory_is_empty(const std::string& directory); + std::vector list_files(const std::string& directory); + void copy_folder(const std::filesystem::path& src, const std::filesystem::path& target); +} diff --git a/src/shared/irp_data.hpp b/src/shared/irp_data.hpp index bd5f704..2bdccbd 100644 --- a/src/shared/irp_data.hpp +++ b/src/shared/irp_data.hpp @@ -2,6 +2,8 @@ #define HOOK_DRV_IOCTL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_NEITHER, FILE_ANY_ACCESS) #define UNHOOK_DRV_IOCTL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_NEITHER, FILE_ANY_ACCESS) +#define WATCH_DRV_IOCTL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_NEITHER, FILE_ANY_ACCESS) +#define GET_RECORDS_DRV_IOCTL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_NEITHER, FILE_ANY_ACCESS) static_assert(sizeof(void*) == 8); @@ -12,3 +14,16 @@ struct hook_request const void* source_data{}; uint64_t source_data_size{}; }; + +struct watch_region +{ + const void* virtual_address{}; + size_t length{}; +}; + +struct watch_request +{ + uint32_t process_id{}; + const void* watch_region{}; + uint64_t watch_region_count{}; +}; From c8817b3ee4314935fcaca477432d9fa2571ac830 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 16 May 2022 09:20:37 +0200 Subject: [PATCH 4/8] Quick and dirty code watching bridge for usermode/kernelmode --- src/driver/hypervisor.cpp | 5 ++ src/driver/hypervisor.hpp | 2 + src/driver/irp.cpp | 104 +++++++++++++++++++++++++++- src/runner/driver_device.cpp | 26 +++++-- src/runner/driver_device.hpp | 1 + src/runner/main.cpp | 129 ++++++++++++++++++++++++++++++++--- src/shared/irp_data.hpp | 2 +- 7 files changed, 251 insertions(+), 18 deletions(-) diff --git a/src/driver/hypervisor.cpp b/src/driver/hypervisor.cpp index 9a494ed..a42ab7c 100644 --- a/src/driver/hypervisor.cpp +++ b/src/driver/hypervisor.cpp @@ -211,6 +211,11 @@ void hypervisor::disable_all_ept_hooks() const }); } +vmx::ept& hypervisor::get_ept() const +{ + return *this->ept_; +} + hypervisor* hypervisor::get_instance() { return instance; diff --git a/src/driver/hypervisor.hpp b/src/driver/hypervisor.hpp index 092661a..2bae9b1 100644 --- a/src/driver/hypervisor.hpp +++ b/src/driver/hypervisor.hpp @@ -23,6 +23,8 @@ public: vmx::ept_translation_hint* translation_hint = nullptr); void disable_all_ept_hooks() const; + vmx::ept& get_ept() const; + static hypervisor* get_instance(); private: diff --git a/src/driver/irp.cpp b/src/driver/irp.cpp index ca10c44..133609e 100644 --- a/src/driver/irp.cpp +++ b/src/driver/irp.cpp @@ -114,6 +114,9 @@ namespace void try_apply_hook(const PIO_STACK_LOCATION irp_sp) { + memory::assert_readability(irp_sp->Parameters.DeviceIoControl.Type3InputBuffer, + irp_sp->Parameters.DeviceIoControl.InputBufferLength); + if (irp_sp->Parameters.DeviceIoControl.InputBufferLength < sizeof(hook_request)) { throw std::runtime_error("Invalid hook request"); @@ -126,10 +129,103 @@ namespace apply_hook(request); } + void watch_regions(const watch_request& watch_request) + { + auto* hypervisor = hypervisor::get_instance(); + if (!hypervisor) + { + throw std::runtime_error("Hypervisor not installed"); + } + + std::unique_ptr buffer(new watch_region[watch_request.watch_region_count]); + if (!buffer) + { + throw std::runtime_error("Failed to copy buffer"); + } + + memcpy(buffer.get(), watch_request.watch_regions, watch_request.watch_region_count * sizeof(watch_region)); + + auto watch_request_copy = watch_request; + watch_request_copy.watch_regions = buffer.get(); + + thread::kernel_thread t([watch_request_copy, hypervisor] + { + debug_log("Looking up process: %d\n", watch_request_copy.process_id); + + const auto process_handle = process::find_process_by_id(watch_request_copy.process_id); + if (!process_handle || !process_handle.is_alive()) + { + debug_log("Bad process\n"); + return; + } + + const auto name = process_handle.get_image_filename(); + if (name) + { + debug_log("Attaching to %s\n", name); + } + + process::scoped_process_attacher attacher{process_handle}; + + for (size_t i = 0; i < watch_request_copy.watch_region_count; ++i) + { + const auto& watch_region = watch_request_copy.watch_regions[i]; + + auto start = static_cast(watch_region.virtual_address); + auto end = start + watch_region.length; + + start = static_cast(PAGE_ALIGN(start)); + end = static_cast(PAGE_ALIGN(reinterpret_cast(end) + (PAGE_SIZE - 1))); + + for (auto current = start; current < end; current += PAGE_SIZE) + { + const auto physical_address = memory::get_physical_address(const_cast(current)); + if (physical_address) + { + hypervisor->get_ept().install_code_watch_point(physical_address); + } + } + } + }); + + t.join(); + } + + void try_watch_regions(const PIO_STACK_LOCATION irp_sp) + { + memory::assert_readability(irp_sp->Parameters.DeviceIoControl.Type3InputBuffer, + irp_sp->Parameters.DeviceIoControl.InputBufferLength); + + if (irp_sp->Parameters.DeviceIoControl.InputBufferLength < sizeof(watch_request)) + { + throw std::runtime_error("Invalid watch request"); + } + + const auto& request = *static_cast(irp_sp->Parameters.DeviceIoControl.Type3InputBuffer); + memory::assert_readability(request.watch_regions, request.watch_region_count * sizeof(watch_region)); + + watch_regions(request); + } + + void get_records(const PIRP irp, const PIO_STACK_LOCATION irp_sp) + { + auto* hypervisor = hypervisor::get_instance(); + if (!hypervisor) + { + throw std::runtime_error("Hypervisor not installed"); + } + + size_t count{}; + const auto records = hypervisor->get_ept().get_access_records(&count); + + memset(irp->UserBuffer, 0, irp_sp->Parameters.DeviceIoControl.OutputBufferLength); + memcpy(irp->UserBuffer, records, min(irp_sp->Parameters.DeviceIoControl.OutputBufferLength, count * 8)); + } + void handle_irp(const PIRP irp) { irp->IoStatus.Information = 0; - irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + irp->IoStatus.Status = STATUS_SUCCESS; const auto irp_sp = IoGetCurrentIrpStackLocation(irp); @@ -145,6 +241,12 @@ namespace case UNHOOK_DRV_IOCTL: unhook(); break; + case WATCH_DRV_IOCTL: + try_watch_regions(irp_sp); + break; + case GET_RECORDS_DRV_IOCTL: + get_records(irp, irp_sp); + break; default: debug_log("Invalid IOCTL Code: 0x%X\n", ioctr_code); irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; diff --git a/src/runner/driver_device.cpp b/src/runner/driver_device.cpp index 6c5377d..31de047 100644 --- a/src/runner/driver_device.cpp +++ b/src/runner/driver_device.cpp @@ -24,21 +24,35 @@ bool driver_device::send(const DWORD ioctl_code, const data& input) const } bool driver_device::send(const DWORD ioctl_code, const data& input, data& output) const +{ + size_t out_len = output.size(); + if (this->send(ioctl_code, input.data(), input.size(), output.data(), &out_len)) + { + output.resize(out_len); + return true; + } + + return false; +} + +bool driver_device::send(const DWORD ioctl_code, const void* input, const size_t input_length, void* output, + size_t* output_length) const { DWORD size_returned = 0; const auto success = DeviceIoControl(this->device_, ioctl_code, - const_cast(input.data()), - static_cast(input.size()), - output.data(), - static_cast(output.size()), + const_cast(input), + static_cast(input_length), + output, + static_cast(*output_length), &size_returned, nullptr ) != FALSE; - if (success && size_returned < output.size()) + *output_length = 0; + if (success) { - output.resize(size_returned); + *output_length = size_returned; } return success; diff --git a/src/runner/driver_device.hpp b/src/runner/driver_device.hpp index 5a3c5da..08c0913 100644 --- a/src/runner/driver_device.hpp +++ b/src/runner/driver_device.hpp @@ -16,6 +16,7 @@ public: using data = std::vector; bool send(DWORD ioctl_code, const data& input) const; bool send(DWORD ioctl_code, const data& input, data& output) const; + bool send(DWORD ioctl_code, const void* input, size_t input_length, void* output, size_t* output_length) const; private: native_handle device_{}; diff --git a/src/runner/main.cpp b/src/runner/main.cpp index 3b6413f..9356eaa 100644 --- a/src/runner/main.cpp +++ b/src/runner/main.cpp @@ -4,7 +4,7 @@ #include #include #include - +#include #include "driver.hpp" #include "driver_device.hpp" @@ -107,16 +107,114 @@ std::vector> find_executable_regions(const std::string return regions; } -void unsafe_main(const int /*argc*/, char* /*argv*/[]) +uint32_t get_process_id() { std::string pid_str{}; printf("Please enter the pid: "); std::getline(std::cin, pid_str); - const auto pid = atoi(pid_str.data()); + return atoi(pid_str.data()); +} + +void watch_regions(const driver_device& driver_device, const uint32_t pid, const HMODULE module, + const std::vector>& regions) +{ + std::vector watch_regions{}; + watch_regions.reserve(regions.size()); + + for (const auto& region : regions) + { + watch_region watch_region{}; + watch_region.virtual_address = reinterpret_cast(module) + region.first; + watch_region.length = region.second; + watch_regions.push_back(watch_region); + } + + watch_request request{}; + request.process_id = pid; + request.watch_regions = watch_regions.data(); + request.watch_region_count = watch_regions.size(); + + driver_device::data out{}; + size_t out_len = 0; + driver_device.send(WATCH_DRV_IOCTL, &request, sizeof(request), out.data(), &out_len); +} + +std::vector query_records(const driver_device& driver_device, const size_t current_size = 0) +{ + std::vector result{}; + result.resize(std::max(size_t(1024), current_size * 2)); + + while (true) + { + char in[1]; + constexpr auto element_len = sizeof(decltype(result)::value_type); + const size_t initial_len = result.size() * element_len; + size_t out_len = initial_len; + if (!driver_device.send(GET_RECORDS_DRV_IOCTL, in, 0, result.data(), &out_len)) + { + return {}; + } + + //if (out_len <= initial_len) + if (result.back() == 0) + { + //result.resize(out_len / element_len); + break; + } + + //result.resize((out_len / element_len) + 10); + const auto new_size = result.size() * 2; + + result = {}; + result.resize(result.size() * 2); + } + + // Shrink + size_t i; + for (i = result.size(); i > 0; --i) + { + if (result[i - 1] != 0) + { + break; + } + } + + result.resize(i); + + return result; +} + +void report_records(const std::atomic_bool& flag, const driver_device& driver_device) +{ + std::set access_addresses{}; + + while (flag) + { + std::this_thread::sleep_for(std::chrono::seconds(1)); + const auto new_records = query_records(driver_device, access_addresses.size()); + + for (const auto& new_record : new_records) + { + if (access_addresses.emplace(new_record).second) + { + printf("%p\n", reinterpret_cast(new_record)); + } + } + } +} + +void unsafe_main(const int /*argc*/, char* /*argv*/[]) +{ + const auto driver_file = extract_driver(); + + driver driver{driver_file, "MomoLul"}; + const driver_device driver_device{R"(\\.\HelloDev)"}; + + const auto pid = get_process_id(); printf("Opening process...\n"); - const auto proc = process::open(pid, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ); + auto proc = process::open(pid, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ); if (!proc) { printf("Failed to open process...\n"); @@ -138,6 +236,9 @@ void unsafe_main(const int /*argc*/, char* /*argv*/[]) module_files.emplace_back(std::move(name)); } + // We don't need this anymore + proc = {}; + std::string module_str{}; printf("\nPlease enter the module number: "); std::getline(std::cin, module_str); @@ -151,7 +252,8 @@ void unsafe_main(const int /*argc*/, char* /*argv*/[]) return; } - const auto module_base = reinterpret_cast(modules[module_num]); + const auto target_module = modules[module_num]; + const auto module_base = reinterpret_cast(target_module); const auto& file = module_files[module_num]; printf("Analyzing %s...\n", file.data()); const auto regions = find_executable_regions(file); @@ -161,14 +263,21 @@ void unsafe_main(const int /*argc*/, char* /*argv*/[]) printf("%p - %zu\n", module_base + region.first, region.second); } + watch_regions(driver_device, pid, target_module, regions); + + std::atomic_bool terminate{false}; + std::thread t([&]() + { + report_records(terminate, driver_device); + }); + _getch(); + + terminate = true; + t.join(); + return; - const auto driver_file = extract_driver(); - - driver driver{driver_file, "MomoLul"}; - const driver_device driver_device{R"(\\.\HelloDev)"}; - /* // IW5 insert_nop(driver_device, pid, 0x4488A8, 2); // Force calling CG_DrawFriendOrFoeTargetBoxes diff --git a/src/shared/irp_data.hpp b/src/shared/irp_data.hpp index 2bdccbd..99ebad1 100644 --- a/src/shared/irp_data.hpp +++ b/src/shared/irp_data.hpp @@ -24,6 +24,6 @@ struct watch_region struct watch_request { uint32_t process_id{}; - const void* watch_region{}; + const watch_region* watch_regions{}; uint64_t watch_region_count{}; }; From 4d1f94d65aa9cf623a3da954078827153ff49465 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 16 May 2022 10:15:57 +0200 Subject: [PATCH 5/8] More code watching progress ... but it still bug checks --- src/driver/ept.cpp | 18 ++++++++++++++++++ src/driver/hypervisor.cpp | 25 +++++++++++++++++++++++++ src/driver/hypervisor.hpp | 3 +++ src/driver/irp.cpp | 7 ++++++- src/runner/main.cpp | 10 ++++++++-- 5 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/driver/ept.cpp b/src/driver/ept.cpp index 1407a2f..55c5679 100644 --- a/src/driver/ept.cpp +++ b/src/driver/ept.cpp @@ -94,6 +94,20 @@ namespace vmx } } } + + void reset_all_watch_point_pages(ept_code_watch_point* watch_point) + { + while (watch_point) + { + if (watch_point->target_page) + { + watch_point->target_page->read_access = 0; + watch_point->target_page->execute_access = 1; + } + + watch_point = watch_point->next_watch_point; + } + } } ept_hook::ept_hook(const uint64_t physical_base) @@ -251,6 +265,8 @@ namespace vmx auto* watch_point = this->find_ept_code_watch_point(physical_base_address); if (watch_point) { + reset_all_watch_point_pages(this->ept_code_watch_points); + if (!violation_qualification.ept_executable && violation_qualification.execute_access) { watch_point->target_page->execute_access = 1; @@ -368,6 +384,8 @@ namespace vmx { throw std::runtime_error("Failed to get PML1 entry for target address"); } + + watch_point->target_page->read_access = 0; } ept_pointer ept::get_ept_pointer() const diff --git a/src/driver/hypervisor.cpp b/src/driver/hypervisor.cpp index a42ab7c..eb6f675 100644 --- a/src/driver/hypervisor.cpp +++ b/src/driver/hypervisor.cpp @@ -192,6 +192,31 @@ bool hypervisor::install_ept_hook(const void* destination, const void* source, c return failures == 0; } +bool hypervisor::install_ept_code_watch_point(const uint64_t physical_page) const +{ + try + { + this->ept_->install_code_watch_point(physical_page); + } + catch (std::exception& e) + { + debug_log("Failed to install ept watch point on core %d: %s\n", thread::get_processor_index(), e.what()); + return false; + } + catch (...) + { + debug_log("Failed to install ept watch point on core %d.\n", thread::get_processor_index()); + return false; + } + + thread::dispatch_on_all_cores([&] + { + this->ept_->invalidate(); + }); + + return true; +} + void hypervisor::disable_all_ept_hooks() const { this->ept_->disable_all_hooks(); diff --git a/src/driver/hypervisor.hpp b/src/driver/hypervisor.hpp index 2bae9b1..25edaca 100644 --- a/src/driver/hypervisor.hpp +++ b/src/driver/hypervisor.hpp @@ -21,6 +21,9 @@ public: bool install_ept_hook(const void* destination, const void* source, size_t length, vmx::ept_translation_hint* translation_hint = nullptr); + + bool install_ept_code_watch_point(uint64_t physical_page) const; + void disable_all_ept_hooks() const; vmx::ept& get_ept() const; diff --git a/src/driver/irp.cpp b/src/driver/irp.cpp index 133609e..aabebc5 100644 --- a/src/driver/irp.cpp +++ b/src/driver/irp.cpp @@ -182,7 +182,12 @@ namespace const auto physical_address = memory::get_physical_address(const_cast(current)); if (physical_address) { - hypervisor->get_ept().install_code_watch_point(physical_address); + debug_log("Watching %p -> %llX\n", current, physical_address); + (void)hypervisor->install_ept_code_watch_point(physical_address); + } + else + { + debug_log("Failed to resovle physical address for %p\n", current); } } } diff --git a/src/runner/main.cpp b/src/runner/main.cpp index 9356eaa..a764aa9 100644 --- a/src/runner/main.cpp +++ b/src/runner/main.cpp @@ -185,10 +185,11 @@ std::vector query_records(const driver_device& driver_device, const si return result; } -void report_records(const std::atomic_bool& flag, const driver_device& driver_device) +void report_records(const std::atomic_bool& flag, const driver_device& driver_device, const uint32_t pid, const HMODULE target_module, const std::vector>& regions) { std::set access_addresses{}; + int i = 0; while (flag) { std::this_thread::sleep_for(std::chrono::seconds(1)); @@ -201,6 +202,11 @@ void report_records(const std::atomic_bool& flag, const driver_device& driver_de printf("%p\n", reinterpret_cast(new_record)); } } + + if((++i) % 5 == 0) + { + watch_regions(driver_device, pid, target_module, regions); + } } } @@ -268,7 +274,7 @@ void unsafe_main(const int /*argc*/, char* /*argv*/[]) std::atomic_bool terminate{false}; std::thread t([&]() { - report_records(terminate, driver_device); + report_records(terminate, driver_device, pid, target_module, regions); }); _getch(); From f37a919f777d9d65a0cdafed81ddc1a3ebe0d783 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 16 May 2022 11:51:33 +0200 Subject: [PATCH 6/8] Fix watch points --- src/driver/ept.cpp | 30 +++++++++++++++--------------- src/driver/ept.hpp | 1 - src/driver/hypervisor.cpp | 30 ++++++++++++++++++++++++------ src/driver/hypervisor.hpp | 3 ++- src/driver/irp.cpp | 32 +++++++++++++++++++++++++++++--- 5 files changed, 70 insertions(+), 26 deletions(-) diff --git a/src/driver/ept.cpp b/src/driver/ept.cpp index 55c5679..f369423 100644 --- a/src/driver/ept.cpp +++ b/src/driver/ept.cpp @@ -102,6 +102,7 @@ namespace vmx if (watch_point->target_page) { watch_point->target_page->read_access = 0; + watch_point->target_page->write_access = 0; watch_point->target_page->execute_access = 1; } @@ -162,7 +163,7 @@ namespace vmx { auto* current_watch_point = watch_point; watch_point = watch_point->next_watch_point; - memory::free_aligned_object(current_watch_point); + memory::free_non_paged_object(current_watch_point); } } @@ -177,16 +178,6 @@ namespace vmx void ept::record_access(const uint64_t rip) { - const auto _ = utils::finally([&] - { - InterlockedExchange(&this->access_records_barrier, 0); - }); - - // Aaaahhh, fuck that xD - while (InterlockedExchange(&this->access_records_barrier, 1)) - { - } - for (unsigned long long& access_record : this->access_records) { if (access_record == 0) @@ -271,15 +262,21 @@ namespace vmx { watch_point->target_page->execute_access = 1; watch_point->target_page->read_access = 0; + watch_point->target_page->write_access = 0; guest_context.increment_rip = false; } - - if (violation_qualification.ept_executable && violation_qualification.read_access) + else if (violation_qualification.ept_executable && (violation_qualification.read_access || + violation_qualification. + write_access)) { watch_point->target_page->execute_access = 0; watch_point->target_page->read_access = 1; + watch_point->target_page->write_access = 1; guest_context.increment_rip = false; - this->record_access(guest_context.guest_rip); + if (violation_qualification.read_access) + { + this->record_access(guest_context.guest_rip); + } } return; @@ -310,6 +307,7 @@ namespace vmx void ept::handle_misconfiguration(guest_context& guest_context) const { + // We can actually not recover from this, but this should not occur anyways guest_context.increment_rip = false; guest_context.exit_vm = true; } @@ -379,12 +377,14 @@ namespace vmx this->split_large_page(physical_base_address); + watch_point->physical_base_address = physical_base_address; watch_point->target_page = this->get_pml1_entry(physical_base_address); if (!watch_point->target_page) { throw std::runtime_error("Failed to get PML1 entry for target address"); } + watch_point->target_page->write_access = 0; watch_point->target_page->read_access = 0; } @@ -511,7 +511,7 @@ namespace vmx ept_code_watch_point* ept::allocate_ept_code_watch_point() { - auto* watch_point = memory::allocate_aligned_object(); + auto* watch_point = memory::allocate_non_paged_object(); if (!watch_point) { throw std::runtime_error("Failed to allocate ept watch point object"); diff --git a/src/driver/ept.hpp b/src/driver/ept.hpp index a667c1b..30483e8 100644 --- a/src/driver/ept.hpp +++ b/src/driver/ept.hpp @@ -97,7 +97,6 @@ namespace vmx DECLSPEC_PAGE_ALIGN pml2 epde[EPT_PDPTE_ENTRY_COUNT][EPT_PDE_ENTRY_COUNT]; uint64_t access_records[1024]; - volatile long access_records_barrier{0}; ept_split* ept_splits{nullptr}; ept_hook* ept_hooks{nullptr}; diff --git a/src/driver/hypervisor.cpp b/src/driver/hypervisor.cpp index eb6f675..19c5566 100644 --- a/src/driver/hypervisor.cpp +++ b/src/driver/hypervisor.cpp @@ -192,7 +192,7 @@ bool hypervisor::install_ept_hook(const void* destination, const void* source, c return failures == 0; } -bool hypervisor::install_ept_code_watch_point(const uint64_t physical_page) const +bool hypervisor::install_ept_code_watch_point(const uint64_t physical_page, bool invalidate) const { try { @@ -209,12 +209,31 @@ bool hypervisor::install_ept_code_watch_point(const uint64_t physical_page) cons return false; } + if (invalidate) + { + thread::dispatch_on_all_cores([&] + { + this->ept_->invalidate(); + }); + } + + return true; +} + +bool hypervisor::install_ept_code_watch_points(const uint64_t* physical_pages, const size_t count) const +{ + bool success = true; + for (size_t i = 0; i < count; ++i) + { + success &= this->install_ept_code_watch_point(physical_pages[i], false); + } + thread::dispatch_on_all_cores([&] { this->ept_->invalidate(); }); - return true; + return success; } void hypervisor::disable_all_ept_hooks() const @@ -534,14 +553,13 @@ extern "C" [[ noreturn ]] void vm_exit_handler(CONTEXT* context) if (guest_context.exit_vm) { context->Rcx = 0x43434343; - restore_descriptor_tables(vm_state->launch_context); - - __writecr3(read_vmx(VMCS_GUEST_CR3)); - context->Rsp = guest_context.guest_rsp; context->Rip = guest_context.guest_rip; context->EFlags = static_cast(guest_context.guest_e_flags); + restore_descriptor_tables(vm_state->launch_context); + + __writecr3(read_vmx(VMCS_GUEST_CR3)); __vmx_off(); } else diff --git a/src/driver/hypervisor.hpp b/src/driver/hypervisor.hpp index 25edaca..7ae7e93 100644 --- a/src/driver/hypervisor.hpp +++ b/src/driver/hypervisor.hpp @@ -22,7 +22,8 @@ public: bool install_ept_hook(const void* destination, const void* source, size_t length, vmx::ept_translation_hint* translation_hint = nullptr); - bool install_ept_code_watch_point(uint64_t physical_page) 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; void disable_all_ept_hooks() const; diff --git a/src/driver/irp.cpp b/src/driver/irp.cpp index aabebc5..0f8be63 100644 --- a/src/driver/irp.cpp +++ b/src/driver/irp.cpp @@ -148,7 +148,27 @@ namespace auto watch_request_copy = watch_request; watch_request_copy.watch_regions = buffer.get(); - thread::kernel_thread t([watch_request_copy, hypervisor] + size_t page_count = 0; + for (size_t i = 0; i < watch_request_copy.watch_region_count; ++i) + { + const auto& watch_region = watch_request_copy.watch_regions[i]; + + auto start = static_cast(watch_region.virtual_address); + auto end = start + watch_region.length; + + start = static_cast(PAGE_ALIGN(start)); + end = static_cast(PAGE_ALIGN(reinterpret_cast(end) + (PAGE_SIZE - 1))); + page_count += (end - start) / PAGE_SIZE; + } + + volatile long index = 0; + std::unique_ptr page_buffer(new uint64_t[page_count]); + if (!page_buffer) + { + throw std::runtime_error("Failed to copy buffer"); + } + + thread::kernel_thread t([watch_request_copy, hypervisor, &index, &page_buffer] { debug_log("Looking up process: %d\n", watch_request_copy.process_id); @@ -182,8 +202,10 @@ namespace const auto physical_address = memory::get_physical_address(const_cast(current)); if (physical_address) { - debug_log("Watching %p -> %llX\n", current, physical_address); - (void)hypervisor->install_ept_code_watch_point(physical_address); + debug_log("Resolved %p -> %llX\n", current, physical_address); + page_buffer.get()[index] = physical_address; + InterlockedIncrement(&index); + //(void)hypervisor->install_ept_code_watch_point(physical_address); } else { @@ -194,6 +216,10 @@ namespace }); t.join(); + + debug_log("Installing watch points...\n"); + (void)hypervisor->install_ept_code_watch_points(page_buffer.get(), index); + debug_log("Watch points installed\n"); } void try_watch_regions(const PIO_STACK_LOCATION irp_sp) From 7c1e10d164449289da9abbcb8c960c72b4c60ad1 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 16 May 2022 12:17:11 +0200 Subject: [PATCH 7/8] Finish access watching --- src/driver/ept.cpp | 2 +- src/runner/main.cpp | 133 +++++++++++++++++++++++--------------------- 2 files changed, 72 insertions(+), 63 deletions(-) diff --git a/src/driver/ept.cpp b/src/driver/ept.cpp index f369423..2113f67 100644 --- a/src/driver/ept.cpp +++ b/src/driver/ept.cpp @@ -178,7 +178,7 @@ namespace vmx void ept::record_access(const uint64_t rip) { - for (unsigned long long& access_record : this->access_records) + for (auto& access_record : this->access_records) { if (access_record == 0) { diff --git a/src/runner/main.cpp b/src/runner/main.cpp index a764aa9..c4dd38d 100644 --- a/src/runner/main.cpp +++ b/src/runner/main.cpp @@ -185,12 +185,13 @@ std::vector query_records(const driver_device& driver_device, const si return result; } -void report_records(const std::atomic_bool& flag, const driver_device& driver_device, const uint32_t pid, const HMODULE target_module, const std::vector>& regions) +void report_records(const std::atomic_bool& flag, const driver_device& driver_device, const uint32_t pid, + const HMODULE target_module, const std::vector>& regions) { std::set access_addresses{}; int i = 0; - while (flag) + while (!flag) { std::this_thread::sleep_for(std::chrono::seconds(1)); const auto new_records = query_records(driver_device, access_addresses.size()); @@ -203,7 +204,7 @@ void report_records(const std::atomic_bool& flag, const driver_device& driver_de } } - if((++i) % 5 == 0) + if ((++i) % 5 == 0) { watch_regions(driver_device, pid, target_module, regions); } @@ -212,76 +213,84 @@ void report_records(const std::atomic_bool& flag, const driver_device& driver_de void unsafe_main(const int /*argc*/, char* /*argv*/[]) { - const auto driver_file = extract_driver(); - - driver driver{driver_file, "MomoLul"}; - const driver_device driver_device{R"(\\.\HelloDev)"}; - - const auto pid = get_process_id(); - - printf("Opening process...\n"); - auto proc = process::open(pid, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ); - if (!proc) { - printf("Failed to open process...\n"); - return; - } + const auto driver_file = extract_driver(); - printf("Reading modules...\n"); - const auto modules = process::get_modules(proc); - printf("Found %zu modules\n", modules.size()); + driver driver{driver_file, "MomoLul"}; + const driver_device driver_device{R"(\\.\HelloDev)"}; - std::vector module_files{}; - module_files.reserve(modules.size()); + const auto pid = get_process_id(); - int i = 0; - for (const auto& module : modules) - { - auto name = process::get_module_filename(proc, module); - printf("(%i)\t%p: %s\n", i++, static_cast(module), name.data()); - module_files.emplace_back(std::move(name)); - } + printf("Opening process...\n"); + auto proc = process::open(pid, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ); + if (!proc) + { + printf("Failed to open process...\n"); + return; + } - // We don't need this anymore - proc = {}; + printf("Reading modules...\n"); + const auto modules = process::get_modules(proc); + printf("Found %zu modules:\n", modules.size()); - std::string module_str{}; - printf("\nPlease enter the module number: "); - std::getline(std::cin, module_str); + std::vector module_files{}; + module_files.reserve(modules.size()); + + int i = 0; + for (const auto& module : modules) + { + auto name = process::get_module_filename(proc, module); + printf("(%i)\t%p: %s\n", i++, static_cast(module), name.data()); + module_files.emplace_back(std::move(name)); + } + + // We don't need this anymore + proc = {}; + + std::string module_str{}; + printf("\nPlease enter the module number: "); + std::getline(std::cin, module_str); + + const auto module_num = atoi(module_str.data()); + + if (module_num < 0 || static_cast(module_num) >= modules.size()) + { + printf("Invalid module num\n"); + _getch(); + return; + } + + const auto target_module = modules[module_num]; + const auto module_base = reinterpret_cast(target_module); + const auto& file = module_files[module_num]; + printf("Analyzing %s...\n", file.data()); + const auto regions = find_executable_regions(file); + + printf("Executable regions:\n"); + for (const auto& region : regions) + { + printf("%p - %zu\n", module_base + region.first, region.second); + } + + watch_regions(driver_device, pid, target_module, regions); + + std::atomic_bool terminate{false}; + std::thread t([&]() + { + printf("\nWatching access:\n"); + report_records(terminate, driver_device, pid, target_module, regions); + }); - const auto module_num = atoi(module_str.data()); - if (module_num < 0 || static_cast(module_num) >= modules.size()) - { - printf("Invalid module num\n"); _getch(); - return; + + terminate = true; + t.join(); } - const auto target_module = modules[module_num]; - const auto module_base = reinterpret_cast(target_module); - const auto& file = module_files[module_num]; - printf("Analyzing %s...\n", file.data()); - const auto regions = find_executable_regions(file); - - for (const auto& region : regions) - { - printf("%p - %zu\n", module_base + region.first, region.second); - } - - watch_regions(driver_device, pid, target_module, regions); - - std::atomic_bool terminate{false}; - std::thread t([&]() - { - report_records(terminate, driver_device, pid, target_module, regions); - }); - + printf("\nWatching stopped.\n"); _getch(); - terminate = true; - t.join(); - return; /* @@ -315,13 +324,13 @@ void unsafe_main(const int /*argc*/, char* /*argv*/[]) patch_data(driver_device, pid, 0x52512C, data3, sizeof(data3)); */ - printf("Press any key to disable all hooks!\n"); + /*printf("Press any key to disable all hooks!\n"); (void)_getch(); remove_hooks(driver_device); printf("Press any key to exit!\n"); - (void)_getch(); + (void)_getch();*/ } int main(const int argc, char* argv[]) From ab6e9808b58e8d53a018a75ba9700e55e0470aad Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 16 May 2022 12:39:59 +0200 Subject: [PATCH 8/8] Prevent bug checks due to race conditions Zeroing the read access before the write access can result in an ept misconfiguration (page writable, but not readable) if a separate core accesses the same page inbetween the zeroing. --- src/driver/ept.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/driver/ept.cpp b/src/driver/ept.cpp index 2113f67..f333211 100644 --- a/src/driver/ept.cpp +++ b/src/driver/ept.cpp @@ -101,8 +101,8 @@ namespace vmx { if (watch_point->target_page) { - watch_point->target_page->read_access = 0; watch_point->target_page->write_access = 0; + watch_point->target_page->read_access = 0; watch_point->target_page->execute_access = 1; } @@ -261,8 +261,8 @@ namespace vmx if (!violation_qualification.ept_executable && violation_qualification.execute_access) { watch_point->target_page->execute_access = 1; - watch_point->target_page->read_access = 0; watch_point->target_page->write_access = 0; + watch_point->target_page->read_access = 0; guest_context.increment_rip = false; } else if (violation_qualification.ept_executable && (violation_qualification.read_access ||