1.04 -> 1.15

This commit is contained in:
Skull Merlin
2022-05-17 17:56:26 +03:00
parent 8f02b94b03
commit 31d18eb618
61 changed files with 516 additions and 293 deletions

View File

@ -0,0 +1,163 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "scheduler.hpp"
#include "game/game.hpp"
#include <utils/hook.hpp>
namespace arxan
{
namespace
{
DWORD get_steam_pid()
{
static DWORD pid = 0; //234567;//GetCurrentProcessId();
if (pid) return pid;
HKEY hRegKey;
if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Valve\\Steam\\ActiveProcess", 0, KEY_QUERY_VALUE,
&hRegKey) != ERROR_SUCCESS)
return pid;
DWORD dwLength = sizeof(pid);
RegQueryValueExA(hRegKey, "pid", nullptr, nullptr, reinterpret_cast<BYTE*>(&pid), &dwLength);
RegCloseKey(hRegKey);
return pid;
}
utils::hook::detour nt_close_hook;
utils::hook::detour nt_query_information_process_hook;
NTSTATUS WINAPI nt_query_information_process_stub(const HANDLE handle, const PROCESSINFOCLASS info_class,
const PVOID info,
const ULONG info_length, const PULONG ret_length)
{
auto* orig = static_cast<decltype(NtQueryInformationProcess)*>(nt_query_information_process_hook.
get_original());
const auto status = orig(handle, info_class, info, info_length, ret_length);
if (NT_SUCCESS(status))
{
if (info_class == ProcessBasicInformation)
{
static DWORD explorer_pid = 0;
if (!explorer_pid)
{
auto* const shell_window = GetShellWindow();
GetWindowThreadProcessId(shell_window, &explorer_pid);
}
static_cast<PPROCESS_BASIC_INFORMATION>(info)->Reserved3 = PVOID(DWORD64(get_steam_pid()));
}
else if (info_class == 30) // ProcessDebugObjectHandle
{
*static_cast<HANDLE*>(info) = nullptr;
return 0xC0000353;
}
else if (info_class == 7) // ProcessDebugPort
{
*static_cast<HANDLE*>(info) = nullptr;
}
else if (info_class == 31)
{
*static_cast<ULONG*>(info) = 1;
}
//https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess
}
return status;
}
NTSTATUS NTAPI nt_close_stub(const HANDLE handle)
{
char info[16];
if (NtQueryObject(handle, OBJECT_INFORMATION_CLASS(4), &info, 2, nullptr) >= 0 && size_t(handle) != 0x12345)
{
auto* orig = static_cast<decltype(NtClose)*>(nt_close_hook.get_original());
return orig(handle);
}
return STATUS_INVALID_HANDLE;
}
LONG WINAPI exception_filter(const LPEXCEPTION_POINTERS info)
{
if (info->ExceptionRecord->ExceptionCode == STATUS_INVALID_HANDLE)
{
return EXCEPTION_CONTINUE_EXECUTION;
}
return EXCEPTION_CONTINUE_SEARCH;
}
void hide_being_debugged()
{
auto* const peb = PPEB(__readgsqword(0x60));
peb->BeingDebugged = false;
*reinterpret_cast<PDWORD>(LPSTR(peb) + 0xBC) &= ~0x70;
}
void remove_hardware_breakpoints()
{
CONTEXT context;
ZeroMemory(&context, sizeof(context));
context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
auto* const thread = GetCurrentThread();
GetThreadContext(thread, &context);
context.Dr0 = 0;
context.Dr1 = 0;
context.Dr2 = 0;
context.Dr3 = 0;
context.Dr6 = 0;
context.Dr7 = 0;
SetThreadContext(thread, &context);
}
BOOL WINAPI set_thread_context_stub(const HANDLE thread, CONTEXT* context)
{
return SetThreadContext(thread, context);
}
}
class component final : public component_interface
{
public:
void* load_import(const std::string& library, const std::string& function) override
{
if (function == "SetThreadContext")
{
//return set_thread_context_stub;
}
return nullptr;
}
void post_load() override
{
hide_being_debugged();
scheduler::loop(hide_being_debugged, scheduler::pipeline::async);
const utils::nt::library ntdll("ntdll.dll");
nt_close_hook.create(ntdll.get_proc<void*>("NtClose"), nt_close_stub);
nt_query_information_process_hook.create(ntdll.get_proc<void*>("NtQueryInformationProcess"),
nt_query_information_process_stub);
// https://www.geoffchappell.com/studies/windows/win32/ntdll/api/index.htm
AddVectoredExceptionHandler(1, exception_filter);
}
void post_unpack() override
{
// cba to implement sp, not sure if it's even needed
if (game::environment::is_sp()) return;
}
};
}
REGISTER_COMPONENT(arxan::component)

