diff --git a/src/client/component/network.cpp b/src/client/component/network.cpp index 9f4a99f9..ba3bb160 100644 --- a/src/client/component/network.cpp +++ b/src/client/component/network.cpp @@ -5,33 +5,57 @@ #include +#include "utils/string.hpp" + namespace network { namespace { - int net_compare_base_address(const game::netadr_t* a1, const game::netadr_t* a2) - { - if (a1->type == a2->type) - { - switch (a1->type) - { - case game::netadrtype_t::NA_BOT: - case game::netadrtype_t::NA_LOOPBACK: - return a1->port == a2->port; + using callback = std::function&)>; - case game::netadrtype_t::NA_IP: - return memcmp(&a1->ipv4.a, &a2->ipv4.a, 4) == 0; - default: - break; - } + std::unordered_map& get_callbacks() + { + static std::unordered_map callbacks{}; + return callbacks; + } + + bool handle_command(game::netadr_t* address, const char* command, const game::msg_t* message) + { + /*const auto cmd_string = utils::string::to_lower(command); + auto& callbacks = get_callbacks(); + const auto handler = callbacks.find(cmd_string); + const auto offset = cmd_string.size() + 5; + if (message->cursize < offset || handler == callbacks.end()) + { + return false; } + + const std::basic_string_view data(message->data + offset, message->cursize - offset); + + handler->second(*address, data); + return true;*/ + + OutputDebugStringA(command); return false; } - int net_compare_address(const game::netadr_t* a1, const game::netadr_t* a2) + void handle_command_stub(utils::hook::assembler& a) { - return net_compare_base_address(a1, a2) && a1->port == a2->port; + a.pushad64(); + + a.mov(r8, r12); + a.mov(rdx, rcx); // command + a.lea(rcx, qword_ptr(rsp, 0x30 + 0x80)); // address + + a.call_aligned(handle_command); + + a.movzx(rax, al); + a.mov(qword_ptr(rsp, 0x78), rax); + + a.popad64(); + + a.jmp(0x14134D14B_g); } } @@ -43,52 +67,65 @@ namespace network // redirect dw_sendto to raw socket utils::hook::jump(0x14233307E_g, 0x1423330C7_g); + utils::hook::nop(0x142333056_g, 5); // don't add sock to packet + utils::hook::set(0x14233305E_g, 0); // don't add checksum to packet + + utils::hook::set(0x142332E55_g, 0); // clear local net id + utils::hook::jump(0x142332E72_g, 0x142332E8E_g); // skip checksum parsing + // intercept command handling - /*utils::hook::jump(0x14020A175, utils::hook::assemble(handle_command_stub), true); + utils::hook::jump(0x14134D146_g, utils::hook::assemble(handle_command_stub)); - // handle xuid without secure connection - utils::hook::nop(0x14043FFF8, 6); + /*std::thread([] + { + while (true) + { + { + MessageBoxA(0, 0, 0, 0); - utils::hook::jump(0x1403DA700, net_compare_address); - utils::hook::jump(0x1403DA750, net_compare_base_address); + static auto& ip_socket = *(SOCKET*)0x157E77818_g; + if (!ip_socket) + { + ip_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - // don't establish secure conenction - utils::hook::set(0x140232BBD, 0xEB); - utils::hook::set(0x140232C9A, 0xEB); - utils::hook::set(0x140232F8D, 0xEB); - utils::hook::set(0x14020862F, 0xEB); + const auto address = htonl(INADDR_ANY); + const auto port = htons(28960); - // ignore unregistered connection - utils::hook::jump(0x140439EA9, reinterpret_cast(0x140439E28)); - utils::hook::set(0x140439E9E, 0xEB); + sockaddr_in server_addr{}; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = address; + server_addr.sin_port = port; - // disable xuid verification - utils::hook::set(0x140022319, 0xEB); - utils::hook::set(0x140022334, 0xEB); + if (bind(ip_socket, reinterpret_cast(&server_addr), sizeof(server_addr)) == + SOCKET_ERROR) + { + throw std::runtime_error("Failed to bind socket"); + } + } - // disable xuid verification - utils::hook::nop(0x14043CC4C, 2); - utils::hook::set(0x14043CCA8, 0xEB); + std::string data = utils::string::va("\xFF\xFF\xFF\xFF" "getservers S1 %i full empty", 1); - // ignore configstring mismatch - utils::hook::set(0x140211610, 0xEB); + game::netadr_t addr{}; + addr.type = game::NA_RAWIP; + addr.port = 20810; + *(unsigned long*)&addr.ipv4.a = inet_addr("116.203.183.23"); + addr.localNetID = game::NS_CLIENT1; + game::NET_SendPacket(game::NS_CLIENT1, (int)data.size(), data.data(), &addr); + } + } + }).detach();*/ + } - // ignore dw handle in SV_PacketEvent - utils::hook::set(0x140442F6D, 0xEB); - utils::hook::call(0x140442F61, &net_compare_address); - - // ignore dw handle in SV_FindClientByAddress - utils::hook::set(0x14044256D, 0xEB); - utils::hook::call(0x140442561, &net_compare_address); - - // ignore dw handle in SV_DirectConnect - utils::hook::set(0x140439BA8, 0xEB); - utils::hook::set(0x140439DA5, 0xEB); - utils::hook::call(0x140439B9B, &net_compare_address); - utils::hook::call(0x140439D98, &net_compare_address); - */ + void pre_destroy() override + { + static auto& ip_socket = *(SOCKET*)0x157E77818_g; + if (ip_socket) + { + closesocket(ip_socket); + ip_socket = 0; + } } }; } -//REGISTER_COMPONENT(network::component) +REGISTER_COMPONENT(network::component) diff --git a/src/client/game/structs.hpp b/src/client/game/structs.hpp index ab7c0a18..a5014bfb 100644 --- a/src/client/game/structs.hpp +++ b/src/client/game/structs.hpp @@ -491,6 +491,57 @@ namespace game netsrc_t localNetID; }; + typedef int qboolean; + + enum PacketModeList + { + PACKETDATA_FIRST = 0x0, + PACKETDATA_UNDEFINED = 0x0, + PACKETDATA_HEADER = 0x1, + PACKETDATA_OVERHEAD = 0x2, + PACKETDATA_DATA = 0x3, + PACKETDATA_RELIABLEDATA = 0x4, + PACKETDATA_ZEROFLOAT = 0x5, + PACKETDATA_SMALLFLOAT = 0x6, + PACKETDATA_LARGEFLOAT = 0x7, + PACKETDATA_ZEROINT = 0x8, + PACKETDATA_SMALLANGLE = 0x9, + PACKETDATA_ZEROANGLE = 0xA, + PACKETDATA_TIMEDELTA = 0xB, + PACKETDATA_TIME = 0xC, + PACKETDATA_24BITFLAGINDEX = 0xD, + PACKETDATA_GROUNDENTITY = 0xE, + PACKETDATA_ENTITYNUM = 0xF, + PACKETDATA_LASTFIELDCHANGED = 0x10, + PACKETDATA_NOTNETWORKDATA = 0x11, + PACKETDATA_ORIGINDELTA = 0x12, + PACKETDATA_ORIGIN = 0x13, + NUM_PACKETDATA_MODES = 0x14, + }; + + struct PacketMode + { + unsigned int start; + PacketModeList mode; + }; + + struct msg_t + { + qboolean overflowed; + qboolean readOnly; + byte* data; + byte* splitData; + int maxsize; + int cursize; + int splitSize; + int readcount; + int bit; + int lastEntityRef; + qboolean flush; + netsrc_t targetLocalNetID; + //PacketMode analysis; + }; + #ifdef __cplusplus } #endif diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index a2173bc4..9fe9357c 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -22,6 +22,8 @@ namespace game // Live WEAK symbol Live_GetConnectivityInformation{0x141E0C410_g}; + // NET + WEAK symbol NET_SendPacket{0x142332F70_g}; // Sys WEAK symbol Sys_ShowConsole{0x142333F80_g}; WEAK symbol Sys_GetTLS{0x142184210_g};