Skip to content

Commit

Permalink
Patch r_preloadShaders crash
Browse files Browse the repository at this point in the history
  • Loading branch information
alicealys committed Dec 15, 2023
1 parent 5d87fdb commit 58c5571
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/client/component/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,21 @@ namespace renderer
a.jmp(0x1C4136_b);
});
}

void r_preload_shaders_stub(utils::hook::assembler& a)
{
const auto is_zero = a.newLabel();

a.mov(rax, qword_ptr(SELECT_VALUE(0x123FFF30_b, 0x111DC230_b)));
a.test(rax, rax);
a.jz(is_zero);

a.mov(rcx, qword_ptr(rax, 0x540C68));
a.jmp(SELECT_VALUE(0x5CF1FF_b, 0x6E76FF_b));

a.bind(is_zero);
a.jmp(SELECT_VALUE(0x5CF20A_b, 0x6E7722_b));
}
}

class component final : public component_interface
Expand Down Expand Up @@ -166,6 +181,10 @@ namespace renderer
r_use_custom_red_dot_brightness = dvars::register_bool("r_useCustomRedDotBrightness",
true, game::DVAR_FLAG_SAVED, "Use custom red-dot brightness values");
}

// patch r_preloadShaders crash at init
utils::hook::jump(SELECT_VALUE(0x5CF1F1_b, 0x6E76F1_b), utils::hook::assemble(r_preload_shaders_stub), true);
dvars::override::register_bool("r_preloadShaders", false, game::DVAR_FLAG_SAVED);
}
};
}
Expand Down
7 changes: 7 additions & 0 deletions src/common/utils/hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@

#include <MinHook.h>

Mem seg_ptr(const SReg& segment, const uint64_t off)
{
auto mem = ptr_abs(off);
mem.setSegment(segment);
return mem;
}

namespace utils::hook
{
namespace
Expand Down
58 changes: 58 additions & 0 deletions src/common/utils/hook.hpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#pragma once
#include "signature.hpp"
#include "memory.hpp"

#include <asmjit/core/jitruntime.h>
#include <asmjit/x86/x86assembler.h>

using namespace asmjit::x86;

Mem seg_ptr(const SReg& segment, const uint64_t off);

namespace utils::hook
{
namespace detail
Expand Down Expand Up @@ -204,4 +207,59 @@ namespace utils::hook
}

uint8_t* allocate_somewhere_near(const void* base_address, const size_t size);

template <size_t Base>
void* allocate_far_jump()
{
constexpr auto alloc_size = 0x1000;
constexpr auto far_jmp_size = 0xC;

const auto alloc_jump_table = []
{
return reinterpret_cast<char*>(
memory::allocate_near(Base, alloc_size, PAGE_EXECUTE_READWRITE));
};

static auto jump_table = alloc_jump_table();
static auto current_pos = jump_table;

if (current_pos + far_jmp_size >= jump_table + alloc_size)
{
jump_table = alloc_jump_table();
current_pos = jump_table;
}

const auto ptr = current_pos;
current_pos += far_jmp_size;
return ptr;
}

template <size_t Base, typename T>
void* create_far_jump(const T dest)
{
static std::unordered_map<void*, void*> allocated_jumps;
if (const auto iter = allocated_jumps.find(reinterpret_cast<void*>(dest)); iter != allocated_jumps.end())
{
return iter->second;
}

const auto pos = allocate_far_jump<Base>();
jump(pos, dest, true);
allocated_jumps.insert(std::make_pair(dest, pos));
return pos;
}

template <size_t Base, typename T>
void far_jump(const size_t address, const T dest)
{
const auto pos = create_far_jump<Base>(dest);
jump(address, pos, false);
}

template <size_t Base, typename T>
void far_call(const size_t address, const T dest)
{
const auto pos = create_far_jump<Base>(dest);
call(address, pos);
}
}
27 changes: 27 additions & 0 deletions src/common/utils/memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,33 @@ namespace utils
return false;
}

void* memory::allocate_near(const size_t address, const size_t size, const std::uint32_t protect)
{
SYSTEM_INFO system_info{};
GetSystemInfo(&system_info);

const auto page_size = system_info.dwPageSize;
const auto aligned_size = size + (~size & (page_size - 1));
auto current_address = address;

while (true)
{
current_address -= page_size;

if (current_address <= reinterpret_cast<size_t>(system_info.lpMinimumApplicationAddress))
{
return nullptr;
}

const auto result = VirtualAlloc(reinterpret_cast<void*>(current_address), aligned_size, MEM_RESERVE | MEM_COMMIT, protect);
if (result != nullptr)
{
std::memset(result, 0, aligned_size);
return result;
}
}
}

memory::allocator* memory::get_allocator()
{
return &memory::mem_allocator_;
Expand Down
2 changes: 2 additions & 0 deletions src/common/utils/memory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ namespace utils
static bool is_bad_code_ptr(const void* ptr);
static bool is_rdata_ptr(void* ptr);

static void* allocate_near(const size_t address, const size_t size, const std::uint32_t protect);

static allocator* get_allocator();

private:
Expand Down

0 comments on commit 58c5571

Please sign in to comment.