View File

@ -218,19 +218,19 @@ namespace auth
}
else
{
utils::hook::jump(0x140571E07, 0x140571E5A); // H1(1.4)
utils::hook::jump(0x14004B223, 0x14004B4F2); // H1(1.4)
utils::hook::jump(0x14004B4AD, 0x14004B4F2); // H1(1.4)
utils::hook::jump(0x140572F6F, 0x140572FB0); // H1(1.4)
utils::hook::jump(0x140573470, 0x1405734B6); // H1(1.4)
utils::hook::jump(0x1D6193_b, 0x1D61FA_b); // 1.15
utils::hook::jump(0x60153_b, 0x60426_b); // 1.15
utils::hook::jump(0x603E1_b, 0x60426_b); // 1.15
utils::hook::jump(0x1D7542_b, 0x1D7587_b); // 1.15, MAYBE `1D7553` ON FIRST
utils::hook::jump(0x1D7A82_b, 0x1D7AC8_b); // 1.15
utils::hook::jump(0x140488BC1, get_direct_connect_stub(), true); // H1(1.4)
utils::hook::call(0x140250ED2, send_connect_data_stub); // H1(1.4)
//utils::hook::jump(0x140488BC1, get_direct_connect_stub(), true); // H1(1.4) couldn't find
utils::hook::call(0x12D437_b, send_connect_data_stub); // 1.15
// Skip checks for sending connect packet
utils::hook::jump(0x1402508FC, 0x140250946);
utils::hook::jump(0x12CDFC_b, 0x12CE5C_b); // 1.15
// Don't instantly timeout the connecting client ? not sure about this
utils::hook::set(0x14025136B, 0xC3);
//utils::hook::set(0x14025136B, 0xC3); // gonna lookup for this soon
}
command::add("guid", []()
@ -241,4 +241,4 @@ namespace auth
};
}
REGISTER_COMPONENT(auth::component)
//REGISTER_COMPONENT(auth::component)

View File

@ -135,4 +135,4 @@ namespace binding
};
}
REGISTER_COMPONENT(binding::component)
//REGISTER_COMPONENT(binding::component)

View File

@ -106,4 +106,4 @@ namespace bots
};
}
REGISTER_COMPONENT(bots::component)
//REGISTER_COMPONENT(bots::component)

View File

@ -34,7 +34,6 @@ namespace branding
public:
void post_unpack() override
{
if (game::environment::is_dedi())
{
return;
@ -42,24 +41,26 @@ namespace branding
if (game::environment::is_mp())
{
localized_strings::override("LUA_MENU_MULTIPLAYER_CAPS", "H1-MOD: MULTIPLAYER\n");
localized_strings::override("MENU_MULTIPLAYER_CAPS", "H1-MOD: MULTIPLAYER");
//localized_strings::override("LUA_MENU_MULTIPLAYER_CAPS", "H1-MOD: MULTIPLAYER\n");
//localized_strings::override("MENU_MULTIPLAYER_CAPS", "H1-MOD: MULTIPLAYER");
}
dvars::override::set_string("version", utils::string::va("H1-Mod %s", VERSION));
//dvars::override::set_string("version", utils::string::va("H1-Mod %s", VERSION));
ui_get_formatted_build_number_hook.create(
SELECT_VALUE(0x1403B1C40, 0x1404E74C0), ui_get_formatted_build_number_stub);
SELECT_VALUE(0x0, 0x1DF300_b), ui_get_formatted_build_number_stub);
scheduler::loop([]()
{
const auto font = game::R_RegisterFont("fonts/fira_mono_bold.ttf", 20);
game::R_AddCmdDrawText("H1-Mod: " VERSION, 0x7FFFFFFF, font, 10.f,
5.f + static_cast<float>(font->pixelHeight), 1.f, 1.f, 0.0f, color, 0);
if (font)
{
game::R_AddCmdDrawText("H1-Mod: " VERSION, 0x7FFFFFFF, font, 10.f,
5.f + static_cast<float>(font->pixelHeight), 1.f, 1.f, 0.0f, color, 0);
}
}, scheduler::pipeline::renderer);
}
};
}
REGISTER_COMPONENT(branding::component)
//REGISTER_COMPONENT(branding::component)

View File

