cat_chat_crypto 1
This commit is contained in:
parent
4b61c8ac1a
commit
ad6c1c3f05
256
src/base64.h
Normal file
256
src/base64.h
Normal file
@ -0,0 +1,256 @@
|
||||
#ifndef BASE64_H
|
||||
#define BASE64_H
|
||||
|
||||
#include <string>
|
||||
|
||||
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
|
@ -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);
|
||||
|
51
src/xb64.hpp
Normal file
51
src/xb64.hpp
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* xb64.hpp
|
||||
*
|
||||
* Created on: Jul 1, 2017
|
||||
* Author: nullifiedcat
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#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);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user