From 26b477483d93c8f896e335635d6ddceaac5e6531 Mon Sep 17 00:00:00 2001 From: nullifiedcat Date: Mon, 20 Mar 2017 19:35:22 +0300 Subject: [PATCH] working IPC exec commands --- makefile | 2 +- simple-ipc | 2 +- src/common.h | 2 ++ src/hack.cpp | 11 +++++---- src/hack.h | 2 ++ src/helpers.cpp | 14 +++++++---- src/hooks/PaintTraverse.cpp | 11 +++++---- src/ipc.cpp | 48 +++++++++++++++++++++++++++++++++---- src/ipc.h | 8 +++++-- 9 files changed, 78 insertions(+), 22 deletions(-) diff --git a/makefile b/makefile index 58660df2..98b1ecff 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,5 @@ CXX=g++ -CXXFLAGS=-std=gnu++14 -D_POSIX=1 -DRAD_TELEMETRY_DISABLED -DLINUX=1 -D_LINUX=1 -DPOSIX=1 -DGNUC=1 -D_DEVELOPER=1 -DNO_MALLOC_OVERRIDE -O3 -g3 -ggdb -w -shared -Wall -Wno-unknown-pragmas -fmessage-length=0 -m32 -fvisibility=hidden -fPIC +CXXFLAGS=-std=gnu++14 -D_GLIBCXX_USE_CXX11_ABI=0 -D_POSIX=1 -DRAD_TELEMETRY_DISABLED -DLINUX=1 -D_LINUX=1 -DPOSIX=1 -DGNUC=1 -D_DEVELOPER=1 -DNO_MALLOC_OVERRIDE -O3 -g3 -ggdb -w -shared -Wall -Wno-unknown-pragmas -fmessage-length=0 -m32 -fvisibility=hidden -fPIC SDKFOLDER=$(realpath source-sdk-2013/mp/src) SIMPLE_IPC_DIR = $(realpath simple-ipc/src/include) INCLUDES=-I$(SIMPLE_IPC_DIR) -I$(SDKFOLDER)/public -I$(SDKFOLDER)/mathlib -I$(SDKFOLDER)/common -I$(SDKFOLDER)/public/tier1 -I$(SDKFOLDER)/public/tier0 -I$(SDKFOLDER) diff --git a/simple-ipc b/simple-ipc index 70ce7ced..eccb7cc4 160000 --- a/simple-ipc +++ b/simple-ipc @@ -1 +1 @@ -Subproject commit 70ce7ced4e982292410df783967ab486290e7865 +Subproject commit eccb7cc43302b1c391b431d4415a7cdaf043fe6b diff --git a/src/common.h b/src/common.h index a47f1d21..1a661809 100644 --- a/src/common.h +++ b/src/common.h @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include "aftercheaders.h" #include "drawing.h" #include "entitycache.h" diff --git a/src/hack.cpp b/src/hack.cpp index d09831d4..f607f60e 100644 --- a/src/hack.cpp +++ b/src/hack.cpp @@ -61,6 +61,7 @@ std::stack& hack::command_stack() { void hack::InitHacks() { } +std::mutex hack::command_stack_mutex; ConCommand* hack::c_Cat = 0; void hack::CC_Cat(const CCommand& args) { @@ -93,11 +94,13 @@ void hack::Initialize() { dumper.SaveDump(); ClientClass* cc = g_IBaseClient->GetAllClasses(); FILE* cd = fopen("/tmp/cathook-classdump.txt", "w"); - while (cc) { - fprintf(cd, "[%d] %s\n", cc->m_ClassID, cc->GetName()); - cc = cc->m_pNext; + if (cd) { + while (cc) { + fprintf(cd, "[%d] %s\n", cc->m_ClassID, cc->GetName()); + cc = cc->m_pNext; + } + fclose(cd); } - fclose(cd); if (TF2) g_pClassID = new ClassIDTF2(); else if (TF2C) g_pClassID = new ClassIDTF2C(); else if (HL2DM) g_pClassID = new ClassIDHL2DM(); diff --git a/src/hack.h b/src/hack.h index 07254f2e..ba947bee 100644 --- a/src/hack.h +++ b/src/hack.h @@ -18,10 +18,12 @@ class CCommand; #include "beforecheaders.h" #include #include +#include #include "aftercheaders.h" namespace hack { +extern std::mutex command_stack_mutex; std::stack& command_stack(); extern bool shutdown; diff --git a/src/helpers.cpp b/src/helpers.cpp index a87d65ae..4a4092d0 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -20,16 +20,20 @@ void BeginConVars() { FILE* hAutoexec = fopen(strfmt("%scfg/cat_autoexec.cfg", g_pszTFPath), "r+"); if (!hAutoexec) { hAutoexec = fopen(strfmt("%scfg/cat_autoexec.cfg", g_pszTFPath), "w"); - fprintf(hAutoexec, "// Put your custom cathook settings in this file\n// This script will be executed EACH TIME YOU INJECT CATHOOK\n"); - fclose(hAutoexec); + if (hAutoexec) { + fprintf(hAutoexec, "// Put your custom cathook settings in this file\n// This script will be executed EACH TIME YOU INJECT CATHOOK\n"); + fclose(hAutoexec); + } } else fclose(hAutoexec); FILE* hMatchexec = fopen(strfmt("%scfg/cat_matchexec.cfg", g_pszTFPath), "r+"); if (!hMatchexec) { hMatchexec = fopen(strfmt("%scfg/cat_matchexec.cfg", g_pszTFPath), "w"); - fprintf(hMatchexec, "// Put your custom cathook settings in this file\n// This script will be executed EACH TIME YOU JOIN A MATCH\n"); - fclose(hMatchexec); + if (hMatchexec) { + fprintf(hMatchexec, "// Put your custom cathook settings in this file\n// This script will be executed EACH TIME YOU JOIN A MATCH\n"); + fclose(hMatchexec); + } } else fclose(hMatchexec); - fprintf(hConVarsFile, "// THIS FILE IS AUTO-GENERATED BY CATHOOK\n// DO NOT EDIT IT, ALL CHANGES WILL BE UNDONE!\n// If you want to change default settings, add changed convars to cat_autoexec.cfg\n"); + if (hConVarsFile) fprintf(hConVarsFile, "// THIS FILE IS AUTO-GENERATED BY CATHOOK\n// DO NOT EDIT IT, ALL CHANGES WILL BE UNDONE!\n// If you want to change default settings, add changed convars to cat_autoexec.cfg\n"); SetCVarInterface(g_ICvar); } diff --git a/src/hooks/PaintTraverse.cpp b/src/hooks/PaintTraverse.cpp index 407c5933..7bdefb94 100644 --- a/src/hooks/PaintTraverse.cpp +++ b/src/hooks/PaintTraverse.cpp @@ -40,14 +40,17 @@ void PaintTraverse_hook(void* p, unsigned int vp, bool fr, bool ar) { if (call_default) SAFE_CALL(((PaintTraverse_t*)hooks::hkPanel->GetMethod(hooks::offPaintTraverse))(p, vp, fr, ar)); // To avoid threading problems. - while (!hack::command_stack().empty()) { - g_IEngine->ExecuteClientCmd(hack::command_stack().top().c_str()); - hack::command_stack().pop(); + { + std::lock_guard guard(hack::command_stack_mutex); + while (!hack::command_stack().empty()) { + g_IEngine->ExecuteClientCmd(hack::command_stack().top().c_str()); + hack::command_stack().pop(); + } } + PROF_SECTION(PaintTraverse); if (vp == panel_top) draw_flag = true; if (!cathook) return; - // Because of single-multi thread shit I'm gonna put this thing riiiight here. if (!panel_top) { const char* name = g_IPanel->GetName(vp); diff --git a/src/ipc.cpp b/src/ipc.cpp index 059d7870..c9293ccf 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -8,31 +8,69 @@ #include "ipc.h" #include "common.h" +#include "hack.h" namespace ipc { void CommandCallback(cat_ipc::command_s& command, void* payload) { if (!strcmp("exec", (const char*)command.cmd_data) && payload) { + std::lock_guard lock(hack::command_stack_mutex); hack::command_stack().push(std::string((const char*)payload)); } } +std::atomic thread_running(false); +pthread_t listener_thread { 0 }; + +void* listen(void*) { + while (thread_running) { + if (peer->HasCommands()) { + peer->ProcessCommands(); + } + usleep(10000); + } + return 0; +} + CatCommand connect("ipc_connect", "Connect to IPC server", []() { - if (peer) { + if (peer || thread_running) { logging::Info("Already connected!"); return; } - peer = new peer_t(std::string(server_name.GetString()), false, false); + peer = new peer_t("cathook_followbot_server", false, false); peer->Connect(); + logging::Info("peer count: %i", peer->memory->peer_count); + logging::Info("magic number: 0x%08x", peer->memory->global_data.magic_number); + logging::Info("magic number offset: 0x%08x", (uintptr_t)&peer->memory->global_data.magic_number - (uintptr_t)peer->memory); peer->SetCallback(CommandCallback); StoreClientData(); + thread_running = true; + pthread_create(&listener_thread, nullptr, listen, nullptr); }); CatCommand disconnect("ipc_disconnect", "Disconnect from IPC server", []() { + thread_running = false; + pthread_join(listener_thread, nullptr); if (peer) delete peer; + listener_thread = 0; peer = nullptr; }); CatCommand exec("ipc_exec", "Execute command (first argument = bot ID)", [](const CCommand& args) { - unsigned target_id = atoi(args.Arg(1)); + char* endptr = nullptr; + unsigned target_id = strtol(args.Arg(1), &endptr, 10); + if (endptr == args.Arg(1)) { + logging::Info("Target id is NaN!"); + return; + } + if (target_id == 0 || target_id > 31) { + logging::Info("Invalid target id: %u", target_id); + return; + } + { + if (peer->memory->peer_data[target_id].free) { + logging::Info("Trying to send command to a dead peer"); + return; + } + } std::string command = std::string(args.ArgS()); command = command.substr(command.find(' ', 0) + 1); peer->SendMessage("exec", (1 << target_id), command.c_str(), command.length() + 1); @@ -40,12 +78,12 @@ CatCommand exec("ipc_exec", "Execute command (first argument = bot ID)", [](cons CatCommand exec_all("ipc_exec_all", "Execute command (on every peer)", [](const CCommand& args) { peer->SendMessage("exec", 0, args.ArgS(), strlen(args.ArgS()) + 1); }); -CatVar server_name(CV_STRING, "ipc_server", "cathook_ipc_server", "IPC server name"); +CatVar server_name(CV_STRING, "ipc_server", "cathook_followbot_server", "IPC server name"); peer_t* peer { nullptr }; void StoreClientData() { - peer_t::MutexLock lock; + peer_t::MutexLock lock(peer); user_data_s& data = peer->memory->peer_user_data[peer->client_id]; data.friendid = g_ISteamUser->GetSteamID().GetAccountID(); strncpy(data.name, g_ISteamFriends->GetPersonaName(), sizeof(data.name)); diff --git a/src/ipc.h b/src/ipc.h index 34a1db27..464cf9aa 100644 --- a/src/ipc.h +++ b/src/ipc.h @@ -9,6 +9,7 @@ #define IPC_H_ #include "ipcb.hpp" +#include "pthread.h" class CatCommand; class CatVar; @@ -21,10 +22,11 @@ extern CatCommand exec; extern CatCommand exec_all; extern CatVar server_name; -using peer_t = cat_ipc::Peer; +extern pthread_t listener_thread; +constexpr unsigned cathook_magic_number = 0x0DEADCA7; struct server_data_s { - bool dummy; + unsigned magic_number; }; struct user_data_s { @@ -32,6 +34,8 @@ struct user_data_s { unsigned friendid; }; +using peer_t = cat_ipc::Peer; + extern peer_t* peer; void StoreClientData();