@ -49,4 +49,4 @@ namespace chat
};
}
REGISTER_COMPONENT(chat::component)
//REGISTER_COMPONENT(chat::component)

View File

@ -179,4 +179,4 @@ namespace colors
};
}
REGISTER_COMPONENT(colors::component)
//REGISTER_COMPONENT(colors::component)

View File

@ -818,4 +818,4 @@ namespace command
};
}
REGISTER_COMPONENT(command::component)
//REGISTER_COMPONENT(command::component)

View File

@ -296,4 +296,4 @@ namespace console
}
}
REGISTER_COMPONENT(console::component)
//REGISTER_COMPONENT(console::component)

View File

@ -330,4 +330,4 @@ namespace dedicated
};
}
REGISTER_COMPONENT(dedicated::component)
//REGISTER_COMPONENT(dedicated::component)

View File

@ -62,4 +62,4 @@ namespace dedicated_info
};
}
REGISTER_COMPONENT(dedicated_info::component)
//REGISTER_COMPONENT(dedicated_info::component)

View File

@ -596,4 +596,4 @@ namespace demonware
};
}
REGISTER_COMPONENT(demonware::component)
//REGISTER_COMPONENT(demonware::component)

View File

@ -285,4 +285,4 @@ namespace discord
};
}
REGISTER_COMPONENT(discord::component)
//REGISTER_COMPONENT(discord::component)

View File

@ -198,4 +198,4 @@ namespace dvar_cheats
};
}
REGISTER_COMPONENT(dvar_cheats::component)
//REGISTER_COMPONENT(dvar_cheats::component)

View File

@ -440,4 +440,4 @@ namespace dvars
};
}
REGISTER_COMPONENT(dvars::component)
//REGISTER_COMPONENT(dvars::component)

View File

@ -258,4 +258,4 @@ namespace exception
};
}
REGISTER_COMPONENT(exception::component)
//REGISTER_COMPONENT(exception::component)

View File

@ -56,4 +56,4 @@ namespace fastfiles
};
}
REGISTER_COMPONENT(fastfiles::component)
//REGISTER_COMPONENT(fastfiles::component)

View File

@ -130,4 +130,4 @@ namespace filesystem
};
}
REGISTER_COMPONENT(filesystem::component)
//REGISTER_COMPONENT(filesystem::component)

View File

@ -133,4 +133,4 @@ namespace fonts
};
}
REGISTER_COMPONENT(fonts::component)
//REGISTER_COMPONENT(fonts::component)

View File

@ -179,4 +179,4 @@ namespace fps
};
}
REGISTER_COMPONENT(fps::component)
//REGISTER_COMPONENT(fps::component)

View File

@ -797,4 +797,4 @@ namespace game_console
};
}
REGISTER_COMPONENT(game_console::component)
//REGISTER_COMPONENT(game_console::component)

View File

@ -3,6 +3,7 @@
#include "game_module.hpp"
#include <utils/hook.hpp>
#include <game/game.hpp>
namespace game_module
{
@ -90,7 +91,7 @@ namespace game_module
utils::nt::library get_game_module()
{
static utils::nt::library game{HMODULE(0x140000000)};
static utils::nt::library game{HMODULE(game::base_address)};
return game;
}
@ -110,7 +111,11 @@ namespace game_module
void post_load() override
{
#ifdef INJECT_HOST_AS_LIB
hook_module_resolving();
#else
assert(get_host_module() == get_game_module());
#endif
}
};
}

View File

@ -227,4 +227,4 @@ namespace gameplay
};
}
REGISTER_COMPONENT(gameplay::component)
//REGISTER_COMPONENT(gameplay::component)

View File

@ -72,4 +72,4 @@ namespace input
};
}
REGISTER_COMPONENT(input::component)
//REGISTER_COMPONENT(input::component)

View File

@ -44,9 +44,9 @@ namespace localized_strings
void post_unpack() override
{
// Change some localized strings
seh_string_ed_get_string_hook.create(SELECT_VALUE(0x1403924A0, 0x1404BB2A0), &seh_string_ed_get_string);
seh_string_ed_get_string_hook.create(SELECT_VALUE(0x0, 0x585DA0_b), &seh_string_ed_get_string); // 1.15
}
};
}
REGISTER_COMPONENT(localized_strings::component)
//REGISTER_COMPONENT(localized_strings::component)

View File

@ -314,4 +314,4 @@ namespace logfile
};
}
REGISTER_COMPONENT(logfile::component)
//REGISTER_COMPONENT(logfile::component)

View File

