From ad6c1c3f05983e650d12153d9e30db88a1d5dd7d Mon Sep 17 00:00:00 2001 From: nullifiedcat Date: Sat, 1 Jul 2017 18:24:48 +0300 Subject: [PATCH] cat_chat_crypto 1 --- src/base64.h | 256 +++++++++++++++++++++++++++++++++++++++++++ src/hooks/others.cpp | 32 +++++- src/xb64.hpp | 51 +++++++++ 3 files changed, 335 insertions(+), 4 deletions(-) create mode 100644 src/base64.h create mode 100644 src/xb64.hpp diff --git a/src/base64.h b/src/base64.h new file mode 100644 index 00000000..d0e2705e --- /dev/null +++ b/src/base64.h @@ -0,0 +1,256 @@ +#ifndef BASE64_H +#define BASE64_H + +#include + +const char kBase64Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +class Base64 { + public: + static bool Encode(const std::string &in, std::string *out) { + int i = 0, j = 0; + size_t enc_len = 0; + unsigned char a3[3]; + unsigned char a4[4]; + + out->resize(EncodedLength(in)); + + int input_len = in.size(); + std::string::const_iterator input = in.begin(); + + while (input_len--) { + a3[i++] = *(input++); + if (i == 3) { + a3_to_a4(a4, a3); + + for (i = 0; i < 4; i++) { + (*out)[enc_len++] = kBase64Alphabet[a4[i]]; + } + + i = 0; + } + } + + if (i) { + for (j = i; j < 3; j++) { + a3[j] = '\0'; + } + + a3_to_a4(a4, a3); + + for (j = 0; j < i + 1; j++) { + (*out)[enc_len++] = kBase64Alphabet[a4[j]]; + } + + while ((i++ < 3)) { + (*out)[enc_len++] = '='; + } + } + + return (enc_len == out->size()); + } + + static bool Encode(const char *input, size_t input_length, char *out, size_t out_length) { + int i = 0, j = 0; + char *out_begin = out; + unsigned char a3[3]; + unsigned char a4[4]; + + size_t encoded_length = EncodedLength(input_length); + + if (out_length < encoded_length) return false; + + while (input_length--) { + a3[i++] = *input++; + if (i == 3) { + a3_to_a4(a4, a3); + + for (i = 0; i < 4; i++) { + *out++ = kBase64Alphabet[a4[i]]; + } + + i = 0; + } + } + + if (i) { + for (j = i; j < 3; j++) { + a3[j] = '\0'; + } + + a3_to_a4(a4, a3); + + for (j = 0; j < i + 1; j++) { + *out++ = kBase64Alphabet[a4[j]]; + } + + while ((i++ < 3)) { + *out++ = '='; + } + } + + return (out == (out_begin + encoded_length)); + } + + static bool Decode(const std::string &in, std::string *out) { + int i = 0, j = 0; + size_t dec_len = 0; + unsigned char a3[3]; + unsigned char a4[4]; + + int input_len = in.size(); + std::string::const_iterator input = in.begin(); + + out->resize(DecodedLength(in)); + + while (input_len--) { + if (*input == '=') { + break; + } + + a4[i++] = *(input++); + if (i == 4) { + for (i = 0; i <4; i++) { + a4[i] = b64_lookup(a4[i]); + } + + a4_to_a3(a3,a4); + + for (i = 0; i < 3; i++) { + (*out)[dec_len++] = a3[i]; + } + + i = 0; + } + } + + if (i) { + for (j = i; j < 4; j++) { + a4[j] = '\0'; + } + + for (j = 0; j < 4; j++) { + a4[j] = b64_lookup(a4[j]); + } + + a4_to_a3(a3,a4); + + for (j = 0; j < i - 1; j++) { + (*out)[dec_len++] = a3[j]; + } + } + + return (dec_len == out->size()); + } + + static bool Decode(const char *input, size_t input_length, char *out, size_t out_length) { + int i = 0, j = 0; + char *out_begin = out; + unsigned char a3[3]; + unsigned char a4[4]; + + size_t decoded_length = DecodedLength(input, input_length); + + if (out_length < decoded_length) return false; + + while (input_length--) { + if (*input == '=') { + break; + } + + a4[i++] = *(input++); + if (i == 4) { + for (i = 0; i <4; i++) { + a4[i] = b64_lookup(a4[i]); + } + + a4_to_a3(a3,a4); + + for (i = 0; i < 3; i++) { + *out++ = a3[i]; + } + + i = 0; + } + } + + if (i) { + for (j = i; j < 4; j++) { + a4[j] = '\0'; + } + + for (j = 0; j < 4; j++) { + a4[j] = b64_lookup(a4[j]); + } + + a4_to_a3(a3,a4); + + for (j = 0; j < i - 1; j++) { + *out++ = a3[j]; + } + } + + return (out == (out_begin + decoded_length)); + } + + static int DecodedLength(const char *in, size_t in_length) { + int numEq = 0; + + const char *in_end = in + in_length; + while (*--in_end == '=') ++numEq; + + return ((6 * in_length) / 8) - numEq; + } + + static int DecodedLength(const std::string &in) { + int numEq = 0; + int n = in.size(); + + for (std::string::const_reverse_iterator it = in.rbegin(); *it == '='; ++it) { + ++numEq; + } + + return ((6 * n) / 8) - numEq; + } + + inline static int EncodedLength(size_t length) { + return (length + 2 - ((length + 2) % 3)) / 3 * 4; + } + + inline static int EncodedLength(const std::string &in) { + return EncodedLength(in.length()); + } + + inline static void StripPadding(std::string *in) { + while (!in->empty() && *(in->rbegin()) == '=') in->resize(in->size() - 1); + } + + private: + static inline void a3_to_a4(unsigned char * a4, unsigned char * a3) { + a4[0] = (a3[0] & 0xfc) >> 2; + a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4); + a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6); + a4[3] = (a3[2] & 0x3f); + } + + static inline void a4_to_a3(unsigned char * a3, unsigned char * a4) { + a3[0] = (a4[0] << 2) + ((a4[1] & 0x30) >> 4); + a3[1] = ((a4[1] & 0xf) << 4) + ((a4[2] & 0x3c) >> 2); + a3[2] = ((a4[2] & 0x3) << 6) + a4[3]; + } + + static inline unsigned char b64_lookup(unsigned char c) { + if(c >='A' && c <='Z') return c - 'A'; + if(c >='a' && c <='z') return c - 71; + if(c >='0' && c <='9') return c + 4; + if(c == '+') return 62; + if(c == '/') return 63; + return 255; + } +}; + + + +#endif // BASE64_H diff --git a/src/hooks/others.cpp b/src/hooks/others.cpp index bf4d7fc1..e8bca0cc 100644 --- a/src/hooks/others.cpp +++ b/src/hooks/others.cpp @@ -8,6 +8,7 @@ #include "../common.h" #include "../netmessage.h" #include "../hack.h" +#include "../xb64.hpp" #include "hookedmethods.h" static CatVar no_invisibility(CV_SWITCH, "no_invis", "0", "Remove Invisibility", "Useful with chams!"); @@ -127,6 +128,7 @@ static CatVar newlines_msg(CV_INT, "chat_newlines", "0", "Prefix newlines", "Add //static CatVar queue_messages(CV_SWITCH, "chat_queue", "0", "Queue messages", "Use this if you want to use spam/killsay and still be able to chat normally (without having your msgs eaten by valve cooldown)"); static CatVar airstuck(CV_KEY, "airstuck", "0", "Airstuck"); +static CatVar crypt_chat(CV_SWITCH, "chat_crypto", "0", "Crypto chat", "Start message with !! and it will be only visible to cathook users"); bool SendNetMsg_hook(void* _this, INetMessage& msg, bool bForceReliable = false, bool bVoice = false) { static size_t say_idx, say_team_idx; @@ -138,13 +140,23 @@ bool SendNetMsg_hook(void* _this, INetMessage& msg, bool bForceReliable = false, const SendNetMsg_t original = (SendNetMsg_t)hooks::netchannel.GetMethod(offsets::SendNetMsg()); SEGV_BEGIN; // net_StringCmd - if (msg.GetType() == 4 && (newlines_msg)) { + if (msg.GetType() == 4 && (newlines_msg || crypt_chat)) { std::string str(msg.ToString()); say_idx = str.find("net_StringCmd: \"say \""); say_team_idx = str.find("net_StringCmd: \"say_team \""); if (!say_idx || !say_team_idx) { offset = say_idx ? 26 : 21; - if (newlines_msg) { + bool crpt = false; + if (crypt_chat) { + std::string msg(str.substr(offset)); + msg = msg.substr(0, msg.length() - 2); + if (msg.find("!!") == 0) { + msg = "!!" + xb64::encrypt(msg.substr(2)); + str = str.substr(0, offset) + msg + "\"\""; + crpt = true; + } + } + if (!crpt && newlines_msg) { // TODO move out? update in a value change callback? newlines = std::string((int)newlines_msg, '\n'); str.insert(offset, newlines); @@ -315,7 +327,7 @@ bool DispatchUserMessage_hook(void* _this, int type, bf_read& buf) { static const DispatchUserMessage_t original = (DispatchUserMessage_t)hooks::client.GetMethod(offsets::DispatchUserMessage()); SEGV_BEGIN; - if (clean_chat) { + if (clean_chat || crypt_chat) { if (type == 4) { loop_index = 0; s = buf.GetNumBytesLeft(); @@ -324,10 +336,22 @@ bool DispatchUserMessage_hook(void* _this, int type, bf_read& buf) { for (i = 0; i < s; i++) data[i] = buf.ReadByte(); j = 0; + std::string name; + std::string message; for (i = 0; i < 3; i++) { while ((c = data[j++]) && (loop_index < 128)) { loop_index++; - if ((c == '\n' || c == '\r') && (i == 1 || i == 2)) data[j - 1] = '*'; + if (clean_chat) + if ((c == '\n' || c == '\r') && (i == 1 || i == 2)) data[j - 1] = '*'; + if (i == 1) name.push_back(c); + if (i == 2) message.push_back(c); + } + } + if (crypt_chat) { + if (message.find("!!") == 0) { + if (xb64::validate(message.substr(2))) { + PrintChat("\x07%06X%s\x01: %s", 0xe05938, name.c_str(), xb64::decrypt(message.substr(2)).c_str()); + } } } buf = bf_read(data, s); diff --git a/src/xb64.hpp b/src/xb64.hpp new file mode 100644 index 00000000..464101e9 --- /dev/null +++ b/src/xb64.hpp @@ -0,0 +1,51 @@ +/* + * xb64.hpp + * + * Created on: Jul 1, 2017 + * Author: nullifiedcat + */ + +#pragma once + +#include +#include "base64.h" + +namespace xb64 { + +std::string crappy_checksum(const std::string& in) { + int s = 0, ss = 0; + for (int i = 0; i < in.length(); i += 2) { + s += (int)in[i]; + if (i < in.length() - 1) + ss += (int)in[i + 1] * (int)in[i + 1]; + } + return { kBase64Alphabet[s % 64], kBase64Alphabet[ss % 64] }; +} + +std::string crappy_xorstring(const std::string& in) { + std::string out; + for (int i = 0; i < in.length(); i++) { + // 696969th prime, 13371337th prime + out.push_back(in[i] ^ ((10522103 * in.length()) + i * 244053389 % 256)); + } + return out; +} + +bool validate(const std::string& in) { + if (in.length() < 2) return false; + return crappy_checksum(in.substr(0, in.length() - 2)) == in.substr(in.length() - 2); +} + +std::string decrypt(const std::string& in) { + std::string b64; + Base64::Decode(in.substr(0, in.length() - 2), &b64); + return crappy_xorstring(b64); +} + +std::string encrypt(const std::string& in) { + std::string b64; + Base64::Encode(crappy_xorstring(in), &b64); + return b64 + crappy_checksum(b64); +} + +}