From 45c18bf60968146384a43882d10c856e749dd09a Mon Sep 17 00:00:00 2001 From: TotallyNotElite <1yourexperiment@protonmail.com> Date: Thu, 6 Dec 2018 18:50:02 +0100 Subject: [PATCH] Revert "IRC removed" This reverts commit a536e90c1db168a399a2eadfe580ed56ce6214dc. --- include/CMakeLists.txt | 1 + include/irc.hpp | 7 + src/CMakeLists.txt | 1 + src/hooks/CreateMove.cpp | 2 + src/hooks/DispatchUserMessage.cpp | 86 +++++- src/hooks/SendNetMsg.cpp | 2 + src/irc.cpp | 469 ++++++++++++++++++++++++++++++ 7 files changed, 560 insertions(+), 8 deletions(-) create mode 100644 include/irc.hpp create mode 100644 src/irc.cpp diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index f7d4793d..5f589e8a 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -20,6 +20,7 @@ target_sources(cathook PRIVATE "${CMAKE_CURRENT_LIST_DIR}/hoovy.hpp" "${CMAKE_CURRENT_LIST_DIR}/init.hpp" "${CMAKE_CURRENT_LIST_DIR}/ipc.hpp" + "${CMAKE_CURRENT_LIST_DIR}/irc.hpp" "${CMAKE_CURRENT_LIST_DIR}/itemtypes.hpp" "${CMAKE_CURRENT_LIST_DIR}/json.hpp" "${CMAKE_CURRENT_LIST_DIR}/localplayer.hpp" diff --git a/include/irc.hpp b/include/irc.hpp new file mode 100644 index 00000000..59dbc458 --- /dev/null +++ b/include/irc.hpp @@ -0,0 +1,7 @@ +#include + +namespace IRC +{ +bool sendmsg(std::string &msg, bool loopback = false); +void auth(bool reply = false); +} // namespace IRC diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 08b5b548..80250000 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,6 +32,7 @@ target_sources(cathook PRIVATE "${CMAKE_CURRENT_LIST_DIR}/MiscTemporary.cpp" "${CMAKE_CURRENT_LIST_DIR}/navparser.cpp" "${CMAKE_CURRENT_LIST_DIR}/Options.cpp" + "${CMAKE_CURRENT_LIST_DIR}/irc.cpp" "${CMAKE_CURRENT_LIST_DIR}/PlayerTools.cpp") add_subdirectory(core) diff --git a/src/hooks/CreateMove.cpp b/src/hooks/CreateMove.cpp index 533b39bd..f8d69d90 100644 --- a/src/hooks/CreateMove.cpp +++ b/src/hooks/CreateMove.cpp @@ -15,6 +15,7 @@ #include #include "NavBot.hpp" #include "HookTools.hpp" +#include "irc.hpp" #include "HookedMethods.hpp" #include "PreDataUpdate.hpp" @@ -302,6 +303,7 @@ DEFINE_HOOKED_METHOD(CreateMove, bool, void *this_, float input_sample_time, // hacks::tf2::NavBot::Init(); // hacks::tf2::NavBot::initonce(); nav::status = nav::off; + IRC::auth(); hacks::tf2::NavBot::init(true); firstcm = false; } diff --git a/src/hooks/DispatchUserMessage.cpp b/src/hooks/DispatchUserMessage.cpp index 942f9503..63df1a73 100644 --- a/src/hooks/DispatchUserMessage.cpp +++ b/src/hooks/DispatchUserMessage.cpp @@ -197,19 +197,89 @@ DEFINE_HOOKED_METHOD(DispatchUserMessage, bool, void *this_, int type, gitgud.update(); break; } - } - if (crypt_chat && message.find("!!B") == 0 && ucccccp::validate(message)) - { - std::string msg = ucccccp::decrypt(message); + + std::vector res = { + "skid", "script", "cheat", "hak", "hac", "f1", + "hax", "vac", "ban", "lmao", "bot", "report", + "cat", "insta", "revv", "brass", "kick", claz + }; + name2 = SplitName(name1, 2); + for (auto i : name2) + res.push_back(i); + name2 = SplitName(name1, 3); + for (auto i : name2) + res.push_back(i); + std::string message2 = message; + std::vector toreplace{ " ", "4", "3", "0", + "6", "5", "7" }; + std::vector replacewith{ "", "a", "e", "o", + "g", "s", "t" }; + boost::to_lower(message2); + + for (int i = 0; i < toreplace.size(); i++) + boost::replace_all(message2, toreplace[i], replacewith[i]); + bool filtered = false; + for (auto filter : res) + if (boost::contains(message2, filter) && !filtered) + { + filtered = true; + chat_stack::Say("." + clear, true); + retrun = true; + lastfilter = message; + lastname = format(name); + gitgud.update(); + } + } #if !LAGBOT_MODE - CachedEntity *ent = ENTITY(data[0]); - if (msg != "Attempt at ucccccping and failing" && - msg != "Unsupported version" && ent != LOCAL_E) + if (*identify && sendmsg.test_and_set(300000)) + chat_stack::Say("!!meow"); +#endif + if (crypt_chat) { auto &state = playerlist::AccessData(ent).state; if (state == playerlist::k_EState::DEFAULT) { - state = playerlist::k_EState::CAT; + if (ucccccp::validate(message)) + { + std::string msg = ucccccp::decrypt(message); +#if !LAGBOT_MODE + // if (ucccccp::decrypt(message) + // == "meow" && + // hacks::shared::antiaim::communicate + // && data[0] != + // LOCAL_E->m_IDX && + // playerlist::AccessData(ENTITY(data[0])).state + // != + // playerlist::k_EState::CAT) + // { + // playerlist::AccessData(ENTITY(data[0])).state + // = + // playerlist::k_EState::CAT; + // chat_stack::Say("!!meow"); + // } + CachedEntity *ent = ENTITY(cleaned_data[0]); + if (msg != "Attempt at ucccccping and failing" && + msg != "Unsupported version" && ent != LOCAL_E) + { + auto &state = playerlist::AccessData(ent).state; + if (state == playerlist::k_EState::DEFAULT) + { + state = playerlist::k_EState::CAT; + if (*answerIdentify && + sendmsg.test_and_set(5000)) + chat_stack::Say("!!meow"); + } + else if (state == playerlist::k_EState::CAT) + { + if (*answerIdentify && + sendmsg.test_and_set(60000)) + chat_stack::Say("!!meow"); + } + } +#endif + PrintChat("\x07%06X%s\x01: %s", 0xe05938, name.c_str(), + msg.c_str()); + } } } #endif diff --git a/src/hooks/SendNetMsg.cpp b/src/hooks/SendNetMsg.cpp index ecba2b56..9d1aa061 100644 --- a/src/hooks/SendNetMsg.cpp +++ b/src/hooks/SendNetMsg.cpp @@ -8,6 +8,7 @@ #include #include "HookedMethods.hpp" #include +#include "irc.hpp" static settings::Int newlines_msg{ "chat.prefix-newlines", "0" }; static settings::Bool log_sent{ "debug.log-sent-chat", "false" }; @@ -48,6 +49,7 @@ DEFINE_HOOKED_METHOD(SendNetMsg, bool, INetChannel *this_, INetMessage &msg, if (msg.find("!!!") == 0) sub_val = 3; std::string substrmsg(msg.substr(sub_val)); + IRC::sendmsg(substrmsg, true); // Do not send message over normal chat. return false; } diff --git a/src/irc.cpp b/src/irc.cpp new file mode 100644 index 00000000..805928e7 --- /dev/null +++ b/src/irc.cpp @@ -0,0 +1,469 @@ +#include "common.hpp" +#include "irc.hpp" +#include "CatBot.hpp" +#include "ChIRC.hpp" +#include "hack.hpp" +#include "ucccccp.hpp" + +namespace IRC +{ +static settings::Bool enabled("irc.enabled", "true"); +static settings::Bool anon("irc.anon", "true"); +static settings::Bool authenticate("irc.auth", "true"); +static settings::String channel("irc.channel", "#cat_comms"); +static settings::String address("irc.address", "cathook.irc.inkcat.net"); +static settings::Int port("irc.port", "8080"); +static settings::String commandandcontrol_channel("irc.cc.channel", ""); +static settings::String commandandcontrol_password("irc.cc.password", ""); + +static settings::Bool botonly("irc.cc.command-bot-only", "true"); +static settings::Bool irc_party{ "irc.cc.party", "false" }; +static settings::Bool answer_steam{ "irc.cc.respondparty", "false" }; +static settings::Int party_cooldown{ "irc.cc.party-cooldown", "60" }; +static settings::Int party_size{ "irc.cc.party-size", "6" }; +static Timer last_sent_steamid{}; +static Timer last_steamid_received{}; +static std::vector steamidvec{}; + +static ChIRC::ChIRC irc; + +void printmsg(std::string &usr, std::string &msg) +{ + if (msg.size() > 256 || usr.size() > 256) + { + logging::Info("IRC: Message too large."); + return; + } + if (g_Settings.bInvalid) + logging::Info("[IRC] %s: %s", usr.c_str(), msg.c_str()); + else + PrintChat("\x07%06X[IRC] %s\x01: %s", 0xe05938, usr.c_str(), + msg.c_str()); +} +void printmsgcopy(std::string usr, std::string msg) +{ + printmsg(usr, msg); +} + +namespace handlers +{ +void message(std::string &usr, std::string &msg) +{ + std::string toprint = msg.substr(3); + if (toprint.empty()) + return; + printmsg(usr, toprint); +} +void authreq(std::string &msg) +{ + // Check if we are in a game + if (g_Settings.bInvalid) + return; + bool isreply = false; + + if (msg.find("authrep") == 0) + isreply = true; + + // Get steamid hash from string + std::string steamidhash; + if (isreply) + steamidhash = msg.substr(7); + else + steamidhash = msg.substr(4); + + for (int i = 0; i < g_IEngine->GetMaxClients(); i++) + { + if (i == g_pLocalPlayer->entity_idx) + continue; + player_info_s pinfo; + // Get playerinfo and check if player on server + if (!g_IEngine->GetPlayerInfo(i, &pinfo)) + continue; + auto tarsteamid = pinfo.friendsID; + std::string total_hash = std::to_string(tarsteamid) + pinfo.name; + MD5Value_t result; + // Hash steamid + MD5_ProcessSingleBuffer(total_hash.c_str(), strlen(total_hash.c_str()), + result); + // Get bits of hash and store in string + std::string tarhash; + for (auto i : result.bits) + { + for (int j = 0; j < 8; j++) + tarhash.append(std::to_string((i >> j) & 1)); + } + // Check if steamid of sender == steamid we currently check + // (using hashes) + if (tarhash == steamidhash) + { + // Use actual steamid to set cat status + auto &playerlistdata = playerlist::AccessData(tarsteamid); + if (playerlistdata.state == playerlist::k_EState::DEFAULT) + { + playerlistdata.state = playerlist::k_EState::CAT; + } + // Avoid replying to a reply + if (isreply) + // We are done here. Steamid duplicates don't exist. + return; + // If message is not a reply, reply. + auth(true); + // We are done here. Steamid duplicates don't exist. + return; + } + } +} +void cc_party(std::string &msg) +{ + static uintptr_t addr = gSignatures.GetClientSignature( + "55 89 E5 57 56 53 83 EC ? 8B 7D ? 8B 77 ? 85 F6 0F 84"); + typedef int (*GetNumOnlineMembers_t)(re::CTFPartyClient *); + auto GetNumOnlineMembers_fn = GetNumOnlineMembers_t(addr); + auto party_client = re::CTFPartyClient::GTFPartyClient(); + int online_members = GetNumOnlineMembers_fn(party_client); + if (msg.find("cc_partysteamrep") == 0 && online_members < *party_size && + online_members != 6) + { + if (!irc_party) + return; + unsigned steamid; + try + { + steamid = std::stoul(msg.substr(16)); + } + catch (std::invalid_argument) + { + return; + } + steamidvec.push_back(steamid); + last_steamid_received.update(); + } + else if (answer_steam && msg.find("cc_partysteam") == 0 && + online_members < *party_size && online_members != 6) + { + irc.privmsg(format("cc_partysteamrep", + g_ISteamUser->GetSteamID().GetAccountID()), + true); + } +} +void cc_cmd(std::string &msg) +{ + if (!hacks::shared::catbot::catbotmode && botonly) + return; + // Outdated cc_cmd. Return + if (msg.find("$cmd") == msg.npos) + return; + // Command applys to all bots + if (msg.find("$id") == msg.npos) + { + // Todo: Remove debug + std::cout << msg.substr(msg.find("$cmd") + 4) << std::endl; + hack::ExecuteCommand(msg.substr(msg.find("$cmd") + 4)); + } + else + { + std::string string_id = msg.substr( + msg.find("$id") + 3, msg.find("$cmd") - (msg.find("$id") + 3)); + int id; + // Todo: Remove debug + std::cout << "id:" << string_id << std::endl; + try + { + id = std::stoi(string_id); + } + catch (std::invalid_argument) + { + // id is not int??? + return; + } + if (id == irc.getData().id) + { + // Thats me! + std::cout << msg.substr(msg.find("$cmd") + 4) << std::endl; + hack::ExecuteCommand(msg.substr(msg.find("$cmd") + 4)); + } + } +} +} // namespace handlers + +void handleIRC(IRCMessage message, IRCClient *client) +{ + std::string &cmd = message.command; + try + { + message.parameters.at(0); + message.parameters.at(1); + } + catch (std::out_of_range) + { + logging::Info("Something is out of range"); + return; + } + std::string &channel = message.parameters.at(0); + std::string &rawmsg = message.parameters.at(1); + std::string &usr = message.prefix.nick; + if (!ucccccp::validate(rawmsg)) + return; + std::string msg(ucccccp::decrypt(rawmsg)); + if (msg == "Attempt at ucccccping and failing" || + msg == "Unsupported version") + return; + + // Handle privmsg (Message to #channel) + if (cmd == "PRIVMSG") + { + if (msg.empty() || usr.empty()) + return; + // Handle public messages + if (channel == irc.getData().comms_channel) + { + // Handle messages + if (msg.find("msg") == 0) + { + handlers::message(usr, msg); + return; + } + // Handle auth requests + else if (msg.find("auth") == 0) + { + handlers::authreq(msg); + } + } + else if (channel == irc.getData().commandandcontrol_channel) + { + if (msg.find("cc_cmd") == 0) + { + handlers::cc_cmd(msg); + } + if (msg.find("cc_party") == 0) + { + handlers::cc_party(msg); + } + } + } +} + +void updateData() +{ + std::string nick("Anon"); + if (!*anon) + nick = g_ISteamFriends->GetPersonaName(); + irc.UpdateData(nick, nick, *channel, *commandandcontrol_channel, + *commandandcontrol_password, *address, *port, + *hacks::shared::catbot::catbotmode); +} + +bool sendmsg(std::string &msg, bool loopback) +{ + std::string raw = "msg" + msg; + if (irc.privmsg(raw)) + { + if (loopback) + { + printmsgcopy(irc.getData().nick, msg); + } + return true; + } + if (loopback) + printmsgcopy("Cathook", "Error! Couldn't send message."); + return false; +} + +void auth(bool reply) +{ + if (g_Settings.bInvalid && !g_Settings.is_create_move) + return; + if (!*authenticate) + return; + MD5Value_t result; + player_info_s pinfo{}; + if (!g_IEngine->GetPlayerInfo(LOCAL_E->m_IDX, &pinfo)) + return; + std::string total_hash = std::to_string(pinfo.friendsID) + pinfo.name; + MD5_ProcessSingleBuffer(total_hash.c_str(), strlen(total_hash.c_str()), + result); + std::string msg("auth"); + if (reply) + msg.append("rep"); + for (auto i : result.bits) + { + for (int j = 0; j < 8; j++) + msg.append(std::to_string((i >> j) & 1)); + } + irc.privmsg(msg); +} + +static bool restarting{ false }; + +Timer calledonce{}; +Timer ircstate{}; +int GetMaxParty() +{ + int partyable = 1; + auto peers = irc.getPeers(); + for (auto peer : peers) + { + if (peer.second.party_size != -1) + partyable++; + } + return partyable; +} +CatCommand debug_maxparty("debug_partysize", "Debug party size", + []() { logging::Info("%d", GetMaxParty()); }); + +static Timer resize_party{}; +static HookedFunction paint(HookedFunctions_types::HF_Paint, "IRC", 16, []() { + if (!restarting) + { + static const uintptr_t addr = gSignatures.GetClientSignature( + "55 89 E5 57 56 53 83 EC ? 8B 7D ? 8B 77 ? 85 F6 0F 84"); + typedef int (*GetNumOnlineMembers_t)(re::CTFPartyClient *); + static const auto GetNumOnlineMembers_fn = GetNumOnlineMembers_t(addr); + auto party_client = re::CTFPartyClient::GTFPartyClient(); + int online_members = GetNumOnlineMembers_fn(party_client); + + if (resize_party.test_and_set(10000) && party_client && + online_members > *party_size) + { + int lowest_id = INT_MAX; + for (auto peer : irc.getPeers()) + { + int id = peer.first; + int party_size = peer.second.party_size; + if (party_size != online_members) + continue; + if (id < lowest_id) + lowest_id = id; + } + if (irc.getData().id < lowest_id) + hack::command_stack().push("tf_party_leave"); + } + if (last_sent_steamid.check(8000) && calledonce.test_and_set(2000) && + online_members < *party_size) + { + if (!steamidvec.empty() && party_client && online_members != 6 && + online_members < GetMaxParty()) + { + steamidvec.push_back(g_ISteamUser->GetSteamID().GetAccountID()); + int idx = -1; + unsigned lowest = UINT_MAX; + for (int i = 0; i < steamidvec.size(); i++) + if (steamidvec[i] < lowest) + { + lowest = steamidvec[i]; + idx = i; + } + if (idx != -1 && steamidvec[idx] != + g_ISteamUser->GetSteamID().GetAccountID()) + hack::command_stack().push("tf_party_leave"); + } + } + if (last_steamid_received.test_and_set(10000) && + online_members < *party_size) + { + if (party_client && online_members != 6 && + online_members < GetMaxParty()) + if (!steamidvec.empty()) + { + steamidvec.push_back( + g_ISteamUser->GetSteamID().GetAccountID()); + int idx = -1; + unsigned lowest = UINT_MAX; + for (int i = 0; i < steamidvec.size(); i++) + if (steamidvec[i] < lowest) + { + lowest = steamidvec[i]; + idx = i; + } + if (idx != -1 && + steamidvec[idx] != + g_ISteamUser->GetSteamID().GetAccountID()) + hack::command_stack().push(format( + "tf_party_request_join_user ", steamidvec[idx])); + steamidvec.clear(); + } + } + if (irc_party && + last_sent_steamid.test_and_set(*party_cooldown * 1000) && + online_members < *party_size && online_members != 6) + irc.privmsg(format("cc_partysteam", + g_ISteamUser->GetSteamID().GetAccountID()), + true); + irc.Update(); + if (ircstate.test_and_set(20000)) + { + ChIRC::GameState state; + int size; + if (irc_party && answer_steam) + size = online_members; + else + size = -1; + state.party_size = size; + irc.setState(state); + } + } +}); + +template void rvarCallback(settings::VariableBase &var, T after) +{ + if (!restarting) + { + restarting = true; + std::thread reload([]() { + std::this_thread::sleep_for( + std::chrono_literals::operator""ms(500)); + irc.Disconnect(); + updateData(); + if (enabled) + irc.Connect(); + restarting = false; + }); + reload.detach(); + } +} + +static InitRoutine init([]() { + updateData(); + enabled.installChangeCallback(rvarCallback); + anon.installChangeCallback(rvarCallback); + authenticate.installChangeCallback(rvarCallback); + channel.installChangeCallback(rvarCallback); + address.installChangeCallback(rvarCallback); + port.installChangeCallback(rvarCallback); + commandandcontrol_channel.installChangeCallback(rvarCallback); + commandandcontrol_password.installChangeCallback(rvarCallback); + + irc.installCallback("PRIVMSG", handleIRC); + irc.Connect(); +}); + +static CatCommand irc_send_cmd("irc_send_cmd", "Send cmd to IRC", + [](const CCommand &args) { + irc.sendraw(args.ArgS()); + }); +static CatCommand irc_exec_all("irc_exec_all", "Send command to C&C channel", + [](const CCommand &args) { + std::string msg("cc_cmd$cmd"); + msg.append(args.ArgS()); + irc.privmsg(msg, true); + }); + +static CatCommand invite_all( + "irc_invite_all", "Inivte all people in C&C channel", + [](const CCommand &args) { + std::string msg("cc_cmd$cmdtf_party_request_join_user "); + msg.append(std::to_string(g_ISteamUser->GetSteamID().GetAccountID())); + irc.privmsg(msg, true); + }); + +static CatCommand irc_send("irc_send", "Send message to IRC", + [](const CCommand &args) { + std::string msg(args.ArgS()); + sendmsg(msg, true); + }); + +static CatCommand irc_auth("irc_auth", + "Auth via IRC (Find users on same server)", + []() { auth(); }); + +} // namespace IRC