@ -177,4 +177,4 @@ namespace logger
};
}
REGISTER_COMPONENT(logger::component)
//REGISTER_COMPONENT(logger::component)

View File

@ -55,4 +55,4 @@ namespace lui
};
}
REGISTER_COMPONENT(lui::component)
//REGISTER_COMPONENT(lui::component)

View File

@ -177,4 +177,4 @@ namespace map_rotation
};
}
REGISTER_COMPONENT(map_rotation::component)
//REGISTER_COMPONENT(map_rotation::component)

View File

@ -209,4 +209,4 @@ namespace materials
};
}
REGISTER_COMPONENT(materials::component)
//REGISTER_COMPONENT(materials::component)

View File

@ -116,4 +116,4 @@ namespace mods
};
}
REGISTER_COMPONENT(mods::component)
//REGISTER_COMPONENT(mods::component)

View File

@ -323,4 +323,4 @@ namespace network
};
}
REGISTER_COMPONENT(network::component)
//REGISTER_COMPONENT(network::component)

View File

@ -642,4 +642,4 @@ namespace party
};
}
REGISTER_COMPONENT(party::component)
//REGISTER_COMPONENT(party::component)

View File

@ -283,4 +283,4 @@ namespace patches
};
}
REGISTER_COMPONENT(patches::component)
//REGISTER_COMPONENT(patches::component)

View File

@ -44,4 +44,4 @@ namespace ranked
};
}
REGISTER_COMPONENT(ranked::component)
//REGISTER_COMPONENT(ranked::component)

View File

@ -80,4 +80,4 @@ namespace redirect
};
}
REGISTER_COMPONENT(redirect::component)
//REGISTER_COMPONENT(redirect::component)

View File

@ -82,4 +82,4 @@ namespace renderer
};
}
REGISTER_COMPONENT(renderer::component)
//REGISTER_COMPONENT(renderer::component)

View File

@ -75,7 +75,8 @@ namespace scheduler
{
new_callbacks_.access([&](task_list& new_tasks)
{
tasks.insert(tasks.end(), std::move_iterator<task_list::iterator>(new_tasks.begin()), std::move_iterator<task_list::iterator>(new_tasks.end()));
tasks.insert(tasks.end(), std::move_iterator<task_list::iterator>(new_tasks.begin()),
std::move_iterator<task_list::iterator>(new_tasks.end()));
new_tasks = {};
});
});
@ -88,7 +89,7 @@ namespace scheduler
utils::hook::detour r_end_frame_hook;
utils::hook::detour g_run_frame_hook;
utils::hook::detour main_frame_hook;
utils::hook::detour hks_frame_hook;
//utils::hook::detour hks_frame_hook; //no scripting for now
void execute(const pipeline type)
{
@ -99,7 +100,7 @@ namespace scheduler
void r_end_frame_stub()
{
execute(pipeline::renderer);
r_end_frame_hook.invoke<void>();
//r_end_frame_hook.invoke<void>();
}
void server_frame_stub()
@ -125,7 +126,7 @@ namespace scheduler
}
void schedule(const std::function<bool()>& callback, const pipeline type,
const std::chrono::milliseconds delay)
const std::chrono::milliseconds delay)
{
assert(type >= 0 && type < pipeline::count);
@ -138,7 +139,7 @@ namespace scheduler
}
void loop(const std::function<void()>& callback, const pipeline type,
const std::chrono::milliseconds delay)
const std::chrono::milliseconds delay)
{
schedule([callback]()
{
@ -148,7 +149,7 @@ namespace scheduler
}
void once(const std::function<void()>& callback, const pipeline type,
const std::chrono::milliseconds delay)
const std::chrono::milliseconds delay)
{
schedule([callback]()
{
@ -158,7 +159,7 @@ namespace scheduler
}
void on_game_initialized(const std::function<void()>& callback, const pipeline type,
const std::chrono::milliseconds delay)
const std::chrono::milliseconds delay)
{
schedule([=]()
{
@ -190,10 +191,23 @@ namespace scheduler
void post_unpack() override
{
r_end_frame_hook.create(SELECT_VALUE(0x1404F7310, 0x1405FE470), scheduler::r_end_frame_stub);
g_run_frame_hook.create(SELECT_VALUE(0x1402772D0, 0x14033A640), scheduler::server_frame_stub);
main_frame_hook.create(SELECT_VALUE(0x1401CE8D0, 0x1400D8310), scheduler::main_frame_stub);
hks_frame_hook.create(SELECT_VALUE(0x1400E37F0, 0x1401755B0), scheduler::hks_frame_stub);
utils::hook::jump(SELECT_VALUE(0, 0x6A6300_b), utils::hook::assemble([](utils::hook::assembler& a)
{
a.pushad64();
a.call_aligned(r_end_frame_stub);
a.popad64();
a.sub(rsp, 0x28);
a.call(0x6A5C20_b);
a.mov(rax, 0xEAB4308_b);
a.mov(rax, qword_ptr(rax));
a.jmp(0x6A6310_b);
}), true);
//r_end_frame_hook.create(SELECT_VALUE(0x0, 0x6A6300_b), scheduler::r_end_frame_stub);
//g_run_frame_hook.create(SELECT_VALUE(0x0, 0x417940_b), scheduler::server_frame_stub);
//main_frame_hook.create(SELECT_VALUE(0x0, 0x0), scheduler::main_frame_stub);
//hks_frame_hook.create(SELECT_VALUE(0x0, 0x0), scheduler::hks_frame_stub); // no scripting for now
}
void pre_destroy() override
@ -207,4 +221,4 @@ namespace scheduler
};
}
REGISTER_COMPONENT(scheduler::component)
//REGISTER_COMPONENT(scheduler::component)

View File

@ -216,4 +216,4 @@ namespace scripting
};
}
REGISTER_COMPONENT(scripting::component)
//REGISTER_COMPONENT(scripting::component)

View File

@ -423,4 +423,4 @@ namespace server_list
};
}
REGISTER_COMPONENT(server_list::component)
//REGISTER_COMPONENT(server_list::component)

