From 0acfae0c883126e18f76281c2bbf4685149d4b33 Mon Sep 17 00:00:00 2001 From: xThrasherrr Date: Mon, 5 Oct 2026 23:59:32 -0600 Subject: [PATCH] Refuse a build prefix longer than the buffer it is read into --- Extension/Assets/loose_files.cpp | 5 +++-- Extension/Assets/mod_layers.cpp | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Extension/Assets/loose_files.cpp b/Extension/Assets/loose_files.cpp index 03e414b5..932958b2 100644 --- a/Extension/Assets/loose_files.cpp +++ b/Extension/Assets/loose_files.cpp @@ -47,7 +47,7 @@ struct State { // Hooks and the native mount live until process exit, like the pinned runtime. State& state() { static auto* value = new State; return *value; } -// Supported September 8 build, checked after runtime image validation. +// Supported game build, checked after runtime image validation. bool validate_contract(std::uintptr_t base) { struct Contract { std::uintptr_t rva; std::span bytes; }; const Contract contracts[]{ @@ -58,7 +58,8 @@ bool validate_contract(std::uintptr_t base) { for (const auto& contract : contracts) { std::array actual{}; SIZE_T count{}; - if (!ReadProcessMemory(GetCurrentProcess(), reinterpret_cast(base + contract.rva), + if (contract.bytes.size() > actual.size() || // a longer prefix would overrun actual + !ReadProcessMemory(GetCurrentProcess(), reinterpret_cast(base + contract.rva), actual.data(), contract.bytes.size(), &count) || count != contract.bytes.size() || std::memcmp(actual.data(), contract.bytes.data(), contract.bytes.size())) return false; } diff --git a/Extension/Assets/mod_layers.cpp b/Extension/Assets/mod_layers.cpp index 840d7be2..b3f4e1f8 100644 --- a/Extension/Assets/mod_layers.cpp +++ b/Extension/Assets/mod_layers.cpp @@ -126,7 +126,7 @@ bool read_memory(std::uintptr_t address, void* destination, std::size_t size) no destination, size, &read) && read == size; } -// Supported September 8 build, checked after runtime image validation. +// Supported game build, checked after runtime image validation. bool validate_contract(std::uintptr_t base) noexcept { struct Contract { std::uintptr_t rva; std::span bytes; }; const Contract contracts[]{ @@ -134,7 +134,8 @@ bool validate_contract(std::uintptr_t base) noexcept { {layers::layout_bootstrap, layers::layout_bootstrap_prefix}}; for (const auto& contract : contracts) { std::array actual{}; - if (!read_memory(base + contract.rva, actual.data(), contract.bytes.size()) || + if (contract.bytes.size() > actual.size() || // a longer prefix would overrun actual + !read_memory(base + contract.rva, actual.data(), contract.bytes.size()) || std::memcmp(actual.data(), contract.bytes.data(), contract.bytes.size())) return false; } std::uintptr_t slot{};