Fix all issues related to running doghook on linux (#21)
* add more linux signatures * Update premake script to generate correct symbols on respective platforms * Add debugger gdb for linux builds * Change from -ggdb to -gdwarf * change from -gdward to -g3 * Update linux signatures * Fix issues with virtual function calling * Fix a bunch of crashes. * Update prediction vfunc indexes * Update more indexes * No more crashes! * Fix usercmd padding * Fix more index issues * Change attach scripts to reflect what they do * Fix windows compilation issues - remove hardcoded path from attach-basic * Update attach script
This commit is contained in:
parent
5357480f24
commit
7d54105fec
61
attach-basic.sh
Executable file
61
attach-basic.sh
Executable file
@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# cwd into where this script is located
|
||||
line=$(pidof hl2_linux)
|
||||
arr=($line)
|
||||
inst=$1
|
||||
if [ $# == 0 ]; then
|
||||
inst=0
|
||||
fi
|
||||
|
||||
if [ ${#arr[@]} == 0 ]; then
|
||||
echo TF2 isn\'t running!
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ $inst -gt ${#arr[@]} ] || [ $inst == ${#arr[@]} ]; then
|
||||
echo wrong index!
|
||||
exit
|
||||
fi
|
||||
|
||||
proc=${arr[$inst]}
|
||||
|
||||
echo Running instances: "${arr[@]}"
|
||||
echo Attaching to "$proc"
|
||||
|
||||
#sudo ./detach $inst bin/libcathook.so
|
||||
|
||||
#if grep -q "$(realpath bin/libcathook.so)" /proc/"$proc"/maps; then
|
||||
# echo already loaded
|
||||
# exit
|
||||
#fi
|
||||
|
||||
# pBypass for crash dumps being sent
|
||||
# You may also want to consider using -nobreakpad in your launch options.
|
||||
sudo rm -rf /tmp/dumps # Remove if it exists
|
||||
sudo mkdir /tmp/dumps # Make it as root
|
||||
sudo chmod 000 /tmp/dumps # No permissions
|
||||
|
||||
#FILENAME="/tmp/.gl$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 6 | head -n 1)"
|
||||
|
||||
#cp "bin/Debug/libdoghook.so" "$FILENAME"
|
||||
FILENAME=$(readlink -f "${0%/*}/bin/Debug/libdoghook.so")
|
||||
|
||||
echo loading "$FILENAME" to "$proc"
|
||||
|
||||
sudo killall -19 steam
|
||||
sudo killall -19 steamwebhelper
|
||||
|
||||
sudo gdb -n -q -batch \
|
||||
-ex "attach $proc" \
|
||||
-ex "set \$dlopen = (void*(*)(char*, int)) dlopen" \
|
||||
-ex "call \$dlopen(\"$FILENAME\", 1)" \
|
||||
-ex "call dlerror()" \
|
||||
-ex 'print (char *) $2' \
|
||||
-ex "detach" \
|
||||
-ex "quit"
|
||||
|
||||
#rm $FILENAME
|
||||
|
||||
sudo killall -18 steamwebhelper
|
||||
sudo killall -18 steam
|
105
attach-interactive.sh
Executable file
105
attach-interactive.sh
Executable file
@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
pid=$(pidof hl2_linux) # Default to TF2
|
||||
|
||||
if [[ -n "$1" ]]; then
|
||||
if [ "$1" -eq "$1" ] 2>/dev/null; then
|
||||
# First argument is a int (PID)
|
||||
pid=$1
|
||||
else
|
||||
# First argument is a string (Process ID)
|
||||
pid=$(pidof $1)
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$pid" ]; then
|
||||
echo -e "\e[91mCould not find target process.\e[39m"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
# Get the full path of the .so that we'll be faking
|
||||
victim_lib=$(cat /proc/${pid}/maps | grep ".so" | shuf -n 1)
|
||||
|
||||
echo $victim_lib
|
||||
|
||||
victim_lib=${victim_lib##* }
|
||||
|
||||
# Some magic that I copied straight from StackOverflow
|
||||
victim_lib_array=(${victim_lib//./ })
|
||||
|
||||
number_to_spoof=${victim_lib_array[-1]}
|
||||
library_path=$(IFS=. ; echo "${victim_lib_array[*]}")
|
||||
|
||||
if [ "$number_to_spoof" == "so" ]; then
|
||||
# If the shared library doesn't have multiple versions, let's just append .0 at the end.
|
||||
number_to_spoof="$number_to_spoof.0"
|
||||
else
|
||||
# else we'll increase the found version by one
|
||||
number_to_spoof=$(($number_to_spoof + 1))
|
||||
fi
|
||||
|
||||
victim_lib_array[-1]="$number_to_spoof"
|
||||
library_path=$(IFS=. ; echo "${victim_lib_array[*]}")
|
||||
|
||||
if [ -e "$library_path" ]; then
|
||||
echo -e "\e[91mA error occurred. Please retry.\e[39m"
|
||||
exit -1
|
||||
else
|
||||
sudo cp "bin/Debug/libdoghook.so" "$library_path"
|
||||
|
||||
# Get the file name of the resulting library
|
||||
result_lib_name=$(basename ${library_path})
|
||||
result_lib="${result_lib_name%.*}"
|
||||
|
||||
# and patch the soname
|
||||
sudo patchelf --set-soname "$library_path" "$result_lib"
|
||||
fi
|
||||
|
||||
echo "Attaching as $result_lib ($library_path) to PID $pid"
|
||||
|
||||
# Allows only root to use ptrace. This is temporary until the user reboots the machine.
|
||||
ptrace_input=$(sudo echo "2" | sudo tee /proc/sys/kernel/yama/ptrace_scope)
|
||||
|
||||
# Prevent crash dumps from being sent to kisak
|
||||
sudo rm -rf /tmp/dumps
|
||||
sudo mkdir /tmp/dumps
|
||||
sudo chmod 000 /tmp/dumps
|
||||
|
||||
# Pause Steam
|
||||
sudo killall -19 steam
|
||||
sudo killall -19 steamwebhelper
|
||||
|
||||
# Uses dlmopen instead of normal dlopen - Credit to LWSS
|
||||
sudo gdb -n \
|
||||
-ex "set logging on" \
|
||||
-ex "set logging file /dev/null" \
|
||||
-ex "attach $pid" \
|
||||
-ex "set \$linkMapID = (long int)0" \
|
||||
-ex "set \$dlopen = (void*(*)(char*, int)) dlopen" \
|
||||
-ex "set \$dlmopen = (void*(*)(long int, char*, int)) dlmopen" \
|
||||
-ex "set \$dlinfo = (int (*)(void*, int, void*)) dlinfo" \
|
||||
-ex "set \$malloc = (void*(*)(long long)) malloc" \
|
||||
-ex "set \$target = \$dlopen(\"$library_path\", 2)" \
|
||||
-ex "p \$target" \
|
||||
-ex "p \$linkMapID" \
|
||||
-ex "call \$dlmopen(0, \"$library_path\", 1)" \
|
||||
-ex "set \$error = call dlerror()" \
|
||||
-ex "x/s \$error"
|
||||
|
||||
# Resume Steam
|
||||
sleep 1
|
||||
sudo killall -18 steamwebhelper
|
||||
sudo killall -18 steam
|
||||
|
||||
sudo rm -rf "$library_path"
|
||||
|
||||
if grep -q "$library_path" /proc/${pid}/maps; then
|
||||
echo "Successfully attached to PID $pid."
|
||||
else
|
||||
echo -e "\e[91mA error occurred. See gdb.txt\e[39m"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
if [ -f "$(pwd)/gdb.txt" ]; then
|
||||
sudo rm -rf gdb.txt
|
||||
fi
|
@ -70,7 +70,7 @@ sudo killall -19 steam
|
||||
sudo killall -19 steamwebhelper
|
||||
|
||||
# Uses dlmopen instead of normal dlopen - Credit to LWSS
|
||||
sudo gdb -n \
|
||||
sudo gdb -n -batch \
|
||||
-ex "set logging on" \
|
||||
-ex "set logging file /dev/null" \
|
||||
-ex "attach $pid" \
|
||||
@ -85,7 +85,11 @@ sudo gdb -n \
|
||||
-ex "call \$dlmopen(0, \"$library_path\", 1)" \
|
||||
-ex "set \$error = call dlerror()" \
|
||||
-ex "x/s \$error" \
|
||||
-ex "catch syscall exit exit_group"
|
||||
-ex "catch syscall exit exit_group" \
|
||||
-ex "continue" \
|
||||
-ex "backtrace" \
|
||||
-ex "detach" \
|
||||
-ex "quit"
|
||||
|
||||
# Resume Steam
|
||||
sleep 1
|
||||
|
@ -25,7 +25,13 @@ workspace "doghook"
|
||||
filter "configurations:Debug"
|
||||
defines { "DEBUG", "_DEBUG" }
|
||||
optimize "Off"
|
||||
|
||||
filter "system:windows"
|
||||
symbols "Full"
|
||||
filter "system:linux"
|
||||
symbols "On"
|
||||
buildoptions "-g3"
|
||||
filter ""
|
||||
runtime "Debug"
|
||||
|
||||
filter "configurations:Release"
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "precompiled.hh"
|
||||
|
||||
#include "doghook.hh"
|
||||
|
||||
#include "sdk/gamesystem.hh"
|
||||
#include "sdk/log.hh"
|
||||
|
||||
@ -14,6 +16,8 @@
|
||||
|
||||
#include "hooks/createmove.hh"
|
||||
|
||||
#include "sdk/signature.hh"
|
||||
|
||||
// Singleton for doing init / deinit of doghook
|
||||
// and dealing with hooks from gamesystem
|
||||
|
||||
@ -39,14 +43,33 @@ public:
|
||||
IFace<sdk::Client>().set_from_interface("client", "VClient");
|
||||
IFace<sdk::Engine>().set_from_interface("engine", "VEngineClient");
|
||||
IFace<sdk::EntList>().set_from_interface("client", "VClientEntityList");
|
||||
|
||||
if constexpr (doghook_platform::windows())
|
||||
IFace<sdk::Input>().set_from_pointer(**reinterpret_cast<sdk::Input ***>(
|
||||
vfunc::get_func<u8 *>(IFace<sdk::Client>().get(), 15, 0) + 0x2));
|
||||
else if constexpr (doghook_platform::linux())
|
||||
IFace<sdk::Input>().set_from_pointer(**reinterpret_cast<sdk::Input ***>(
|
||||
vfunc::get_func<u8 *>(IFace<sdk::Client>().get(), 15, 0) + 0x1));
|
||||
|
||||
IFace<sdk::Cvar>().set_from_interface("vstdlib", "VEngineCvar");
|
||||
|
||||
// TODO linux signatures
|
||||
if constexpr (doghook_platform::windows())
|
||||
IFace<sdk::ClientMode>().set_from_pointer(
|
||||
*signature::find_pattern<sdk::ClientMode **>(
|
||||
"client", "B9 ? ? ? ? A3 ? ? ? ? E8 ? ? ? ? 68 ? ? ? ? E8 ? ? ? ? 83 C4 04 C7 05", 1));
|
||||
else if constexpr (doghook_platform::linux()) {
|
||||
// ClientMode is a magic static. So getting a sig for it is difficult (conflicts with all other magic statics)
|
||||
// So we are going to do some multistage shit in order to retrieve it
|
||||
auto outer_function = signature::find_pattern<void *>("client", "55 89 E5 83 EC 18 E8 ? ? ? ? A3 ? ? ? ? E8", 6);
|
||||
assert(outer_function);
|
||||
|
||||
auto inner_function = static_cast<u8 *>(signature::resolve_callgate(outer_function));
|
||||
assert(outer_function);
|
||||
|
||||
IFace<sdk::ClientMode>().set_from_pointer(*reinterpret_cast<sdk::ClientMode **>(inner_function + 10));
|
||||
assert(IFace<sdk::ClientMode>().get());
|
||||
}
|
||||
|
||||
IFace<sdk::ModelInfo>().set_from_interface("engine", "VModelInfoClient");
|
||||
IFace<sdk::Trace>().set_from_interface("engine", "EngineTraceClient");
|
||||
IFace<sdk::DebugOverlay>().set_from_interface("engine", "VDebugOverlay");
|
||||
@ -59,17 +82,32 @@ public:
|
||||
// TODO: this globals_real_address is windows only!
|
||||
if constexpr (doghook_platform::windows()) {
|
||||
auto globals_real_address = (u32)*signature::find_pattern<sdk::Globals **>("engine", "A1 ? ? ? ? 8B 11 68", 8);
|
||||
IFace<sdk::Globals>().set_from_pointer((sdk::Globals *)globals_real_address);
|
||||
} else if constexpr (doghook_platform::linux()) {
|
||||
auto globals_real_address = (u32) * *signature::find_pattern<sdk::Globals ***>("client", "8B 15 ? ? ? ? F3 0F 10 88 D0 08 00 00", 2);
|
||||
|
||||
IFace<sdk::Globals>().set_from_pointer((sdk::Globals *)globals_real_address);
|
||||
}
|
||||
|
||||
IFace<sdk::GameMovement>().set_from_interface("client", "GameMovement");
|
||||
IFace<sdk::Prediction>().set_from_interface("client", "VClientPrediction");
|
||||
|
||||
if constexpr (doghook_platform::windows())
|
||||
IFace<sdk::MoveHelper>().set_from_pointer(
|
||||
*signature::find_pattern<sdk::MoveHelper **>(
|
||||
"client", "8B 0D ? ? ? ? 8B 01 FF 50 28 56", 2));
|
||||
else if constexpr (doghook_platform::linux())
|
||||
IFace<sdk::MoveHelper>().set_from_pointer(nullptr);
|
||||
|
||||
inited = true;
|
||||
}
|
||||
|
||||
void process_attach() {
|
||||
// Wait for init...
|
||||
while (!inited) {
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
Log::msg("process_attach()");
|
||||
|
||||
// make sure that the netvars are initialised
|
||||
@ -130,4 +168,8 @@ auto __stdcall doghook_process_attach([[maybe_unused]] void *hmodule) -> u32 {
|
||||
|
||||
return 0;
|
||||
}
|
||||
#elif doghook_platform_linux()
|
||||
void doghook_process_attach() {
|
||||
doghook.process_attach();
|
||||
}
|
||||
#endif
|
||||
|
1
src/doghook.hh
Normal file
1
src/doghook.hh
Normal file
@ -0,0 +1 @@
|
||||
#pragma once
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include "modules/aimbot.hh"
|
||||
|
||||
#include "utils/math.hh"
|
||||
|
||||
using namespace sdk;
|
||||
|
||||
namespace create_move {
|
||||
@ -28,18 +30,28 @@ static inline auto local_player_prediction(Player *local, UserCmd *cmd) {
|
||||
IFace<Globals>()->tickcount = local->tick_base();
|
||||
|
||||
// Set the current usercmd and run prediction
|
||||
if constexpr (doghook_platform::windows())
|
||||
local->set<UserCmd *, 0x107C>(cmd);
|
||||
else if constexpr (doghook_platform::linux())
|
||||
local->set<UserCmd *, 0x105C>(cmd);
|
||||
|
||||
IFace<Prediction>()->setup_move(local, cmd, IFace<MoveHelper>().get(), move_data_buffer);
|
||||
IFace<GameMovement>()->process_movement(local, move_data_buffer);
|
||||
IFace<Prediction>()->finish_move(local, cmd, move_data_buffer);
|
||||
|
||||
if constexpr (doghook_platform::windows())
|
||||
local->set<UserCmd *, 0x107C>(0);
|
||||
else if constexpr (doghook_platform::linux())
|
||||
local->set<UserCmd *, 0x105C>(0);
|
||||
|
||||
// Cleanup from prediction
|
||||
IFace<Globals>()->curtime = old_cur_time;
|
||||
IFace<Globals>()->frametime = old_frame_time;
|
||||
IFace<Globals>()->tickcount = old_tick_count;
|
||||
|
||||
// TODO: if you do this then make sure to change the fov time calculation
|
||||
// in aimbot::try_autoshoot!!
|
||||
//local->tick_base() += 1;
|
||||
}
|
||||
|
||||
hooks::HookFunction<ClientMode, 0> *create_move_hook = nullptr;
|
||||
@ -51,14 +63,13 @@ bool hooked_create_move(void *instance, float sample_framerate, UserCmd *user_cm
|
||||
#endif
|
||||
{
|
||||
auto local_player = Player::local();
|
||||
if (local_player == nullptr) return true;
|
||||
assert(local_player);
|
||||
|
||||
// TODO: call original
|
||||
// Currently possible but the method is slow
|
||||
// Fixme in HookFunction!
|
||||
|
||||
// Do create_move_pre_predict()
|
||||
|
||||
aimbot::create_move_pre_predict(user_cmd);
|
||||
|
||||
local_player_prediction(local_player, user_cmd);
|
||||
@ -74,7 +85,7 @@ void level_init() {
|
||||
Log::msg("=> Hooking up!");
|
||||
|
||||
assert(create_move_hook == nullptr);
|
||||
create_move_hook = new hooks::HookFunction<ClientMode, 0>(IFace<ClientMode>().get(), 21, reinterpret_cast<void *>(&hooked_create_move));
|
||||
create_move_hook = new hooks::HookFunction<ClientMode, 0>(IFace<ClientMode>().get(), 21, 22, 22, reinterpret_cast<void *>(&hooked_create_move));
|
||||
}
|
||||
|
||||
void level_shutdown() {
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "precompiled.hh"
|
||||
|
||||
#include <thread>
|
||||
|
||||
#if doghook_platform_windows()
|
||||
|
||||
extern u32 __stdcall doghook_process_attach(void *a);
|
||||
@ -18,7 +20,11 @@ __declspec(dllexport) BOOL APIENTRY DllMain(HMODULE hModule,
|
||||
#else
|
||||
// TODO: send process attach over to gamesystem
|
||||
|
||||
void __attribute__((constructor)) startup() {}
|
||||
extern void doghook_process_attach();
|
||||
|
||||
void __attribute__((constructor)) startup() {
|
||||
std::thread{&doghook_process_attach}.detach();
|
||||
}
|
||||
|
||||
void __attribute__((destructor)) shutdown() {}
|
||||
#endif
|
||||
|
@ -301,7 +301,7 @@ static Convar<bool> doghook_aimbot_aim_if_not_attack = Convar<bool>{"
|
||||
static Convar<bool> doghook_aimbot_disallow_attack_if_no_target = Convar<bool>{"doghook_aimbot_disallow_attack_if_no_target", false, nullptr};
|
||||
|
||||
void create_move(sdk::UserCmd *cmd) {
|
||||
if (local_weapon == nullptr) return;
|
||||
if (local_weapon == nullptr || !can_find_targets) return;
|
||||
|
||||
find_targets();
|
||||
|
||||
@ -341,6 +341,11 @@ void create_move_pre_predict(sdk::UserCmd *cmd) {
|
||||
local_player = Player::local();
|
||||
assert(local_player);
|
||||
|
||||
if (local_player->alive() == false) {
|
||||
can_find_targets = false;
|
||||
return;
|
||||
}
|
||||
|
||||
local_weapon = local_player->active_weapon()->to_weapon();
|
||||
|
||||
local_team = local_player->team();
|
||||
|
@ -10,5 +10,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
@ -9,6 +9,9 @@
|
||||
// implementation of a source convar
|
||||
namespace sdk {
|
||||
|
||||
// Helper to prevent crashes if Cvar isnt initied properly yet
|
||||
bool can_init_convars_at_construction_time = false;
|
||||
|
||||
class IConVar;
|
||||
|
||||
using ChangeCallbackFn = void (*)(IConVar *, const char *, float);
|
||||
@ -33,7 +36,9 @@ public:
|
||||
virtual const char *get_name() const { return name; }
|
||||
virtual const char *get_help_text() const { return help_string; }
|
||||
|
||||
virtual bool is_registered() const { return registered; }
|
||||
virtual bool is_registered() const {
|
||||
return registered;
|
||||
}
|
||||
|
||||
virtual int get_dll_identifier() const {
|
||||
if (dll_identifier == -1) dll_identifier = IFace<Cvar>()->allocate_dll_identifier();
|
||||
@ -55,7 +60,7 @@ public:
|
||||
|
||||
// We might not have Cvar here (global variables)
|
||||
|
||||
if (auto cvar = IFace<Cvar>()) {
|
||||
if (auto cvar = IFace<Cvar>() && can_init_convars_at_construction_time) {
|
||||
IFace<Cvar>()->register_command(this);
|
||||
}
|
||||
}
|
||||
@ -158,12 +163,19 @@ public:
|
||||
static auto to_iconvar(ConCommandBase *b) { return reinterpret_cast<IConVar *>(reinterpret_cast<u8 *>(b) + 24); }
|
||||
auto to_iconvar() -> IConVar * { return ConCommandBase::to_iconvar(this); }
|
||||
|
||||
#if doghook_platform_windows()
|
||||
#define DEFINE_THUNK(type, name, real_name) \
|
||||
static void __fastcall name(IConVar *ecx, void *edx, type v) { \
|
||||
auto *real = ConCommandBase::from_iconvar(ecx); \
|
||||
real->real_name(v); \
|
||||
}
|
||||
|
||||
#elif doghook_platform_linux()
|
||||
#define DEFINE_THUNK(type, name, real_name) \
|
||||
static void name(IConVar *ecx, type v) { \
|
||||
auto *real = ConCommandBase::from_iconvar(ecx); \
|
||||
real->real_name(v); \
|
||||
}
|
||||
#endif
|
||||
DEFINE_THUNK(const char *, set_value_string_thunk, set_value);
|
||||
DEFINE_THUNK(float, set_value_float_thunk, set_value);
|
||||
DEFINE_THUNK(int, set_value_int_thunk, set_value);
|
||||
@ -233,7 +245,7 @@ public:
|
||||
|
||||
// Convar is an mi class and therefore needs this
|
||||
// TODO: is this windows only - what is the linux equivilent??
|
||||
void *convar_vtable;
|
||||
void *convar_vtable; // Should be at 0x24
|
||||
|
||||
// Convar members
|
||||
ConCommandBase *parent;
|
||||
@ -317,6 +329,8 @@ ConvarBase::~ConvarBase() {
|
||||
void ConvarBase::init_all() {
|
||||
assert(IFace<sdk::Cvar>());
|
||||
|
||||
sdk::can_init_convars_at_construction_time = true;
|
||||
|
||||
// We have to do this goofy loop here as register_command() will
|
||||
// change the `next` pointer to the next in its chain
|
||||
// which will cause all kinds of problems for us
|
||||
|
@ -11,7 +11,7 @@
|
||||
using namespace sdk;
|
||||
|
||||
auto Entity::to_handle() -> EntityHandle & {
|
||||
return_virtual_func(to_handle, 2, 0, 0, 0);
|
||||
return_virtual_func(to_handle, 2, 3, 3, 0);
|
||||
}
|
||||
|
||||
auto Entity::is_valid() -> bool {
|
||||
@ -37,13 +37,13 @@ auto Entity::to_weapon() -> class Weapon * {
|
||||
}
|
||||
|
||||
auto Entity::client_class() -> struct ClientClass * {
|
||||
return_virtual_func(client_class, 2, 0, 0, 8);
|
||||
return_virtual_func(client_class, 2, 17, 17, 8);
|
||||
}
|
||||
|
||||
auto Entity::dormant() -> bool {
|
||||
return_virtual_func(dormant, 8, 0, 0, 8);
|
||||
return_virtual_func(dormant, 8, 75, 75, 8);
|
||||
}
|
||||
|
||||
auto Entity::index() -> u32 {
|
||||
return_virtual_func(index, 9, 0, 0, 8);
|
||||
return_virtual_func(index, 9, 79, 79, 8);
|
||||
}
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
// TODO: in all of these cases shouldnt offset be in terms of bytes instead of dwords???
|
||||
|
||||
namespace hooks {
|
||||
template <typename T, u32 offset>
|
||||
class HookInstance {
|
||||
@ -42,7 +44,6 @@ class HookInstance {
|
||||
|
||||
public:
|
||||
HookInstance(T *instance) : instance(instance) {
|
||||
|
||||
assert(instance);
|
||||
|
||||
original_table = get_table();
|
||||
@ -127,7 +128,7 @@ class HookFunction {
|
||||
u32 index;
|
||||
|
||||
public:
|
||||
HookFunction(T *instance, u32 index, void *f) {
|
||||
HookFunction(T *instance, u32 index_windows, u32 index_linux, u32 index_osx, void *f) {
|
||||
assert(instance);
|
||||
HookInstance<T, offset> *val = nullptr;
|
||||
|
||||
@ -138,6 +139,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: osx
|
||||
u32 index;
|
||||
if constexpr (doghook_platform::windows())
|
||||
index = index_windows;
|
||||
else if constexpr (doghook_platform::linux())
|
||||
index = index_linux;
|
||||
|
||||
if (val == nullptr) {
|
||||
// we havent hooked this instance yet, so do that now
|
||||
create_hook_instance(instance)->hook_function(index, f);
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
T *Interface<T>::value;
|
||||
T *Interface<T>::value = nullptr;
|
||||
|
||||
template <typename T>
|
||||
using IFace = Interface<T>;
|
||||
|
@ -25,7 +25,7 @@ auto Player::alive() -> bool {
|
||||
}
|
||||
|
||||
auto Player::origin() -> math::Vector & {
|
||||
return_virtual_func(origin, 9, 0, 0, 0);
|
||||
return_virtual_func(origin, 9, 11, 11, 0);
|
||||
}
|
||||
|
||||
auto Player::set_origin(const math::Vector &v) -> void {
|
||||
@ -39,7 +39,7 @@ auto Player::set_origin(const math::Vector &v) -> void {
|
||||
}
|
||||
|
||||
auto Player::angles() -> math::Vector & {
|
||||
return_virtual_func(angles, 10, 0, 0, 0);
|
||||
return_virtual_func(angles, 10, 12, 12, 0);
|
||||
}
|
||||
|
||||
auto Player::set_angles(const math::Vector &v) -> void {
|
||||
@ -63,7 +63,7 @@ auto Player::cond() -> u32 & {
|
||||
}
|
||||
|
||||
auto Player::render_bounds() -> std::pair<math::Vector, math::Vector> {
|
||||
auto func = vfunc::Func<void (Player::*)(math::Vector &, math::Vector &)>(this, 20, 0, 0, 4);
|
||||
auto func = vfunc::Func<void (Player::*)(math::Vector &, math::Vector &)>(this, 20, 60, 60, 4);
|
||||
|
||||
std::pair<math::Vector, math::Vector> ret;
|
||||
|
||||
@ -98,7 +98,7 @@ auto Player::tf_class() -> int {
|
||||
}
|
||||
|
||||
static auto tick_base = Netvar("DT_BasePlayer", "localdata", "m_nTickBase");
|
||||
auto Player::tick_base() -> int {
|
||||
auto Player::tick_base() -> int & {
|
||||
return ::tick_base.get<int>(this);
|
||||
}
|
||||
|
||||
@ -189,11 +189,11 @@ auto Player::view_position() -> math::Vector {
|
||||
}
|
||||
|
||||
auto Player::bone_transforms(math::Matrix3x4 *hitboxes_out, u32 max_bones, u32 bone_mask, float current_time) -> bool {
|
||||
return_virtual_func(bone_transforms, 16, 0, 0, 4, hitboxes_out, max_bones, bone_mask, current_time);
|
||||
return_virtual_func(bone_transforms, 16, 96, 96, 4, hitboxes_out, max_bones, bone_mask, current_time);
|
||||
}
|
||||
|
||||
auto Player::model_handle() -> const ModelHandle * {
|
||||
return_virtual_func(model_handle, 9, 0, 0, 4);
|
||||
return_virtual_func(model_handle, 9, 55, 55, 4);
|
||||
}
|
||||
|
||||
auto Player::studio_model() -> const StudioModel * {
|
||||
|
@ -52,7 +52,7 @@ public:
|
||||
|
||||
auto tf_class() -> int;
|
||||
|
||||
auto tick_base() -> int;
|
||||
auto tick_base() -> int &;
|
||||
auto sim_time() -> float &;
|
||||
auto anim_time() -> float &;
|
||||
auto cycle() -> float &;
|
||||
|
@ -154,15 +154,19 @@ public:
|
||||
EntList() = delete;
|
||||
|
||||
auto entity(u32 index) -> Entity * {
|
||||
return_virtual_func(entity, 3, 0, 0, 0, index);
|
||||
return_virtual_func(entity, 3, 3, 3, 0, index);
|
||||
}
|
||||
|
||||
auto from_handle(EntityHandle h) -> Entity * {
|
||||
|
||||
if constexpr (doghook_platform::windows()) {
|
||||
return_virtual_func(from_handle, 4, 4, 4, 0, h);
|
||||
} else if constexpr (doghook_platform::linux())
|
||||
return entity(h.serial_index & 0xFFF);
|
||||
}
|
||||
|
||||
auto max_entity_index() -> u32 {
|
||||
return_virtual_func(max_entity_index, 6, 0, 0, 0);
|
||||
return_virtual_func(max_entity_index, 6, 6, 6, 0);
|
||||
}
|
||||
|
||||
class EntityRange {
|
||||
@ -365,11 +369,11 @@ public:
|
||||
ModelInfo() = delete;
|
||||
|
||||
auto model_name(const ModelHandle *m) -> const char * {
|
||||
return_virtual_func(model_name, 3, 0, 0, 0, m);
|
||||
return_virtual_func(model_name, 3, 4, 4, 0, m);
|
||||
}
|
||||
|
||||
auto studio_model(const ModelHandle *m) -> const StudioModel * {
|
||||
return_virtual_func(studio_model, 28, 0, 0, 0, m);
|
||||
return_virtual_func(studio_model, 28, 29, 29, 0, m);
|
||||
}
|
||||
};
|
||||
|
||||
@ -416,17 +420,17 @@ class MoveHelper;
|
||||
class Prediction {
|
||||
public:
|
||||
auto setup_move(Player *player, UserCmd *ucmd, MoveHelper *helper, void *move) -> void {
|
||||
return_virtual_func(setup_move, 18, 18, 18, 0, player, ucmd, helper, move);
|
||||
return_virtual_func(setup_move, 18, 19, 19, 0, player, ucmd, helper, move);
|
||||
}
|
||||
void finish_move(Player *player, UserCmd *ucmd, void *move) {
|
||||
return_virtual_func(finish_move, 19, 19, 19, 0, player, ucmd, move);
|
||||
return_virtual_func(finish_move, 19, 20, 20, 0, player, ucmd, move);
|
||||
}
|
||||
};
|
||||
|
||||
class GameMovement {
|
||||
public:
|
||||
void process_movement(Player *player, void *move) {
|
||||
return_virtual_func(process_movement, 1, 1, 1, 0, player, move);
|
||||
return_virtual_func(process_movement, 1, 2, 2, 0, player, move);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,11 @@ class Func;
|
||||
template <typename ObjectType, typename Ret, typename... Args>
|
||||
class Func<Ret (ObjectType::*)(Args...)> {
|
||||
|
||||
#if doghook_platform_windows()
|
||||
using function_type = Ret(__thiscall *)(ObjectType *, Args...);
|
||||
#elif doghook_platform_linux()
|
||||
using function_type = Ret (*)(ObjectType *, Args...);
|
||||
#endif
|
||||
function_type f;
|
||||
|
||||
// On windows this will take into account the offset
|
||||
|
@ -140,12 +140,12 @@ public:
|
||||
else
|
||||
pitch = 90;
|
||||
} else {
|
||||
yaw = (atan2(y, x) * 180 / PI);
|
||||
yaw = (to_degrees(atan2(y, x)));
|
||||
if (yaw < 0)
|
||||
yaw += 360;
|
||||
|
||||
tmp = sqrt(x * x + y * y);
|
||||
pitch = (atan2(-z, tmp) * 180 / PI);
|
||||
pitch = (to_degrees(atan2(-z, tmp)));
|
||||
if (pitch < 0)
|
||||
pitch += 360;
|
||||
}
|
||||
@ -350,3 +350,5 @@ inline void matrix_angles(const Matrix3x4 &matrix, Vector &angles, Vector &posit
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
|
||||
#define Vector_split_components(v) (v).x, (v).y, (v).z
|
||||
|
Reference in New Issue
Block a user