From 77b52da44b263df4884be2f35f885d8edccbb6fa Mon Sep 17 00:00:00 2001 From: boris Date: Wed, 19 Dec 2018 00:13:24 +1300 Subject: added new loader project :) merry christmas --- csgo-loader/csgo-server/Networking/TCPServer.cpp | 124 +++++++++++++++++++++++ csgo-loader/csgo-server/Networking/TCPServer.hpp | 87 ++++++++++++++++ csgo-loader/csgo-server/Networking/WebSocket.cpp | 44 ++++++++ csgo-loader/csgo-server/Networking/WebSocket.hpp | 37 +++++++ 4 files changed, 292 insertions(+) create mode 100644 csgo-loader/csgo-server/Networking/TCPServer.cpp create mode 100644 csgo-loader/csgo-server/Networking/TCPServer.hpp create mode 100644 csgo-loader/csgo-server/Networking/WebSocket.cpp create mode 100644 csgo-loader/csgo-server/Networking/WebSocket.hpp (limited to 'csgo-loader/csgo-server/Networking') diff --git a/csgo-loader/csgo-server/Networking/TCPServer.cpp b/csgo-loader/csgo-server/Networking/TCPServer.cpp new file mode 100644 index 0000000..725bf1a --- /dev/null +++ b/csgo-loader/csgo-server/Networking/TCPServer.cpp @@ -0,0 +1,124 @@ +#include + +namespace Networking { + void TCPConnection::Close() { + printf("[<=] %s disconnected!\n", m_IpAddress); + + if(m_Socket) + closesocket(m_Socket); + } + + // We will only receive up to 256 bytes per cycle. + constexpr int BufferSize = 256; + + void TCPConnection::SendRawBytes(ByteArray &Bytes) { + // Send data. + int32_t Result = send(m_Socket, (char *)Bytes.data(), (int)Bytes.size(), 0); + + printf("[=>] Sending %zd bytes to %s.\n", Bytes.size(), m_IpAddress); + + if(Result == -1) + printf("[=>] Failed to send %zd bytes to %s. (Socket %04Ix)\n", Bytes.size(), m_IpAddress, m_Socket); + } + + ByteArray TCPConnection::ReceiveRawBytes() { + ByteArray ReceivedBytes; + uint8_t RecvBuffer[BufferSize]; + + // Attempt to receive a packet. + while(true) { + int32_t Received = recv(m_Socket, (char*)RecvBuffer, BufferSize, 0); + + // No more bytes left to receive. + if(Received < 0) + break; + + // Emplace all received bytes. + for(int n = 0; n < Received; ++n) { + ReceivedBytes.push_back(RecvBuffer[n]); + } + + // No more bytes left to receive. + if(Received < BufferSize) + break; + } + + printf("[<=] Received %zd bytes from %s.\n", ReceivedBytes.size(), m_IpAddress); + + return ReceivedBytes; + } + + void TCPConnection::SendBytes(ByteArray &Bytes) { + // Encrypt outgoing data. + ByteArray Encrypted = m_Encryption.Encrypt(Bytes); + + SendRawBytes(Encrypted); + } + + ByteArray TCPConnection::ReceiveBytes() { + ByteArray ReceivedBytes = ReceiveRawBytes(); + + // Decrypt incoming data. + ByteArray Decrypted = m_Encryption.Decrypt(ReceivedBytes); + + return Decrypted; + } + + bool TCPServer::Start(uint16_t ServerPort) { + const int32_t version = 0x101; + + // Initialise WinSocks. + if(WSAStartup(version, &m_WinSocks)) + return false; + + // Create an IPv4 socket. + m_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + if(m_Socket == INVALID_SOCKET) + return false; + + // Set up server context. + m_Context.sin_addr.s_addr = INADDR_ANY; + m_Context.sin_family = AF_INET; + m_Context.sin_port = htons(ServerPort); + + int32_t Bind = bind(m_Socket, (sockaddr *)&m_Context, sizeof sockaddr_in); + + if(Bind == INVALID_SOCKET) + return false; + + // Start listening. + printf("[INFO] Server listening on port %d.\n", ServerPort); + listen(m_Socket, 1); + + return true; + } + + void TCPServer::AcceptConnection() { + sockaddr_in IncomingConnection; + int32_t AddressLength = sizeof IncomingConnection; + + // Accept the incoming connection. + SOCKET IncomingSocket = accept(m_Socket, (sockaddr *)&IncomingConnection, &AddressLength); + + if(IncomingSocket != INVALID_SOCKET) { + Wrapper::Encryption Encryption; + + // Initialise encryption context. + Encryption.Start(); + + // Attempt handshake with client. + TCPConnection Connection(IncomingSocket, inet_ntoa(IncomingConnection.sin_addr), Encryption); + + ByteArray EncryptionKey = Connection.GetEncryptionKey(); + Connection.SendRawBytes(EncryptionKey); + + // Detach a thread to handle the connection. + std::thread thread([&] { + m_ConnectionHandler(Connection); + Connection.Close(); + }); + thread.detach(); + } + } +} \ No newline at end of file diff --git a/csgo-loader/csgo-server/Networking/TCPServer.hpp b/csgo-loader/csgo-server/Networking/TCPServer.hpp new file mode 100644 index 0000000..adb6e7c --- /dev/null +++ b/csgo-loader/csgo-server/Networking/TCPServer.hpp @@ -0,0 +1,87 @@ +#pragma once + +// For encryption wrappers. +#include + +// WinSocks +#include +#pragma comment(lib, "ws2_32.lib") + +// std::function +#include + +// std::min +#include + +// std::thread +#include + +namespace Networking { + // Base connection class, used to handle multiple connections in a thread-based model. + class TCPConnection { + SOCKET m_Socket; + Wrapper::Encryption m_Encryption; + const char *m_IpAddress; + public: + // Initialiser for TCPConnection class. + TCPConnection(SOCKET Connection, const char *IpAddress, Wrapper::Encryption &RSA) : + m_Encryption(RSA), m_Socket(Connection), m_IpAddress(IpAddress) { + printf("[=>] %s connected!\n", IpAddress); + } + + // Release the connection once it goes out of scope. + void Close(); + + // Wrappers for sending/receiving data. + void SendRawBytes(ByteArray &Bytes); + ByteArray ReceiveRawBytes(); + + void SendBytes(ByteArray &Bytes); + ByteArray ReceiveBytes(); + + // Overload for getting the socket, in case we need to expose it. + SOCKET operator()() { + return m_Socket; + } + + // Expose the encryption key for the connection. + ByteArray GetEncryptionKey() { + return m_Encryption.GetKey(); + } + }; + + // Basic TCP server. Supports custom connection handling (pass a lambda to the handler list). + using ConnectionHandler = std::function; + + class TCPServer { + WSADATA m_WinSocks; + SOCKET m_Socket; + sockaddr_in m_Context; + + // Connection handlers, will be called sequentially upon connection. + ConnectionHandler m_ConnectionHandler; + + public: + // Default constructor, nothing needed for now. + TCPServer() = default; + + // Handle destruction of server once it goes out of scope. + ~TCPServer() { + // If we have a socket, close it. + if(m_Socket) + closesocket(m_Socket); + + // Close WSA context. + WSACleanup(); + } + + // Handle the creation and handling of TCPServer connections. + bool Start(uint16_t ServerPort); + void AcceptConnection(); + + // Overload for adding connection handlers, C# style support for events. + void operator+=(std::function Function) { + m_ConnectionHandler = Function; + } + }; +} \ No newline at end of file diff --git a/csgo-loader/csgo-server/Networking/WebSocket.cpp b/csgo-loader/csgo-server/Networking/WebSocket.cpp new file mode 100644 index 0000000..755e89b --- /dev/null +++ b/csgo-loader/csgo-server/Networking/WebSocket.cpp @@ -0,0 +1,44 @@ +#include + +namespace Networking { + // Initialises a basic HTTP socket. + bool WebSocket::Start(const char *Address, const char *Username, const char *Password) { + m_Internet = InternetOpenA("none", INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0); + + if(!m_Internet) + return false; + + m_Address = InternetConnectA(m_Internet, Address, INTERNET_DEFAULT_HTTPS_PORT, Username, Password, INTERNET_SERVICE_HTTP, 0, 0); + + if(!m_Address) + return false; + + return true; + } + + // Receives a response from a request. + ByteArray WebSocket::Request(const char *File, const char *Header, ByteArray &Data) { + ByteArray Response; + InternetHandle WebRequest = HttpOpenRequestA(m_Address, "POST", File, 0, 0, 0, INTERNET_FLAG_SECURE | INTERNET_FLAG_KEEP_CONNECTION, 0); + + // Make connection request. + bool Sent = HttpSendRequestA(WebRequest, Header, (DWORD)strlen(Header), Data.data(), (DWORD)Data.size()); + + if(Sent) { + DWORD ReceivedSize{}; + + uint8_t *Block = (uint8_t *)malloc(4096); + + // Read response. + while(InternetReadFile(WebRequest, Block, 4096, &ReceivedSize)) { + for(size_t n{}; n < std::min< int >(4096, ReceivedSize); ++n) { + Response.push_back(Block[n]); + } + } + + free(Block); + } + + return Response; + } +} \ No newline at end of file diff --git a/csgo-loader/csgo-server/Networking/WebSocket.hpp b/csgo-loader/csgo-server/Networking/WebSocket.hpp new file mode 100644 index 0000000..f503913 --- /dev/null +++ b/csgo-loader/csgo-server/Networking/WebSocket.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include +#include +#include + +#pragma comment(lib, "wininet.lib") + +using ByteArray = std::vector; + +namespace Networking { + // Whenever the handle goes out of scope, it will automatically be released. + class InternetHandle { + HINTERNET m_Internet; + public: + InternetHandle() = default; + InternetHandle(HINTERNET Internet) : + m_Internet(Internet) { } + + ~InternetHandle() { + InternetCloseHandle(m_Internet); + } + + operator HINTERNET() { return m_Internet; }; + }; + + class WebSocket { + InternetHandle m_Internet; + InternetHandle m_Address; + + public: + bool Start(const char *Address, const char *Username, const char *Password); + ByteArray Request(const char *File, const char *Header, ByteArray &Data); + }; +} \ No newline at end of file -- cgit v1.2.3