jump hook working, but asm bad?
This commit is contained in:
parent
8f72a0d870
commit
5bda17ffbf
@ -89,7 +89,7 @@ namespace gsc
|
||||
}
|
||||
}
|
||||
|
||||
void vm_call_builtin_function_internal(builtin_function func)
|
||||
void vm_call_builtin_function_internal(int specific_function_id)
|
||||
{
|
||||
const auto function_id = get_function_id();
|
||||
const auto custom = functions.contains(static_cast<std::uint16_t>(function_id));
|
||||
@ -99,6 +99,7 @@ namespace gsc
|
||||
return;
|
||||
}
|
||||
|
||||
builtin_function func = func_table[specific_function_id];
|
||||
if (func == nullptr)
|
||||
{
|
||||
scr_error(utils::string::va("builtin function \"%s\" doesn't exist", gsc_ctx->func_name(function_id).data()), true);
|
||||
@ -110,8 +111,13 @@ namespace gsc
|
||||
|
||||
void vm_call_builtin_function_stub(utils::hook::assembler& a)
|
||||
{
|
||||
a.mov(rax, qword_ptr(0x6B22918_b)); // 7
|
||||
a.mov(qword_ptr(0x6B183D0_b), rax); // 7
|
||||
a.lea(eax, dword_ptr(rcx, -1)); // 3
|
||||
a.mov(qword_ptr(0x6B22908_b), rsi); // 7
|
||||
|
||||
a.pushad64();
|
||||
a.mov(rbx, qword_ptr(rdx, rax, 3));
|
||||
a.mov(rcx, rax); // TODO: pass builtin_function or id, but is this the right ID???
|
||||
a.call_aligned(vm_call_builtin_function_internal); // call with builtin_function
|
||||
a.popad64();
|
||||
|
||||
@ -348,8 +354,8 @@ namespace gsc
|
||||
utils::hook::set<uint32_t>(0xC0E5CE_b + 3,
|
||||
static_cast<uint32_t>(reverse_b((&func_table))));
|
||||
*/
|
||||
utils::hook::nop(0xC0E5CE_b, 12);
|
||||
utils::hook::jump(0xC0E5CE_b, utils::hook::assemble(vm_call_builtin_function_stub), true);
|
||||
utils::hook::nop(0xC0E5BD_b, 24); // nop everything from the lea instruction to the jmp
|
||||
utils::hook::far_jump<0x140000000>(0xC0E5BD_b, utils::hook::assemble(vm_call_builtin_function_stub));
|
||||
|
||||
utils::hook::inject(0xBFD5A1_b + 3, &func_table);
|
||||
utils::hook::set<uint32_t>(0xBFD595_b + 2, sizeof(func_table));
|
||||
|
@ -15,6 +15,13 @@
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
Mem seg_ptr(const SReg& segment, const uint64_t off)
|
||||
{
|
||||
auto mem = ptr_abs(off);
|
||||
mem.setSegment(segment);
|
||||
return mem;
|
||||
}
|
||||
|
||||
namespace utils::hook
|
||||
{
|
||||
namespace
|
||||
|
@ -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
|
||||
@ -214,4 +217,52 @@ namespace utils::hook
|
||||
{
|
||||
return static_cast<T(*)(Args ...)>(func)(args...);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -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_;
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user