diff --git a/cheat-base/src/cheat-base/util.h b/cheat-base/src/cheat-base/util.h index d3cf0eb..aa09c1b 100644 --- a/cheat-base/src/cheat-base/util.h +++ b/cheat-base/src/cheat-base/util.h @@ -66,17 +66,39 @@ namespace util } template - static T ReadMapped(void* data, int offset, bool littleEndian = false) + static T ReadMapped(void* data, int offset, bool is_little_endian = false) { - char* cData = (char*)data; - T result = {}; - if (IsLittleEndian() != littleEndian) + T value; // No need to initialize, because we will fill it later + constexpr size_t value_size = sizeof(T); + auto ptr_src = reinterpret_cast(data) + offset; + auto ptr_value = reinterpret_cast(&value); + + if (IsLittleEndian() == is_little_endian) { - for (int i = 0; i < sizeof(T); i++) - ((char*)&result)[i] = cData[offset + sizeof(T) - i - 1]; - return result; + memcpy_s(ptr_value, value_size, ptr_src, value_size); + return value; } - memcpy_s(&result, sizeof(result), cData + offset, sizeof(result)); - return result; + + for (size_t i = 0; i < value_size; i++) + ptr_value[i] = ptr_src[value_size - i - 1]; + + return value; + } + + template + static void WriteMapped(void* data, int offset, const T& value, bool is_little_endian = false) + { + constexpr size_t value_size = sizeof(T); + auto ptr_dest = reinterpret_cast(data) + offset; + auto ptr_value = reinterpret_cast(&value); + + if (IsLittleEndian() == is_little_endian) + { + memcpy_s(ptr_dest, value_size, ptr_value, value_size); + return; + } + + for (size_t i = 0; i < value_size; i++) + ptr_dest[i] = ptr_value[value_size - i - 1]; } } diff --git a/cheat-library/src/appdata/il2cpp-functions.h b/cheat-library/src/appdata/il2cpp-functions.h index acd5423..93995be 100644 --- a/cheat-library/src/appdata/il2cpp-functions.h +++ b/cheat-library/src/appdata/il2cpp-functions.h @@ -86,6 +86,8 @@ DO_APP_FUNC(0x066218D0, Byte__Array*, Application_RecordUserData, (int32_t nType // Networking +DO_APP_FUNC(0x01251620, void, Kcp_KcpNative_kcp_packet_destroy, (KcpPacket_1* packet, MethodInfo* method)); +DO_APP_FUNC(0x01251820, KcpPacket_1*, Kcp_KcpNative_kcp_packet_create, (uint8_t* data, int32_t len, MethodInfo* method)); DO_APP_FUNC(0x012519C0, int32_t, Kcp_KcpNative_kcp_client_send_packet, (void* kcp_client, KcpPacket_1* packet, MethodInfo* method)); DO_APP_FUNC(0x00BD08A0, bool, MoleMole_KcpClient_TryDequeueEvent, (void* __this, ClientKcpEvent* evt, MethodInfo* method)); DO_APP_FUNC(0x029C3D60, void, MoleMole_Packet_XorEncrypt, (Byte__Array** bytes, int32_t length, MethodInfo* method)); diff --git a/cheat-library/src/user/cheat/misc/sniffer/PacketSniffer.cpp b/cheat-library/src/user/cheat/misc/sniffer/PacketSniffer.cpp index c8f1771..040f694 100644 --- a/cheat-library/src/user/cheat/misc/sniffer/PacketSniffer.cpp +++ b/cheat-library/src/user/cheat/misc/sniffer/PacketSniffer.cpp @@ -42,22 +42,48 @@ namespace cheat::feature return instance; } - bool ProcessModifiedData(app::KcpPacket_1* packet) + bool PacketSniffer::ProcessModifiedData(app::KcpPacket_1* packet) { - auto modifyData = sniffer::MessageManager::WaitFor(); - if (!modifyData) + auto modify_data = sniffer::MessageManager::WaitFor(); + if (!modify_data) return false; - switch (modifyData->modifyType) + switch (modify_data->modify_type) { case PacketModifyType::Blocked: return true; + case PacketModifyType::Modified: { - auto dataSize = modifyData->modifiedData.size(); - packet->data = new byte[dataSize](); - memcpy_s(packet->data, dataSize, modifyData->modifiedData.data(), dataSize); - packet->dataLen = static_cast(dataSize); + auto data_size = modify_data->modified_head.size() + modify_data->modified_message.size() + 12; + char* data = new char[data_size]; + + auto head_size = static_cast(modify_data->modified_head.size()); + auto message_size = static_cast(modify_data->modified_message.size()); + + util::WriteMapped(data, 0, static_cast(0x4567)); // Magic number + util::WriteMapped(data, 2, modify_data->message_id); // Message id + util::WriteMapped(data, 4, head_size); // Head size + util::WriteMapped(data, 6, message_size); // Message size + + // Fill content + char* ptr_head_content = data + 10; + memcpy_s(ptr_head_content, head_size, modify_data->modified_head.data(), head_size); + + char* ptr_message_content = ptr_head_content + modify_data->modified_head.size(); + memcpy_s(ptr_message_content, message_size, modify_data->modified_message.data(), message_size); + + util::WriteMapped(ptr_message_content, message_size, static_cast(0x89AB)); + + EncryptXor(data, data_size); + + // Can be memory leak. + auto new_packet = app::Kcp_KcpNative_kcp_packet_create(reinterpret_cast(data), static_cast(data_size), nullptr); + delete[] data; + + // Will be deleted by KcpNative_kcp_client_network_thread + // app::Kcp_KcpNative_kcp_packet_destroy(packet, nullptr); + packet = new_packet; } break; case PacketModifyType::Unchanged: @@ -88,26 +114,36 @@ namespace cheat::feature return !canceled; } - char* PacketSniffer::EncryptXor(void* content, uint32_t length) + void PacketSniffer::EncryptXor(void* content, uint32_t length) { - app::Byte__Array* byteArray = (app::Byte__Array*)new char[length + 0x20]; + auto byteArray = reinterpret_cast(new char[length + 0x20]); byteArray->max_length = length; memcpy_s(byteArray->vector, length, content, length); app::MoleMole_Packet_XorEncrypt(&byteArray, length, nullptr); - auto result = new char[length]; - memcpy_s(result, length, byteArray->vector, length); + memcpy_s(content, length, byteArray->vector, length); delete[] byteArray; - - return (char*)result; } PacketData PacketSniffer::ParseRawPacketData(char* encryptedData, uint32_t length) { + // Packet structure + // * Magic word (0x4567) [2 bytes] + // * message_id [2 bytes] + // * head_size [2 bytes] + // * message_size [4 bytes] + // * head_content [ bytes] + // * message_content [ bytes] + // * Magic word (0x89AB) [2 bytes] + + // Header size - 12 bytes + PacketData packetData = sniffer::MessageManager::CreateMessage(); // Decrypting packetData - auto data = EncryptXor(encryptedData, length); + auto data = new char[length]; + memcpy_s(data, length, encryptedData, length); + EncryptXor(data, length); uint16_t magicHead = util::ReadMapped(data, 0); diff --git a/cheat-library/src/user/cheat/misc/sniffer/PacketSniffer.h b/cheat-library/src/user/cheat/misc/sniffer/PacketSniffer.h index 68a9934..1a64a09 100644 --- a/cheat-library/src/user/cheat/misc/sniffer/PacketSniffer.h +++ b/cheat-library/src/user/cheat/misc/sniffer/PacketSniffer.h @@ -30,8 +30,9 @@ namespace cheat::feature private: PacketSniffer(); + bool ProcessModifiedData(app::KcpPacket_1* packet); PacketData ParseRawPacketData(char* encryptedData, uint32_t length); - static char* EncryptXor(void* content, uint32_t length); + static void EncryptXor(void* content, uint32_t length); static bool KcpClient_TryDequeueEvent_Hook(void* __this, app::ClientKcpEvent* evt, MethodInfo* method); static int32_t KcpNative_kcp_client_send_packet_Hook(void* kcp_client, app::KcpPacket_1* packet, MethodInfo* method); diff --git a/cheat-library/src/user/cheat/misc/sniffer/messages/ModifyData.cpp b/cheat-library/src/user/cheat/misc/sniffer/messages/ModifyData.cpp index f1b0d6b..09f79ef 100644 --- a/cheat-library/src/user/cheat/misc/sniffer/messages/ModifyData.cpp +++ b/cheat-library/src/user/cheat/misc/sniffer/messages/ModifyData.cpp @@ -2,21 +2,27 @@ #include "ModifyData.h" ModifyData::ModifyData(const MessageHeader& header) : MessageBase(header), - modifyType(PacketModifyType::Unchanged), modifiedData({}) -{ - -} + modify_type(PacketModifyType::Unchanged) +{ } void ModifyData::Write(PipeTransfer* transfer) { - transfer->Write(modifyType); - if (modifyType == PacketModifyType::Modified) - transfer->Write(modifiedData); + transfer->Write(modify_type); + if (modify_type == PacketModifyType::Modified) + { + transfer->Write(message_id); + transfer->Write(modified_head); + transfer->Write(modified_message); + } } void ModifyData::Read(PipeTransfer* transfer) { - transfer->Read(modifyType); - if (modifyType == PacketModifyType::Modified) - transfer->Read(modifiedData); + transfer->Read(modify_type); + if (modify_type == PacketModifyType::Modified) + { + transfer->Read(message_id); + transfer->Read(modified_head); + transfer->Read(modified_message); + } } diff --git a/cheat-library/src/user/cheat/misc/sniffer/messages/ModifyData.h b/cheat-library/src/user/cheat/misc/sniffer/messages/ModifyData.h index 224ebe7..322fe15 100644 --- a/cheat-library/src/user/cheat/misc/sniffer/messages/ModifyData.h +++ b/cheat-library/src/user/cheat/misc/sniffer/messages/ModifyData.h @@ -12,14 +12,17 @@ enum class PacketModifyType class ModifyData : public MessageBase { public: - PacketModifyType modifyType; - std::string modifiedData; + PacketModifyType modify_type; + + uint16_t message_id; + std::string modified_head; + std::string modified_message; ModifyData(const MessageHeader& header); ~ModifyData() {} // Inherited via PipeSerializedObject - virtual void Write(PipeTransfer* transfer) override; - virtual void Read(PipeTransfer* transfer) override; + void Write(PipeTransfer* transfer) override; + void Read(PipeTransfer* transfer) override; }; diff --git a/cheat-library/src/user/main.cpp b/cheat-library/src/user/main.cpp index 2e09bcd..7666741 100644 --- a/cheat-library/src/user/main.cpp +++ b/cheat-library/src/user/main.cpp @@ -35,15 +35,16 @@ void Run(HMODULE* phModule) DebuggerBypassPre(); -#ifdef _DEBUG - LOG_DEBUG("Waiting 10sec for loading game library."); - Sleep(10000); -#else while (GetModuleHandle("UserAssembly.dll") == nullptr) { LOG_DEBUG("UserAssembly.dll isn't initialized, waiting for 2 sec."); Sleep(2000); } + +#ifdef _DEBUG + LOG_DEBUG("Waiting 10sec for loading game library."); + Sleep(10000); +#else LOG_DEBUG("Waiting 15sec for game initialize."); Sleep(15000); #endif