diff options
| -rw-r--r-- | csgo-loader/csgo-client/Client.cpp | 35 | ||||
| -rw-r--r-- | csgo-loader/csgo-client/Login/RemoteLogin.cpp | 30 | ||||
| -rw-r--r-- | csgo-loader/csgo-client/Login/RemoteLogin.hpp | 3 | ||||
| -rw-r--r-- | csgo-loader/csgo-client/Networking/TCPClient.cpp | 4 | ||||
| -rw-r--r-- | csgo-loader/csgo-client/Security/Encryption.cpp | 17 | ||||
| -rw-r--r-- | csgo-loader/csgo-client/Security/RuntimeSecurity.cpp | 124 | ||||
| -rw-r--r-- | csgo-loader/csgo-client/Security/RuntimeSecurity.hpp | 25 | ||||
| -rw-r--r-- | csgo-loader/csgo-server/Login/RemoteLogin.cpp | 4 | ||||
| -rw-r--r-- | csgo-loader/csgo-server/Login/RemoteLogin.hpp | 3 | ||||
| -rw-r--r-- | csgo-loader/csgo-server/Networking/TCPServer.cpp | 6 | ||||
| -rw-r--r-- | csgo-loader/csgo-server/Server.cpp | 12 |
11 files changed, 182 insertions, 81 deletions
diff --git a/csgo-loader/csgo-client/Client.cpp b/csgo-loader/csgo-client/Client.cpp index 52a288d..7285b6b 100644 --- a/csgo-loader/csgo-client/Client.cpp +++ b/csgo-loader/csgo-client/Client.cpp @@ -2,12 +2,6 @@ /*
TODO:
- - Finish off security on client:
- - Add dump protection (closes csgo.exe if a handle is detected, probably explorer shellcode)
- - Add HWID generation [half-assed atm]
-
- - Switch Themida with VMP (Superior VM imho and I can fuck people over with my cool script (: )
-
- Finish off shellcode execution wrapper:
- The shellcode can be executed via two ways
- Either the code is mapped and called via CreateRemoteThread (allows custom param)
@@ -15,16 +9,14 @@ - This will probably be the easiest thing to do.
- Finish off injection wrapper:
- - Allocate a 4KB page for trampoline imports (4096/6) { E9 ? ? ? ? C3 }
- - Actually, allocate every memory page as a bunch of consecutive 4kb sections
- - Trampoline for imports
- - Everything is already laid out, tbh.
+ - Allocate every memory page as a bunch of consecutive 4kb sections (in order to fuck with people trying to dump)
- Have the loader inject a .DLL :^)
TODO (Nave):
- Make the UI look nice.
- Adapt the server to work with your backend.
+ - Add dump protection (closes csgo.exe if a handle is detected, probably explorer shellcode)
*/
@@ -32,11 +24,11 @@ int __stdcall WinMain(HINSTANCE inst, HINSTANCE prev, char* str, int cmdshow)
{
- (Utils::OpenConsole());
+ WRAP_IF_DEBUG(Utils::OpenConsole());
///////////////////////////////////////////////////////////////
- VMProtectBeginUltra("EntryPoint");
+ VMProtectBeginMutation("EntryPoint");
///////////////////////////////////////////////////////////////
@@ -66,16 +58,33 @@ int __stdcall WinMain(HINSTANCE inst, HINSTANCE prev, char* str, int cmdshow) UserInterface->m_Data.m_ExecutionState = UserExperience::EXECUTION_WAITING;
// Attempt to connect to the remote server.
+ WRAP_IF_DEBUG(
+ printf("[DEBUG] Server IP: %08x\n", inet_addr("35.165.60.229"));
+ );
+
Networking::TCPClientPtr Client = std::make_unique<Networking::TCPClient>();
if(!Client->Start(LOCAL_IP, SERVER_PORT))
ERROR_ASSERT(STR("[000F:0002A000] Server closed the connection unexpectedly."));
-
+
// Allow the user to input their log-in data.
UserInterface->m_Data.m_ExecutionState = UserExperience::EXECUTION_LOG_IN;
while(UserInterface->m_Data.m_ExecutionState != UserExperience::EXECUTION_WAITING) { Sleep(1); }
+ Login::RemoteLoginTransaction LoginTransaction;
+ LoginTransaction.Start(UserInterface->m_Data.m_Username, UserInterface->m_Data.m_Password);
+
+ ByteArray Transaction = LoginTransaction.GetHeader();
+ Client->SendBytes(Transaction);
+
+ ByteArray LoginResponse = Client->ReceiveBytes();
+ if(!LoginTransaction.TranslateResponse(LoginResponse))
+ ExitProcess(0);
+
+ // Allow the user to choose a cheat to inject.
+ UserInterface->m_Data.m_ExecutionState = UserExperience::EXECUTION_CHOOSE;
+
// TODO: Add game selection.
while(1) { if(GetAsyncKeyState(VK_END) & 0x8000) break; Sleep(1); }
diff --git a/csgo-loader/csgo-client/Login/RemoteLogin.cpp b/csgo-loader/csgo-client/Login/RemoteLogin.cpp index 6e70f86..7942c3b 100644 --- a/csgo-loader/csgo-client/Login/RemoteLogin.cpp +++ b/csgo-loader/csgo-client/Login/RemoteLogin.cpp @@ -18,13 +18,25 @@ namespace Login strcpy_s< 128 >(m_Header.m_Password, Password);
// Initialise the header with the Hardware ID.
- m_Header.m_HardwareId = 0xFFFFFFFF;
+ Security::HardwareIdentifier HardwareId = Protection->GetHardwareId();
+
+ WRAP_IF_DEBUG(
+ printf("[DEBUG] LoginTransactionStart\n");
+ printf("[DEBUG] Processor count: %d\n", HardwareId.m_CpuCount);
+ printf("[DEBUG] Processor architecture: %d\n", HardwareId.m_CpuArchitecture);
+ printf("[DEBUG] Hard-drive Serial: %llx\n", HardwareId.m_HardDiskSerialHash);
+
+ for(int i = 0; i < 4; ++i)
+ printf("[DEBUG] Safety check #%d: %s\n", i, HardwareId.m_SpecialMode[i] ? "TRUE" : "FALSE");
+ );
+
+ m_Header.m_HardwareId = fnv::hash_runtime_data((void *)(&HardwareId), sizeof Security::HardwareIdentifier);
// TODO: Verify integrity of system.
// 0 for integrity passed, random bit for failure
- m_Header.m_IntegrityBit1 = 0;
- m_Header.m_IntegrityBit2 = 0;
- m_Header.m_IntegrityBit3 = 0;
+ m_Header.m_IntegrityBit1 = HardwareId.m_SpecialMode[Security::DEBUGGING_MODE];
+ m_Header.m_IntegrityBit2 = HardwareId.m_SpecialMode[Security::TEST_BUILD_MODE];
+ m_Header.m_IntegrityBit3 = HardwareId.m_SpecialMode[Security::TEST_SIGN_MODE];
// The checksum bit, the server will check this first to detect possible tampering.
m_Header.m_IntegrityBit4 = m_Header.m_IntegrityBit1
@@ -48,20 +60,20 @@ namespace Login case RemoteLoginResponse::ACCESS_AUTHORISED:
return true;
case RemoteLoginResponse::OUTDATED_CLIENT:
- INFO_ASSERT(STR("[000A:%08x] Your client is outdated.\nPlease download the latest client at 'moneybot.cc'."), m_Header.m_HardwareId ^ ServerResponse);
+ INFO_ASSERT(STR("[000A:%llx] Your client is outdated.\nPlease download the latest client at 'moneybot.cc'."), m_Header.m_HardwareId ^ ServerResponse);
break;
case RemoteLoginResponse::USER_BANNED:
- INFO_ASSERT(STR("[000D:%08x] Your account is banned.\nPlease contact 'admin@moneybot.cc' for additional information."), m_Header.m_HardwareId ^ ServerResponse);
+ INFO_ASSERT(STR("[000D:%llx] Your account is banned.\nPlease contact 'admin@moneybot.cc' for additional information."), m_Header.m_HardwareId ^ ServerResponse);
break;
case RemoteLoginResponse::INVALID_HARDWARE:
- UserInterface->m_Data.m_Error = UserExperience::ERROR_INVALID_HWID;
+ INFO_ASSERT(STR("[000D:%llx] Your Hardware-ID is incorrect!\nPlease contact a staff member."), m_Header.m_HardwareId ^ ServerResponse);
break;
case RemoteLoginResponse::INVALID_CREDENTIALS:
- INFO_ASSERT(STR("[000C:%08x] Your credentials are invalid. Please check your spelling and try again."), m_Header.m_HardwareId ^ ServerResponse);
+ INFO_ASSERT(STR("[000C:%llx] Your credentials are invalid. Please check your spelling and try again."), m_Header.m_HardwareId ^ ServerResponse);
break;
case RemoteLoginResponse::INTEGRITY_FAILURE:
case RemoteLoginResponse::NO_SUBSCRIPTION:
- INFO_ASSERT(STR("[0005:%08x] No active subscription found."), m_Header.m_HardwareId ^ ServerResponse);
+ INFO_ASSERT(STR("[0005:%llx] No active subscription found."), m_Header.m_HardwareId ^ ServerResponse);
break;
}
diff --git a/csgo-loader/csgo-client/Login/RemoteLogin.hpp b/csgo-loader/csgo-client/Login/RemoteLogin.hpp index 071bb13..9575193 100644 --- a/csgo-loader/csgo-client/Login/RemoteLogin.hpp +++ b/csgo-loader/csgo-client/Login/RemoteLogin.hpp @@ -6,6 +6,7 @@ #include <UserExperience/UserInterface.hpp>
#include <Security/RuntimeSecurity.hpp>
+#include <Security/FnvHash.hpp>
using ByteArray = std::vector<uint8_t>;
@@ -24,7 +25,7 @@ namespace Login char m_Password[128];
// This will provide the hardware ID of the machine.
- uint32_t m_HardwareId;
+ uint64_t m_HardwareId;
// These fields will be set according
// to security check results.
diff --git a/csgo-loader/csgo-client/Networking/TCPClient.cpp b/csgo-loader/csgo-client/Networking/TCPClient.cpp index 0611d89..c20c831 100644 --- a/csgo-loader/csgo-client/Networking/TCPClient.cpp +++ b/csgo-loader/csgo-client/Networking/TCPClient.cpp @@ -40,10 +40,6 @@ namespace Networking break;
}
- // Stay in sync with client.
- ByteArray Array = { 1 };
- SendRawBytes(Array);
-
return ReceivedBytes;
}
diff --git a/csgo-loader/csgo-client/Security/Encryption.cpp b/csgo-loader/csgo-client/Security/Encryption.cpp index 00b0fee..083460a 100644 --- a/csgo-loader/csgo-client/Security/Encryption.cpp +++ b/csgo-loader/csgo-client/Security/Encryption.cpp @@ -80,7 +80,7 @@ namespace Wrapper };
// Implementation of the AES256 encryption algorithm.
- unsigned char rj_xtime(unsigned char x);
+ uint8_t rj_xtime(uint8_t x);
Aes256::Aes256(const ByteArray& key)
: m_key(ByteArray(key.size() > KEY_SIZE ? KEY_SIZE : key.size(), 0))
@@ -144,7 +144,7 @@ namespace Wrapper ByteArray::size_type Aes256::encrypt_start(const ByteArray::size_type plain_length, ByteArray& encrypted)
{
- VMProtectBegin("AESEncryptStart");
+ VMProtectBeginUltra("AESEncryptStart");
m_remainingLength = plain_length;
@@ -265,7 +265,7 @@ namespace Wrapper {
unsigned char j;
- VMProtectBegin("AESDecryptStart");
+ VMProtectBeginUltra("AESDecryptStart");
m_remainingLength = encrypted_length;
@@ -314,7 +314,7 @@ namespace Wrapper void Aes256::check_and_decrypt_buffer(ByteArray& plain)
{
- VMProtectBegin("AESDecryptBuffer");
+ VMProtectBeginUltra("AESDecryptBuffer");
if(!m_decryptInitialized && m_buffer_pos == m_salt.size() + 1)
{
@@ -384,7 +384,7 @@ namespace Wrapper {
unsigned char i;
- VMProtectBegin("AESExpandKey");
+ VMProtectBeginUltra("AESExpandKey");
m_rkey[0] = m_rkey[0] ^ sbox[m_rkey[29]] ^ (*rc);
m_rkey[1] = m_rkey[1] ^ sbox[m_rkey[30]];
@@ -419,7 +419,7 @@ namespace Wrapper {
unsigned char i;
- VMProtectBegin("AESExpandKey");
+ VMProtectBeginUltra("AESExpandKey");
for(i = 28; i > 16; i -= 4)
{
@@ -585,10 +585,7 @@ namespace Wrapper VMProtectEnd();
}
- inline unsigned char rj_xtime(unsigned char x)
- {
- return (x & 0x80) ? ((x << 1) ^ 0x1b) : (x << 1);
- }
+ inline uint8_t rj_xtime(uint8_t x) { return (x & 0x80) ? ((x << 1) ^ 0x1b) : (x << 1); }
// Wrapper for the AES256 encryption algorithm.
void Encryption::Start()
diff --git a/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp b/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp index 572c9b1..7f528e3 100644 --- a/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp +++ b/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp @@ -209,6 +209,9 @@ namespace Security for(;;)
{
+ if(VMProtectIsVirtualMachinePresent())
+ SecurityCallback(STR("Malicious activity [Virtualized environment]."));
+
// Don't put too much stress on the CPU.
Sleep(1);
}
@@ -227,36 +230,18 @@ namespace Security // Offset for x64 is 0x60 ; mov ..., qword ptr gs:[0x60]
PEB *ProcessEnvBlock = (PEB *)__readgsqword(0x60);
- //if(ProcessEnvBlock->BeingDebugged)
- // SecurityCallback(__FUNCSIG__);
+ if(ProcessEnvBlock->BeingDebugged)
+ SecurityCallback(STR("Malicious activity [Debugging attempt]."));
// TODO: Check for x64dbg window?
- /*
- ------------------------------
- HWND: 000305A4
- HWND->m_Class = "ID"
- HWND->m_Text = "Immunity
- ------------------------------
- HWND: 00060574
- HWND->m_Class = || NON CONSTANT ||
- HWND->m_Text = "x64dbg"
- ------------------------------
- HWND: 002C0680
- HWND->m_Class = || NON CONSTANT ||
- HWND->m_Text = "Progress Telerik Fiddler Web Debugger"
- ------------------------------
- HWND: 000406E4
- HWND->m_Class = "OLLYDBG"
- HWND->m_Text = "OllyDbg"
- ------------------------------
- */
using WindowParams = std::pair<const char *, const char *>;
static std::vector<WindowParams> BlackListedWindows = {
{STR("ID"), STR("Immunity")}, // Immunity Debugger
- {STR("Qt5QWindowIcon"), STR("x64dbg")}, // x64dbg
- {STR("Qt5QWindowIcon"), STR("x32dbg")}, // x32dbg
- {STR("OLLYDBG"), STR("OllyDbg")}, // OllyDbg
- {nullptr, STR("Progress Telerik Fiddler Web Debugger")}, // Telerik Fiddler
+ {STR("Qt5QWindowIcon"), STR("x64dbg")}, // x64dbg
+ {STR("Qt5QWindowIcon"), STR("x32dbg")}, // x32dbg
+ {STR("Qt5QWindowIcon"), STR("The Wireshark Network Analyzer")}, // x32dbg
+ {STR("OLLYDBG"), STR("OllyDbg")}, // OllyDbg
+ {nullptr, STR("Progress Telerik Fiddler Web Debugger")}, // Telerik Fiddler
};
for(auto &It : BlackListedWindows)
@@ -284,7 +269,7 @@ namespace Security STR("NPF"), // WireShark / WinPCAP
STR("acker"), // Process Hacker
STR("CEDRI"), // Cheat Engine
- //STR("VBox") // VirtualBox
+ //STR("VBox") // VirtualBox
};
static const char *BlackListReasons[] = {
@@ -303,7 +288,11 @@ namespace Security if(K32EnumDeviceDrivers(DriverList, sizeof DriverList, &Needed))
{
if(Needed > sizeof DriverList)
- ERROR_ASSERT(STR("[00DF:00001CFF] A security thread has failed. Contact an administrator."));
+ {
+ ERROR_ASSERT(
+ STR("[00DF:00001CFF] A security thread has failed. Contact an administrator.")
+ );
+ }
char DriverName[1024];
uint32_t DriverCount = Needed / sizeof DriverList[0];
@@ -330,6 +319,12 @@ namespace Security {
for(;;)
{
+ if(!VMProtectIsProtected())
+ SecurityCallback(STR("Malicious activity [Tampering]."));
+
+ if(!VMProtectIsValidImageCRC())
+ SecurityCallback(STR("Malicious activity [Tampering]."));
+
// Don't put too much stress on the CPU.
Sleep(1);
}
@@ -358,22 +353,93 @@ namespace Security constexpr uintptr_t KUSER_SHARED_DATA = 0x7FFE0000;
+ __forceinline uint64_t get_hdd_hash() { + STORAGE_PROPERTY_QUERY query{ }; + STORAGE_DESCRIPTOR_HEADER desc_header{ }; + STORAGE_DEVICE_DESCRIPTOR* device_descriptor{ }; + HANDLE device; + DWORD bytes_returned; + uint8_t* out_buffer; + + const wchar_t* device_path = L"\\??\\PhysicalDrive0"; + device = CreateFileA("\\\\.\\PhysicalDrive0", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); + if(!device) return uint64_t{ }; + + query.PropertyId = StorageDeviceProperty; + query.QueryType = PropertyStandardQuery; + + if(!DeviceIoControl(device, IOCTL_STORAGE_QUERY_PROPERTY, + &query, sizeof(STORAGE_PROPERTY_QUERY), + &desc_header, sizeof(STORAGE_DESCRIPTOR_HEADER), + &bytes_returned, 0)) { + return uint64_t{ }; + } + + out_buffer = new uint8_t[desc_header.Size]; + memset(out_buffer, 0, desc_header.Size); + + if(!DeviceIoControl(device, IOCTL_STORAGE_QUERY_PROPERTY, + &query, sizeof(STORAGE_PROPERTY_QUERY), + out_buffer, desc_header.Size, + &bytes_returned, 0)) { + delete[] out_buffer; + return uint64_t{ }; + } + + device_descriptor = (STORAGE_DEVICE_DESCRIPTOR*)out_buffer; + if(device_descriptor->SerialNumberOffset) { + std::string serial_num = reinterpret_cast<const char*>( + out_buffer + device_descriptor->SerialNumberOffset); + + delete[] out_buffer; + CloseHandle(device); + return fnv::hash_runtime(serial_num.c_str()); + } + + return 0; + }
+
HardwareIdentifier RuntimeSecurity::GetHardwareId()
{
+ VMProtectBeginMutation("HardwareIdentifier");
+
HardwareIdentifier Identifier{};
// CPU information
Identifier.m_CpuCount = *(uint32_t *)(KUSER_SHARED_DATA + 0x3C0);
Identifier.m_CpuArchitecture = *(uint16_t *)(KUSER_SHARED_DATA + 0x26A);
- // CPU features
+ // HDD serial number
+ Identifier.m_HardDiskSerialHash = get_hdd_hash();
// Safe-mode
Identifier.m_SpecialMode[0] = *(uint8_t *)(KUSER_SHARED_DATA + 0x2EC);
// Test-signing mode
+ static auto ZwQuerySystemInformation = Syscalls->Find<long(__stdcall *)(uint32_t, void *, uint32_t, uint32_t *)>(FNV("ZwQuerySystemInformation"));
+
+ // 0x02 CODEINTEGRITY_OPTION_TESTSIGN
+ // 0x20 CODEINTEGRITY_OPTION_TEST_BUILD
+ // 0x80 CODEINTEGRITY_OPTION_DEBUGMODE_ENABLED
+
+ CodeIntegrityInformation Info{ sizeof CodeIntegrityInformation };
+ NTSTATUS Status = ZwQuerySystemInformation(0x67, &Info, sizeof Info, nullptr);
+
+ if(NT_ERROR(Status))
+ ERROR_ASSERT(STR("[00CF:%08x] Critical execution error."), Status);
+
+ if(Info.m_Options & 0x02)
+ Identifier.m_SpecialMode[1] = true;
+
+ if(Info.m_Options & 0x20)
+ Identifier.m_SpecialMode[2] = true;
+
+ if(Info.m_Options & 0x40)
+ Identifier.m_SpecialMode[3] = true;
+
+ VMProtectEnd();
- return HardwareIdentifier{};
+ return Identifier;
}
#pragma optimize("", off)
diff --git a/csgo-loader/csgo-client/Security/RuntimeSecurity.hpp b/csgo-loader/csgo-client/Security/RuntimeSecurity.hpp index 08e6490..06df3bf 100644 --- a/csgo-loader/csgo-client/Security/RuntimeSecurity.hpp +++ b/csgo-loader/csgo-client/Security/RuntimeSecurity.hpp @@ -10,6 +10,9 @@ #include <windows.h>
#include <winternl.h>
+// IOCTL
+#include <winioctl.h>
+
// EnumDeviceDrivers
#include <psapi.h>
@@ -47,6 +50,19 @@ namespace Security
{
+ // Sigh..
+ struct CodeIntegrityInformation {
+ uint32_t m_Size;
+ uint32_t m_Options;
+ };
+
+ enum SpecialMode {
+ SAFE_MODE,
+ TEST_SIGN_MODE,
+ TEST_BUILD_MODE,
+ DEBUGGING_MODE
+ };
+
// Hardware ID structure (this is hashed and sent to server, but it's easier to use it
// this way internally)
struct HardwareIdentifier
@@ -54,15 +70,12 @@ namespace Security // Generic CPU information.
uint16_t m_CpuArchitecture;
uint32_t m_CpuCount;
-
- // Contains list of CPU features.
- char m_CpuFeatures[64];
-
+
// Hash of the hard disk serial identifier.
- uint32_t m_HardDiskSerialHash;
+ uint64_t m_HardDiskSerialHash;
// Safe-mode/Test-signing mode status
- uint8_t m_SpecialMode[2];
+ uint8_t m_SpecialMode[4];
};
// This class implements the runtime security system.
diff --git a/csgo-loader/csgo-server/Login/RemoteLogin.cpp b/csgo-loader/csgo-server/Login/RemoteLogin.cpp index 3cc5c77..2f30e7f 100644 --- a/csgo-loader/csgo-server/Login/RemoteLogin.cpp +++ b/csgo-loader/csgo-server/Login/RemoteLogin.cpp @@ -33,6 +33,8 @@ namespace Login return RemoteLoginResponse::INVALID_CREDENTIALS;
// User failed to obtain HWID?
+ printf("[ => ] User HWID: %llx\n", m_Header.m_HardwareId);
+
if(!m_Header.m_HardwareId)
{
// TODO: Shadow ban the user.
@@ -41,7 +43,7 @@ namespace Login }
// TODO: Check if the HWID is present in DB.
- if(false)
+ if(m_Header.m_HardwareId != 0x2F769B06FA897376)
return RemoteLoginResponse::INVALID_HARDWARE;
// TODO: Check if the user has a subscription.
diff --git a/csgo-loader/csgo-server/Login/RemoteLogin.hpp b/csgo-loader/csgo-server/Login/RemoteLogin.hpp index f69e588..c3ceea3 100644 --- a/csgo-loader/csgo-server/Login/RemoteLogin.hpp +++ b/csgo-loader/csgo-server/Login/RemoteLogin.hpp @@ -21,7 +21,7 @@ namespace Login char m_Password[128];
// This will provide the hardware ID of the machine.
- uint32_t m_HardwareId;
+ uint64_t m_HardwareId;
// These fields will be set according
// to security check results.
@@ -45,6 +45,7 @@ namespace Login NO_SUBSCRIPTION = 'G', // '[000G:{HWID}] No active subscription.'
ACCESS_SPECIAL_USER = 'H', // Allows the user to continue, sets the m_SpecialAccess var
};
+
// Implementation of the server (handles login bullshit).
class RemoteLoginServer
{
diff --git a/csgo-loader/csgo-server/Networking/TCPServer.cpp b/csgo-loader/csgo-server/Networking/TCPServer.cpp index 37a21bc..0652fe5 100644 --- a/csgo-loader/csgo-server/Networking/TCPServer.cpp +++ b/csgo-loader/csgo-server/Networking/TCPServer.cpp @@ -22,12 +22,6 @@ namespace Networking if(Result == -1)
printf("[ E! ] Failed to send %zd bytes to %s. (Socket %04Ix)\n", Bytes.size(), m_IpAddress, m_Socket);
-
- // Stay in sync with client.
- ByteArray Array = ReceiveRawBytes();
-
- if(Array.empty())
- printf("[ E! ] No client reply.\n");
}
ByteArray TCPConnection::ReceiveRawBytes()
diff --git a/csgo-loader/csgo-server/Server.cpp b/csgo-loader/csgo-server/Server.cpp index 580c17a..a78bb9a 100644 --- a/csgo-loader/csgo-server/Server.cpp +++ b/csgo-loader/csgo-server/Server.cpp @@ -1,6 +1,16 @@ #include <Server.hpp>
-void ConnectionHandler(Networking::TCPConnection &Connection) { }
+void ConnectionHandler(Networking::TCPConnection &Connection) {
+ Login::RemoteLoginServer LoginServer;
+
+ ByteArray LoginHeader = Connection.ReceiveBytes();
+
+ if(!LoginServer.Start(LoginHeader))
+ return;
+
+ ByteArray LoginReply = LoginServer.GetResponse();
+ Connection.SendBytes(LoginReply);
+}
int __stdcall WinMain(HINSTANCE, HINSTANCE, char*, int)
{
|
