working IPC exec commands
This commit is contained in:
parent
d860d7d516
commit
26b477483d
2
makefile
2
makefile
@ -1,5 +1,5 @@
|
|||||||
CXX=g++
|
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)
|
SDKFOLDER=$(realpath source-sdk-2013/mp/src)
|
||||||
SIMPLE_IPC_DIR = $(realpath simple-ipc/src/include)
|
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)
|
INCLUDES=-I$(SIMPLE_IPC_DIR) -I$(SDKFOLDER)/public -I$(SDKFOLDER)/mathlib -I$(SDKFOLDER)/common -I$(SDKFOLDER)/public/tier1 -I$(SDKFOLDER)/public/tier0 -I$(SDKFOLDER)
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 70ce7ced4e982292410df783967ab486290e7865
|
Subproject commit eccb7cc43302b1c391b431d4415a7cdaf043fe6b
|
@ -13,6 +13,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <mutex>
|
||||||
|
#include <atomic>
|
||||||
#include "aftercheaders.h"
|
#include "aftercheaders.h"
|
||||||
#include "drawing.h"
|
#include "drawing.h"
|
||||||
#include "entitycache.h"
|
#include "entitycache.h"
|
||||||
|
11
src/hack.cpp
11
src/hack.cpp
@ -61,6 +61,7 @@ std::stack<std::string>& hack::command_stack() {
|
|||||||
void hack::InitHacks() {
|
void hack::InitHacks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::mutex hack::command_stack_mutex;
|
||||||
ConCommand* hack::c_Cat = 0;
|
ConCommand* hack::c_Cat = 0;
|
||||||
|
|
||||||
void hack::CC_Cat(const CCommand& args) {
|
void hack::CC_Cat(const CCommand& args) {
|
||||||
@ -93,11 +94,13 @@ void hack::Initialize() {
|
|||||||
dumper.SaveDump();
|
dumper.SaveDump();
|
||||||
ClientClass* cc = g_IBaseClient->GetAllClasses();
|
ClientClass* cc = g_IBaseClient->GetAllClasses();
|
||||||
FILE* cd = fopen("/tmp/cathook-classdump.txt", "w");
|
FILE* cd = fopen("/tmp/cathook-classdump.txt", "w");
|
||||||
while (cc) {
|
if (cd) {
|
||||||
fprintf(cd, "[%d] %s\n", cc->m_ClassID, cc->GetName());
|
while (cc) {
|
||||||
cc = cc->m_pNext;
|
fprintf(cd, "[%d] %s\n", cc->m_ClassID, cc->GetName());
|
||||||
|
cc = cc->m_pNext;
|
||||||
|
}
|
||||||
|
fclose(cd);
|
||||||
}
|
}
|
||||||
fclose(cd);
|
|
||||||
if (TF2) g_pClassID = new ClassIDTF2();
|
if (TF2) g_pClassID = new ClassIDTF2();
|
||||||
else if (TF2C) g_pClassID = new ClassIDTF2C();
|
else if (TF2C) g_pClassID = new ClassIDTF2C();
|
||||||
else if (HL2DM) g_pClassID = new ClassIDHL2DM();
|
else if (HL2DM) g_pClassID = new ClassIDHL2DM();
|
||||||
|
@ -18,10 +18,12 @@ class CCommand;
|
|||||||
#include "beforecheaders.h"
|
#include "beforecheaders.h"
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <mutex>
|
||||||
#include "aftercheaders.h"
|
#include "aftercheaders.h"
|
||||||
|
|
||||||
namespace hack {
|
namespace hack {
|
||||||
|
|
||||||
|
extern std::mutex command_stack_mutex;
|
||||||
std::stack<std::string>& command_stack();
|
std::stack<std::string>& command_stack();
|
||||||
|
|
||||||
extern bool shutdown;
|
extern bool shutdown;
|
||||||
|
@ -20,16 +20,20 @@ void BeginConVars() {
|
|||||||
FILE* hAutoexec = fopen(strfmt("%scfg/cat_autoexec.cfg", g_pszTFPath), "r+");
|
FILE* hAutoexec = fopen(strfmt("%scfg/cat_autoexec.cfg", g_pszTFPath), "r+");
|
||||||
if (!hAutoexec) {
|
if (!hAutoexec) {
|
||||||
hAutoexec = fopen(strfmt("%scfg/cat_autoexec.cfg", g_pszTFPath), "w");
|
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");
|
if (hAutoexec) {
|
||||||
fclose(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);
|
} else fclose(hAutoexec);
|
||||||
FILE* hMatchexec = fopen(strfmt("%scfg/cat_matchexec.cfg", g_pszTFPath), "r+");
|
FILE* hMatchexec = fopen(strfmt("%scfg/cat_matchexec.cfg", g_pszTFPath), "r+");
|
||||||
if (!hMatchexec) {
|
if (!hMatchexec) {
|
||||||
hMatchexec = fopen(strfmt("%scfg/cat_matchexec.cfg", g_pszTFPath), "w");
|
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");
|
if (hMatchexec) {
|
||||||
fclose(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);
|
} 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);
|
SetCVarInterface(g_ICvar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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));
|
if (call_default) SAFE_CALL(((PaintTraverse_t*)hooks::hkPanel->GetMethod(hooks::offPaintTraverse))(p, vp, fr, ar));
|
||||||
// To avoid threading problems.
|
// To avoid threading problems.
|
||||||
while (!hack::command_stack().empty()) {
|
{
|
||||||
g_IEngine->ExecuteClientCmd(hack::command_stack().top().c_str());
|
std::lock_guard<std::mutex> guard(hack::command_stack_mutex);
|
||||||
hack::command_stack().pop();
|
while (!hack::command_stack().empty()) {
|
||||||
|
g_IEngine->ExecuteClientCmd(hack::command_stack().top().c_str());
|
||||||
|
hack::command_stack().pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PROF_SECTION(PaintTraverse);
|
PROF_SECTION(PaintTraverse);
|
||||||
if (vp == panel_top) draw_flag = true;
|
if (vp == panel_top) draw_flag = true;
|
||||||
if (!cathook) return;
|
if (!cathook) return;
|
||||||
// Because of single-multi thread shit I'm gonna put this thing riiiight here.
|
|
||||||
|
|
||||||
if (!panel_top) {
|
if (!panel_top) {
|
||||||
const char* name = g_IPanel->GetName(vp);
|
const char* name = g_IPanel->GetName(vp);
|
||||||
|
48
src/ipc.cpp
48
src/ipc.cpp
@ -8,31 +8,69 @@
|
|||||||
#include "ipc.h"
|
#include "ipc.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "hack.h"
|
||||||
|
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
|
|
||||||
void CommandCallback(cat_ipc::command_s& command, void* payload) {
|
void CommandCallback(cat_ipc::command_s& command, void* payload) {
|
||||||
if (!strcmp("exec", (const char*)command.cmd_data) && payload) {
|
if (!strcmp("exec", (const char*)command.cmd_data) && payload) {
|
||||||
|
std::lock_guard<std::mutex> lock(hack::command_stack_mutex);
|
||||||
hack::command_stack().push(std::string((const char*)payload));
|
hack::command_stack().push(std::string((const char*)payload));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::atomic<bool> 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", []() {
|
CatCommand connect("ipc_connect", "Connect to IPC server", []() {
|
||||||
if (peer) {
|
if (peer || thread_running) {
|
||||||
logging::Info("Already connected!");
|
logging::Info("Already connected!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
peer = new peer_t(std::string(server_name.GetString()), false, false);
|
peer = new peer_t("cathook_followbot_server", false, false);
|
||||||
peer->Connect();
|
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);
|
peer->SetCallback(CommandCallback);
|
||||||
StoreClientData();
|
StoreClientData();
|
||||||
|
thread_running = true;
|
||||||
|
pthread_create(&listener_thread, nullptr, listen, nullptr);
|
||||||
});
|
});
|
||||||
CatCommand disconnect("ipc_disconnect", "Disconnect from IPC server", []() {
|
CatCommand disconnect("ipc_disconnect", "Disconnect from IPC server", []() {
|
||||||
|
thread_running = false;
|
||||||
|
pthread_join(listener_thread, nullptr);
|
||||||
if (peer) delete peer;
|
if (peer) delete peer;
|
||||||
|
listener_thread = 0;
|
||||||
peer = nullptr;
|
peer = nullptr;
|
||||||
});
|
});
|
||||||
CatCommand exec("ipc_exec", "Execute command (first argument = bot ID)", [](const CCommand& args) {
|
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());
|
std::string command = std::string(args.ArgS());
|
||||||
command = command.substr(command.find(' ', 0) + 1);
|
command = command.substr(command.find(' ', 0) + 1);
|
||||||
peer->SendMessage("exec", (1 << target_id), command.c_str(), command.length() + 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) {
|
CatCommand exec_all("ipc_exec_all", "Execute command (on every peer)", [](const CCommand& args) {
|
||||||
peer->SendMessage("exec", 0, args.ArgS(), strlen(args.ArgS()) + 1);
|
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 };
|
peer_t* peer { nullptr };
|
||||||
|
|
||||||
void StoreClientData() {
|
void StoreClientData() {
|
||||||
peer_t::MutexLock lock;
|
peer_t::MutexLock lock(peer);
|
||||||
user_data_s& data = peer->memory->peer_user_data[peer->client_id];
|
user_data_s& data = peer->memory->peer_user_data[peer->client_id];
|
||||||
data.friendid = g_ISteamUser->GetSteamID().GetAccountID();
|
data.friendid = g_ISteamUser->GetSteamID().GetAccountID();
|
||||||
strncpy(data.name, g_ISteamFriends->GetPersonaName(), sizeof(data.name));
|
strncpy(data.name, g_ISteamFriends->GetPersonaName(), sizeof(data.name));
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#define IPC_H_
|
#define IPC_H_
|
||||||
|
|
||||||
#include "ipcb.hpp"
|
#include "ipcb.hpp"
|
||||||
|
#include "pthread.h"
|
||||||
|
|
||||||
class CatCommand;
|
class CatCommand;
|
||||||
class CatVar;
|
class CatVar;
|
||||||
@ -21,10 +22,11 @@ extern CatCommand exec;
|
|||||||
extern CatCommand exec_all;
|
extern CatCommand exec_all;
|
||||||
extern CatVar server_name;
|
extern CatVar server_name;
|
||||||
|
|
||||||
using peer_t = cat_ipc::Peer<server_data_s, user_data_s>;
|
extern pthread_t listener_thread;
|
||||||
|
constexpr unsigned cathook_magic_number = 0x0DEADCA7;
|
||||||
|
|
||||||
struct server_data_s {
|
struct server_data_s {
|
||||||
bool dummy;
|
unsigned magic_number;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct user_data_s {
|
struct user_data_s {
|
||||||
@ -32,6 +34,8 @@ struct user_data_s {
|
|||||||
unsigned friendid;
|
unsigned friendid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using peer_t = cat_ipc::Peer<server_data_s, user_data_s>;
|
||||||
|
|
||||||
extern peer_t* peer;
|
extern peer_t* peer;
|
||||||
|
|
||||||
void StoreClientData();
|
void StoreClientData();
|
||||||
|
Reference in New Issue
Block a user