View File

@ -48,4 +48,4 @@ namespace shaders
};
}
REGISTER_COMPONENT(shaders::component)
//REGISTER_COMPONENT(shaders::component)

View File

@ -50,4 +50,4 @@ namespace slowmotion
};
}
REGISTER_COMPONENT(slowmotion::component)
//REGISTER_COMPONENT(slowmotion::component)

View File

@ -138,4 +138,4 @@ namespace splash
};
}
REGISTER_COMPONENT(splash::component)
//REGISTER_COMPONENT(splash::component)

View File

@ -88,4 +88,4 @@ namespace stats
};
}
REGISTER_COMPONENT(stats::component)
//REGISTER_COMPONENT(stats::component)

View File

@ -185,4 +185,4 @@ namespace steam_proxy
}
}
REGISTER_COMPONENT(steam_proxy::component)
//REGISTER_COMPONENT(steam_proxy::component)

View File

@ -51,13 +51,13 @@ namespace system_check
{
static std::unordered_map<std::string, std::string> mp_zone_hashes =
{
{"patch_common_mp.ff", "3F44B0CFB0B8E0FBD9687C2942204AB7F11E66E6E15C73B8B4A5EB5920115A31"},
{"patch_common_mp.ff", "E45EF5F29D12A5A47F405F89FBBEE479C0A90D02141ABF852D481689514134A1"},
};
static std::unordered_map<std::string, std::string> sp_zone_hashes =
{
// Steam doesn't necessarily deliver this file :(
{"patch_common.ff", "BB0617DD94AF2F511571E7184BBEDE76E64D97E5D0DAFDB457F00717F035EBF0"},
{"patch_common.ff", "1D32A9770F90ED022AA76F4859B4AB178E194A703383E61AC2CE83B1E828B18F"},
};
@ -85,7 +85,7 @@ namespace system_check
public:
void post_load() override
{
verify_binary_version();
//verify_binary_version();
if (!is_valid())
{
@ -97,4 +97,4 @@ namespace system_check
};
}
REGISTER_COMPONENT(system_check::component)
//REGISTER_COMPONENT(system_check::component)

View File

@ -57,4 +57,4 @@ namespace thread_names
};
}
REGISTER_COMPONENT(thread_names::component)
//REGISTER_COMPONENT(thread_names::component)

View File

@ -206,4 +206,4 @@ namespace ui_scripting
};
}
REGISTER_COMPONENT(ui_scripting::component)
//REGISTER_COMPONENT(ui_scripting::component)

View File

@ -468,4 +468,4 @@ namespace updater
};
}
REGISTER_COMPONENT(updater::component)
//REGISTER_COMPONENT(updater::component)

View File

@ -52,4 +52,4 @@ namespace videos
};
}
REGISTER_COMPONENT(videos::component)
//REGISTER_COMPONENT(videos::component)

View File

@ -61,4 +61,4 @@ namespace virtuallobby
};
}
REGISTER_COMPONENT(virtuallobby::component)
//REGISTER_COMPONENT(virtuallobby::component)