Refuse a build prefix longer than the buffer it is read into

This commit is contained in:
xThrasherrr committed 2026-10-06 10:29:44 -06:00
1 parent ed979c45af
commit 0acfae0c88
2 files changed
+6 -4

No files matched your search

+3 -2
View File
@@ -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<const unsigned char> bytes; };
const Contract contracts[]{
@@ -58,7 +58,8 @@ bool validate_contract(std::uintptr_t base) {
for (const auto& contract : contracts) {
std::array<unsigned char, 32> actual{};
SIZE_T count{};
if (!ReadProcessMemory(GetCurrentProcess(), reinterpret_cast<const void*>(base + contract.rva),
if (contract.bytes.size() > actual.size() || // a longer prefix would overrun actual
!ReadProcessMemory(GetCurrentProcess(), reinterpret_cast<const void*>(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;
}
+3 -2
View File
@@ -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<const std::uint8_t> 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<std::uint8_t, 32> 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{};