From 16a241599f96642613aeff18af5c93794665c766 Mon Sep 17 00:00:00 2001 From: otavepto Date: Mon, 18 Mar 2024 03:32:37 +0200 Subject: [PATCH] updated stub drm patterns (for v2) and added a workaround for older variants --- CHANGELOG.md | 1 + helpers/pe_helpers.cpp | 2 +- .../win/extra_protection/stubdrm.cpp | 64 ++++++++++++++++--- 3 files changed, 57 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83247202..65bec984 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ * **[detiam]** fix linking errors when build on archlinux +* for windows: updated stub drm patterns and added a workaround for older variants * added missing example file `disable_lobby_creation.txt` in `steam_settings` folder + updated release `README` --- diff --git a/helpers/pe_helpers.cpp b/helpers/pe_helpers.cpp index e57e83d6..5bc31875 100644 --- a/helpers/pe_helpers.cpp +++ b/helpers/pe_helpers.cpp @@ -462,7 +462,7 @@ size_t pe_helpers::get_current_exe_mem_size() for (size_t i = 0; i < sections.count; ++i) { auto section = sections.ptr[i]; MEMORY_BASIC_INFORMATION mbi{}; - if (!VirtualQuery((LPVOID)((uint8_t *)hmod + section.VirtualAddress), &mbi, sizeof(mbi))) { + if (!VirtualQuery((LPCVOID)((uint8_t *)hmod + section.VirtualAddress), &mbi, sizeof(mbi))) { return 0; } size = mbi.RegionSize; // actual section size in mem diff --git a/tools/steamclient_loader/win/extra_protection/stubdrm.cpp b/tools/steamclient_loader/win/extra_protection/stubdrm.cpp index a918baef..d6f6bcf0 100644 --- a/tools/steamclient_loader/win/extra_protection/stubdrm.cpp +++ b/tools/steamclient_loader/win/extra_protection/stubdrm.cpp @@ -13,15 +13,18 @@ typedef struct SnrUnit { typedef struct SnrDetails { std::string detection_patt{}; + bool change_mem_access = false; std::vector snr_units{}; } SnrDetails_t; // x64 #if defined(_WIN64) - const std::vector snr_patts { + static const std::vector snr_patts { { // detection_patt "FF 94 24 ?? ?? ?? ?? 88 44 24 ?? 0F BE 44 24 ?? 83 ?? 30 74 ?? E9", + // change memory pages access to r/w/e + false, // snr_units { // patt 1 is a bunch of checks for registry + files validity (including custom DOS stub) @@ -40,6 +43,8 @@ typedef struct SnrDetails { { // detection_patt "FF D? 44 0F B6 ?? 3C 30 0F 85", + // change memory pages access to r/w/e + false, // snr_units { { @@ -55,10 +60,12 @@ typedef struct SnrDetails { // x32 #if !defined(_WIN64) - const std::vector snr_patts { + static const std::vector snr_patts { { // detection_patt "FF 95 ?? ?? ?? ?? 88 45 ?? 0F BE 4D ?? 83 ?? 30 74 ?? E9", + // change memory pages access to r/w/e + false, // snr_units { // patt 1 is a bunch of checks for registry + files validity (including custom DOS stub) @@ -77,18 +84,26 @@ typedef struct SnrDetails { { // detection_patt "FF 95 ?? ?? ?? ?? 89 85 ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B ?? ?? 89 ?? ?? ?? ?? ?? 83 A5 ?? ?? ?? ?? ?? EB", + // change memory pages access to r/w/e + true, // snr_units { { "F6 C? 02 0F 85 ?? ?? ?? ?? 5? FF ?? 6?", "?? ?? ?? 90 E9 00 03", }, + { + "F6 C? 02 89 ?? ?? ?? ?? ?? A3 ?? ?? ?? ?? 0F 85", + "?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 90 E9 00 03 00 00", + }, }, }, { // detection_patt "FF D? 88 45 ?? 3C 30 0F 85 ?? ?? ?? ?? B8 4D 5A", + // change memory pages access to r/w/e + false, // snr_units { { @@ -106,15 +121,45 @@ typedef struct SnrDetails { #endif // _WIN64 -const std::vector *current_snr_units = nullptr; + +static size_t current_snr_details = static_cast(-1); static std::recursive_mutex mtx_win32_api{}; -static uint8_t *proc_addr_base = (uint8_t *)GetModuleHandleW(NULL); +static uint8_t *exe_addr_base = (uint8_t *)GetModuleHandleW(NULL); static uint8_t *bind_addr_base = nullptr; static uint8_t *bind_addr_end = nullptr; bool restore_win32_apis(); +// stub v2 needs manual change for .text, section must have write access +static void change_mem_pages_access() +{ + auto sections = pe_helpers::get_section_headers((HMODULE)exe_addr_base); + if (!sections.count) return; + + for (size_t i = 0; i < sections.count; ++i) { + auto section = sections.ptr[i]; + uint8_t *section_base_addr = exe_addr_base + section.VirtualAddress; + MEMORY_BASIC_INFORMATION mbi{}; + constexpr const static auto ANY_EXECUTE_RIGHT = PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY; + if (VirtualQuery((LPCVOID)section_base_addr, &mbi, sizeof(mbi)) && // function succeeded + (mbi.Protect & ANY_EXECUTE_RIGHT)) { // this page (not entire section) has execute rights + DWORD current_protection = 0; + auto res = VirtualProtect(section_base_addr, mbi.RegionSize, PAGE_EXECUTE_READWRITE, ¤t_protection); + // if (!res) { + // MessageBoxA( + // nullptr, + // (std::string("Failed to change access of page '") + (char *)section.Name + "' ").c_str(), + // "Failed", + // MB_OK + // ); + // } + } + } + + +} + static void patch_if_possible(void *ret_addr) { if (!ret_addr) return; @@ -123,7 +168,7 @@ static void patch_if_possible(void *ret_addr) if (!page_details.BaseAddress || page_details.AllocationProtect != PAGE_READWRITE) return; bool anything_found = false; - for (const auto &snr_unit : *current_snr_units) { + for (const auto &snr_unit : snr_patts[current_snr_details].snr_units) { auto mem = pe_helpers::search_memory( (uint8_t *)page_details.BaseAddress, page_details.RegionSize, @@ -144,6 +189,7 @@ static void patch_if_possible(void *ret_addr) if (anything_found) { restore_win32_apis(); + if (snr_patts[current_snr_details].change_mem_access) change_mem_pages_access(); } // MessageBoxA(NULL, ("ret addr = " + std::to_string((size_t)ret_addr)).c_str(), "Patched", MB_OK); @@ -239,15 +285,15 @@ static bool restore_win32_apis() bool stubdrm::patch() { - auto bind_section = pe_helpers::get_section_header_with_name(((HMODULE)proc_addr_base), ".bind"); + auto bind_section = pe_helpers::get_section_header_with_name(((HMODULE)exe_addr_base), ".bind"); if (!bind_section) return false; // we don't have .bind section - bind_addr_base = proc_addr_base + bind_section->VirtualAddress; + bind_addr_base = exe_addr_base + bind_section->VirtualAddress; MEMORY_BASIC_INFORMATION mbi{}; if (!VirtualQuery((LPVOID)bind_addr_base, &mbi, sizeof(mbi))) return false; bind_addr_end = bind_addr_base + mbi.RegionSize; - auto addrOfEntry = proc_addr_base + pe_helpers::get_optional_header((HMODULE)proc_addr_base)->AddressOfEntryPoint; + auto addrOfEntry = exe_addr_base + pe_helpers::get_optional_header((HMODULE)exe_addr_base)->AddressOfEntryPoint; if (addrOfEntry < bind_addr_base || addrOfEntry >= bind_addr_end) return false; // entry addr is not inside .bind for (const auto &patt : snr_patts) { @@ -257,7 +303,7 @@ bool stubdrm::patch() patt.detection_patt); if (mem) { - current_snr_units = &patt.snr_units; + current_snr_details = &patt - &snr_patts[0]; return redirect_win32_apis(); } }