Add call_safe method to symbols to spoof call stack

This commit is contained in:
momo5502 2023-03-19 18:21:48 +01:00
parent 37fd619e89
commit de3c598885
2 changed files with 106 additions and 4 deletions

View File

@ -4,14 +4,16 @@
#include "game/game.hpp" #include "game/game.hpp"
#include "steam/steam.hpp" #include "steam/steam.hpp"
#include <utils/hook.hpp>
#include <utils/io.hpp> #include <utils/io.hpp>
#include <utils/hook.hpp>
#include <utils/string.hpp> #include <utils/string.hpp>
#include <utils/thread.hpp> #include <utils/thread.hpp>
#include "integrity.hpp" #include "integrity.hpp"
#include <stack>
#define ProcessDebugPort 7 #define ProcessDebugPort 7
#define ProcessDebugObjectHandle 30 #define ProcessDebugObjectHandle 30
#define ProcessDebugFlags 31 #define ProcessDebugFlags 31
@ -19,8 +21,84 @@
namespace arxan namespace arxan
{ {
namespace detail
{
void* callstack_proxy_addr{nullptr};
static thread_local const void* address_to_call{};
void set_address_to_call(const void* address)
{
address_to_call = address;
}
}
namespace namespace
{ {
thread_local std::stack<uint64_t> address_stack{};
const void* get_address_to_call()
{
return detail::address_to_call;
}
void store_address(const uint64_t address)
{
address_stack.push(address);
}
uint64_t get_stored_address()
{
const auto res = address_stack.top();
address_stack.pop();
return res;
}
void callstack_return_stub(utils::hook::assembler& a)
{
a.push(rax);
a.pushad64();
a.call_aligned(get_stored_address);
a.mov(qword_ptr(rsp, 0x80), rax);
a.popad64();
a.add(rsp, 8);
a.jmp(qword_ptr(rsp, -8));
}
uint64_t get_callstack_return_stub()
{
const auto placeholder = game::select(0x140001056, 0x140101167);
utils::hook::nop(placeholder, 1);
utils::hook::jump(placeholder + 1, utils::hook::assemble(callstack_return_stub));
return placeholder;
}
void callstack_stub(utils::hook::assembler& a)
{
a.push(rax);
a.pushad64();
a.call_aligned(get_address_to_call);
a.mov(qword_ptr(rsp, 0x80), rax);
a.mov(rcx, qword_ptr(rsp, 0x88));
a.call_aligned(store_address);
a.mov(rax, get_callstack_return_stub());
a.mov(qword_ptr(rsp, 0x88), rax);
a.popad64();
a.add(rsp, 8);
a.jmp(qword_ptr(rsp, -8));
}
constexpr auto pseudo_steam_id = 0x1337; constexpr auto pseudo_steam_id = 0x1337;
const auto pseudo_steam_handle = reinterpret_cast<HANDLE>(reinterpret_cast<uint64_t>(INVALID_HANDLE_VALUE) - const auto pseudo_steam_handle = reinterpret_cast<HANDLE>(reinterpret_cast<uint64_t>(INVALID_HANDLE_VALUE) -
pseudo_steam_id); pseudo_steam_id);
@ -788,6 +866,8 @@ namespace arxan
{ {
search_and_patch_integrity_checks(); search_and_patch_integrity_checks();
//restore_debug_functions(); //restore_debug_functions();
detail::callstack_proxy_addr = utils::hook::assemble(callstack_stub);
} }
component_priority priority() const override component_priority priority() const override

View File

@ -3,6 +3,12 @@
#include "structs.hpp" #include "structs.hpp"
#include <utils/nt.hpp> #include <utils/nt.hpp>
namespace arxan::detail
{
void set_address_to_call(const void* address);
extern void* callstack_proxy_addr;
}
namespace game namespace game
{ {
size_t get_base(); size_t get_base();
@ -42,15 +48,15 @@ namespace game
} }
template <typename T> template <typename T>
class symbol class base_symbol
{ {
public: public:
symbol(const size_t address) base_symbol(const size_t address)
: address_(address) : address_(address)
{ {
} }
symbol(const size_t address, const size_t server_address) base_symbol(const size_t address, const size_t server_address)
: address_(address) : address_(address)
, server_address_(server_address) , server_address_(server_address)
{ {
@ -76,6 +82,22 @@ namespace game
size_t server_address_{}; size_t server_address_{};
}; };
template <typename T>
struct callable_symbol : base_symbol<T>
{
using base_symbol<T>::base_symbol;
template <typename... Args>
std::invoke_result_t<T> call_safe(Args... args)
{
arxan::detail::set_address_to_call(this->get());
return static_cast<T*>(arxan::detail::callstack_proxy_addr)(args...);
}
};
template <typename T>
using symbol = std::conditional_t<std::is_invocable_v<T>, callable_symbol<T>, base_symbol<T>>;
std::filesystem::path get_appdata_path(); std::filesystem::path get_appdata_path();
} }