From a5acd4c9a3b24c9d5af3a8f504e5af053fa7fa09 Mon Sep 17 00:00:00 2001 From: boris Date: Thu, 20 Dec 2018 21:38:04 +1300 Subject: yo is this loss --- csgo-loader/csgo-client/Client.cpp | 27 ++-- csgo-loader/csgo-client/Login/RemoteLogin.cpp | 34 ++-- csgo-loader/csgo-client/Login/RemoteLogin.hpp | 23 +-- csgo-loader/csgo-client/Networking/TCPClient.cpp | 33 ++-- csgo-loader/csgo-client/Networking/TCPClient.hpp | 8 +- .../csgo-client/RemoteCode/RemoteCodeClient.cpp | 1 + .../csgo-client/RemoteCode/RemoteCodeClient.hpp | 6 + .../RemoteCode/RemoteInjectionClient.cpp | 1 + .../RemoteCode/RemoteInjectionClient.hpp | 6 + .../csgo-client/RemoteCode/RemoteProcess.cpp | 118 ++++++++++---- .../csgo-client/RemoteCode/RemoteProcess.hpp | 49 +++--- csgo-loader/csgo-client/Security/Encryption.cpp | 174 +++++++++++++------- csgo-loader/csgo-client/Security/Encryption.hpp | 12 +- csgo-loader/csgo-client/Security/FnvHash.hpp | 24 ++- .../csgo-client/Security/SyscallManager.cpp | 40 +++-- .../csgo-client/Security/SyscallManager.hpp | 15 +- .../csgo-client/UserExperience/UserInterface.cpp | 32 ++-- .../csgo-client/UserExperience/UserInterface.hpp | 17 +- csgo-loader/csgo-client/csgo-client.vcxproj | 4 + .../csgo-client/csgo-client.vcxproj.filters | 12 ++ csgo-loader/csgo-server/Login/RemoteLogin.cpp | 51 ++++-- csgo-loader/csgo-server/Login/RemoteLogin.hpp | 14 +- csgo-loader/csgo-server/Networking/TCPServer.cpp | 46 ++++-- csgo-loader/csgo-server/Networking/TCPServer.hpp | 26 +-- csgo-loader/csgo-server/Networking/WebSocket.cpp | 18 ++- csgo-loader/csgo-server/Networking/WebSocket.hpp | 16 +- csgo-loader/csgo-server/RemoteCode/FileReader.cpp | 29 ++++ csgo-loader/csgo-server/RemoteCode/FileReader.hpp | 31 ++++ .../csgo-server/RemoteCode/RemoteCodeServer.cpp | 1 + .../csgo-server/RemoteCode/RemoteCodeServer.hpp | 6 + .../RemoteCode/RemoteInjectionServer.cpp | 1 + .../RemoteCode/RemoteInjectionServer.hpp | 6 + csgo-loader/csgo-server/Security/Encryption.cpp | 176 ++++++++++++++------- csgo-loader/csgo-server/Security/Encryption.hpp | 12 +- csgo-loader/csgo-server/Server.cpp | 12 +- csgo-loader/csgo-server/csgo-server.vcxproj | 4 + .../csgo-server/csgo-server.vcxproj.filters | 12 ++ 37 files changed, 763 insertions(+), 334 deletions(-) create mode 100644 csgo-loader/csgo-client/RemoteCode/RemoteCodeClient.cpp create mode 100644 csgo-loader/csgo-client/RemoteCode/RemoteCodeClient.hpp create mode 100644 csgo-loader/csgo-client/RemoteCode/RemoteInjectionClient.cpp create mode 100644 csgo-loader/csgo-client/RemoteCode/RemoteInjectionClient.hpp create mode 100644 csgo-loader/csgo-server/RemoteCode/RemoteCodeServer.cpp create mode 100644 csgo-loader/csgo-server/RemoteCode/RemoteCodeServer.hpp create mode 100644 csgo-loader/csgo-server/RemoteCode/RemoteInjectionServer.cpp create mode 100644 csgo-loader/csgo-server/RemoteCode/RemoteInjectionServer.hpp diff --git a/csgo-loader/csgo-client/Client.cpp b/csgo-loader/csgo-client/Client.cpp index 077b14b..d2dbd7a 100644 --- a/csgo-loader/csgo-client/Client.cpp +++ b/csgo-loader/csgo-client/Client.cpp @@ -3,37 +3,42 @@ #include #include #include +#include #define LOCAL_IP 0x0100007F // '127.0.0.1' #define SERVER_IP 0xE53CA523 // Hexadecimal representation of the server IP, obtained by inet_addr() #define SERVER_PORT 0xF2C // Hexadecimal representation of the server port. -int __stdcall WinMain(HINSTANCE inst, HINSTANCE prev, char* str, int cmdshow) { +int __stdcall WinMain(HINSTANCE inst, HINSTANCE prev, char* str, int cmdshow) +{ + AllocConsole(); + FILE *file; + freopen_s(&file, "CONOUT$", "w", stdout); + + RemoteCode::RemoteProcess Process; + if(!Syscalls->Start()) ERROR_ASSERT("[000F:00001A00] Failed to initialize. Please contact an administrator."); UserInterface->m_Data.m_ExecutionState = UserExperience::EXECUTION_WAITING; - std::thread WindowThread([] { + std::thread WindowThread([] + { if(!UserInterface->Start()) ERROR_ASSERT("[000F:00001B00] Failed to initialize. Please contact an administrator."); UserInterface->RunUiFrame(); }); WindowThread.detach(); - // Allow the window to start, etc. - Sleep(2000); - Networking::TCPClient Client; if(!Client.Start(LOCAL_IP, SERVER_PORT)) ERROR_ASSERT("[000F:0002A000] Server did not accept the connection."); UserInterface->m_Data.m_ExecutionState = UserExperience::EXECUTION_LOG_IN; - - while(UserInterface->m_Data.m_ExecutionState != UserExperience::EXECUTION_WAITING) { + + while(UserInterface->m_Data.m_ExecutionState != UserExperience::EXECUTION_WAITING) Sleep(1); - } Login::RemoteLoginTransaction Transaction; Transaction.Start(UserInterface->m_Data.m_Username, UserInterface->m_Data.m_Password); @@ -42,10 +47,12 @@ int __stdcall WinMain(HINSTANCE inst, HINSTANCE prev, char* str, int cmdshow) { Client.SendBytes(RawLoginHeader); ByteArray RawServerResponse = Client.ReceiveBytes(); - if(!Transaction.TranslateResponse(RawServerResponse)) { + if(!Transaction.TranslateResponse(RawServerResponse)) + { UserInterface->m_Data.m_ExecutionState = UserExperience::EXECUTION_ERROR; } - else { + else + { UserInterface->m_Data.m_ExecutionState = UserExperience::EXECUTION_CHOOSE; } diff --git a/csgo-loader/csgo-client/Login/RemoteLogin.cpp b/csgo-loader/csgo-client/Login/RemoteLogin.cpp index 45f7953..2f82744 100644 --- a/csgo-loader/csgo-client/Login/RemoteLogin.cpp +++ b/csgo-loader/csgo-client/Login/RemoteLogin.cpp @@ -5,8 +5,10 @@ // NOTE: You must change this on the server as well. #define CURRENT_CLIENT_HEADER 0xDEADBEEF -namespace Login { - void RemoteLoginTransaction::Start(const char *Username, const char *Password) { +namespace Login +{ + void RemoteLoginTransaction::Start(const char *Username, const char *Password) + { // Initialise the header with the client header. m_Header.m_ClientHeader = CURRENT_CLIENT_HEADER; @@ -23,26 +25,30 @@ namespace Login { m_Header.m_IntegrityBit3 = 0; // The checksum bit, the server will check this first to detect possible tampering. - m_Header.m_IntegrityBit4 = m_Header.m_IntegrityBit1 - | m_Header.m_IntegrityBit2 - | m_Header.m_IntegrityBit3; + m_Header.m_IntegrityBit4 = m_Header.m_IntegrityBit1 + | m_Header.m_IntegrityBit2 + | m_Header.m_IntegrityBit3; } // TODO: Hardware ID check. - ByteArray RemoteLoginTransaction::DoWmiQuery(const char *Query) { + ByteArray RemoteLoginTransaction::DoWmiQuery(const char *Query) + { ByteArray Response{}; - + return Response; } - uint32_t RemoteLoginTransaction::GetHardwareId() { + uint32_t RemoteLoginTransaction::GetHardwareId() + { return 123456789; } - bool RemoteLoginTransaction::TranslateResponse(ByteArray &RawResponse) { + bool RemoteLoginTransaction::TranslateResponse(ByteArray &RawResponse) + { RemoteLoginResponse ServerResponse = *reinterpret_cast(&RawResponse[0]); - switch(ServerResponse) { + switch(ServerResponse) + { case RemoteLoginResponse::ACCESS_SPECIAL_USER: // Allow the user to load special access cheats. UserInterface->m_Data.m_SpecialAccess = true; @@ -52,21 +58,19 @@ namespace Login { INFO_ASSERT("[000A:%08x] Your client is outdated.\nPlease download the latest client at 'moneybot.cc'.", m_Header.m_HardwareId); break; case RemoteLoginResponse::INTEGRITY_FAILURE: - INFO_ASSERT("[000F:%08x] Failed to verify session.\nPlease contact an administrator.", m_Header.m_HardwareId); + UserInterface->m_Data.m_Error = UserExperience::ERROR_SHADOW_BAN; break; case RemoteLoginResponse::USER_BANNED: INFO_ASSERT("[000D:%08x] Your account is banned.\nPlease contact 'admin@moneybot.cc' for additional information.", m_Header.m_HardwareId); break; case RemoteLoginResponse::INVALID_HARDWARE: UserInterface->m_Data.m_Error = UserExperience::ERROR_INVALID_HWID; - //INFO_ASSERT("[000C:%08x] Hardware ID mismatch.\nPlease contact an administrator to request a hardware ID reset.", m_Header.m_HardwareId); break; case RemoteLoginResponse::INVALID_CREDENTIALS: - UserInterface->m_Data.m_Error = UserExperience::ERROR_SHADOW_BAN; - //INFO_ASSERT("[000C:%08x] Your credentials are invalid. Please check your spelling and try again.", m_Header.m_HardwareId ^ RemoteLoginResponse::INVALID_CREDENTIALS); + INFO_ASSERT("[000C:%08x] Your credentials are invalid. Please check your spelling and try again.", m_Header.m_HardwareId); break; case RemoteLoginResponse::NO_SUBSCRIPTION: - INFO_ASSERT("[000G:%08x] No active subscription found.", m_Header.m_HardwareId ^ RemoteLoginResponse::NO_SUBSCRIPTION); + INFO_ASSERT("[000G:%08x] No active subscription found.", m_Header.m_HardwareId); break; } diff --git a/csgo-loader/csgo-client/Login/RemoteLogin.hpp b/csgo-loader/csgo-client/Login/RemoteLogin.hpp index e543d27..31649c6 100644 --- a/csgo-loader/csgo-client/Login/RemoteLogin.hpp +++ b/csgo-loader/csgo-client/Login/RemoteLogin.hpp @@ -6,9 +6,11 @@ using ByteArray = std::vector; -namespace Login { +namespace Login +{ // Login header that is sent over to the server - struct RemoteLoginHeader { + struct RemoteLoginHeader + { // The first four bytes are encoded by the client. // This will carry the client version which can be checked. uint32_t m_ClientHeader; @@ -32,9 +34,10 @@ namespace Login { // Possible server responses // The hardware ID is encoded (XORed with the message ID) within the message for // shadow ban/forum ban purposes. :) - enum RemoteLoginResponse : uint8_t { - OUTDATED_CLIENT = 'A', // '[000A:{HWID}] Your client is outdated. Please download the latest client at 'moneybot.cc'.' - ACCESS_AUTHORISED = 'B', // Allows the user to continue with injection. + enum RemoteLoginResponse : uint8_t + { + OUTDATED_CLIENT = 'A', // '[000A:{HWID}] Your client is outdated. Please download the latest client at 'moneybot.cc'.' + ACCESS_AUTHORISED = 'B', // Allows the user to continue with injection. INVALID_CREDENTIALS = 'C', // '[000C:{HWID}] Your credentials are invalid. Please check your spelling and try again.' USER_BANNED = 'D', // '[000D:{HWID}] Your account is banned. Please contact 'admin@moneybot.cc' for additional information.' INVALID_HARDWARE = 'E', // '[000E:{HWID}] Please contact an administrator to request a hardware ID reset.' @@ -44,9 +47,10 @@ namespace Login { }; // Runs the security checks and creates the login header to send to the server. - class RemoteLoginTransaction { + class RemoteLoginTransaction + { RemoteLoginHeader m_Header; - + public: // Initialises the header. void Start(const char *Username, const char *Password); @@ -62,9 +66,10 @@ namespace Login { // the response is not ACCESS_AUTHORISED. bool TranslateResponse(ByteArray &RawResponse); - ByteArray GetHeader() { + ByteArray GetHeader() + { ByteArray Header; - + // Copy header to the ByteArray. Header.insert( Header.begin(), diff --git a/csgo-loader/csgo-client/Networking/TCPClient.cpp b/csgo-loader/csgo-client/Networking/TCPClient.cpp index 3bdea21..8065c50 100644 --- a/csgo-loader/csgo-client/Networking/TCPClient.cpp +++ b/csgo-loader/csgo-client/Networking/TCPClient.cpp @@ -1,11 +1,13 @@ #include #include -namespace Networking { +namespace Networking +{ // We will only receive up to 256 bytes per cycle. constexpr int BufferSize = 256; - void TCPClient::SendRawBytes(ByteArray &Bytes) { + void TCPClient::SendRawBytes(ByteArray &Bytes) + { // Send data. int32_t Result = send(m_Socket, (char *)Bytes.data(), (int)Bytes.size(), 0); @@ -13,12 +15,14 @@ namespace Networking { INFO_ASSERT("[000F:00002B00] Server closed the connection suddenly."); } - ByteArray TCPClient::ReceiveRawBytes() { + ByteArray TCPClient::ReceiveRawBytes() + { ByteArray ReceivedBytes; uint8_t RecvBuffer[BufferSize]; // Attempt to receive a packet. - while(true) { + while(true) + { int32_t Received = recv(m_Socket, (char*)RecvBuffer, BufferSize, 0); // No more bytes left to receive. @@ -26,7 +30,8 @@ namespace Networking { break; // Emplace all received bytes. - for(int n = 0; n < Received; ++n) { + for(int n = 0; n < Received; ++n) + { ReceivedBytes.push_back(RecvBuffer[n]); } @@ -38,14 +43,16 @@ namespace Networking { return ReceivedBytes; } - void TCPClient::SendBytes(ByteArray &Bytes) { + void TCPClient::SendBytes(ByteArray &Bytes) + { // Encrypt outgoing data. ByteArray Encrypted = m_Encryption.Encrypt(Bytes); SendRawBytes(Encrypted); } - ByteArray TCPClient::ReceiveBytes() { + ByteArray TCPClient::ReceiveBytes() + { ByteArray ReceivedBytes = ReceiveRawBytes(); // Decrypt incoming data. @@ -54,7 +61,8 @@ namespace Networking { return Decrypted; } - bool TCPClient::Start(uint32_t ServerAddress, uint16_t ServerPort) { + bool TCPClient::Start(uint32_t ServerAddress, uint16_t ServerPort) + { const int32_t version = 0x101; // Initialise WinSocks. @@ -69,8 +77,8 @@ namespace Networking { // Set up client context. m_Context.sin_addr.s_addr = ServerAddress; - m_Context.sin_family = AF_INET; - m_Context.sin_port = htons(ServerPort); + m_Context.sin_family = AF_INET; + m_Context.sin_port = htons(ServerPort); // Attempt connection. if(connect(m_Socket, (sockaddr *)&m_Context, sizeof m_Context)) @@ -93,10 +101,11 @@ namespace Networking { return true; } - void TCPClient::Kill() { + void TCPClient::Kill() + { if(m_Socket) closesocket(m_Socket); - + WSACleanup(); } } \ No newline at end of file diff --git a/csgo-loader/csgo-client/Networking/TCPClient.hpp b/csgo-loader/csgo-client/Networking/TCPClient.hpp index f057cdc..4e3e089 100644 --- a/csgo-loader/csgo-client/Networking/TCPClient.hpp +++ b/csgo-loader/csgo-client/Networking/TCPClient.hpp @@ -10,10 +10,12 @@ // std::min #include -namespace Networking { +namespace Networking +{ // A TCPClient is essentially the same as the TCPConnection counterpart on the server, // however, it independently handles connection. - class TCPClient { + class TCPClient + { WSADATA m_WinSocks; SOCKET m_Socket; sockaddr_in m_Context; @@ -25,7 +27,7 @@ namespace Networking { // Connects to a remote server. // Also handles the initial handshake between server and client. bool Start(uint32_t ServerAddress, uint16_t ServerPort); - + // Kills the client. void Kill(); diff --git a/csgo-loader/csgo-client/RemoteCode/RemoteCodeClient.cpp b/csgo-loader/csgo-client/RemoteCode/RemoteCodeClient.cpp new file mode 100644 index 0000000..7e6575b --- /dev/null +++ b/csgo-loader/csgo-client/RemoteCode/RemoteCodeClient.cpp @@ -0,0 +1 @@ +#include diff --git a/csgo-loader/csgo-client/RemoteCode/RemoteCodeClient.hpp b/csgo-loader/csgo-client/RemoteCode/RemoteCodeClient.hpp new file mode 100644 index 0000000..57f1499 --- /dev/null +++ b/csgo-loader/csgo-client/RemoteCode/RemoteCodeClient.hpp @@ -0,0 +1,6 @@ +#pragma once + +namespace RemoteCode +{ + +} \ No newline at end of file diff --git a/csgo-loader/csgo-client/RemoteCode/RemoteInjectionClient.cpp b/csgo-loader/csgo-client/RemoteCode/RemoteInjectionClient.cpp new file mode 100644 index 0000000..d142264 --- /dev/null +++ b/csgo-loader/csgo-client/RemoteCode/RemoteInjectionClient.cpp @@ -0,0 +1 @@ +#include diff --git a/csgo-loader/csgo-client/RemoteCode/RemoteInjectionClient.hpp b/csgo-loader/csgo-client/RemoteCode/RemoteInjectionClient.hpp new file mode 100644 index 0000000..57f1499 --- /dev/null +++ b/csgo-loader/csgo-client/RemoteCode/RemoteInjectionClient.hpp @@ -0,0 +1,6 @@ +#pragma once + +namespace RemoteCode +{ + +} \ No newline at end of file diff --git a/csgo-loader/csgo-client/RemoteCode/RemoteProcess.cpp b/csgo-loader/csgo-client/RemoteCode/RemoteProcess.cpp index 7397c7d..969f907 100644 --- a/csgo-loader/csgo-client/RemoteCode/RemoteProcess.cpp +++ b/csgo-loader/csgo-client/RemoteCode/RemoteProcess.cpp @@ -1,47 +1,99 @@ #include -namespace RemoteCode { +namespace RemoteCode +{ // RemoteModule implementation - RemoteModule::RemoteModule(HANDLE Module, RemoteProcess &Process) : - m_Module(Module) { - // Read information about module. - MODULEINFO ModuleInfo{}; - if(!K32GetModuleInformation(Process, (HMODULE)Module, &ModuleInfo, sizeof ModuleInfo)) - return; - - // Read module data. - m_ModuleData.reserve(ModuleInfo.SizeOfImage); - Process.Read(ModuleInfo.lpBaseOfDll, m_ModuleData.data(), m_ModuleData.size()); - } + RemoteModule::RemoteModule(HANDLE Module) : + m_Module(Module) {} - uintptr_t RemoteModule::Scan(ByteArray &Data) { - if(m_ModuleData.empty()) - return uintptr_t{}; + // RemoteProcess implementation + bool RemoteProcess::Start(const char *ProcessName) + { + void *Toolhelp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - // We have a valid file (?) - uint8_t *Buffer = m_ModuleData.data(); + if(!Toolhelp) + return false; - if(!Buffer || *(uint16_t *)Buffer != IMAGE_DOS_SIGNATURE) - return uintptr_t{}; + PROCESSENTRY32 ProcessEntry{}; + ProcessEntry.dwSize = sizeof PROCESSENTRY32; - // Read PE information. - IMAGE_DOS_HEADER *DosHeader = (IMAGE_DOS_HEADER *)Buffer; - IMAGE_NT_HEADERS *NtHeaders = (IMAGE_NT_HEADERS *)(Buffer + DosHeader->e_lfanew); + if(!Process32First(Toolhelp, &ProcessEntry)) + return false; - if(NtHeaders->Signature != IMAGE_NT_SIGNATURE) - return uintptr_t{}; + while(Process32Next(Toolhelp, &ProcessEntry)) + { + if(strstr(ProcessName, ProcessEntry.szExeFile)) + { + CloseHandle(Toolhelp); - // Find signature. - ByteArray::iterator Iterator = std::search( - m_ModuleData.begin(), - m_ModuleData.end(), - Data.begin(), - Data.end() - ); + // swoo + m_ProcessId = ProcessEntry.th32ProcessID; + m_Process = OpenProcess(PROCESS_ALL_ACCESS, false, ProcessEntry.th32ProcessID); + return true; + } + } - return (uintptr_t)std::distance(m_ModuleData.begin(), Iterator); + CloseHandle(Toolhelp); + return false; } - // RemoteProcess implementation + void RemoteProcess::ReadMemoryWrapper_Internal(void *Address, void *Data, size_t SizeOfData) + { + static auto ZwReadVirtualMemory = Syscalls->Find(FNV("ZwReadVirtualMemory")); + ZwReadVirtualMemory(m_Process, Address, Data, SizeOfData, nullptr); + } + + void RemoteProcess::WriteMemoryWrapper_Internal(void *Address, void *Data, size_t SizeOfData) + { + static auto ZwWriteVirtualMemory = Syscalls->Find(FNV("ZwWriteVirtualMemory")); + ZwWriteVirtualMemory(m_Process, Address, Data, SizeOfData, nullptr); + } + void *RemoteProcess::Allocate(size_t AllocationSize) + { + void *AllocationAddress = nullptr; + static auto ZwAllocateVirtualMemory = Syscalls->Find(FNV("ZwAllocateVirtualMemory")); + + // :b:invoke the :b:unction :b:oi + NTSTATUS Status = ZwAllocateVirtualMemory( + m_Process, + &AllocationAddress, + 0, + &AllocationSize, + MEM_COMMIT | MEM_RESERVE, + PAGE_EXECUTE_READWRITE + ); + + if(!NT_SUCCESS(Status)) + return nullptr; + + return AllocationAddress; + } + + RemoteModule RemoteProcess::FindModule(const char *ModuleName) + { + void *Toolhelp = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, m_ProcessId); + + if(!Toolhelp) + return RemoteModule{}; + + MODULEENTRY32 ModuleEntry{}; + ModuleEntry.dwSize = sizeof MODULEENTRY32; + + if(!Module32First(Toolhelp, &ModuleEntry)) + return RemoteModule{}; + + while(Module32Next(Toolhelp, &ModuleEntry)) + { + printf("%s\n", ModuleEntry.szModule); + if(strstr(ModuleEntry.szModule, ModuleName)) + { + CloseHandle(Toolhelp); + return RemoteModule(ModuleEntry.hModule); + } + } + + CloseHandle(Toolhelp); + return RemoteModule{}; + } } \ No newline at end of file diff --git a/csgo-loader/csgo-client/RemoteCode/RemoteProcess.hpp b/csgo-loader/csgo-client/RemoteCode/RemoteProcess.hpp index b1c716b..d86ecfa 100644 --- a/csgo-loader/csgo-client/RemoteCode/RemoteProcess.hpp +++ b/csgo-loader/csgo-client/RemoteCode/RemoteProcess.hpp @@ -2,35 +2,32 @@ #include #include +#include #include #include -namespace RemoteCode { +namespace RemoteCode +{ // The module wrapper. class RemoteProcess; - class RemoteModule { + class RemoteModule + { HANDLE m_Module; - int32_t m_SizeOfModule; - - // All the module data will be read upon class initialisation. - ByteArray m_ModuleData; public: - // The constructor (reads all module data into m_ModuleData). - RemoteModule(HANDLE Module, RemoteProcess &Process); - - // TODO: Add support for wild-cards (not currently implemented) - uintptr_t Scan(ByteArray &Pattern); + RemoteModule() = default; + RemoteModule(HANDLE Module); + ~RemoteModule() { CloseHandle(m_Module); } // Allow us to access the module by just passing the // handle as a parameter. operator HANDLE() { return m_Module; } - operator HINSTANCE() { return (HINSTANCE)m_Module; } }; // The process wrapper. - class RemoteProcess { + class RemoteProcess + { HANDLE m_Process; int32_t m_ProcessId; @@ -42,12 +39,14 @@ namespace RemoteCode { RemoteProcess() = default; // For portability, will ignore exceptions. - RemoteProcess(const char *ProcessName) { + RemoteProcess(const char *ProcessName) + { Start(ProcessName); } // Release the handle when the process goes out of scope. - ~RemoteProcess() { + ~RemoteProcess() + { if(m_Process) CloseHandle(m_Process); } @@ -57,25 +56,29 @@ namespace RemoteCode { // Writes to the process memory. template - void Write(void *Address, T Data) { + void Write(void *Address, T Data) + { WriteMemoryWrapper_Internal(Address, (void *)&Data, sizeof T); } - void Write(void *Address, uint8_t *Data, size_t SizeOfData) { - WriteMemoryWrapper_Internal(Address, (void *)Data, SizeOfData); + void Write(void *Address, uint8_t *Data, size_t SizeOfData) + { + WriteMemoryWrapper_Internal(Address, (void *)&Data, SizeOfData); } - + // Reads from the process memory. template - T Read(void *Address) { + T Read(void *Address) + { T Buffer{}; ReadMemoryWrapper_Internal(Address, (void *)&Buffer, sizeof T); - + return Buffer; } - void Read(void *Address, uint8_t *Data, size_t SizeOfData) { - ReadMemoryWrapper_Internal(Address, (void *)Data, SizeOfData); + void Read(void *Address, uint8_t *Data, size_t SizeOfData) + { + ReadMemoryWrapper_Internal(Address, &Data, SizeOfData); } // Allocates a memory region in the process. diff --git a/csgo-loader/csgo-client/Security/Encryption.cpp b/csgo-loader/csgo-client/Security/Encryption.cpp index 7d4fd05..4d42ee7 100644 --- a/csgo-loader/csgo-client/Security/Encryption.cpp +++ b/csgo-loader/csgo-client/Security/Encryption.cpp @@ -6,7 +6,8 @@ #define KEY_SIZE 32 #define NUM_ROUNDS 14 -namespace Wrapper { +namespace Wrapper +{ // Constants used for the AES256 algorithm. uint8_t sbox[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, @@ -87,15 +88,18 @@ namespace Wrapper { , m_rkey(ByteArray(KEY_SIZE, 0)) , m_buffer_pos(0) , m_remainingLength(0) - , m_decryptInitialized(false) { + , m_decryptInitialized(false) + { for(ByteArray::size_type i = 0; i < m_key.size(); ++i) m_key[i] = key[i]; } - Aes256::~Aes256() { + Aes256::~Aes256() + { } - ByteArray::size_type Aes256::encrypt(const ByteArray& key, const ByteArray& plain, ByteArray& encrypted) { + ByteArray::size_type Aes256::encrypt(const ByteArray& key, const ByteArray& plain, ByteArray& encrypted) + { Aes256 aes(key); aes.encrypt_start(plain.size(), encrypted); @@ -105,7 +109,8 @@ namespace Wrapper { return encrypted.size(); } - ByteArray::size_type Aes256::encrypt(const ByteArray& key, const unsigned char* plain, const ByteArray::size_type plain_length, ByteArray& encrypted) { + ByteArray::size_type Aes256::encrypt(const ByteArray& key, const unsigned char* plain, const ByteArray::size_type plain_length, ByteArray& encrypted) + { Aes256 aes(key); aes.encrypt_start(plain_length, encrypted); @@ -115,7 +120,8 @@ namespace Wrapper { return encrypted.size(); } - ByteArray::size_type Aes256::decrypt(const ByteArray& key, const ByteArray& encrypted, ByteArray& plain) { + ByteArray::size_type Aes256::decrypt(const ByteArray& key, const ByteArray& encrypted, ByteArray& plain) + { Aes256 aes(key); aes.decrypt_start(encrypted.size()); @@ -125,7 +131,8 @@ namespace Wrapper { return plain.size(); } - ByteArray::size_type Aes256::decrypt(const ByteArray& key, const unsigned char* encrypted, const ByteArray::size_type encrypted_length, ByteArray& plain) { + ByteArray::size_type Aes256::decrypt(const ByteArray& key, const unsigned char* encrypted, const ByteArray::size_type encrypted_length, ByteArray& plain) + { Aes256 aes(key); aes.decrypt_start(encrypted_length); @@ -135,7 +142,8 @@ namespace Wrapper { return plain.size(); } - ByteArray::size_type Aes256::encrypt_start(const ByteArray::size_type plain_length, ByteArray& encrypted) { + ByteArray::size_type Aes256::encrypt_start(const ByteArray::size_type plain_length, ByteArray& encrypted) + { m_remainingLength = plain_length; // Generate salt @@ -163,10 +171,12 @@ namespace Wrapper { return encrypted.size(); } - ByteArray::size_type Aes256::encrypt_continue(const ByteArray& plain, ByteArray& encrypted) { + ByteArray::size_type Aes256::encrypt_continue(const ByteArray& plain, ByteArray& encrypted) + { ByteArray::const_iterator it = plain.begin(), itEnd = plain.end(); - while(it != itEnd) { + while(it != itEnd) + { m_buffer[m_buffer_pos++] = *(it++); check_and_encrypt_buffer(encrypted); @@ -175,10 +185,12 @@ namespace Wrapper { return encrypted.size(); } - ByteArray::size_type Aes256::encrypt_continue(const unsigned char* plain, const ByteArray::size_type plain_length, ByteArray& encrypted) { + ByteArray::size_type Aes256::encrypt_continue(const unsigned char* plain, const ByteArray::size_type plain_length, ByteArray& encrypted) + { ByteArray::size_type i = 0; - while(i < plain_length) { + while(i < plain_length) + { m_buffer[m_buffer_pos++] = plain[i++]; check_and_encrypt_buffer(encrypted); @@ -187,11 +199,14 @@ namespace Wrapper { return encrypted.size(); } - void Aes256::check_and_encrypt_buffer(ByteArray& encrypted) { - if(m_buffer_pos == BLOCK_SIZE) { + void Aes256::check_and_encrypt_buffer(ByteArray& encrypted) + { + if(m_buffer_pos == BLOCK_SIZE) + { encrypt(m_buffer); - for(m_buffer_pos = 0; m_buffer_pos < BLOCK_SIZE; ++m_buffer_pos) { + for(m_buffer_pos = 0; m_buffer_pos < BLOCK_SIZE; ++m_buffer_pos) + { encrypted.push_back(m_buffer[m_buffer_pos]); --m_remainingLength; } @@ -200,14 +215,17 @@ namespace Wrapper { } } - ByteArray::size_type Aes256::encrypt_end(ByteArray& encrypted) { - if(m_buffer_pos > 0) { + ByteArray::size_type Aes256::encrypt_end(ByteArray& encrypted) + { + if(m_buffer_pos > 0) + { while(m_buffer_pos < BLOCK_SIZE) m_buffer[m_buffer_pos++] = 0; encrypt(m_buffer); - for(m_buffer_pos = 0; m_buffer_pos < BLOCK_SIZE; ++m_buffer_pos) { + for(m_buffer_pos = 0; m_buffer_pos < BLOCK_SIZE; ++m_buffer_pos) + { encrypted.push_back(m_buffer[m_buffer_pos]); --m_remainingLength; } @@ -218,12 +236,14 @@ namespace Wrapper { return encrypted.size(); } - void Aes256::encrypt(unsigned char* buffer) { + void Aes256::encrypt(unsigned char* buffer) + { unsigned char i, rcon; copy_key(); add_round_key(buffer, 0); - for(i = 1, rcon = 1; i < NUM_ROUNDS; ++i) { + for(i = 1, rcon = 1; i < NUM_ROUNDS; ++i) + { sub_bytes(buffer); shift_rows(buffer); mix_columns(buffer); @@ -237,7 +257,8 @@ namespace Wrapper { add_round_key(buffer, i); } - ByteArray::size_type Aes256::decrypt_start(const ByteArray::size_type encrypted_length) { + ByteArray::size_type Aes256::decrypt_start(const ByteArray::size_type encrypted_length) + { unsigned char j; m_remainingLength = encrypted_length; @@ -255,10 +276,12 @@ namespace Wrapper { return m_remainingLength; } - ByteArray::size_type Aes256::decrypt_continue(const ByteArray& encrypted, ByteArray& plain) { + ByteArray::size_type Aes256::decrypt_continue(const ByteArray& encrypted, ByteArray& plain) + { ByteArray::const_iterator it = encrypted.begin(), itEnd = encrypted.end(); - while(it != itEnd) { + while(it != itEnd) + { m_buffer[m_buffer_pos++] = *(it++); check_and_decrypt_buffer(plain); @@ -267,10 +290,12 @@ namespace Wrapper { return plain.size(); } - ByteArray::size_type Aes256::decrypt_continue(const unsigned char* encrypted, const ByteArray::size_type encrypted_length, ByteArray& plain) { + ByteArray::size_type Aes256::decrypt_continue(const unsigned char* encrypted, const ByteArray::size_type encrypted_length, ByteArray& plain) + { ByteArray::size_type i = 0; - while(i < encrypted_length) { + while(i < encrypted_length) + { m_buffer[m_buffer_pos++] = encrypted[i++]; check_and_decrypt_buffer(plain); @@ -279,8 +304,10 @@ namespace Wrapper { return plain.size(); } - void Aes256::check_and_decrypt_buffer(ByteArray& plain) { - if(!m_decryptInitialized && m_buffer_pos == m_salt.size() + 1) { + void Aes256::check_and_decrypt_buffer(ByteArray& plain) + { + if(!m_decryptInitialized && m_buffer_pos == m_salt.size() + 1) + { unsigned char j; ByteArray::size_type padding; @@ -297,11 +324,13 @@ namespace Wrapper { m_decryptInitialized = true; } - else if(m_decryptInitialized && m_buffer_pos == BLOCK_SIZE) { + else if(m_decryptInitialized && m_buffer_pos == BLOCK_SIZE) + { decrypt(m_buffer); for(m_buffer_pos = 0; m_buffer_pos < BLOCK_SIZE; ++m_buffer_pos) - if(m_remainingLength > 0) { + if(m_remainingLength > 0) + { plain.push_back(m_buffer[m_buffer_pos]); --m_remainingLength; } @@ -310,11 +339,13 @@ namespace Wrapper { } } - ByteArray::size_type Aes256::decrypt_end(ByteArray& plain) { + ByteArray::size_type Aes256::decrypt_end(ByteArray& plain) + { return plain.size(); } - void Aes256::decrypt(unsigned char* buffer) { + void Aes256::decrypt(unsigned char* buffer) + { unsigned char i, rcon = 1; copy_key(); @@ -325,7 +356,8 @@ namespace Wrapper { shift_rows_inv(buffer); sub_bytes_inv(buffer); - for(i = NUM_ROUNDS, rcon = 0x80; --i;) { + for(i = NUM_ROUNDS, rcon = 0x80; --i;) + { if((i & 1)) expand_dec_key(&rcon); add_round_key(buffer, i); @@ -336,7 +368,8 @@ namespace Wrapper { add_round_key(buffer, i); } - void Aes256::expand_enc_key(unsigned char* rc) { + void Aes256::expand_enc_key(unsigned char* rc) + { unsigned char i; m_rkey[0] = m_rkey[0] ^ sbox[m_rkey[29]] ^ (*rc); @@ -345,7 +378,8 @@ namespace Wrapper { m_rkey[3] = m_rkey[3] ^ sbox[m_rkey[28]]; *rc = FE(*rc); - for(i = 4; i < 16; i += 4) { + for(i = 4; i < 16; i += 4) + { m_rkey[i] = m_rkey[i] ^ m_rkey[i - 4]; m_rkey[i + 1] = m_rkey[i + 1] ^ m_rkey[i - 3]; m_rkey[i + 2] = m_rkey[i + 2] ^ m_rkey[i - 2]; @@ -356,7 +390,8 @@ namespace Wrapper { m_rkey[18] = m_rkey[18] ^ sbox[m_rkey[14]]; m_rkey[19] = m_rkey[19] ^ sbox[m_rkey[15]]; - for(i = 20; i < 32; i += 4) { + for(i = 20; i < 32; i += 4) + { m_rkey[i] = m_rkey[i] ^ m_rkey[i - 4]; m_rkey[i + 1] = m_rkey[i + 1] ^ m_rkey[i - 3]; m_rkey[i + 2] = m_rkey[i + 2] ^ m_rkey[i - 2]; @@ -364,10 +399,12 @@ namespace Wrapper { } } - void Aes256::expand_dec_key(unsigned char* rc) { + void Aes256::expand_dec_key(unsigned char* rc) + { unsigned char i; - for(i = 28; i > 16; i -= 4) { + for(i = 28; i > 16; i -= 4) + { m_rkey[i + 0] = m_rkey[i + 0] ^ m_rkey[i - 4]; m_rkey[i + 1] = m_rkey[i + 1] ^ m_rkey[i - 3]; m_rkey[i + 2] = m_rkey[i + 2] ^ m_rkey[i - 2]; @@ -379,7 +416,8 @@ namespace Wrapper { m_rkey[18] = m_rkey[18] ^ sbox[m_rkey[14]]; m_rkey[19] = m_rkey[19] ^ sbox[m_rkey[15]]; - for(i = 12; i > 0; i -= 4) { + for(i = 12; i > 0; i -= 4) + { m_rkey[i + 0] = m_rkey[i + 0] ^ m_rkey[i - 4]; m_rkey[i + 1] = m_rkey[i + 1] ^ m_rkey[i - 3]; m_rkey[i + 2] = m_rkey[i + 2] ^ m_rkey[i - 2]; @@ -393,21 +431,24 @@ namespace Wrapper { m_rkey[3] = m_rkey[3] ^ sbox[m_rkey[28]]; } - void Aes256::sub_bytes(unsigned char* buffer) { + void Aes256::sub_bytes(unsigned char* buffer) + { unsigned char i = KEY_SIZE / 2; while(i--) buffer[i] = sbox[buffer[i]]; } - void Aes256::sub_bytes_inv(unsigned char* buffer) { + void Aes256::sub_bytes_inv(unsigned char* buffer) + { unsigned char i = KEY_SIZE / 2; while(i--) buffer[i] = sboxinv[buffer[i]]; } - void Aes256::copy_key() { + void Aes256::copy_key() + { ByteArray::size_type i; for(i = 0; i < m_key.size(); ++i) @@ -416,14 +457,16 @@ namespace Wrapper { m_rkey[i + m_key.size()] = m_salt[i]; } - void Aes256::add_round_key(unsigned char* buffer, const unsigned char round) { + void Aes256::add_round_key(unsigned char* buffer, const unsigned char round) + { unsigned char i = KEY_SIZE / 2; while(i--) buffer[i] ^= m_rkey[(round & 1) ? i + 16 : i]; } - void Aes256::shift_rows(unsigned char* buffer) { + void Aes256::shift_rows(unsigned char* buffer) + { unsigned char i, j, k, l; /* to make it potentially parallelable :) */ i = buffer[1]; @@ -447,7 +490,8 @@ namespace Wrapper { buffer[6] = l; } - void Aes256::shift_rows_inv(unsigned char* buffer) { + void Aes256::shift_rows_inv(unsigned char* buffer) + { unsigned char i, j, k, l; /* same as above :) */ i = buffer[1]; @@ -471,10 +515,12 @@ namespace Wrapper { buffer[14] = l; } - void Aes256::mix_columns(unsigned char* buffer) { + void Aes256::mix_columns(unsigned char* buffer) + { unsigned char i, a, b, c, d, e; - for(i = 0; i < 16; i += 4) { + for(i = 0; i < 16; i += 4) + { a = buffer[i]; b = buffer[i + 1]; c = buffer[i + 2]; @@ -489,10 +535,12 @@ namespace Wrapper { } } - void Aes256::mix_columns_inv(unsigned char* buffer) { + void Aes256::mix_columns_inv(unsigned char* buffer) + { unsigned char i, a, b, c, d, e, x, y, z; - for(i = 0; i < 16; i += 4) { + for(i = 0; i < 16; i += 4) + { a = buffer[i]; b = buffer[i + 1]; c = buffer[i + 2]; @@ -509,15 +557,19 @@ namespace Wrapper { } } - inline unsigned char rj_xtime(unsigned char x) { + inline unsigned char rj_xtime(unsigned char x) + { return (x & 0x80) ? ((x << 1) ^ 0x1b) : (x << 1); } // Wrapper for the AES256 encryption algorithm. - void Encryption::Start() { + void Encryption::Start() + { // Create cryptographic context. - if(!CryptAcquireContextA(&m_CryptProvider, nullptr, nullptr, PROV_RSA_AES, 0)) { - if(!CryptAcquireContextA(&m_CryptProvider, nullptr, nullptr, PROV_RSA_AES, CRYPT_NEWKEYSET)) { + if(!CryptAcquireContextA(&m_CryptProvider, nullptr, nullptr, PROV_RSA_AES, 0)) + { + if(!CryptAcquireContextA(&m_CryptProvider, nullptr, nullptr, PROV_RSA_AES, CRYPT_NEWKEYSET)) + { printf("Failed to initialise encryption provider.\n"); return; } @@ -527,7 +579,8 @@ namespace Wrapper { uint32_t RandomBytesCount = sizeof RandomBytes; // Generate random bytes to use as encryption key. - if(CryptGenRandom(m_CryptProvider, RandomBytesCount, RandomBytes)) { + if(CryptGenRandom(m_CryptProvider, RandomBytesCount, RandomBytes)) + { m_EncryptionKey.reserve(RandomBytesCount); m_EncryptionKey.insert( m_EncryptionKey.begin(), @@ -541,19 +594,23 @@ namespace Wrapper { CryptReleaseContext(m_CryptProvider, 0); } - void Encryption::Start(ByteArray &EncryptionKey) { + void Encryption::Start(ByteArray &EncryptionKey) + { // If an encryption key is provided, initialise the wrapper with // the passed parameter. - if(!EncryptionKey.empty()) { + if(!EncryptionKey.empty()) + { m_EncryptionKey.reserve(EncryptionKey.size()); std::copy(EncryptionKey.begin(), EncryptionKey.end(), m_EncryptionKey.begin()); } - else { + else + { Start(); } } - ByteArray Encryption::Encrypt(ByteArray &Data) { + ByteArray Encryption::Encrypt(ByteArray &Data) + { // Encrypt outgoing data. ByteArray Encrypted; @@ -566,7 +623,8 @@ namespace Wrapper { return Encrypted; } - ByteArray Encryption::Decrypt(ByteArray &Data) { + ByteArray Encryption::Decrypt(ByteArray &Data) + { // Decrypt incoming data. ByteArray Decrypted; diff --git a/csgo-loader/csgo-client/Security/Encryption.hpp b/csgo-loader/csgo-client/Security/Encryption.hpp index d55608f..b1c49dc 100644 --- a/csgo-loader/csgo-client/Security/Encryption.hpp +++ b/csgo-loader/csgo-client/Security/Encryption.hpp @@ -9,9 +9,11 @@ using ByteArray = std::vector; #define BLOCK_SIZE 16 -namespace Wrapper { +namespace Wrapper +{ // AES256 implementation. - class Aes256 { + class Aes256 + { public: Aes256(const ByteArray& key); @@ -67,7 +69,8 @@ namespace Wrapper { }; // Encryption wrapper. - class Encryption { + class Encryption + { ByteArray m_EncryptionKey; HCRYPTPROV m_CryptProvider; @@ -82,7 +85,8 @@ namespace Wrapper { ByteArray Decrypt(ByteArray &Data); // Exposes the encryption key. - ByteArray GetKey() { + ByteArray GetKey() + { return m_EncryptionKey; } }; diff --git a/csgo-loader/csgo-client/Security/FnvHash.hpp b/csgo-loader/csgo-client/Security/FnvHash.hpp index da7e80d..35c9ad0 100644 --- a/csgo-loader/csgo-client/Security/FnvHash.hpp +++ b/csgo-loader/csgo-client/Security/FnvHash.hpp @@ -4,9 +4,11 @@ // Credits: namazso // Implements FNV-1a hash algorithm -namespace detail { +namespace detail +{ template - struct SizeDependantData { + struct SizeDependantData + { using type = Type; constexpr static auto k_offset_basis = OffsetBasis; @@ -23,7 +25,8 @@ namespace detail { struct SizeSelector<64> : SizeDependantData {}; template - class FnvHash { + class FnvHash + { private: using data_t = SizeSelector; @@ -36,14 +39,16 @@ namespace detail { public: static __forceinline constexpr auto hash_init( - ) -> hash { + ) -> hash + { return k_offset_basis; } static __forceinline constexpr auto hash_byte( hash current, std::uint8_t byte - ) -> hash { + ) -> hash + { return (current ^ byte) * k_prime; } @@ -51,7 +56,8 @@ namespace detail { static __forceinline constexpr auto hash_constexpr( const char(&str)[N], const std::size_t size = N - 1 /* do not hash the null */ - ) -> hash { + ) -> hash + { const auto prev_hash = size == 1 ? hash_init() : hash_constexpr(str, size - 1); const auto cur_hash = hash_byte(prev_hash, str[size - 1]); return cur_hash; @@ -60,7 +66,8 @@ namespace detail { static auto __forceinline hash_runtime_data( const void* data, const std::size_t sz - ) -> hash { + ) -> hash + { const auto bytes = static_cast(data); const auto end = bytes + sz; auto result = hash_init(); @@ -72,7 +79,8 @@ namespace detail { static auto __forceinline hash_runtime( const char* str - ) -> hash { + ) -> hash + { auto result = hash_init(); do result = hash_byte(result, *str++); diff --git a/csgo-loader/csgo-client/Security/SyscallManager.cpp b/csgo-loader/csgo-client/Security/SyscallManager.cpp index 55d68a3..9de2459 100644 --- a/csgo-loader/csgo-client/Security/SyscallManager.cpp +++ b/csgo-loader/csgo-client/Security/SyscallManager.cpp @@ -4,17 +4,21 @@ // Global accessor for SyscallManager. Wrapper::SyscallManagerPtr Syscalls = std::make_unique(); -namespace Wrapper { - void SyscallStub::SetIndex(uint32_t Index) { +namespace Wrapper +{ + void SyscallStub::SetIndex(uint32_t Index) + { unsigned long OldProtection{}; - + // Make the code executable and set the index. - if(VirtualProtect(m_Shellcode, sizeof m_Shellcode, PAGE_EXECUTE_READWRITE, &OldProtection)) { + if(VirtualProtect(m_Shellcode, sizeof m_Shellcode, PAGE_EXECUTE_READWRITE, &OldProtection)) + { *(uint32_t *)(&m_Shellcode[4]) = Index; } } - ByteArray SyscallManager::GetNtdllFromDisk() { + ByteArray SyscallManager::GetNtdllFromDisk() + { char SystemPath[MAX_PATH]; GetSystemDirectoryA(SystemPath, MAX_PATH); @@ -42,7 +46,8 @@ namespace Wrapper { } // Stolen :-) - uint64_t SyscallManager::GetRawOffsetByRva(IMAGE_SECTION_HEADER *SectionHeader, uint64_t Sections, uint64_t FileSize, uint64_t Rva) { + uint64_t SyscallManager::GetRawOffsetByRva(IMAGE_SECTION_HEADER *SectionHeader, uint64_t Sections, uint64_t FileSize, uint64_t Rva) + { IMAGE_SECTION_HEADER *Header = GetSectionByRva(SectionHeader, Sections, Rva); if(!Header) @@ -59,10 +64,12 @@ namespace Wrapper { return Offset; } - IMAGE_SECTION_HEADER *SyscallManager::GetSectionByRva(IMAGE_SECTION_HEADER *SectionHeader, uint64_t Sections, uint64_t Rva) { + IMAGE_SECTION_HEADER *SyscallManager::GetSectionByRva(IMAGE_SECTION_HEADER *SectionHeader, uint64_t Sections, uint64_t Rva) + { IMAGE_SECTION_HEADER *Header = SectionHeader; - for(size_t i{}; i < Sections; ++i, ++Header) { + for(size_t i{}; i < Sections; ++i, ++Header) + { uint64_t VirtualAddress = Header->VirtualAddress; uint64_t AddressBounds = VirtualAddress + Header->SizeOfRawData; @@ -74,9 +81,10 @@ namespace Wrapper { } // Sick macros, retard. - #define GetRvaPointer(Rva) (Buffer + GetRawOffsetByRva(SectionHeader, SectionCount, FileSize, Rva)) +#define GetRvaPointer(Rva) (Buffer + GetRawOffsetByRva(SectionHeader, SectionCount, FileSize, Rva)) - bool SyscallManager::Start() { + bool SyscallManager::Start() + { // Read contents of NTDLL. ByteArray Ntdll = GetNtdllFromDisk(); @@ -101,7 +109,7 @@ namespace Wrapper { if(!SectionHeader) return false; - + uint64_t ExportRva = NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; uint64_t ExportSize = NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; uint64_t ExportRaw = GetRawOffsetByRva(SectionHeader, SectionCount, FileSize, ExportRva); @@ -120,7 +128,8 @@ namespace Wrapper { return false; // Loop each exported symbol. - for(uint32_t n{}; n < ExportDirectory->NumberOfNames; ++n) { + for(uint32_t n{}; n < ExportDirectory->NumberOfNames; ++n) + { uint32_t NameRva = Names[n]; uint32_t FunctionRva = Functions[Ordinals[n]]; @@ -129,10 +138,11 @@ namespace Wrapper { // We've found a syscall. uint8_t *Opcodes = (uint8_t *)(Buffer + FunctionRawOffset); - - if(!memcmp(Opcodes, "\x4C\x8B\xD1\xB8", 4)) { + + if(!memcmp(Opcodes, "\x4C\x8B\xD1\xB8", 4)) + { uint32_t SyscallIndex = *(uint32_t *)(Buffer + FunctionRawOffset + 4); - + char *SyscallName = (char *)(Buffer + NameRawOffset); uint64_t SyscallNameHash = fnv::hash_runtime(SyscallName); diff --git a/csgo-loader/csgo-client/Security/SyscallManager.hpp b/csgo-loader/csgo-client/Security/SyscallManager.hpp index e154625..a9c67aa 100644 --- a/csgo-loader/csgo-client/Security/SyscallManager.hpp +++ b/csgo-loader/csgo-client/Security/SyscallManager.hpp @@ -11,9 +11,11 @@ using ByteArray = std::vector; -namespace Wrapper { +namespace Wrapper +{ // A stub used for our syscalls. - class SyscallStub { + class SyscallStub + { // The shellcode which executes a low latency system call. uint8_t m_Shellcode[11] = { 0x4C, 0x8B, 0xD1, // mov r10, rcx @@ -28,14 +30,16 @@ namespace Wrapper { // Sets the syscall index. void SetIndex(uint32_t Index); - __forceinline uintptr_t Get() { + __forceinline uintptr_t Get() + { return (uintptr_t)m_Shellcode; } }; // Manager for system calls. Used to iterate NTDLL for all syscall indices. // Read: https://www.evilsocket.net/2014/02/11/on-windows-syscall-mechanism-and-syscall-numbers-extraction-methods/ - class SyscallManager { + class SyscallManager + { // Reading NTDLL from disk because it cannot be modified // due to restrictions put in place by PatchGuard. ByteArray GetNtdllFromDisk(); @@ -54,7 +58,8 @@ namespace Wrapper { // Finds a syscall by hash. template < typename T > - T Find(uint64_t Hash) { + T Find(uint64_t Hash) + { return (T)m_Syscalls[Hash].Get(); } }; diff --git a/csgo-loader/csgo-client/UserExperience/UserInterface.cpp b/csgo-loader/csgo-client/UserExperience/UserInterface.cpp index f8f465f..af1b384 100644 --- a/csgo-loader/csgo-client/UserExperience/UserInterface.cpp +++ b/csgo-loader/csgo-client/UserExperience/UserInterface.cpp @@ -7,11 +7,15 @@ // Global accessor for the user interface. UserExperience::UserInterfacePtr UserInterface = std::make_unique(); -namespace UserExperience { - void OnDirectXFrame() { - if(g_d3d.run_frame(g_window.m_d3d_device)) { +namespace UserExperience +{ + void OnDirectXFrame() + { + if(g_d3d.run_frame(g_window.m_d3d_device)) + { g_d3d.begin(); - for(auto& it : d3d::sprites) { + for(auto& it : d3d::sprites) + { it->begin(g_window.m_d3d_device); } @@ -25,10 +29,12 @@ namespace UserExperience { constexpr float anim_step = 1.0f / 15.f; static float anim_time = 0.f; static bool flip = false; - if(anim_time == 1.0f) { + if(anim_time == 1.0f) + { flip = true; } - if(anim_time == 0.f) { + if(anim_time == 0.f) + { flip = false; } @@ -42,16 +48,19 @@ namespace UserExperience { GetWindowRect(g_window.get_hwnd(), &cur_rect); g_d3d.end(); - for(auto& it : d3d::sprites) { + for(auto& it : d3d::sprites) + { it->end(); } } } - bool UserInterface::Start() { + bool UserInterface::Start() + { bool result = g_window.create(); - - if(result) { + + if(result) + { std::this_thread::sleep_for(std::chrono::milliseconds(100)); g_window.add_on_frame(&OnDirectXFrame); } @@ -59,7 +68,8 @@ namespace UserExperience { return result; } - void UserInterface::RunUiFrame() { + void UserInterface::RunUiFrame() + { g_window.on_frame(); } } \ No newline at end of file diff --git a/csgo-loader/csgo-client/UserExperience/UserInterface.hpp b/csgo-loader/csgo-client/UserExperience/UserInterface.hpp index 332b042..bea8b45 100644 --- a/csgo-loader/csgo-client/UserExperience/UserInterface.hpp +++ b/csgo-loader/csgo-client/UserExperience/UserInterface.hpp @@ -5,24 +5,28 @@ #include #include -namespace UserExperience { +namespace UserExperience +{ // Execution states define a moment in the execution of the loader. // These may be changed externally by other threads. - enum ExecutionState : uint16_t { + enum ExecutionState : uint16_t + { EXECUTION_WAITING, // Displays the message 'please wait...'. EXECUTION_ERROR, // Displays an error. EXECUTION_LOG_IN, // Displays the log-in dialog. EXECUTION_CHOOSE // Displays the game selection dialog. }; - enum ErrorReason : uint16_t { + enum ErrorReason : uint16_t + { ERROR_GENERIC_ERROR, ERROR_INVALID_HWID, ERROR_SHADOW_BAN }; // Structure that holds global data that will be used by the UI. - struct UserExperienceData { + struct UserExperienceData + { // Holds the current execution state of the loader. ExecutionState m_ExecutionState = EXECUTION_WAITING; @@ -41,7 +45,8 @@ namespace UserExperience { }; // User experience handler. - class UserInterface { + class UserInterface + { public: UserExperienceData m_Data; @@ -51,7 +56,7 @@ namespace UserExperience { // Creates an UI thread, call only once. void RunUiFrame(); }; - + using UserInterfacePtr = std::unique_ptr; } diff --git a/csgo-loader/csgo-client/csgo-client.vcxproj b/csgo-loader/csgo-client/csgo-client.vcxproj index 9dc8b61..5c839dc 100644 --- a/csgo-loader/csgo-client/csgo-client.vcxproj +++ b/csgo-loader/csgo-client/csgo-client.vcxproj @@ -22,6 +22,8 @@ + + @@ -35,6 +37,8 @@ + + diff --git a/csgo-loader/csgo-client/csgo-client.vcxproj.filters b/csgo-loader/csgo-client/csgo-client.vcxproj.filters index 2040b2b..049be28 100644 --- a/csgo-loader/csgo-client/csgo-client.vcxproj.filters +++ b/csgo-loader/csgo-client/csgo-client.vcxproj.filters @@ -55,6 +55,12 @@ RemoteCode + + RemoteCode + + + RemoteCode + @@ -150,5 +156,11 @@ RemoteCode + + RemoteCode + + + RemoteCode + \ No newline at end of file diff --git a/csgo-loader/csgo-server/Login/RemoteLogin.cpp b/csgo-loader/csgo-server/Login/RemoteLogin.cpp index 880c072..b9ee44b 100644 --- a/csgo-loader/csgo-server/Login/RemoteLogin.cpp +++ b/csgo-loader/csgo-server/Login/RemoteLogin.cpp @@ -2,8 +2,10 @@ #define EXPECTED_CLIENT_HEADER 0xDEADBEEF -namespace Login { - bool RemoteLoginServer::Start(ByteArray &RawLoginHeader) { +namespace Login +{ + bool RemoteLoginServer::Start(ByteArray &RawLoginHeader) + { if(RawLoginHeader.empty()) return false; @@ -12,35 +14,60 @@ namespace Login { return true; } - RemoteLoginResponse RemoteLoginServer::GetLoginResponse() { + RemoteLoginResponse RemoteLoginServer::GetLoginResponse() + { // The header seems to be wrong, tell the client to update. if(m_Header.m_ClientHeader != EXPECTED_CLIENT_HEADER) return RemoteLoginResponse::OUTDATED_CLIENT; - // TODO: Check login, HWID, bans with websockets. + // TODO: Check if the user is banned. + //return RemoteLoginResponse::USER_BANNED; + + // TODO: Login the user. + if(strcmp(m_Header.m_Username, "betauser")) + return RemoteLoginResponse::INVALID_CREDENTIALS; + + if(strcmp(m_Header.m_Password, "betapassword")) + return RemoteLoginResponse::INVALID_CREDENTIALS; // User failed to obtain HWID? - if(!m_Header.m_HardwareId) { + if(!m_Header.m_HardwareId) + { // TODO: Shadow ban the user. - //return RemoteLoginResponse::INVALID_HARDWARE; + return RemoteLoginResponse::INVALID_HARDWARE; } + // TODO: Check if the HWID is present in DB. + if(false) + return RemoteLoginResponse::INVALID_HARDWARE; + + // TODO: Check if the user has a subscription. + if(false) + return RemoteLoginResponse::NO_SUBSCRIPTION; + + // Checksum validation. uint8_t Checksum = m_Header.m_IntegrityBit1 - | m_Header.m_IntegrityBit2 - | m_Header.m_IntegrityBit3; + | m_Header.m_IntegrityBit2 + | m_Header.m_IntegrityBit3; - if(Checksum || Checksum != m_Header.m_IntegrityBit4) { + if(Checksum || Checksum != m_Header.m_IntegrityBit4) + { // TODO: Shadow ban the user. + return RemoteLoginResponse::INTEGRITY_FAILURE; } - // Assume that they are authorised to use the cheat. - return RemoteLoginResponse::ACCESS_SPECIAL_USER; + // TODO: Check if they have beta access. + if(true) + return RemoteLoginResponse::ACCESS_SPECIAL_USER; + + return RemoteLoginResponse::ACCESS_AUTHORISED; } - ByteArray RemoteLoginServer::GetResponse() { + ByteArray RemoteLoginServer::GetResponse() + { // The way the server handles data transmission is homosexual. // That is the only reason this autism is here. ByteArray Response; diff --git a/csgo-loader/csgo-server/Login/RemoteLogin.hpp b/csgo-loader/csgo-server/Login/RemoteLogin.hpp index 36b7252..5b31db1 100644 --- a/csgo-loader/csgo-server/Login/RemoteLogin.hpp +++ b/csgo-loader/csgo-server/Login/RemoteLogin.hpp @@ -6,9 +6,11 @@ using ByteArray = std::vector; -namespace Login { +namespace Login +{ // Login header that is sent over to the server - struct RemoteLoginHeader { + struct RemoteLoginHeader + { // The first four bytes are encoded by the client. // This will carry the client version which can be checked. uint32_t m_ClientHeader; @@ -32,7 +34,8 @@ namespace Login { // Possible server responses // The hardware ID is encoded (XORed with the message ID) within the message for // shadow ban/forum ban purposes. :) - enum RemoteLoginResponse : uint8_t { + enum RemoteLoginResponse : uint8_t + { OUTDATED_CLIENT = 'A', // '[000A:{HWID}] Your client is outdated. Please download the latest client at 'moneybot.cc'.' ACCESS_AUTHORISED = 'B', // Allows the user to continue with injection. INVALID_CREDENTIALS = 'C', // '[000C:{HWID}] Your credentials are invalid. Please check your spelling and try again.' @@ -43,7 +46,8 @@ namespace Login { ACCESS_SPECIAL_USER = 'H', // Allows the user to continue, sets the m_SpecialAccess var }; // Implementation of the server (handles login bullshit). - class RemoteLoginServer { + class RemoteLoginServer + { RemoteLoginHeader m_Header; // Polls the server for data, responds with whether or not the client @@ -53,7 +57,7 @@ namespace Login { public: // Initialises the login header. bool Start(ByteArray &RawLoginHeader); - + ByteArray GetResponse(); // TODO: Implement shadow banning based on IP and HWID. diff --git a/csgo-loader/csgo-server/Networking/TCPServer.cpp b/csgo-loader/csgo-server/Networking/TCPServer.cpp index 725bf1a..b6bc3bd 100644 --- a/csgo-loader/csgo-server/Networking/TCPServer.cpp +++ b/csgo-loader/csgo-server/Networking/TCPServer.cpp @@ -1,17 +1,20 @@ #include -namespace Networking { - void TCPConnection::Close() { +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) { + void TCPConnection::SendRawBytes(ByteArray &Bytes) + { // Send data. int32_t Result = send(m_Socket, (char *)Bytes.data(), (int)Bytes.size(), 0); @@ -21,12 +24,14 @@ namespace Networking { printf("[=>] Failed to send %zd bytes to %s. (Socket %04Ix)\n", Bytes.size(), m_IpAddress, m_Socket); } - ByteArray TCPConnection::ReceiveRawBytes() { + ByteArray TCPConnection::ReceiveRawBytes() + { ByteArray ReceivedBytes; uint8_t RecvBuffer[BufferSize]; // Attempt to receive a packet. - while(true) { + while(true) + { int32_t Received = recv(m_Socket, (char*)RecvBuffer, BufferSize, 0); // No more bytes left to receive. @@ -34,7 +39,8 @@ namespace Networking { break; // Emplace all received bytes. - for(int n = 0; n < Received; ++n) { + for(int n = 0; n < Received; ++n) + { ReceivedBytes.push_back(RecvBuffer[n]); } @@ -48,14 +54,16 @@ namespace Networking { return ReceivedBytes; } - void TCPConnection::SendBytes(ByteArray &Bytes) { + void TCPConnection::SendBytes(ByteArray &Bytes) + { // Encrypt outgoing data. ByteArray Encrypted = m_Encryption.Encrypt(Bytes); SendRawBytes(Encrypted); } - ByteArray TCPConnection::ReceiveBytes() { + ByteArray TCPConnection::ReceiveBytes() + { ByteArray ReceivedBytes = ReceiveRawBytes(); // Decrypt incoming data. @@ -64,7 +72,8 @@ namespace Networking { return Decrypted; } - bool TCPServer::Start(uint16_t ServerPort) { + bool TCPServer::Start(uint16_t ServerPort) + { const int32_t version = 0x101; // Initialise WinSocks. @@ -79,11 +88,11 @@ namespace Networking { // Set up server context. m_Context.sin_addr.s_addr = INADDR_ANY; - m_Context.sin_family = AF_INET; - m_Context.sin_port = htons(ServerPort); + 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; @@ -94,16 +103,18 @@ namespace Networking { return true; } - void TCPServer::AcceptConnection() { + 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) { + if(IncomingSocket != INVALID_SOCKET) + { Wrapper::Encryption Encryption; - + // Initialise encryption context. Encryption.Start(); @@ -114,7 +125,8 @@ namespace Networking { Connection.SendRawBytes(EncryptionKey); // Detach a thread to handle the connection. - std::thread thread([&] { + std::thread thread([&] + { m_ConnectionHandler(Connection); Connection.Close(); }); diff --git a/csgo-loader/csgo-server/Networking/TCPServer.hpp b/csgo-loader/csgo-server/Networking/TCPServer.hpp index adb6e7c..388bdc2 100644 --- a/csgo-loader/csgo-server/Networking/TCPServer.hpp +++ b/csgo-loader/csgo-server/Networking/TCPServer.hpp @@ -16,16 +16,19 @@ // std::thread #include -namespace Networking { +namespace Networking +{ // Base connection class, used to handle multiple connections in a thread-based model. - class TCPConnection { + 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) { + m_Encryption(RSA), m_Socket(Connection), m_IpAddress(IpAddress) + { printf("[=>] %s connected!\n", IpAddress); } @@ -40,12 +43,14 @@ namespace Networking { ByteArray ReceiveBytes(); // Overload for getting the socket, in case we need to expose it. - SOCKET operator()() { + SOCKET operator()() + { return m_Socket; } // Expose the encryption key for the connection. - ByteArray GetEncryptionKey() { + ByteArray GetEncryptionKey() + { return m_Encryption.GetKey(); } }; @@ -53,7 +58,8 @@ namespace Networking { // Basic TCP server. Supports custom connection handling (pass a lambda to the handler list). using ConnectionHandler = std::function; - class TCPServer { + class TCPServer + { WSADATA m_WinSocks; SOCKET m_Socket; sockaddr_in m_Context; @@ -64,9 +70,10 @@ namespace Networking { public: // Default constructor, nothing needed for now. TCPServer() = default; - + // Handle destruction of server once it goes out of scope. - ~TCPServer() { + ~TCPServer() + { // If we have a socket, close it. if(m_Socket) closesocket(m_Socket); @@ -80,7 +87,8 @@ namespace Networking { void AcceptConnection(); // Overload for adding connection handlers, C# style support for events. - void operator+=(std::function Function) { + void operator+=(std::function Function) + { m_ConnectionHandler = Function; } }; diff --git a/csgo-loader/csgo-server/Networking/WebSocket.cpp b/csgo-loader/csgo-server/Networking/WebSocket.cpp index 755e89b..2c42001 100644 --- a/csgo-loader/csgo-server/Networking/WebSocket.cpp +++ b/csgo-loader/csgo-server/Networking/WebSocket.cpp @@ -1,8 +1,10 @@ #include -namespace Networking { +namespace Networking +{ // Initialises a basic HTTP socket. - bool WebSocket::Start(const char *Address, const char *Username, const char *Password) { + 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) @@ -17,21 +19,25 @@ namespace Networking { } // Receives a response from a request. - ByteArray WebSocket::Request(const char *File, const char *Header, ByteArray &Data) { + 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) { + 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) { + while(InternetReadFile(WebRequest, Block, 4096, &ReceivedSize)) + { + for(size_t n{}; n < std::min< int >(4096, ReceivedSize); ++n) + { Response.push_back(Block[n]); } } diff --git a/csgo-loader/csgo-server/Networking/WebSocket.hpp b/csgo-loader/csgo-server/Networking/WebSocket.hpp index f503913..2087e89 100644 --- a/csgo-loader/csgo-server/Networking/WebSocket.hpp +++ b/csgo-loader/csgo-server/Networking/WebSocket.hpp @@ -10,26 +10,30 @@ using ByteArray = std::vector; -namespace Networking { +namespace Networking +{ // Whenever the handle goes out of scope, it will automatically be released. - class InternetHandle { + class InternetHandle + { HINTERNET m_Internet; public: InternetHandle() = default; InternetHandle(HINTERNET Internet) : m_Internet(Internet) { } - ~InternetHandle() { + ~InternetHandle() + { InternetCloseHandle(m_Internet); } - + operator HINTERNET() { return m_Internet; }; }; - class WebSocket { + 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); diff --git a/csgo-loader/csgo-server/RemoteCode/FileReader.cpp b/csgo-loader/csgo-server/RemoteCode/FileReader.cpp index e69de29..48fc374 100644 --- a/csgo-loader/csgo-server/RemoteCode/FileReader.cpp +++ b/csgo-loader/csgo-server/RemoteCode/FileReader.cpp @@ -0,0 +1,29 @@ +#include + +namespace RemoteCode +{ + bool FileReader::Start(const char *FileName) + { + std::ifstream File(FileName, std::ios::in | std::ios::binary); + + // File does not exist/is not open. + if(!File.is_open()) + return false; + + // Do not skip white-space, read file. + File.unsetf(std::ios::skipws); + m_Contents.insert( + m_Contents.begin(), + std::istream_iterator(File), + std::istream_iterator() + ); + + if(m_Contents.empty()) + return false; + + // Close the handle. + File.close(); + + return true; + } +} \ No newline at end of file diff --git a/csgo-loader/csgo-server/RemoteCode/FileReader.hpp b/csgo-loader/csgo-server/RemoteCode/FileReader.hpp index 50e9667..85e5770 100644 --- a/csgo-loader/csgo-server/RemoteCode/FileReader.hpp +++ b/csgo-loader/csgo-server/RemoteCode/FileReader.hpp @@ -1 +1,32 @@ #pragma once + +#include +#include +#include +#include + +using ByteArray = std::vector< uint8_t >; + +namespace RemoteCode +{ + class FileReader + { + // Contents of the file. + ByteArray m_Contents; + + public: + FileReader() = default; + + // Constructor (ignores exception-handling). + FileReader(const char *FileName) { Start(FileName); } + + // Read a file. + bool Start(const char *FileName); + + // Self-explanatory. + size_t GetFileLength() { return m_Contents.size(); } + + // Allow the user to walk the data. + operator uint8_t *() { return m_Contents.data(); } + }; +} \ No newline at end of file diff --git a/csgo-loader/csgo-server/RemoteCode/RemoteCodeServer.cpp b/csgo-loader/csgo-server/RemoteCode/RemoteCodeServer.cpp new file mode 100644 index 0000000..7e4b553 --- /dev/null +++ b/csgo-loader/csgo-server/RemoteCode/RemoteCodeServer.cpp @@ -0,0 +1 @@ +#include diff --git a/csgo-loader/csgo-server/RemoteCode/RemoteCodeServer.hpp b/csgo-loader/csgo-server/RemoteCode/RemoteCodeServer.hpp new file mode 100644 index 0000000..57f1499 --- /dev/null +++ b/csgo-loader/csgo-server/RemoteCode/RemoteCodeServer.hpp @@ -0,0 +1,6 @@ +#pragma once + +namespace RemoteCode +{ + +} \ No newline at end of file diff --git a/csgo-loader/csgo-server/RemoteCode/RemoteInjectionServer.cpp b/csgo-loader/csgo-server/RemoteCode/RemoteInjectionServer.cpp new file mode 100644 index 0000000..fd3efc0 --- /dev/null +++ b/csgo-loader/csgo-server/RemoteCode/RemoteInjectionServer.cpp @@ -0,0 +1 @@ +#include diff --git a/csgo-loader/csgo-server/RemoteCode/RemoteInjectionServer.hpp b/csgo-loader/csgo-server/RemoteCode/RemoteInjectionServer.hpp new file mode 100644 index 0000000..57f1499 --- /dev/null +++ b/csgo-loader/csgo-server/RemoteCode/RemoteInjectionServer.hpp @@ -0,0 +1,6 @@ +#pragma once + +namespace RemoteCode +{ + +} \ No newline at end of file diff --git a/csgo-loader/csgo-server/Security/Encryption.cpp b/csgo-loader/csgo-server/Security/Encryption.cpp index 94b9ee7..dc6ef84 100644 --- a/csgo-loader/csgo-server/Security/Encryption.cpp +++ b/csgo-loader/csgo-server/Security/Encryption.cpp @@ -6,7 +6,8 @@ #define KEY_SIZE 32 #define NUM_ROUNDS 14 -namespace Wrapper { +namespace Wrapper +{ // Constants used for the AES256 algorithm. uint8_t sbox[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, @@ -43,7 +44,7 @@ namespace Wrapper { 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; - uint8_t sboxinv[256] = { + uint8_t sboxinv[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, @@ -87,15 +88,18 @@ namespace Wrapper { , m_rkey(ByteArray(KEY_SIZE, 0)) , m_buffer_pos(0) , m_remainingLength(0) - , m_decryptInitialized(false) { + , m_decryptInitialized(false) + { for(ByteArray::size_type i = 0; i < m_key.size(); ++i) m_key[i] = key[i]; } - Aes256::~Aes256() { + Aes256::~Aes256() + { } - ByteArray::size_type Aes256::encrypt(const ByteArray& key, const ByteArray& plain, ByteArray& encrypted) { + ByteArray::size_type Aes256::encrypt(const ByteArray& key, const ByteArray& plain, ByteArray& encrypted) + { Aes256 aes(key); aes.encrypt_start(plain.size(), encrypted); @@ -105,7 +109,8 @@ namespace Wrapper { return encrypted.size(); } - ByteArray::size_type Aes256::encrypt(const ByteArray& key, const unsigned char* plain, const ByteArray::size_type plain_length, ByteArray& encrypted) { + ByteArray::size_type Aes256::encrypt(const ByteArray& key, const unsigned char* plain, const ByteArray::size_type plain_length, ByteArray& encrypted) + { Aes256 aes(key); aes.encrypt_start(plain_length, encrypted); @@ -115,7 +120,8 @@ namespace Wrapper { return encrypted.size(); } - ByteArray::size_type Aes256::decrypt(const ByteArray& key, const ByteArray& encrypted, ByteArray& plain) { + ByteArray::size_type Aes256::decrypt(const ByteArray& key, const ByteArray& encrypted, ByteArray& plain) + { Aes256 aes(key); aes.decrypt_start(encrypted.size()); @@ -125,7 +131,8 @@ namespace Wrapper { return plain.size(); } - ByteArray::size_type Aes256::decrypt(const ByteArray& key, const unsigned char* encrypted, const ByteArray::size_type encrypted_length, ByteArray& plain) { + ByteArray::size_type Aes256::decrypt(const ByteArray& key, const unsigned char* encrypted, const ByteArray::size_type encrypted_length, ByteArray& plain) + { Aes256 aes(key); aes.decrypt_start(encrypted_length); @@ -135,7 +142,8 @@ namespace Wrapper { return plain.size(); } - ByteArray::size_type Aes256::encrypt_start(const ByteArray::size_type plain_length, ByteArray& encrypted) { + ByteArray::size_type Aes256::encrypt_start(const ByteArray::size_type plain_length, ByteArray& encrypted) + { m_remainingLength = plain_length; // Generate salt @@ -163,10 +171,12 @@ namespace Wrapper { return encrypted.size(); } - ByteArray::size_type Aes256::encrypt_continue(const ByteArray& plain, ByteArray& encrypted) { + ByteArray::size_type Aes256::encrypt_continue(const ByteArray& plain, ByteArray& encrypted) + { ByteArray::const_iterator it = plain.begin(), itEnd = plain.end(); - while(it != itEnd) { + while(it != itEnd) + { m_buffer[m_buffer_pos++] = *(it++); check_and_encrypt_buffer(encrypted); @@ -175,10 +185,12 @@ namespace Wrapper { return encrypted.size(); } - ByteArray::size_type Aes256::encrypt_continue(const unsigned char* plain, const ByteArray::size_type plain_length, ByteArray& encrypted) { + ByteArray::size_type Aes256::encrypt_continue(const unsigned char* plain, const ByteArray::size_type plain_length, ByteArray& encrypted) + { ByteArray::size_type i = 0; - while(i < plain_length) { + while(i < plain_length) + { m_buffer[m_buffer_pos++] = plain[i++]; check_and_encrypt_buffer(encrypted); @@ -187,11 +199,14 @@ namespace Wrapper { return encrypted.size(); } - void Aes256::check_and_encrypt_buffer(ByteArray& encrypted) { - if(m_buffer_pos == BLOCK_SIZE) { + void Aes256::check_and_encrypt_buffer(ByteArray& encrypted) + { + if(m_buffer_pos == BLOCK_SIZE) + { encrypt(m_buffer); - for(m_buffer_pos = 0; m_buffer_pos < BLOCK_SIZE; ++m_buffer_pos) { + for(m_buffer_pos = 0; m_buffer_pos < BLOCK_SIZE; ++m_buffer_pos) + { encrypted.push_back(m_buffer[m_buffer_pos]); --m_remainingLength; } @@ -200,14 +215,17 @@ namespace Wrapper { } } - ByteArray::size_type Aes256::encrypt_end(ByteArray& encrypted) { - if(m_buffer_pos > 0) { + ByteArray::size_type Aes256::encrypt_end(ByteArray& encrypted) + { + if(m_buffer_pos > 0) + { while(m_buffer_pos < BLOCK_SIZE) m_buffer[m_buffer_pos++] = 0; encrypt(m_buffer); - for(m_buffer_pos = 0; m_buffer_pos < BLOCK_SIZE; ++m_buffer_pos) { + for(m_buffer_pos = 0; m_buffer_pos < BLOCK_SIZE; ++m_buffer_pos) + { encrypted.push_back(m_buffer[m_buffer_pos]); --m_remainingLength; } @@ -218,12 +236,14 @@ namespace Wrapper { return encrypted.size(); } - void Aes256::encrypt(unsigned char* buffer) { + void Aes256::encrypt(unsigned char* buffer) + { unsigned char i, rcon; copy_key(); add_round_key(buffer, 0); - for(i = 1, rcon = 1; i < NUM_ROUNDS; ++i) { + for(i = 1, rcon = 1; i < NUM_ROUNDS; ++i) + { sub_bytes(buffer); shift_rows(buffer); mix_columns(buffer); @@ -237,7 +257,8 @@ namespace Wrapper { add_round_key(buffer, i); } - ByteArray::size_type Aes256::decrypt_start(const ByteArray::size_type encrypted_length) { + ByteArray::size_type Aes256::decrypt_start(const ByteArray::size_type encrypted_length) + { register unsigned char j; m_remainingLength = encrypted_length; @@ -255,10 +276,12 @@ namespace Wrapper { return m_remainingLength; } - ByteArray::size_type Aes256::decrypt_continue(const ByteArray& encrypted, ByteArray& plain) { + ByteArray::size_type Aes256::decrypt_continue(const ByteArray& encrypted, ByteArray& plain) + { ByteArray::const_iterator it = encrypted.begin(), itEnd = encrypted.end(); - while(it != itEnd) { + while(it != itEnd) + { m_buffer[m_buffer_pos++] = *(it++); check_and_decrypt_buffer(plain); @@ -267,10 +290,12 @@ namespace Wrapper { return plain.size(); } - ByteArray::size_type Aes256::decrypt_continue(const unsigned char* encrypted, const ByteArray::size_type encrypted_length, ByteArray& plain) { + ByteArray::size_type Aes256::decrypt_continue(const unsigned char* encrypted, const ByteArray::size_type encrypted_length, ByteArray& plain) + { ByteArray::size_type i = 0; - while(i < encrypted_length) { + while(i < encrypted_length) + { m_buffer[m_buffer_pos++] = encrypted[i++]; check_and_decrypt_buffer(plain); @@ -279,8 +304,10 @@ namespace Wrapper { return plain.size(); } - void Aes256::check_and_decrypt_buffer(ByteArray& plain) { - if(!m_decryptInitialized && m_buffer_pos == m_salt.size() + 1) { + void Aes256::check_and_decrypt_buffer(ByteArray& plain) + { + if(!m_decryptInitialized && m_buffer_pos == m_salt.size() + 1) + { register unsigned char j; ByteArray::size_type padding; @@ -297,11 +324,13 @@ namespace Wrapper { m_decryptInitialized = true; } - else if(m_decryptInitialized && m_buffer_pos == BLOCK_SIZE) { + else if(m_decryptInitialized && m_buffer_pos == BLOCK_SIZE) + { decrypt(m_buffer); for(m_buffer_pos = 0; m_buffer_pos < BLOCK_SIZE; ++m_buffer_pos) - if(m_remainingLength > 0) { + if(m_remainingLength > 0) + { plain.push_back(m_buffer[m_buffer_pos]); --m_remainingLength; } @@ -310,11 +339,13 @@ namespace Wrapper { } } - ByteArray::size_type Aes256::decrypt_end(ByteArray& plain) { + ByteArray::size_type Aes256::decrypt_end(ByteArray& plain) + { return plain.size(); } - void Aes256::decrypt(unsigned char* buffer) { + void Aes256::decrypt(unsigned char* buffer) + { unsigned char i, rcon = 1; copy_key(); @@ -325,7 +356,8 @@ namespace Wrapper { shift_rows_inv(buffer); sub_bytes_inv(buffer); - for(i = NUM_ROUNDS, rcon = 0x80; --i;) { + for(i = NUM_ROUNDS, rcon = 0x80; --i;) + { if((i & 1)) expand_dec_key(&rcon); add_round_key(buffer, i); @@ -336,7 +368,8 @@ namespace Wrapper { add_round_key(buffer, i); } - void Aes256::expand_enc_key(unsigned char* rc) { + void Aes256::expand_enc_key(unsigned char* rc) + { register unsigned char i; m_rkey[0] = m_rkey[0] ^ sbox[m_rkey[29]] ^ (*rc); @@ -345,7 +378,8 @@ namespace Wrapper { m_rkey[3] = m_rkey[3] ^ sbox[m_rkey[28]]; *rc = FE(*rc); - for(i = 4; i < 16; i += 4) { + for(i = 4; i < 16; i += 4) + { m_rkey[i] = m_rkey[i] ^ m_rkey[i - 4]; m_rkey[i + 1] = m_rkey[i + 1] ^ m_rkey[i - 3]; m_rkey[i + 2] = m_rkey[i + 2] ^ m_rkey[i - 2]; @@ -356,7 +390,8 @@ namespace Wrapper { m_rkey[18] = m_rkey[18] ^ sbox[m_rkey[14]]; m_rkey[19] = m_rkey[19] ^ sbox[m_rkey[15]]; - for(i = 20; i < 32; i += 4) { + for(i = 20; i < 32; i += 4) + { m_rkey[i] = m_rkey[i] ^ m_rkey[i - 4]; m_rkey[i + 1] = m_rkey[i + 1] ^ m_rkey[i - 3]; m_rkey[i + 2] = m_rkey[i + 2] ^ m_rkey[i - 2]; @@ -364,10 +399,12 @@ namespace Wrapper { } } - void Aes256::expand_dec_key(unsigned char* rc) { + void Aes256::expand_dec_key(unsigned char* rc) + { unsigned char i; - for(i = 28; i > 16; i -= 4) { + for(i = 28; i > 16; i -= 4) + { m_rkey[i + 0] = m_rkey[i + 0] ^ m_rkey[i - 4]; m_rkey[i + 1] = m_rkey[i + 1] ^ m_rkey[i - 3]; m_rkey[i + 2] = m_rkey[i + 2] ^ m_rkey[i - 2]; @@ -379,7 +416,8 @@ namespace Wrapper { m_rkey[18] = m_rkey[18] ^ sbox[m_rkey[14]]; m_rkey[19] = m_rkey[19] ^ sbox[m_rkey[15]]; - for(i = 12; i > 0; i -= 4) { + for(i = 12; i > 0; i -= 4) + { m_rkey[i + 0] = m_rkey[i + 0] ^ m_rkey[i - 4]; m_rkey[i + 1] = m_rkey[i + 1] ^ m_rkey[i - 3]; m_rkey[i + 2] = m_rkey[i + 2] ^ m_rkey[i - 2]; @@ -393,21 +431,24 @@ namespace Wrapper { m_rkey[3] = m_rkey[3] ^ sbox[m_rkey[28]]; } - void Aes256::sub_bytes(unsigned char* buffer) { + void Aes256::sub_bytes(unsigned char* buffer) + { register unsigned char i = KEY_SIZE / 2; while(i--) buffer[i] = sbox[buffer[i]]; } - void Aes256::sub_bytes_inv(unsigned char* buffer) { + void Aes256::sub_bytes_inv(unsigned char* buffer) + { register unsigned char i = KEY_SIZE / 2; while(i--) buffer[i] = sboxinv[buffer[i]]; } - void Aes256::copy_key() { + void Aes256::copy_key() + { ByteArray::size_type i; for(i = 0; i < m_key.size(); ++i) @@ -416,14 +457,16 @@ namespace Wrapper { m_rkey[i + m_key.size()] = m_salt[i]; } - void Aes256::add_round_key(unsigned char* buffer, const unsigned char round) { + void Aes256::add_round_key(unsigned char* buffer, const unsigned char round) + { register unsigned char i = KEY_SIZE / 2; while(i--) buffer[i] ^= m_rkey[(round & 1) ? i + 16 : i]; } - void Aes256::shift_rows(unsigned char* buffer) { + void Aes256::shift_rows(unsigned char* buffer) + { register unsigned char i, j, k, l; /* to make it potentially parallelable :) */ i = buffer[1]; @@ -447,7 +490,8 @@ namespace Wrapper { buffer[6] = l; } - void Aes256::shift_rows_inv(unsigned char* buffer) { + void Aes256::shift_rows_inv(unsigned char* buffer) + { register unsigned char i, j, k, l; /* same as above :) */ i = buffer[1]; @@ -471,10 +515,12 @@ namespace Wrapper { buffer[14] = l; } - void Aes256::mix_columns(unsigned char* buffer) { + void Aes256::mix_columns(unsigned char* buffer) + { register unsigned char i, a, b, c, d, e; - for(i = 0; i < 16; i += 4) { + for(i = 0; i < 16; i += 4) + { a = buffer[i]; b = buffer[i + 1]; c = buffer[i + 2]; @@ -489,10 +535,12 @@ namespace Wrapper { } } - void Aes256::mix_columns_inv(unsigned char* buffer) { + void Aes256::mix_columns_inv(unsigned char* buffer) + { register unsigned char i, a, b, c, d, e, x, y, z; - for(i = 0; i < 16; i += 4) { + for(i = 0; i < 16; i += 4) + { a = buffer[i]; b = buffer[i + 1]; c = buffer[i + 2]; @@ -509,15 +557,19 @@ namespace Wrapper { } } - inline unsigned char rj_xtime(unsigned char x) { + inline unsigned char rj_xtime(unsigned char x) + { return (x & 0x80) ? ((x << 1) ^ 0x1b) : (x << 1); } // Wrapper for the AES256 encryption algorithm. - void Encryption::Start() { + void Encryption::Start() + { // Create cryptographic context. - if(!CryptAcquireContextA(&m_CryptProvider, nullptr, nullptr, PROV_RSA_AES, 0)) { - if(!CryptAcquireContextA(&m_CryptProvider, nullptr, nullptr, PROV_RSA_AES, CRYPT_NEWKEYSET)) { + if(!CryptAcquireContextA(&m_CryptProvider, nullptr, nullptr, PROV_RSA_AES, 0)) + { + if(!CryptAcquireContextA(&m_CryptProvider, nullptr, nullptr, PROV_RSA_AES, CRYPT_NEWKEYSET)) + { printf("Failed to initialise encryption provider.\n"); return; } @@ -527,7 +579,8 @@ namespace Wrapper { uint32_t RandomBytesCount = sizeof RandomBytes; // Generate random bytes to use as encryption key. - if(CryptGenRandom(m_CryptProvider, RandomBytesCount, RandomBytes)) { + if(CryptGenRandom(m_CryptProvider, RandomBytesCount, RandomBytes)) + { m_EncryptionKey.reserve(RandomBytesCount); m_EncryptionKey.insert( m_EncryptionKey.begin(), @@ -541,19 +594,23 @@ namespace Wrapper { CryptReleaseContext(m_CryptProvider, 0); } - void Encryption::Start(ByteArray &EncryptionKey) { + void Encryption::Start(ByteArray &EncryptionKey) + { // If an encryption key is provided, initialise the wrapper with // the passed parameter. - if(!EncryptionKey.empty()) { + if(!EncryptionKey.empty()) + { m_EncryptionKey.reserve(EncryptionKey.size()); std::copy(EncryptionKey.begin(), EncryptionKey.end(), m_EncryptionKey.begin()); } - else { + else + { Start(); } } - ByteArray Encryption::Encrypt(ByteArray &Data) { + ByteArray Encryption::Encrypt(ByteArray &Data) + { // Encrypt outgoing data. ByteArray Encrypted; @@ -566,7 +623,8 @@ namespace Wrapper { return Encrypted; } - ByteArray Encryption::Decrypt(ByteArray &Data) { + ByteArray Encryption::Decrypt(ByteArray &Data) + { // Decrypt incoming data. ByteArray Decrypted; diff --git a/csgo-loader/csgo-server/Security/Encryption.hpp b/csgo-loader/csgo-server/Security/Encryption.hpp index d55608f..b1c49dc 100644 --- a/csgo-loader/csgo-server/Security/Encryption.hpp +++ b/csgo-loader/csgo-server/Security/Encryption.hpp @@ -9,9 +9,11 @@ using ByteArray = std::vector; #define BLOCK_SIZE 16 -namespace Wrapper { +namespace Wrapper +{ // AES256 implementation. - class Aes256 { + class Aes256 + { public: Aes256(const ByteArray& key); @@ -67,7 +69,8 @@ namespace Wrapper { }; // Encryption wrapper. - class Encryption { + class Encryption + { ByteArray m_EncryptionKey; HCRYPTPROV m_CryptProvider; @@ -82,7 +85,8 @@ namespace Wrapper { ByteArray Decrypt(ByteArray &Data); // Exposes the encryption key. - ByteArray GetKey() { + ByteArray GetKey() + { return m_EncryptionKey; } }; diff --git a/csgo-loader/csgo-server/Server.cpp b/csgo-loader/csgo-server/Server.cpp index ca6deb4..bf8404d 100644 --- a/csgo-loader/csgo-server/Server.cpp +++ b/csgo-loader/csgo-server/Server.cpp @@ -1,7 +1,8 @@ #include #include -void ConnectionHandler(Networking::TCPConnection &Connection) { +void ConnectionHandler(Networking::TCPConnection &Connection) +{ Login::RemoteLoginServer LoginServer; ByteArray RawLoginHeader = Connection.ReceiveBytes(); @@ -11,11 +12,13 @@ void ConnectionHandler(Networking::TCPConnection &Connection) { Connection.SendBytes(RawServerResponse); } -int main() { +int main() +{ Networking::TCPServer Server; // Create an instance of the TCP server. - if(!Server.Start(3884)) { + if(!Server.Start(3884)) + { printf("[FAIL] Failed to initialise server. (%08lx)\n", WSAGetLastError()); system("pause"); return 1; @@ -25,7 +28,8 @@ int main() { Server += ConnectionHandler; // Accept incoming connections. - while(true) { + while(true) + { Server.AcceptConnection(); } diff --git a/csgo-loader/csgo-server/csgo-server.vcxproj b/csgo-loader/csgo-server/csgo-server.vcxproj index c0fcbca..71fe624 100644 --- a/csgo-loader/csgo-server/csgo-server.vcxproj +++ b/csgo-loader/csgo-server/csgo-server.vcxproj @@ -23,6 +23,8 @@ + + @@ -31,6 +33,8 @@ + + diff --git a/csgo-loader/csgo-server/csgo-server.vcxproj.filters b/csgo-loader/csgo-server/csgo-server.vcxproj.filters index bc0886a..0d915d3 100644 --- a/csgo-loader/csgo-server/csgo-server.vcxproj.filters +++ b/csgo-loader/csgo-server/csgo-server.vcxproj.filters @@ -31,6 +31,12 @@ RemoteCode + + Networking + + + Networking + @@ -48,5 +54,11 @@ RemoteCode + + Networking + + + Networking + \ No newline at end of file -- cgit v1.2.3