This repository has been archived on 2024-06-01. You can view files and clone it, but cannot push or open issues or pull requests.
cathook/src/hack.cpp
2018-02-26 21:22:01 -06:00

415 lines
13 KiB
C++

/*
* hack.cpp
*
* Created on: Oct 3, 2016
* Author: nullifiedcat
*/
#include "hack.hpp"
#include "common.hpp"
#define STRINGIFY(x) #x
#define TO_STRING(x) STRINGIFY(x)
#include "CDumper.hpp"
/*
* Credits to josh33901 aka F1ssi0N for butifel F1Public and Darkstorm 2015
* Linux
*/
bool hack::shutdown = false;
bool hack::initialized = false;
const std::string &hack::GetVersion()
{
static std::string version("Unknown Version");
static bool version_set = false;
if (version_set)
return version;
#if defined(GIT_COMMIT_HASH) && defined(GIT_COMMIT_DATE)
version = "Version: #" GIT_COMMIT_HASH " " GIT_COMMIT_DATE;
#endif
version_set = true;
return version;
}
const std::string &hack::GetType()
{
static std::string version("Unknown Type");
static bool version_set = false;
if (version_set)
return version;
version = "";
#if not defined(ENABLE_IPC)
version += " NOIPC";
#endif
#if not ENABLE_GUI
version += " NOGUI";
#else
version += " IMGUI";
#endif
#ifndef DYNAMIC_CLASSES
#ifdef BUILD_GAME
version += " GAME " TO_STRING(BUILD_GAME);
#else
version += " UNIVERSAL";
#endif
#else
version += " DYNAMIC";
#endif
#if not ENABLE_VISUALS
version += " NOVISUALS";
#endif
version = version.substr(1);
version_set = true;
return version;
}
std::mutex hack::command_stack_mutex;
std::stack<std::string> &hack::command_stack()
{
static std::stack<std::string> stack;
return stack;
}
#if ENABLE_VISUALS == 1 /* Why would we need colored chat stuff in textmode? \
*/
class AdvancedEventListener : public IGameEventListener
{
public:
virtual void FireGameEvent(KeyValues *event)
{
if (!event_log)
return;
const char *name = event->GetName();
if (!strcmp(name, "player_connect_client"))
{
PrintChat("\x07%06X%s\x01 \x07%06X%s\x01 joining", 0xa06ba0,
event->GetString("name"), 0x914e65,
event->GetString("networkid"));
}
else if (!strcmp(name, "player_activate"))
{
int uid = event->GetInt("userid");
int entity = g_IEngine->GetPlayerForUserID(uid);
player_info_s info;
if (g_IEngine->GetPlayerInfo(entity, &info))
{
PrintChat("\x07%06X%s\x01 connected", 0xa06ba0, info.name);
}
}
else if (!strcmp(name, "player_disconnect"))
{
CachedEntity *player =
ENTITY(g_IEngine->GetPlayerForUserID(event->GetInt("userid")));
PrintChat("\x07%06X%s\x01 \x07%06X%s\x01 disconnected",
colors::chat::team(player->m_iTeam),
event->GetString("name"), 0x914e65,
event->GetString("networkid"));
}
else if (!strcmp(name, "player_team"))
{
if (event->GetBool("disconnect") != 1)
{
int oteam = event->GetInt("oldteam");
int nteam = event->GetInt("team");
const char *oteam_s = teamname(oteam);
const char *nteam_s = teamname(nteam);
PrintChat("\x07%06X%s\x01 changed team (\x07%06X%s\x01 -> "
"\x07%06X%s\x01)",
0xa06ba0, event->GetString("name"),
colors::chat::team(oteam), oteam_s,
colors::chat::team(nteam), nteam_s);
}
}
}
};
AdvancedEventListener adv_event_listener{};
#endif /* TEXTMODE */
void hack::ExecuteCommand(const std::string command)
{
std::lock_guard<std::mutex> guard(hack::command_stack_mutex);
hack::command_stack().push(command);
}
ConCommand *hack::c_Cat = 0;
void hack::CC_Cat(const CCommand &args)
{
g_ICvar->ConsoleColorPrintf(Color(255, 255, 255, 255), "cathook");
g_ICvar->ConsoleColorPrintf(Color(0, 0, 255, 255), " by ");
g_ICvar->ConsoleColorPrintf(Color(255, 0, 0, 255), "nullifiedcat\n");
}
void hack::Initialize()
{
signal(SIGPIPE, SIG_IGN);
time_injected = time(nullptr);
/*passwd *pwd = getpwuid(getuid());
char *logname = strfmt("/tmp/cathook-game-stdout-%s-%u.log", pwd->pw_name, time_injected);
freopen(logname, "w", stdout);
free(logname);
logname = strfmt("/tmp/cathook-game-stderr-%s-%u.log", pwd->pw_name, time_injected);
freopen(logname, "w", stderr);
free(logname);*/
// Essential files must always exist, except when the game is running in text
// mode.
#if ENABLE_VISUALS == 1
{
std::vector<std::string> essential = { "shaders/v2f-c4f.frag",
"shaders/v2f-c4f.vert",
"shaders/v2f-t2f-c4f.frag",
"shaders/v2f-t2f-c4f.vert",
"shaders/v3f-t2f-c4f.frag",
"shaders/v3f-t2f-c4f.vert",
"menu.json",
"fonts/tf2build.ttf" };
for (const auto &s : essential)
{
std::ifstream exists(DATA_PATH "/" + s, std::ios::in);
if (not exists)
{
Error("Missing essential file: " DATA_PATH
"/%s\nYou MUST run check-data script to finish "
"installation",
s.c_str());
}
}
}
#endif /* TEXTMODE */
logging::Info("Initializing...");
srand(time(0));
sharedobj::LoadAllSharedObjects();
CreateInterfaces();
CDumper dumper;
dumper.SaveDump();
logging::Info("Is TF2? %d", IsTF2());
logging::Info("Is TF2C? %d", IsTF2C());
logging::Info("Is HL2DM? %d", IsHL2DM());
logging::Info("Is CSS? %d", IsCSS());
logging::Info("Is TF? %d", IsTF());
InitClassTable();
BeginConVars();
hack::c_Cat = CreateConCommand(CON_NAME, &hack::CC_Cat, "Info");
g_Settings.Init();
EndConVars();
#if ENABLE_VISUALS == 1
draw::Initialize();
#if ENABLE_GUI
/*
g_pGUI = new CatGUI();
g_pGUI->Setup();
*/
#endif
#endif /* TEXTMODE */
gNetvars.init();
InitNetVars();
g_pLocalPlayer = new LocalPlayer();
g_pPlayerResource = new TFPlayerResource();
#if ENABLE_VISUALS == 1
hooks::panel.Set(g_IPanel);
hooks::panel.HookMethod((void *) PaintTraverse_hook,
offsets::PaintTraverse());
hooks::panel.Apply();
#endif
uintptr_t *clientMode = 0;
// Bad way to get clientmode.
// FIXME [MP]?
while (!(
clientMode = **(
uintptr_t ***) ((uintptr_t)((*(void ***) g_IBaseClient)[10]) + 1)))
{
sleep(1);
}
hooks::clientmode.Set((void *) clientMode);
hooks::clientmode.HookMethod((void *) CreateMove_hook,
offsets::CreateMove());
#if ENABLE_VISUALS == 1
hooks::clientmode.HookMethod((void *) OverrideView_hook,
offsets::OverrideView());
#endif
hooks::clientmode.HookMethod((void *) LevelInit_hook, offsets::LevelInit());
hooks::clientmode.HookMethod((void *) LevelShutdown_hook,
offsets::LevelShutdown());
hooks::clientmode.Apply();
hooks::clientmode4.Set((void *) (clientMode), 4);
hooks::clientmode4.HookMethod((void *) FireGameEvent_hook,
offsets::FireGameEvent());
hooks::clientmode4.Apply();
hooks::client.Set(g_IBaseClient);
#if ENABLE_VISUALS == 1
hooks::client.HookMethod((void *) FrameStageNotify_hook,
offsets::FrameStageNotify());
#endif
hooks::client.HookMethod((void *) DispatchUserMessage_hook,
offsets::DispatchUserMessage());
#if ENABLE_VISUALS == 1
hooks::vstd.Set((void *)g_pUniformStream);
hooks::vstd.HookMethod((void *)RandomInt_hook, offsets::RandomInt());
hooks::vstd.Apply();
#endif
#if ENABLE_NULL_GRAPHICS == 1
g_IMaterialSystem->SetInStubMode(true);
IF_GAME(IsTF2())
{
logging::Info("Graphics Nullified");
logging::Info("The game will crash");
// TODO offsets::()?
hooks::materialsystem.Set((void *) g_IMaterialSystem);
uintptr_t base = *(uintptr_t *) (g_IMaterialSystem);
hooks::materialsystem.HookMethod((void *) ReloadTextures_null_hook, 70);
hooks::materialsystem.HookMethod((void *) ReloadMaterials_null_hook,
71);
hooks::materialsystem.HookMethod((void *) FindMaterial_null_hook, 73);
hooks::materialsystem.HookMethod((void *) FindTexture_null_hook, 81);
hooks::materialsystem.HookMethod((void *) ReloadFilesInList_null_hook,
121);
hooks::materialsystem.HookMethod((void *) FindMaterialEx_null_hook,
123);
hooks::materialsystem.Apply();
// hooks::materialsystem.HookMethod();
}
#endif
#if ENABLE_VISUALS == 1
hooks::client.HookMethod((void *) IN_KeyEvent_hook, offsets::IN_KeyEvent());
#endif
hooks::client.Apply();
hooks::input.Set(g_IInput);
hooks::input.HookMethod((void *) GetUserCmd_hook, offsets::GetUserCmd());
hooks::input.Apply();
#ifndef HOOK_DME_DISABLED
#if ENABLE_VISUALS == 1
hooks::modelrender.Set(g_IVModelRender);
hooks::modelrender.HookMethod((void *) DrawModelExecute_hook,
offsets::DrawModelExecute());
hooks::modelrender.Apply();
#endif
#endif
hooks::enginevgui.Set(g_IEngineVGui);
hooks::enginevgui.HookMethod((void *)Paint_hook, offsets::PlatformOffset(14, offsets::undefined, offsets::undefined));
hooks::enginevgui.Apply();
hooks::steamfriends.Set(g_ISteamFriends);
hooks::steamfriends.HookMethod((void *) GetFriendPersonaName_hook,
offsets::GetFriendPersonaName());
hooks::steamfriends.Apply();
// logging::Info("After hacking: %s", g_ISteamFriends->GetPersonaName());
// Sadly, it doesn't work as expected :(
/*hooks::hkBaseClientState = new hooks::VMTHook();
hooks::hkBaseClientState->Init((void*)g_IBaseClientState, 0);
hooks::hkBaseClientState->HookMethod((void*)GetClientName_hook,
hooks::offGetClientName); hooks::hkBaseClientState->Apply();*/
// hooks::hkBaseClientState8 = new hooks::VMTHook();
// hooks::hkBaseClientState8->Init((void*)g_IBaseClientState, 8);
// hooks::hkBaseClientState8->HookMethod((void*)ProcessSetConVar_hook,
// hooks::offProcessSetConVar);
// hooks::hkBaseClientState8->HookMethod((void*)ProcessGetCvarValue_hook,
// hooks::offProcessGetCvarValue); hooks::hkBaseClientState8->Apply();
// FIXME [MP]
hacks::shared::killsay::Init();
hacks::shared::announcer::init();
hacks::tf2::killstreak::init();
hacks::shared::catbot::init();
logging::Info("Hooked!");
velocity::Init();
playerlist::Load();
#if ENABLE_VISUALS == 1
InitStrings();
#if ENABLE_GUI
// cat_reloadscheme to load imgui
hack::command_stack().push("cat_reloadscheme");
#endif
#ifndef FEATURE_EFFECTS_DISABLED
if (g_ppScreenSpaceRegistrationHead && g_pScreenSpaceEffects)
{
effect_chams::g_pEffectChams = new CScreenSpaceEffectRegistration(
"_cathook_chams", &effect_chams::g_EffectChams);
g_pScreenSpaceEffects->EnableScreenSpaceEffect("_cathook_chams");
effect_chams::g_EffectChams.Init();
effect_glow::g_pEffectGlow = new CScreenSpaceEffectRegistration(
"_cathook_glow", &effect_glow::g_EffectGlow);
g_pScreenSpaceEffects->EnableScreenSpaceEffect("_cathook_glow");
}
logging::Info("SSE enabled..");
#endif
DoSDLHooking();
logging::Info("SDL hooking done");
g_IGameEventManager->AddListener(&adv_event_listener, false);
#endif /* TEXTMODE */
hacks::shared::anticheat::Init();
hacks::tf2::healarrow::Init();
#if ENABLE_VISUALS == 1
#ifndef FEATURE_FIDGET_SPINNER_DISABLED
InitSpinner();
logging::Info("Initialized Fidget Spinner");
#endif
hacks::shared::spam::Init();
backpacktf::init();
logging::Info("Initialized Backpack.TF integration");
#endif
hacks::shared::walkbot::Initialize();
logging::Info("Clearing initializer stack");
while (!init_stack().empty())
{
init_stack().top()();
init_stack().pop();
}
logging::Info("Initializer stack done");
#if not ENABLE_VISUALS
hack::command_stack().push("exec cat_autoexec_textmode");
#endif
hack::command_stack().push("exec cat_autoexec");
hack::command_stack().push("cat_killsay_reload");
hack::command_stack().push("cat_spam_reload");
hack::initialized = true;
}
void hack::Think()
{
usleep(250000);
}
void hack::Shutdown()
{
if (hack::shutdown)
return;
hack::shutdown = true;
playerlist::Save();
DoSDLUnhooking();
logging::Info("Unregistering convars..");
ConVar_Unregister();
logging::Info("Shutting down killsay...");
hacks::shared::killsay::Shutdown();
hacks::shared::announcer::shutdown();
logging::Info("Success..");
}