diff --git a/src/client/launcher/html/html_frame.cpp b/src/client/launcher/html/html_frame.cpp index d844ffec..277fd4da 100644 --- a/src/client/launcher/html/html_frame.cpp +++ b/src/client/launcher/html/html_frame.cpp @@ -2,39 +2,64 @@ #include "html_frame.hpp" #include +#include std::atomic html_frame::frame_count_ = 0; +namespace +{ + void* original_func{}; + GUID browser_emulation_guid{ 0xac969931, 0x3566, 0x4b50, {0xae, 0x48, 0x71, 0xb9, 0x6a, 0x75, 0xc8, 0x79} }; + + int WINAPI co_internet_feature_value_internal_stub(const GUID* guid, uint32_t* result) + { + const auto res = static_cast(original_func)(guid, result); + + if (IsEqualGUID(*guid, browser_emulation_guid)) + { + *result = 11000; + return 0; + } + + return res; + } + + void setup_ie_hook() + { + static const auto _ = [] + { + const auto urlmon = utils::nt::library::load("urlmon.dll"s); + const auto target = urlmon.get_iat_entry("iertutil.dll", MAKEINTRESOURCEA(700)); + + original_func = *target; + utils::hook::set(target, co_internet_feature_value_internal_stub); + + return 0; + }(); + (void)_; + } +} + 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]; + 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) +html_frame::html_frame() : in_place_frame_(this), in_place_site_(this), ui_handler_(this), client_site_(this), +html_dispatch_(this) { + setup_ie_hook(); 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); - } + set_browser_feature("FEATURE_BROWSER_EMULATION", 11000); + set_browser_feature("FEATURE_GPU_RENDERING", 1); } html_frame::~html_frame() diff --git a/src/common/utils/nt.cpp b/src/common/utils/nt.cpp index 4cead0fa..12ae6109 100644 --- a/src/common/utils/nt.cpp +++ b/src/common/utils/nt.cpp @@ -15,7 +15,8 @@ namespace utils::nt library library::get_by_address(void* address) { HMODULE handle = nullptr; - GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, static_cast(address), &handle); + GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + static_cast(address), &handle); return library(handle); } @@ -157,6 +158,11 @@ namespace utils::nt } void** library::get_iat_entry(const std::string& module_name, const std::string& proc_name) const + { + return this->get_iat_entry(module_name, proc_name.data()); + } + + void** library::get_iat_entry(const std::string& module_name, const char* proc_name) const { if (!this->is_valid()) return nullptr; @@ -166,7 +172,7 @@ namespace utils::nt auto* const target_function = other_module.get_proc(proc_name); if (!target_function) return nullptr; - auto* header = this->get_optional_header(); + const auto* header = this->get_optional_header(); if (!header) return nullptr; auto* import_descriptor = reinterpret_cast(this->get_ptr() + header->DataDirectory @@ -183,16 +189,22 @@ namespace utils::nt while (original_thunk_data->u1.AddressOfData) { - const size_t ordinal_number = original_thunk_data->u1.AddressOfData & 0xFFFFFFF; - - if (ordinal_number > 0xFFFF) continue; - - if (GetProcAddress(other_module.module_, reinterpret_cast(ordinal_number)) == - target_function) + if (thunk_data->u1.Function == reinterpret_cast(target_function)) { return reinterpret_cast(&thunk_data->u1.Function); } + const size_t ordinal_number = original_thunk_data->u1.AddressOfData & 0xFFFFFFF; + + if (ordinal_number <= 0xFFFF) + { + auto* proc = GetProcAddress(other_module.module_, reinterpret_cast(ordinal_number)); + if (reinterpret_cast(proc) == target_function) + { + return reinterpret_cast(&thunk_data->u1.Function); + } + } + ++original_thunk_data; ++thunk_data; } diff --git a/src/common/utils/nt.hpp b/src/common/utils/nt.hpp index c4f58afe..df48c6c5 100644 --- a/src/common/utils/nt.hpp +++ b/src/common/utils/nt.hpp @@ -59,6 +59,13 @@ namespace utils::nt return reinterpret_cast(GetProcAddress(this->module_, process.data())); } + template + T get_proc(const char* name) const + { + if (!this->is_valid()) T{}; + return reinterpret_cast(GetProcAddress(this->module_, name)); + } + template std::function get(const std::string& process) const { @@ -97,6 +104,7 @@ namespace utils::nt PIMAGE_OPTIONAL_HEADER get_optional_header() const; void** get_iat_entry(const std::string& module_name, const std::string& proc_name) const; + void** get_iat_entry(const std::string& module_name, const char* name) const; private: HMODULE module_;