summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorboris <wzn@moneybot.cc>2019-01-09 20:51:16 +1300
committerboris <wzn@moneybot.cc>2019-01-09 20:51:16 +1300
commit4db29589a61f2e7cb663c5734f911c02206c7997 (patch)
tree38ec6f25fe1b807ba76e28720badf4a70a87601c
parent1fbe9543b16fc6edacfc1e1dca75f5938ebb08a3 (diff)
whole buncha shit
FIXME: loader currently corrupts heap on injection because i am retarded
-rw-r--r--csgo-loader/csgo-client/Client.cpp55
-rw-r--r--csgo-loader/csgo-client/Client.hpp5
-rw-r--r--csgo-loader/csgo-client/Login/RemoteLogin.cpp3
-rw-r--r--csgo-loader/csgo-client/Networking/TCPClient.cpp4
-rw-r--r--csgo-loader/csgo-client/RemoteCode/RemoteCodeClient.cpp69
-rw-r--r--csgo-loader/csgo-client/RemoteCode/RemoteCodeClient.hpp33
-rw-r--r--csgo-loader/csgo-client/RemoteCode/RemoteInjectionClient.cpp6
-rw-r--r--csgo-loader/csgo-client/RemoteCode/RemoteInjectionClient.hpp69
-rw-r--r--csgo-loader/csgo-client/RemoteCode/RemoteMapper.cpp139
-rw-r--r--csgo-loader/csgo-client/RemoteCode/RemoteMapper.hpp26
-rw-r--r--csgo-loader/csgo-client/RemoteCode/RemoteProcess.cpp2
-rw-r--r--csgo-loader/csgo-client/RemoteCode/RemoteProcess.hpp10
-rw-r--r--csgo-loader/csgo-client/Security/RuntimeSecurity.cpp113
-rw-r--r--csgo-loader/csgo-client/csgo-client.vcxproj6
-rw-r--r--csgo-loader/csgo-client/csgo-client.vcxproj.filters18
-rw-r--r--csgo-loader/csgo-loader.sln14
-rw-r--r--csgo-loader/csgo-module/Module.cpp76
-rw-r--r--csgo-loader/csgo-module/Module.hpp55
-rw-r--r--csgo-loader/csgo-module/Networking/TCPClient.cpp119
-rw-r--r--csgo-loader/csgo-module/Networking/TCPClient.hpp46
-rw-r--r--csgo-loader/csgo-module/Security/Encryption.cpp614
-rw-r--r--csgo-loader/csgo-module/Security/Encryption.hpp101
-rw-r--r--csgo-loader/csgo-module/Security/FnvHash.hpp100
-rw-r--r--csgo-loader/csgo-module/Security/SyscallManager.cpp159
-rw-r--r--csgo-loader/csgo-module/Security/SyscallManager.hpp77
-rw-r--r--csgo-loader/csgo-module/csgo-module.vcxproj209
-rw-r--r--csgo-loader/csgo-module/csgo-module.vcxproj.filters38
-rw-r--r--csgo-loader/csgo-server/Login/RemoteLogin.cpp20
-rw-r--r--csgo-loader/csgo-server/Networking/TCPServer.hpp3
-rw-r--r--csgo-loader/csgo-server/RemoteCode/RemoteInjectionServer.cpp1
-rw-r--r--csgo-loader/csgo-server/RemoteCode/RemoteInjectionServer.hpp62
-rw-r--r--csgo-loader/csgo-server/Server.cpp99
-rw-r--r--csgo-loader/csgo-server/Server.hpp18
-rw-r--r--csgo-loader/csgo-server/csgo-server.vcxproj2
-rw-r--r--csgo-loader/csgo-server/csgo-server.vcxproj.filters6
35 files changed, 2001 insertions, 376 deletions
diff --git a/csgo-loader/csgo-client/Client.cpp b/csgo-loader/csgo-client/Client.cpp
index 05ceb0b..d7b266f 100644
--- a/csgo-loader/csgo-client/Client.cpp
+++ b/csgo-loader/csgo-client/Client.cpp
@@ -1,23 +1,11 @@
#include <Client.hpp>
/*
- TODO:
- - 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)
- - or the code is mapped and called via DX9 (does not allow custom param)
- - This will probably be the easiest thing to do.
-
--nave note:
you don't need any custom params
it's entirely pointless, we can use a wiped PE header to pass all the data we need
plus passing shit via dllmain is too obvious anyway, dumb idea
- - Finish off injection wrapper:
- - 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 :^)
-
--nave note 2:
what you haven't done and what will completely fuck us up if anyone competent gets the loader:
loading the binary directly via the loader itself is completely stupid and unreasonable
@@ -46,11 +34,7 @@ int __stdcall WinMain(HINSTANCE inst, HINSTANCE prev, char* str, int cmdshow)
Utils::OpenConsole();
);
- ///////////////////////////////////////////////////////////////
-
- //VMProtectBeginMutation("EntryPoint");
-
- ///////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////////////////
// Create a thread to handle UI.
std::thread WindowThread([]
@@ -64,6 +48,8 @@ int __stdcall WinMain(HINSTANCE inst, HINSTANCE prev, char* str, int cmdshow)
while(!UserInterface->m_Data.m_Ready) { Sleep(1); }
+ //////////////////////////////////////////////////////////////////////////////////////////
+
// Initialize the syscall manager.
if(!Syscalls->Start())
ERROR_ASSERT(STR("[000F:00001B00] Failed to initialize. Please contact an administrator."));
@@ -80,11 +66,20 @@ int __stdcall WinMain(HINSTANCE inst, HINSTANCE prev, char* str, int cmdshow)
printf("[DEBUG] Server IP: %08x\n", inet_addr("35.165.60.229"));
);
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ // Connect to server.
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."));
+ // Header for Client.
+ ByteArray Header{ 0x0A, 0x31, 0x42, 0x4D };
+ Client->SendRawBytes(Header);
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
// Allow the user to input their log-in data.
UserInterface->m_Data.m_ExecutionState = UserExperience::EXECUTION_LOG_IN;
@@ -100,17 +95,29 @@ int __stdcall WinMain(HINSTANCE inst, HINSTANCE prev, char* str, int cmdshow)
if(!LoginTransaction.TranslateResponse(LoginResponse))
ExitProcess(0);
- // Allow the user to choose a cheat to inject.
- UserInterface->m_Data.m_ExecutionState = UserExperience::EXECUTION_CHOOSE;
+ // Echo back to server.
+ Client->SendBytes(LoginResponse);
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ // Receive loader module.
+ ByteArray LdrModule = Client->ReceiveBytes();
+
+ // Map loader module.
+ RemoteCode::RemoteProcess Process;
- // TODO: Add game selection.
- while(1) { if(GetAsyncKeyState(VK_END) & 0x8000) break; Sleep(1); }
+ if(!Process.Start(STR("explorer.exe")))
+ ExitProcess(0);
- ///////////////////////////////////////////////////////////////
+ RemoteCode::RemoteMapper Mapper;
- //VMProtectEnd();
+ if(!Mapper.Start(Process))
+ ExitProcess(0);
- ///////////////////////////////////////////////////////////////
+ if(!Mapper.WriteCodeToMap(LdrModule))
+ ExitProcess(0);
+
+ Mapper.ExecuteCodeFromMap();
}
#pragma optimize("", on) \ No newline at end of file
diff --git a/csgo-loader/csgo-client/Client.hpp b/csgo-loader/csgo-client/Client.hpp
index 0f05a34..79f0a17 100644
--- a/csgo-loader/csgo-client/Client.hpp
+++ b/csgo-loader/csgo-client/Client.hpp
@@ -7,6 +7,8 @@
#define SERVER_IP 0xE53CA523 // Hexadecimal representation of the server IP, obtained by inet_addr()
#define SERVER_PORT 0xF2C // Hexadecimal representation of the server port.
+#define CLIENT_HEADER 0x4D42310A
+
// Security features (these will be initialised and ran
// first, failure will terminate loader execution).
#include <Security/RuntimeSecurity.hpp>
@@ -20,8 +22,7 @@
#include <Login/RemoteLogin.hpp>
#include <RemoteCode/RemoteProcess.hpp>
-#include <RemoteCode/RemoteInjectionClient.hpp>
-#include <RemoteCode/RemoteCodeClient.hpp>
+#include <RemoteCode/RemoteMapper.hpp>
// It looked nasty in Client.cpp, so I'm putting it here.
namespace Utils
diff --git a/csgo-loader/csgo-client/Login/RemoteLogin.cpp b/csgo-loader/csgo-client/Login/RemoteLogin.cpp
index 4a46da3..2385ab5 100644
--- a/csgo-loader/csgo-client/Login/RemoteLogin.cpp
+++ b/csgo-loader/csgo-client/Login/RemoteLogin.cpp
@@ -55,6 +55,9 @@ namespace Login
bool RemoteLoginTransaction::TranslateResponse(ByteArray &RawResponse)
{
+ if(RawResponse.empty())
+ return false;
+
RemoteLoginResponse ServerResponse = *(RemoteLoginResponse *)&RawResponse[0];
WRAP_IF_DEBUG(
diff --git a/csgo-loader/csgo-client/Networking/TCPClient.cpp b/csgo-loader/csgo-client/Networking/TCPClient.cpp
index c974f88..2ff5095 100644
--- a/csgo-loader/csgo-client/Networking/TCPClient.cpp
+++ b/csgo-loader/csgo-client/Networking/TCPClient.cpp
@@ -144,12 +144,12 @@ namespace Networking
if(EncryptionKey.empty())
return false;
+ std::memcpy(m_EncryptionKey, EncryptionKey.data(), EncryptionKey.size());
+
WRAP_IF_DEBUG(
printf("[DEBUG] Server handshake successful!\n");
)
- std::memcpy(m_EncryptionKey, EncryptionKey.data(), EncryptionKey.size());
-
return true;
}
diff --git a/csgo-loader/csgo-client/RemoteCode/RemoteCodeClient.cpp b/csgo-loader/csgo-client/RemoteCode/RemoteCodeClient.cpp
deleted file mode 100644
index 21d7851..0000000
--- a/csgo-loader/csgo-client/RemoteCode/RemoteCodeClient.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-#include <RemoteCode/RemoteCodeClient.hpp>
-
-namespace RemoteCode
-{
- uint8_t ShellcodeStub[] = {
- 0x55,
- 0x8B, 0xEC,
- 0x56,
- 0x8B, 0x75, 0x08,
- 0x57,
- 0x80, 0x3E, 0x00,
- 0x74, 0x2F,
- 0x8B, 0x7E, 0x14,
- 0x8D, 0x45, 0x08,
- 0x50,
- 0x8B, 0x46, 0x18,
- 0x81, 0xC7, 0xA8, 0x00, 0x00, 0x00,
- 0x6A, 0x40,
- 0x6A, 0x04,
- 0x57,
- 0xFF, 0xD0,
- 0x84, 0xC0,
- 0x74, 0x4D,
- 0x8B, 0x46, 0x10,
- 0x89, 0x07,
- 0x8D, 0x45, 0x08,
- 0x50,
- 0xFF, 0x75, 0x08,
- 0x8B, 0x46, 0x18,
- 0x6A, 0x04,
- 0x57,
- 0xFF, 0xD0,
-
- 0x8B, 0x46, 0x08,
- 0x85, 0xC0,
- 0x74, 0x09,
- 0x6A, 0x00,
- 0x6A, 0x01,
- 0xFF, 0x76, 0x04,
- 0xFF, 0xD0,
-
- 0x53,
- 0x8B, 0x5E, 0x0C,
- 0x85, 0xDB,
- 0x74, 0x20,
- 0x8B, 0x5B, 0x0C,
- 0x33, 0xFF,
- 0x8B, 0x03,
- 0x85, 0xC0,
- 0x74, 0x15,
- 0x90,
-
- 0x6A, 0x00,
- 0x6A, 0x01,
- 0xFF, 0x76, 0x04,
- 0xFF, 0xD0,
- 0x8B, 0x44, 0xBB, 0x04,
- 0x8D, 0x7F, 0x01,
- 0x85, 0xC0,
- 0x75, 0xEC,
-
- 0x5B,
-
- 0x5F,
- 0x5E,
- 0x5D,
- 0xC2, 0x04, 0x00
- };
-} \ No newline at end of file
diff --git a/csgo-loader/csgo-client/RemoteCode/RemoteCodeClient.hpp b/csgo-loader/csgo-client/RemoteCode/RemoteCodeClient.hpp
deleted file mode 100644
index 84021c6..0000000
--- a/csgo-loader/csgo-client/RemoteCode/RemoteCodeClient.hpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#pragma once
-
-#include <RemoteCode/RemoteProcess.hpp>
-
-namespace RemoteCode
-{
- class RemoteCodeClient
- {
- using MemProtect = bool(__stdcall *)(void *, size_t, uint32_t, uint32_t *);
-
- struct ShellcodeParameters
- {
- // Specifies whether or not the thread hijacking
- // exploit will be used for code execution.
- uint8_t m_ThreadExploit;
-
- // Address of the module allocation base
- uintptr_t m_AllocationBase;
-
- // Specifies the entry-point / optional TLS directory
- // to invoke.
- uintptr_t m_EntryPoint;
- uintptr_t m_TlsDirectory;
-
- // Thread hijacking (original address & VMT)
- uintptr_t m_ThreadOriginal;
- uintptr_t m_ThreadVirtual;
-
- // Function parameters that will be passed
- MemProtect m_ProtectMemory;
- };
- };
-} \ No newline at end of file
diff --git a/csgo-loader/csgo-client/RemoteCode/RemoteInjectionClient.cpp b/csgo-loader/csgo-client/RemoteCode/RemoteInjectionClient.cpp
deleted file mode 100644
index 01f52be..0000000
--- a/csgo-loader/csgo-client/RemoteCode/RemoteInjectionClient.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <RemoteCode/RemoteInjectionClient.hpp>
-
-namespace RemoteCode
-{
-
-} \ No newline at end of file
diff --git a/csgo-loader/csgo-client/RemoteCode/RemoteInjectionClient.hpp b/csgo-loader/csgo-client/RemoteCode/RemoteInjectionClient.hpp
deleted file mode 100644
index 2e5d216..0000000
--- a/csgo-loader/csgo-client/RemoteCode/RemoteInjectionClient.hpp
+++ /dev/null
@@ -1,69 +0,0 @@
-#pragma once
-
-#include <RemoteCode/RemoteProcess.hpp>
-#include <UserExperience/UserInterface.hpp>
-
-namespace RemoteCode
-{
- // Used for TransactionStart
- using ImportedModule = char[64];
- using ImportList = std::vector<ImportedModule>;
-
- // Used for TransactionContinue
- struct ExportedFunction
- {
- // I've never seen modules / functions with names
- // that were larger than 64 characters.
- char m_Module[64];
- char m_Function[64];
-
- // Address of exported module / function
- uintptr_t m_ModuleAddress;
- uintptr_t m_FunctionAddress;
- };
-
- using ExportList = std::vector<ExportedFunction>;
-
- // Used for TransactionCommit
- struct RemoteInjectionHeader
- {
- // Used to decrypt the cheat header (first 1000 bytes of image sent back).
- uint8_t m_HeaderKey;
-
- // Used to call entrypoint/TLS callbacks.
- uintptr_t m_EntryPoint;
- uintptr_t m_TlsDirectory;
- };
-
- struct RemoteInjectionCode
- {
- RemoteInjectionHeader m_Header;
-
- // Actual injection code.
- ByteArray m_Code;
- };
-
- // Implementation of client mapping code
- class RemoteInjectionClient
- {
- RemoteInjectionHeader m_Header;
- RemoteProcess m_Process;
-
- public:
- // Receive hash of selected cheat.
- // Reply with size of image to allocate.
- ByteArray Start(ByteArray &Response);
-
- // Receive client header, send over list of imported functions
- ByteArray TransactionStart(ByteArray &Response);
-
- // Receive list of modules & export addresses
- ByteArray TransactionContinue(ByteArray &Response);
-
- // Write the file to the
- void TransactionCommit(ByteArray &Response);
-
- RemoteProcess GetProcess() { return m_Process; }
- RemoteInjectionHeader GetHeader() { return m_Header; }
- };
-} \ No newline at end of file
diff --git a/csgo-loader/csgo-client/RemoteCode/RemoteMapper.cpp b/csgo-loader/csgo-client/RemoteCode/RemoteMapper.cpp
new file mode 100644
index 0000000..7b72550
--- /dev/null
+++ b/csgo-loader/csgo-client/RemoteCode/RemoteMapper.cpp
@@ -0,0 +1,139 @@
+#include <RemoteCode/RemoteMapper.hpp>
+
+namespace RemoteCode
+{
+ bool RemoteMapper::Start(RemoteProcess Process)
+ {
+ m_Process = Process;
+ return true;
+ }
+
+ bool RemoteMapper::WriteCodeToMap(ByteArray Code)
+ {
+ // Check if the PE file is valid.
+ /*uint8_t *Buffer = Code.data();
+ IMAGE_DOS_HEADER *DosHeader = (IMAGE_DOS_HEADER *)Buffer;
+
+ if(!DosHeader || DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
+ return false;
+
+ IMAGE_NT_HEADERS *NtHeaders = (IMAGE_NT_HEADERS *)(Buffer + DosHeader->e_lfanew);
+
+ if(!NtHeaders || NtHeaders->Signature != IMAGE_NT_SIGNATURE)
+ return false;
+
+ WRAP_IF_DEBUG(
+ printf("[DEBUG] PE file validated!\n");
+ );
+
+ IMAGE_SECTION_HEADER *Sections = (IMAGE_SECTION_HEADER *)((uintptr_t)&NtHeaders->OptionalHeader + NtHeaders->FileHeader.SizeOfOptionalHeader);
+
+ if(!Sections)
+ return false;
+
+ // Allocate map in process.
+ m_Map = m_Process.Allocate(Code.size());
+
+ if(!m_Map)
+ return false;
+
+ // Ghetto workaround so heap doesn't get corrupted (i'm lazy)
+ size_t SizeOfCode = Code.size();
+ m_Mapped = new uint8_t[SizeOfCode];
+
+ uint16_t SectionCount = NtHeaders->FileHeader.NumberOfSections;
+
+ // Write each section to the process.
+ for(uint16_t n{}; n < SectionCount; n++)
+ {
+ uint32_t VirtualAddress = Sections[n].VirtualAddress;
+ uint32_t PointerToData = Sections[n].PointerToRawData;
+ uint32_t SizeOfData = Sections[n].SizeOfRawData;
+
+ WRAP_IF_DEBUG(
+ printf("[DEBUG] Writing PE section #%d!\n", n);
+ printf("[DEBUG] Virtual address: 0x%x\n", VirtualAddress);
+ printf("[DEBUG] Pointer to data: 0x%x\n", PointerToData);
+ printf("[DEBUG] Size of data : %d bytes\n", SizeOfData);
+ );
+
+ // Write the data to map.
+ uint8_t *Data = (uint8_t *)((uintptr_t)Buffer + PointerToData);
+ void *ImageRva = (void *)((uintptr_t)&m_Mapped[0] + VirtualAddress);
+
+ std::memcpy(ImageRva, Data, SizeOfData);
+ }
+
+ // Copy over the PE header (temporarily).
+ uint32_t SizeOfHeaders = NtHeaders->OptionalHeader.SizeOfHeaders;
+ std::memcpy(&m_Mapped[0], Buffer, SizeOfHeaders);
+
+ WRAP_IF_DEBUG(
+ printf("[DEBUG] Successfully copied over PE header!\n");
+ printf("[DEBUG] Relocating image...\n");
+ );
+
+ // Relocate the image.
+ IMAGE_BASE_RELOCATION *Reloc = (IMAGE_BASE_RELOCATION *)(&m_Mapped[0] + NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
+
+ uintptr_t ImageDelta = (uintptr_t)m_Map - NtHeaders->OptionalHeader.ImageBase;
+
+ while(Reloc->SizeOfBlock > 0)
+ {
+ // address in binary where we need to relocate an address used by code
+ uintptr_t RelocationAddress = (uintptr_t)&m_Mapped[Reloc->VirtualAddress];
+ uintptr_t RelocationDataAddress = (uintptr_t)Reloc + sizeof IMAGE_BASE_RELOCATION;
+ size_t RelocationCount = (Reloc->SizeOfBlock - sizeof IMAGE_BASE_RELOCATION) / sizeof uint16_t;
+
+ for(size_t i = 0; i < RelocationCount; i++)
+ {
+ uint16_t RelocationData = *(uint16_t *)(RelocationDataAddress + sizeof uint16_t * i);
+ uint16_t RelocationType = RelocationData >> 12;
+ uint16_t RelocationOffset = RelocationData & 0x0FFF;
+
+ WRAP_IF_DEBUG(
+ printf("[DEBUG] Processing relocation at %llx!\n", RelocationAddress + RelocationOffset);
+ );
+
+ switch(RelocationType)
+ {
+ case IMAGE_REL_BASED_MIPS_JMPADDR:
+ case IMAGE_REL_BASED_HIGH:
+ case IMAGE_REL_BASED_LOW:
+ case IMAGE_REL_BASED_HIGHLOW:
+ {
+ *(uint32_t*)(RelocationAddress + RelocationOffset) += ImageDelta;
+ break;
+ }
+
+ case IMAGE_REL_BASED_ABSOLUTE:
+ default:
+ break;
+ };
+ }
+
+ Reloc = (IMAGE_BASE_RELOCATION*)((uintptr_t)Reloc + Reloc->SizeOfBlock);
+ }
+
+ // Cripple the entire PE header.
+ std::memset(&m_Mapped[0], 0, SizeOfHeaders);
+
+ WRAP_IF_DEBUG(
+ printf("[DEBUG] Successfully crippled PE header!\n");
+ );
+
+ // Write the mapped image to the process.
+ m_Process.Write(m_Map, &m_Mapped[0], Code.size());*/
+
+ return true;
+ }
+
+ bool RemoteMapper::ExecuteCodeFromMap()
+ {
+ WRAP_IF_DEBUG(
+ printf("[DEBUG] Executing payload!\n");
+ )
+
+ return true;
+ }
+} \ No newline at end of file
diff --git a/csgo-loader/csgo-client/RemoteCode/RemoteMapper.hpp b/csgo-loader/csgo-client/RemoteCode/RemoteMapper.hpp
new file mode 100644
index 0000000..21eb569
--- /dev/null
+++ b/csgo-loader/csgo-client/RemoteCode/RemoteMapper.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <RemoteCode/RemoteProcess.hpp>
+
+namespace RemoteCode
+{
+ class RemoteMapper
+ {
+ RemoteProcess m_Process;
+ uint8_t *m_Mapped;
+
+ void *m_Map;
+
+ public:
+ RemoteMapper() = default;
+
+ // Copy process & shellcode to class.
+ bool Start(RemoteProcess Process);
+
+ // Writes code to process in allocated page.
+ bool WriteCodeToMap(ByteArray Code);
+
+ // Calls shellcode to call the library ;D
+ bool ExecuteCodeFromMap();
+ };
+} \ 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 1bbfed0..a6b90d4 100644
--- a/csgo-loader/csgo-client/RemoteCode/RemoteProcess.cpp
+++ b/csgo-loader/csgo-client/RemoteCode/RemoteProcess.cpp
@@ -30,7 +30,7 @@ namespace RemoteCode
m_Process = OpenProcess(PROCESS_ALL_ACCESS, false, ProcessEntry.th32ProcessID);
WRAP_IF_DEBUG(
- printf("[DEBUG] Found process \"%s\" -> %p", ProcessEntry.szExeFile, m_Process);
+ printf("[DEBUG] Found process \"%s\" -> %p\n", ProcessEntry.szExeFile, m_Process);
);
if(!m_Process)
diff --git a/csgo-loader/csgo-client/RemoteCode/RemoteProcess.hpp b/csgo-loader/csgo-client/RemoteCode/RemoteProcess.hpp
index a58320f..5fb3c75 100644
--- a/csgo-loader/csgo-client/RemoteCode/RemoteProcess.hpp
+++ b/csgo-loader/csgo-client/RemoteCode/RemoteProcess.hpp
@@ -48,11 +48,11 @@ namespace RemoteCode
}
// Release the handle when the process goes out of scope.
- ~RemoteProcess()
- {
- if(m_Process)
- CloseHandle(m_Process);
- }
+ //~RemoteProcess()
+ //{
+ // if(m_Process)
+ // CloseHandle(m_Process);
+ //}
// Find the process ID and initialise the process.
bool Start(const char *ProcessName);
diff --git a/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp b/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp
index 6054790..bfe45c5 100644
--- a/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp
+++ b/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp
@@ -92,9 +92,7 @@ namespace Security
// Let's meme anyone who tries to reverse this.
if(ReturnModule != LoaderModule)
- {
return []() { Protection->SecurityCallback(STR("Malicious activity [Tampering].")); return -1; }();
- }
// Call original function
return oWSARecv(Socket, Buffer, Length, Flags);
@@ -115,9 +113,7 @@ namespace Security
// Let's meme anyone who tries to reverse this.
if(ReturnModule != LoaderModule)
- {
return []() { Protection->SecurityCallback(STR("Malicious activity [Tampering].")); return -1; }();
- }
// Call original function
return oWSASend(Socket, Buffer, Length, Flags);
@@ -129,9 +125,9 @@ namespace Security
///////////////////////////////////////////////////////////
// Sick macros, retard.
-#define CreateMinHook() MH_STATUS Status; Status = MH_Initialize();
-#define CheckStatus() if(Status != MH_OK) { return false; }
-#define SafeCallTo(Function) Status = Function; CheckStatus();
+ #define CreateMinHook() MH_STATUS Status; Status = MH_Initialize();
+ #define CheckStatus() if(Status != MH_OK) { return false; }
+ #define SafeCallTo(Function) Status = Function; CheckStatus();
#pragma optimize("", off)
@@ -266,8 +262,6 @@ namespace Security
for(auto &It : BlackListedWindows)
{
- // size_t Index = std::distance(...);
-
if(FindWindowA(It.first, It.second))
SecurityCallback(STR("Malicious activity [Debugging attempt]."));
}
@@ -291,7 +285,8 @@ namespace Security
STR("NPF"), // WireShark / WinPCAP
STR("acker"), // Process Hacker
STR("CEDRI"), // Cheat Engine
- //STR("VBox") // VirtualBox
+ STR("nHide"), // TitanHide
+ //STR("VBox") // VirtualBox
};
static const char *BlackListReasons[] = {
@@ -299,7 +294,8 @@ namespace Security
STR("Please uninstall WireShark."),
STR("Please close Process Hacker."),
STR("Please close Cheat Engine."),
- STR("Please uninstall VirtualBox.")
+ STR("Please uninstall TitanHide."),
+ //STR("Please uninstall VirtualBox.")
};
uint16_t Length = sizeof BlackListedDrivers / sizeof(BlackListedDrivers[0]);
@@ -357,14 +353,6 @@ namespace Security
if(m_Identifier.m_SpecialMode[TEST_BUILD_MODE])
SecurityCallback(STR("Malicious activity [Plausible]."));
- // Check if the file was unpacked.
- //if(!VMProtectIsProtected())
- // SecurityCallback(STR("Malicious activity [Tampering]."));
-
- // Check if the image in memory was partially unpacked or patched.
- //if(!VMProtectIsValidImageCRC())
- // SecurityCallback(STR("Malicious activity [Tampering]."));
-
// Don't put too much stress on the CPU.
Sleep(1);
}
@@ -380,50 +368,49 @@ 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;
+ __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;
+
+ device = CreateFileA(STR("\\\\.\\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;
}
void RuntimeSecurity::SetupSystemIdentifier()
diff --git a/csgo-loader/csgo-client/csgo-client.vcxproj b/csgo-loader/csgo-client/csgo-client.vcxproj
index 40af0a8..d29454f 100644
--- a/csgo-loader/csgo-client/csgo-client.vcxproj
+++ b/csgo-loader/csgo-client/csgo-client.vcxproj
@@ -30,8 +30,7 @@
<ClCompile Include="Client.cpp" />
<ClCompile Include="Login\RemoteLogin.cpp" />
<ClCompile Include="Networking\TCPClient.cpp" />
- <ClCompile Include="RemoteCode\RemoteCodeClient.cpp" />
- <ClCompile Include="RemoteCode\RemoteInjectionClient.cpp" />
+ <ClCompile Include="RemoteCode\RemoteMapper.cpp" />
<ClCompile Include="RemoteCode\RemoteProcess.cpp" />
<ClCompile Include="Security\Encryption.cpp" />
<ClCompile Include="Security\RuntimeSecurity.cpp" />
@@ -47,8 +46,7 @@
<ClInclude Include="Client.hpp" />
<ClInclude Include="Login\RemoteLogin.hpp" />
<ClInclude Include="Networking\TCPClient.hpp" />
- <ClInclude Include="RemoteCode\RemoteCodeClient.hpp" />
- <ClInclude Include="RemoteCode\RemoteInjectionClient.hpp" />
+ <ClInclude Include="RemoteCode\RemoteMapper.hpp" />
<ClInclude Include="RemoteCode\RemoteProcess.hpp" />
<ClInclude Include="resource.h" />
<ClInclude Include="Security\Encryption.hpp" />
diff --git a/csgo-loader/csgo-client/csgo-client.vcxproj.filters b/csgo-loader/csgo-client/csgo-client.vcxproj.filters
index 0957ab9..e4b42c3 100644
--- a/csgo-loader/csgo-client/csgo-client.vcxproj.filters
+++ b/csgo-loader/csgo-client/csgo-client.vcxproj.filters
@@ -55,15 +55,12 @@
<ClCompile Include="RemoteCode\RemoteProcess.cpp">
<Filter>RemoteCode</Filter>
</ClCompile>
- <ClCompile Include="RemoteCode\RemoteCodeClient.cpp">
- <Filter>RemoteCode</Filter>
- </ClCompile>
- <ClCompile Include="RemoteCode\RemoteInjectionClient.cpp">
- <Filter>RemoteCode</Filter>
- </ClCompile>
<ClCompile Include="Security\RuntimeSecurity.cpp">
<Filter>Security</Filter>
</ClCompile>
+ <ClCompile Include="RemoteCode\RemoteMapper.cpp">
+ <Filter>RemoteCode</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Security\Encryption.hpp">
@@ -159,17 +156,14 @@
<ClInclude Include="RemoteCode\RemoteProcess.hpp">
<Filter>RemoteCode</Filter>
</ClInclude>
- <ClInclude Include="RemoteCode\RemoteCodeClient.hpp">
- <Filter>RemoteCode</Filter>
- </ClInclude>
- <ClInclude Include="RemoteCode\RemoteInjectionClient.hpp">
- <Filter>RemoteCode</Filter>
- </ClInclude>
<ClInclude Include="Client.hpp" />
<ClInclude Include="Security\RuntimeSecurity.hpp">
<Filter>Security</Filter>
</ClInclude>
<ClInclude Include="resource.h" />
+ <ClInclude Include="RemoteCode\RemoteMapper.hpp">
+ <Filter>RemoteCode</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="csgo-client.rc" />
diff --git a/csgo-loader/csgo-loader.sln b/csgo-loader/csgo-loader.sln
index 741e3e5..45eeb13 100644
--- a/csgo-loader/csgo-loader.sln
+++ b/csgo-loader/csgo-loader.sln
@@ -7,6 +7,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "csgo-client", "csgo-client\
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "csgo-server", "csgo-server\csgo-server.vcxproj", "{97FAC435-B009-4571-AE91-31DC52D47598}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "csgo-module", "csgo-module\csgo-module.vcxproj", "{3A767D6A-B6D0-4D39-92B6-62FD4537F3BD}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -41,6 +43,18 @@ Global
{97FAC435-B009-4571-AE91-31DC52D47598}.Release|x64.Build.0 = Release|x64
{97FAC435-B009-4571-AE91-31DC52D47598}.Release|x86.ActiveCfg = Release|Win32
{97FAC435-B009-4571-AE91-31DC52D47598}.Release|x86.Build.0 = Release|Win32
+ {3A767D6A-B6D0-4D39-92B6-62FD4537F3BD}.Debug|x64.ActiveCfg = Debug|x64
+ {3A767D6A-B6D0-4D39-92B6-62FD4537F3BD}.Debug|x64.Build.0 = Debug|x64
+ {3A767D6A-B6D0-4D39-92B6-62FD4537F3BD}.Debug|x86.ActiveCfg = Debug|Win32
+ {3A767D6A-B6D0-4D39-92B6-62FD4537F3BD}.Debug|x86.Build.0 = Debug|Win32
+ {3A767D6A-B6D0-4D39-92B6-62FD4537F3BD}.FuckMSVC|x64.ActiveCfg = FuckMSVC|x64
+ {3A767D6A-B6D0-4D39-92B6-62FD4537F3BD}.FuckMSVC|x64.Build.0 = FuckMSVC|x64
+ {3A767D6A-B6D0-4D39-92B6-62FD4537F3BD}.FuckMSVC|x86.ActiveCfg = Release|Win32
+ {3A767D6A-B6D0-4D39-92B6-62FD4537F3BD}.FuckMSVC|x86.Build.0 = Release|Win32
+ {3A767D6A-B6D0-4D39-92B6-62FD4537F3BD}.Release|x64.ActiveCfg = Release|x64
+ {3A767D6A-B6D0-4D39-92B6-62FD4537F3BD}.Release|x64.Build.0 = Release|x64
+ {3A767D6A-B6D0-4D39-92B6-62FD4537F3BD}.Release|x86.ActiveCfg = Release|Win32
+ {3A767D6A-B6D0-4D39-92B6-62FD4537F3BD}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/csgo-loader/csgo-module/Module.cpp b/csgo-loader/csgo-module/Module.cpp
new file mode 100644
index 0000000..1fa638c
--- /dev/null
+++ b/csgo-loader/csgo-module/Module.cpp
@@ -0,0 +1,76 @@
+#include <Module.hpp>
+
+/*
+ TODO:
+ - 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)
+ - or the code is mapped and called via DX9 (does not allow custom param)
+ - This will probably be the easiest thing to do.
+
+ - Allocate via consecutive 64kb sections (TODO: Figure out how)
+
+ - Free and wipe the module from memory once done
+ - Have the module authenticate via HWID or some shit.. idk (AAAAAAAAAAA)
+ - Do reloc/mapping stuff here
+*/
+
+DWORD ModuleThread(void *)
+{
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ // Initialize the syscall manager.
+ if(!Syscalls->Start())
+ return 0;
+
+ // Attempt to connect to the remote server.
+ WRAP_IF_DEBUG(
+ printf("[DEBUG] Server IP: %08x\n", inet_addr("35.165.60.229"));
+ );
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ // Connect to server.
+ Networking::TCPClientPtr Client = std::make_unique<Networking::TCPClient>();
+
+ if(!Client->Start(LOCAL_IP, SERVER_PORT))
+ return 0;
+
+ // Header for Module.
+ ByteArray Header{ 0x0A, 0x32, 0x42, 0x4D };
+ Client->SendRawBytes(Header);
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ return 1;
+}
+
+int __stdcall DllMain(void *, unsigned Reason, void *)
+{
+ if(Reason != 1)
+ return false;
+
+ HANDLE Thread = CreateThread(nullptr, 0, ModuleThread, nullptr, 0, nullptr);
+
+ if(Thread)
+ {
+ // Wait for thread to finish execution
+ WaitForSingleObject(Thread, INFINITE);
+
+ // Get exit code from thread.
+ DWORD ExitCode;
+ GetExitCodeThread(Thread, &ExitCode);
+
+ // If the HWND is 0, the loader will reveal that MessageBoxA was called from
+ // explorer.exe... This meme will get around that.
+ HWND Window = FindWindowA(STR("Valve001"), nullptr);
+
+ if(!Window)
+ return true;
+
+ if(!ExitCode)
+ MessageBoxA(Window, STR("[000F:00004A00] Failed to initialize. Please contact an administrator."), "", MB_ICONERROR | MB_OK);
+ }
+
+ return true;
+} \ No newline at end of file
diff --git a/csgo-loader/csgo-module/Module.hpp b/csgo-loader/csgo-module/Module.hpp
new file mode 100644
index 0000000..18a3ff1
--- /dev/null
+++ b/csgo-loader/csgo-module/Module.hpp
@@ -0,0 +1,55 @@
+#pragma once
+
+// NOTE:
+// THE FOLLOWING MACROS ARE USED ONLY IN CLIENT.CPP
+// PLEASE UPDATE THEM ACCORDINGLY.
+#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.
+
+
+// Security features (these will be initialised and ran
+// first, failure will terminate loader execution).
+#include <Security/SyscallManager.hpp>
+
+// Core functionality
+#include <Networking/TCPClient.hpp>
+
+// Required for the SDK from VMP which offers
+// virtual machines and string encryption, as
+// well as debug/VM checks.
+#include <VMProtectSDK.h>
+
+// Just a neat little feature that I decided to implement :-)
+#ifdef DEBUG
+ // Sick macros, retard.
+#define WRAP_IF_RELEASE( s )
+#define WRAP_IF_DEBUG( s ) { s; }
+
+#define STR( s ) s
+#else
+ // Sick macros, retard.
+#define WRAP_IF_RELEASE( s ) { s; }
+#define WRAP_IF_DEBUG( s )
+
+#define STR( s ) VMProtectDecryptStringA( s )
+#endif
+
+// It looked nasty in Module.cpp, so I'm putting it here.
+namespace Utils
+{
+ inline void OpenConsole()
+ {
+ // Create instance of console.
+ AllocConsole();
+
+ // Allow console to access output stream.
+ FILE *file;
+ freopen_s(&file, STR("CONOUT$"), STR("w"), stdout);
+
+ // :^)
+ SetConsoleTitleA(STR("moneymodule $"));
+
+ printf(STR("[DEBUG] Ready\n"));
+ }
+} \ No newline at end of file
diff --git a/csgo-loader/csgo-module/Networking/TCPClient.cpp b/csgo-loader/csgo-module/Networking/TCPClient.cpp
new file mode 100644
index 0000000..e22bfdf
--- /dev/null
+++ b/csgo-loader/csgo-module/Networking/TCPClient.cpp
@@ -0,0 +1,119 @@
+#include <Networking/TCPClient.hpp>
+
+namespace Networking
+{
+ // We will only receive up to 256 bytes per cycle.
+ constexpr int BufferSize = 256;
+
+ void TCPClient::SendRawBytes(ByteArray &Bytes)
+ {
+ // Send data.
+ send(m_Socket, (char *)Bytes.data(), (int)Bytes.size(), 0);
+ }
+
+ ByteArray TCPClient::ReceiveRawBytes()
+ {
+ ByteArray ReceivedBytes;
+ uint8_t RecvBuffer[BufferSize];
+
+ // Attempt to receive a packet.
+ while(true)
+ {
+ int32_t Received = recv(m_Socket, (char*)RecvBuffer, BufferSize, 0);
+
+ // No more bytes left to receive.
+ if(Received < 0)
+ break;
+
+ // Emplace all received bytes.
+ for(int n = 0; n < Received; ++n)
+ {
+ ReceivedBytes.push_back(RecvBuffer[n]);
+ }
+
+ // No more bytes left to receive.
+ if(Received < BufferSize)
+ break;
+ }
+
+ return ReceivedBytes;
+ }
+
+ void TCPClient::SendBytes(ByteArray &Bytes)
+ {
+ // Encrypt outgoing data.
+ ByteArray EncryptionKey;
+ EncryptionKey.insert(
+ EncryptionKey.begin(),
+ m_EncryptionKey,
+ m_EncryptionKey + sizeof m_EncryptionKey
+ );
+
+ Wrapper::Encryption Encryption; Encryption.Start(EncryptionKey);
+
+ ByteArray Encrypted = Encryption.Encrypt(Bytes);
+
+ SendRawBytes(Encrypted);
+ }
+
+ ByteArray TCPClient::ReceiveBytes()
+ {
+ // Decrypt incoming data.
+ ByteArray ReceivedBytes = ReceiveRawBytes();
+
+ ByteArray EncryptionKey;
+ EncryptionKey.insert(
+ EncryptionKey.begin(),
+ m_EncryptionKey,
+ m_EncryptionKey + sizeof m_EncryptionKey
+ );
+
+ Wrapper::Encryption Encryption; Encryption.Start(EncryptionKey);
+
+ ByteArray Decrypted = Encryption.Decrypt(ReceivedBytes);
+
+ return Decrypted;
+ }
+
+ bool TCPClient::Start(uint32_t ServerAddress, uint16_t ServerPort)
+ {
+ const int32_t version = 0x101;
+
+ // Initialise WinSocks.
+ if(WSAStartup(version, &m_WinSocks))
+ return false;
+
+ // Create an IPv4 socket.
+ m_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ if(m_Socket == INVALID_SOCKET)
+ return false;
+
+ // Set up client context.
+ m_Context.sin_addr.s_addr = ServerAddress;
+ m_Context.sin_family = AF_INET;
+ m_Context.sin_port = htons(ServerPort);
+
+ // Attempt connection.
+ if(connect(m_Socket, (sockaddr *)&m_Context, sizeof m_Context))
+ return false;
+
+ // Initialise encryption wrapper.
+ ByteArray EncryptionKey = ReceiveRawBytes();
+
+ if(EncryptionKey.empty())
+ return false;
+
+ std::memcpy(m_EncryptionKey, EncryptionKey.data(), EncryptionKey.size());
+
+ return true;
+ }
+
+ void TCPClient::Kill()
+ {
+ if(m_Socket)
+ closesocket(m_Socket);
+
+ WSACleanup();
+ }
+} \ No newline at end of file
diff --git a/csgo-loader/csgo-module/Networking/TCPClient.hpp b/csgo-loader/csgo-module/Networking/TCPClient.hpp
new file mode 100644
index 0000000..a5794e9
--- /dev/null
+++ b/csgo-loader/csgo-module/Networking/TCPClient.hpp
@@ -0,0 +1,46 @@
+#pragma once
+
+// For encryption wrappers.
+#include <Security/Encryption.hpp>
+
+// WinSocks
+#include <winsock2.h>
+#pragma comment(lib, "ws2_32.lib")
+
+// std::min
+#include <algorithm>
+
+// std::unique_ptr
+#include <memory>
+
+namespace Networking
+{
+ // A TCPClient is essentially the same as the TCPConnection counterpart on the server,
+ // however, it independently handles connection.
+ class TCPClient
+ {
+ WSADATA m_WinSocks;
+ SOCKET m_Socket;
+ sockaddr_in m_Context;
+ uint8_t m_EncryptionKey[32];
+
+ public:
+ TCPClient() = default;
+
+ // 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();
+
+ // Wrappers for sending/receiving data.
+ void SendRawBytes(ByteArray &Bytes);
+ ByteArray ReceiveRawBytes();
+
+ void SendBytes(ByteArray &Bytes);
+ ByteArray ReceiveBytes();
+ };
+
+ using TCPClientPtr = std::unique_ptr<TCPClient>;
+} \ No newline at end of file
diff --git a/csgo-loader/csgo-module/Security/Encryption.cpp b/csgo-loader/csgo-module/Security/Encryption.cpp
new file mode 100644
index 0000000..2763d23
--- /dev/null
+++ b/csgo-loader/csgo-module/Security/Encryption.cpp
@@ -0,0 +1,614 @@
+#include <Security/Encryption.hpp>
+
+#define FE(x) (((x) << 1) ^ ((((x)>>7) & 1) * 0x1b))
+#define FD(x) (((x) >> 1) ^ (((x) & 1) ? 0x8d : 0))
+
+#define KEY_SIZE 32
+#define NUM_ROUNDS 14
+
+namespace Wrapper
+{
+ // Constants used for the AES256 algorithm.
+ uint8_t sbox[256] = {
+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
+ 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+ 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
+ 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
+ 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+ 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
+ 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
+ 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+ 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
+ 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
+ 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+ 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
+ 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
+ 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+ 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
+ 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
+ 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+ };
+
+ 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,
+ 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
+ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
+ 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
+ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
+ 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
+ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
+ 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
+ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
+ 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
+ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
+ 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
+ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
+ 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
+ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
+ 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
+ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
+ 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
+ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
+ 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
+ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
+ 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
+ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
+ 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
+ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
+ 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
+ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
+ 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
+ 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
+ };
+
+ // Implementation of the AES256 encryption algorithm.
+ uint8_t rj_xtime(uint8_t x);
+
+ Aes256::Aes256(const ByteArray& key)
+ : m_key(ByteArray(key.size() > KEY_SIZE ? KEY_SIZE : key.size(), 0))
+ , m_salt(ByteArray(KEY_SIZE - m_key.size(), 0))
+ , m_rkey(ByteArray(KEY_SIZE, 0))
+ , m_buffer_pos(0)
+ , m_remainingLength(0)
+ , m_decryptInitialized(false)
+ {
+ for(ByteArray::size_type i = 0; i < m_key.size(); ++i)
+ m_key[i] = key[i];
+ }
+
+ Aes256::~Aes256()
+ {
+ }
+
+ ByteArray::size_type Aes256::encrypt(const ByteArray& key, const ByteArray& plain, ByteArray& encrypted)
+ {
+ Aes256 aes(key);
+
+ aes.encrypt_start(plain.size(), encrypted);
+ aes.encrypt_continue(plain, encrypted);
+ aes.encrypt_end(encrypted);
+
+ return encrypted.size();
+ }
+
+ 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);
+ aes.encrypt_continue(plain, plain_length, encrypted);
+ aes.encrypt_end(encrypted);
+
+ return encrypted.size();
+ }
+
+ ByteArray::size_type Aes256::decrypt(const ByteArray& key, const ByteArray& encrypted, ByteArray& plain)
+ {
+ Aes256 aes(key);
+
+ aes.decrypt_start(encrypted.size());
+ aes.decrypt_continue(encrypted, plain);
+ aes.decrypt_end(plain);
+
+ return plain.size();
+ }
+
+ 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);
+ aes.decrypt_continue(encrypted, encrypted_length, plain);
+ aes.decrypt_end(plain);
+
+ return plain.size();
+ }
+
+ ByteArray::size_type Aes256::encrypt_start(const ByteArray::size_type plain_length, ByteArray& encrypted)
+ {
+ m_remainingLength = plain_length;
+
+ // Generate salt
+ ByteArray::iterator it = m_salt.begin(), itEnd = m_salt.end();
+ while(it != itEnd)
+ *(it++) = (rand() & 0xFF);
+
+ // Calculate padding
+ ByteArray::size_type padding = 0;
+ if(m_remainingLength % BLOCK_SIZE != 0)
+ padding = (BLOCK_SIZE - (m_remainingLength % BLOCK_SIZE));
+ m_remainingLength += padding;
+
+ // Add salt
+ encrypted.insert(encrypted.end(), m_salt.begin(), m_salt.end());
+ m_remainingLength += m_salt.size();
+
+ // Add 1 bytes for padding size
+ encrypted.push_back(padding & 0xFF);
+ ++m_remainingLength;
+
+ // Reset buffer
+ m_buffer_pos = 0;
+
+ return encrypted.size();
+ }
+
+ ByteArray::size_type Aes256::encrypt_continue(const ByteArray& plain, ByteArray& encrypted)
+ {
+ ByteArray::const_iterator it = plain.begin(), itEnd = plain.end();
+
+ while(it != itEnd)
+ {
+ m_buffer[m_buffer_pos++] = *(it++);
+
+ check_and_encrypt_buffer(encrypted);
+ }
+
+ return encrypted.size();
+ }
+
+ 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)
+ {
+ m_buffer[m_buffer_pos++] = plain[i++];
+
+ check_and_encrypt_buffer(encrypted);
+ }
+
+ return encrypted.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)
+ {
+ encrypted.push_back(m_buffer[m_buffer_pos]);
+ --m_remainingLength;
+ }
+
+ 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)
+ {
+ encrypted.push_back(m_buffer[m_buffer_pos]);
+ --m_remainingLength;
+ }
+
+ m_buffer_pos = 0;
+ }
+
+ return encrypted.size();
+ }
+
+ 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)
+ {
+ sub_bytes(buffer);
+ shift_rows(buffer);
+ mix_columns(buffer);
+ if(!(i & 1))
+ expand_enc_key(&rcon);
+ add_round_key(buffer, i);
+ }
+ sub_bytes(buffer);
+ shift_rows(buffer);
+ expand_enc_key(&rcon);
+ add_round_key(buffer, i);
+ }
+
+ ByteArray::size_type Aes256::decrypt_start(const ByteArray::size_type encrypted_length)
+ {
+ unsigned char j;
+
+ m_remainingLength = encrypted_length;
+
+ // Reset salt
+ for(j = 0; j < m_salt.size(); ++j)
+ m_salt[j] = 0;
+ m_remainingLength -= m_salt.size();
+
+ // Reset buffer
+ m_buffer_pos = 0;
+
+ m_decryptInitialized = false;
+
+ return m_remainingLength;
+ }
+
+ ByteArray::size_type Aes256::decrypt_continue(const ByteArray& encrypted, ByteArray& plain)
+ {
+ ByteArray::const_iterator it = encrypted.begin(), itEnd = encrypted.end();
+
+ while(it != itEnd)
+ {
+ m_buffer[m_buffer_pos++] = *(it++);
+
+ check_and_decrypt_buffer(plain);
+ }
+
+ return plain.size();
+ }
+
+ 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)
+ {
+ m_buffer[m_buffer_pos++] = encrypted[i++];
+
+ check_and_decrypt_buffer(plain);
+ }
+
+ return plain.size();
+ }
+
+ 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;
+
+ // Get salt
+ for(j = 0; j < m_salt.size(); ++j)
+ m_salt[j] = m_buffer[j];
+
+ // Get padding
+ padding = (m_buffer[j] & 0xFF);
+ m_remainingLength -= padding + 1;
+
+ // Start decrypting
+ m_buffer_pos = 0;
+
+ m_decryptInitialized = true;
+ }
+ 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)
+ {
+ plain.push_back(m_buffer[m_buffer_pos]);
+ --m_remainingLength;
+ }
+
+ m_buffer_pos = 0;
+ }
+ }
+
+ ByteArray::size_type Aes256::decrypt_end(ByteArray& plain)
+ {
+ return plain.size();
+ }
+
+ void Aes256::decrypt(unsigned char* buffer)
+ {
+ unsigned char i, rcon = 1;
+
+ copy_key();
+ for(i = NUM_ROUNDS / 2; i > 0; --i)
+ expand_enc_key(&rcon);
+
+ add_round_key(buffer, NUM_ROUNDS);
+ shift_rows_inv(buffer);
+ sub_bytes_inv(buffer);
+
+ for(i = NUM_ROUNDS, rcon = 0x80; --i;)
+ {
+ if((i & 1))
+ expand_dec_key(&rcon);
+ add_round_key(buffer, i);
+ mix_columns_inv(buffer);
+ shift_rows_inv(buffer);
+ sub_bytes_inv(buffer);
+ }
+ add_round_key(buffer, i);
+ }
+
+ void Aes256::expand_enc_key(unsigned char* rc)
+ {
+ unsigned char i;
+
+ m_rkey[0] = m_rkey[0] ^ sbox[m_rkey[29]] ^ (*rc);
+ m_rkey[1] = m_rkey[1] ^ sbox[m_rkey[30]];
+ m_rkey[2] = m_rkey[2] ^ sbox[m_rkey[31]];
+ m_rkey[3] = m_rkey[3] ^ sbox[m_rkey[28]];
+ *rc = FE(*rc);
+
+ 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];
+ m_rkey[i + 3] = m_rkey[i + 3] ^ m_rkey[i - 1];
+ }
+ m_rkey[16] = m_rkey[16] ^ sbox[m_rkey[12]];
+ m_rkey[17] = m_rkey[17] ^ sbox[m_rkey[13]];
+ 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)
+ {
+ 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];
+ m_rkey[i + 3] = m_rkey[i + 3] ^ m_rkey[i - 1];
+ }
+ }
+
+ void Aes256::expand_dec_key(unsigned char* rc)
+ {
+ unsigned char i;
+
+ 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];
+ m_rkey[i + 3] = m_rkey[i + 3] ^ m_rkey[i - 1];
+ }
+
+ m_rkey[16] = m_rkey[16] ^ sbox[m_rkey[12]];
+ m_rkey[17] = m_rkey[17] ^ sbox[m_rkey[13]];
+ 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)
+ {
+ 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];
+ m_rkey[i + 3] = m_rkey[i + 3] ^ m_rkey[i - 1];
+ }
+
+ *rc = FD(*rc);
+ m_rkey[0] = m_rkey[0] ^ sbox[m_rkey[29]] ^ (*rc);
+ m_rkey[1] = m_rkey[1] ^ sbox[m_rkey[30]];
+ m_rkey[2] = m_rkey[2] ^ sbox[m_rkey[31]];
+ m_rkey[3] = m_rkey[3] ^ sbox[m_rkey[28]];
+ }
+
+ 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)
+ {
+ unsigned char i = KEY_SIZE / 2;
+
+ while(i--)
+ buffer[i] = sboxinv[buffer[i]];
+ }
+
+ void Aes256::copy_key()
+ {
+ ByteArray::size_type i;
+
+ for(i = 0; i < m_key.size(); ++i)
+ m_rkey[i] = m_key[i];
+ for(i = 0; i < m_salt.size(); ++i)
+ m_rkey[i + m_key.size()] = m_salt[i];
+ }
+
+ 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)
+ {
+ unsigned char i, j, k, l; /* to make it potentially parallelable :) */
+
+ i = buffer[1];
+ buffer[1] = buffer[5];
+ buffer[5] = buffer[9];
+ buffer[9] = buffer[13];
+ buffer[13] = i;
+
+ j = buffer[10];
+ buffer[10] = buffer[2];
+ buffer[2] = j;
+
+ k = buffer[3];
+ buffer[3] = buffer[15];
+ buffer[15] = buffer[11];
+ buffer[11] = buffer[7];
+ buffer[7] = k;
+
+ l = buffer[14];
+ buffer[14] = buffer[6];
+ buffer[6] = l;
+ }
+
+ void Aes256::shift_rows_inv(unsigned char* buffer)
+ {
+ unsigned char i, j, k, l; /* same as above :) */
+
+ i = buffer[1];
+ buffer[1] = buffer[13];
+ buffer[13] = buffer[9];
+ buffer[9] = buffer[5];
+ buffer[5] = i;
+
+ j = buffer[2];
+ buffer[2] = buffer[10];
+ buffer[10] = j;
+
+ k = buffer[3];
+ buffer[3] = buffer[7];
+ buffer[7] = buffer[11];
+ buffer[11] = buffer[15];
+ buffer[15] = k;
+
+ l = buffer[6];
+ buffer[6] = buffer[14];
+ buffer[14] = l;
+ }
+
+ void Aes256::mix_columns(unsigned char* buffer)
+ {
+ unsigned char i, a, b, c, d, e;
+
+ for(i = 0; i < 16; i += 4)
+ {
+ a = buffer[i];
+ b = buffer[i + 1];
+ c = buffer[i + 2];
+ d = buffer[i + 3];
+
+ e = a ^ b ^ c ^ d;
+
+ buffer[i] ^= e ^ rj_xtime(a^b);
+ buffer[i + 1] ^= e ^ rj_xtime(b^c);
+ buffer[i + 2] ^= e ^ rj_xtime(c^d);
+ buffer[i + 3] ^= e ^ rj_xtime(d^a);
+ }
+ }
+
+ 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)
+ {
+ a = buffer[i];
+ b = buffer[i + 1];
+ c = buffer[i + 2];
+ d = buffer[i + 3];
+
+ e = a ^ b ^ c ^ d;
+ z = rj_xtime(e);
+ x = e ^ rj_xtime(rj_xtime(z^a^c)); y = e ^ rj_xtime(rj_xtime(z^b^d));
+
+ buffer[i] ^= x ^ rj_xtime(a^b);
+ buffer[i + 1] ^= y ^ rj_xtime(b^c);
+ buffer[i + 2] ^= x ^ rj_xtime(c^d);
+ buffer[i + 3] ^= y ^ rj_xtime(d^a);
+ }
+ }
+
+ 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()
+ {
+ // Create cryptographic context.
+ if(!CryptAcquireContextA(&m_CryptProvider, nullptr, nullptr, PROV_RSA_AES, 0))
+ {
+ if(!CryptAcquireContextA(&m_CryptProvider, nullptr, nullptr, PROV_RSA_AES, CRYPT_NEWKEYSET))
+ return;
+ }
+
+ uint8_t RandomBytes[32];
+ uint32_t RandomBytesCount = sizeof RandomBytes;
+
+ // Generate random bytes to use as encryption key.
+ if(CryptGenRandom(m_CryptProvider, RandomBytesCount, RandomBytes))
+ std::memcpy(m_EncryptionKey, RandomBytes, RandomBytesCount);
+
+ // Release context.
+ if(m_CryptProvider)
+ CryptReleaseContext(m_CryptProvider, 0);
+ }
+
+ void Encryption::Start(ByteArray &EncryptionKey)
+ {
+ // If an encryption key is provided, initialise the wrapper with
+ // the passed parameter.
+ if(!EncryptionKey.empty())
+ std::memcpy(m_EncryptionKey, EncryptionKey.data(), EncryptionKey.size());
+
+ if(EncryptionKey.empty())
+ Start();
+ }
+
+ ByteArray Encryption::Encrypt(ByteArray &Data)
+ {
+ // Encrypt outgoing data.
+ ByteArray Encrypted;
+
+ Aes256::encrypt(GetKey(), Data, Encrypted);
+
+ return Encrypted;
+ }
+
+ ByteArray Encryption::Decrypt(ByteArray &Data)
+ {
+ // Decrypt incoming data.
+ ByteArray Decrypted;
+
+ Aes256::decrypt(GetKey(), Data, Decrypted);
+
+ return Decrypted;
+ }
+} \ No newline at end of file
diff --git a/csgo-loader/csgo-module/Security/Encryption.hpp b/csgo-loader/csgo-module/Security/Encryption.hpp
new file mode 100644
index 0000000..a69b349
--- /dev/null
+++ b/csgo-loader/csgo-module/Security/Encryption.hpp
@@ -0,0 +1,101 @@
+#pragma once
+
+#include <cstdint>
+#include <vector>
+#include <windows.h>
+#include <wincrypt.h>
+
+using ByteArray = std::vector<uint8_t>;
+
+#define BLOCK_SIZE 16
+
+namespace Wrapper
+{
+ // AES256 implementation.
+ class Aes256
+ {
+
+ public:
+ Aes256(const ByteArray& key);
+ ~Aes256();
+
+ static ByteArray::size_type encrypt(const ByteArray& key, const ByteArray& plain, ByteArray& encrypted);
+ static ByteArray::size_type encrypt(const ByteArray& key, const unsigned char* plain, const ByteArray::size_type plain_length, ByteArray& encrypted);
+ static ByteArray::size_type decrypt(const ByteArray& key, const ByteArray& encrypted, ByteArray& plain);
+ static ByteArray::size_type decrypt(const ByteArray& key, const unsigned char* encrypted, const ByteArray::size_type encrypted_length, ByteArray& plain);
+
+ ByteArray::size_type encrypt_start(const ByteArray::size_type plain_length, ByteArray& encrypted);
+ ByteArray::size_type encrypt_continue(const ByteArray& plain, ByteArray& encrypted);
+ ByteArray::size_type encrypt_continue(const unsigned char* plain, const ByteArray::size_type plain_length, ByteArray& encrypted);
+ ByteArray::size_type encrypt_end(ByteArray& encrypted);
+
+ ByteArray::size_type decrypt_start(const ByteArray::size_type encrypted_length);
+ ByteArray::size_type decrypt_continue(const ByteArray& encrypted, ByteArray& plain);
+ ByteArray::size_type decrypt_continue(const unsigned char* encrypted, const ByteArray::size_type encrypted_length, ByteArray& plain);
+ ByteArray::size_type decrypt_end(ByteArray& plain);
+
+ private:
+ ByteArray m_key;
+ ByteArray m_salt;
+ ByteArray m_rkey;
+
+ unsigned char m_buffer[3 * BLOCK_SIZE];
+ unsigned char m_buffer_pos;
+ ByteArray::size_type m_remainingLength;
+
+ bool m_decryptInitialized;
+
+ void check_and_encrypt_buffer(ByteArray& encrypted);
+ void check_and_decrypt_buffer(ByteArray& plain);
+
+ void encrypt(unsigned char *buffer);
+ void decrypt(unsigned char *buffer);
+
+ void expand_enc_key(unsigned char *rc);
+ void expand_dec_key(unsigned char *rc);
+
+ void sub_bytes(unsigned char *buffer);
+ void sub_bytes_inv(unsigned char *buffer);
+
+ void copy_key();
+
+ void add_round_key(unsigned char *buffer, const unsigned char round);
+
+ void shift_rows(unsigned char *buffer);
+ void shift_rows_inv(unsigned char *buffer);
+
+ void mix_columns(unsigned char *buffer);
+ void mix_columns_inv(unsigned char *buffer);
+ };
+
+ // Encryption wrapper.
+ class Encryption
+ {
+ uint8_t m_EncryptionKey[32];
+ HCRYPTPROV m_CryptProvider;
+
+ public:
+ // Generate a random cryptographic key.
+ // OPTIONAL: You can pass a premade encryption key as a parameter.
+ void Start();
+ void Start(ByteArray &EncryptionKey);
+
+ // Handles encryption/decryption of data.
+ ByteArray Encrypt(ByteArray &Data);
+ ByteArray Decrypt(ByteArray &Data);
+
+ // Exposes the encryption key.
+ ByteArray GetKey()
+ {
+ ByteArray TemporaryKey;
+
+ TemporaryKey.insert(
+ TemporaryKey.begin(),
+ m_EncryptionKey,
+ m_EncryptionKey + sizeof m_EncryptionKey
+ );
+
+ return TemporaryKey;
+ }
+ };
+} \ No newline at end of file
diff --git a/csgo-loader/csgo-module/Security/FnvHash.hpp b/csgo-loader/csgo-module/Security/FnvHash.hpp
new file mode 100644
index 0000000..35c9ad0
--- /dev/null
+++ b/csgo-loader/csgo-module/Security/FnvHash.hpp
@@ -0,0 +1,100 @@
+#pragma once
+#include <cstdint>
+#include <type_traits>
+
+// Credits: namazso
+// Implements FNV-1a hash algorithm
+namespace detail
+{
+ template <typename Type, Type OffsetBasis, Type Prime>
+ struct SizeDependantData
+ {
+ using type = Type;
+
+ constexpr static auto k_offset_basis = OffsetBasis;
+ constexpr static auto k_prime = Prime;
+ };
+
+ template <std::size_t Bits>
+ struct SizeSelector : std::false_type {};
+
+ template <>
+ struct SizeSelector<32> : SizeDependantData<std::uint32_t, 0x811c9dc5ul, 16777619ul> {};
+
+ template <>
+ struct SizeSelector<64> : SizeDependantData<std::uint64_t, 0xcbf29ce484222325ull, 1099511628211ull> {};
+
+ template <std::size_t Size>
+ class FnvHash
+ {
+ private:
+ using data_t = SizeSelector<Size>;
+
+ public:
+ using hash = typename data_t::type;
+
+ private:
+ constexpr static auto k_offset_basis = data_t::k_offset_basis;
+ constexpr static auto k_prime = data_t::k_prime;
+
+ public:
+ static __forceinline constexpr auto hash_init(
+ ) -> hash
+ {
+ return k_offset_basis;
+ }
+
+ static __forceinline constexpr auto hash_byte(
+ hash current,
+ std::uint8_t byte
+ ) -> hash
+ {
+ return (current ^ byte) * k_prime;
+ }
+
+ template <std::size_t N>
+ static __forceinline constexpr auto hash_constexpr(
+ const char(&str)[N],
+ const std::size_t size = N - 1 /* do not hash the null */
+ ) -> 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;
+ }
+
+ static auto __forceinline hash_runtime_data(
+ const void* data,
+ const std::size_t sz
+ ) -> hash
+ {
+ const auto bytes = static_cast<const uint8_t*>(data);
+ const auto end = bytes + sz;
+ auto result = hash_init();
+ for(auto it = bytes; it < end; ++it)
+ result = hash_byte(result, *it);
+
+ return result;
+ }
+
+ static auto __forceinline hash_runtime(
+ const char* str
+ ) -> hash
+ {
+ auto result = hash_init();
+ do
+ result = hash_byte(result, *str++);
+ while(*str != '\0');
+
+ return result;
+ }
+ };
+}
+
+using fnv32 = ::detail::FnvHash<32>;
+using fnv64 = ::detail::FnvHash<64>;
+using fnv = ::detail::FnvHash<sizeof(void*) * 8>;
+
+#define FNV(str) (std::integral_constant<fnv::hash, fnv::hash_constexpr(str)>::value)
+#define FNV32(str) (std::integral_constant<fnv32::hash, fnv32::hash_constexpr(str)>::value)
+#define FNV64(str) (std::integral_constant<fnv64::hash, fnv64::hash_constexpr(str)>::value) \ No newline at end of file
diff --git a/csgo-loader/csgo-module/Security/SyscallManager.cpp b/csgo-loader/csgo-module/Security/SyscallManager.cpp
new file mode 100644
index 0000000..0338d88
--- /dev/null
+++ b/csgo-loader/csgo-module/Security/SyscallManager.cpp
@@ -0,0 +1,159 @@
+#include <Security/SyscallManager.hpp>
+
+// Global accessor for SyscallManager.
+Wrapper::SyscallManagerPtr Syscalls = std::make_unique<Wrapper::SyscallManager>();
+
+namespace Wrapper
+{
+ void SyscallStub::SetIndex(uint32_t Index)
+ {
+ DWORD OldProtection{};
+
+ // Make the code executable and set the index.
+ if(VirtualProtect(m_Shellcode, sizeof m_Shellcode, PAGE_EXECUTE_READWRITE, &OldProtection))
+ {
+ *(uint32_t *)(&m_Shellcode[4]) = Index;
+ }
+ }
+
+ ByteArray SyscallManager::GetNtdllFromDisk()
+ {
+ char SystemPath[MAX_PATH];
+ GetSystemDirectoryA(SystemPath, MAX_PATH);
+
+ // Append 'ntdll.dll' to path.
+ strcat_s(SystemPath, "\\ntdll.dll");
+
+ // Open handle to 'ntdll.dll'.
+ std::ifstream FileHandle(SystemPath, std::ios::in | std::ios::binary);
+ FileHandle.unsetf(std::ios::skipws);
+
+ if(!FileHandle.is_open())
+ return ByteArray{};
+
+ // Read bytes to ByteArray.
+ ByteArray Bytes;
+ Bytes.insert(
+ Bytes.begin(),
+ std::istream_iterator<uint8_t>(FileHandle),
+ std::istream_iterator<uint8_t>()
+ );
+
+ FileHandle.close();
+
+ return Bytes;
+ }
+
+ // Stolen :-)
+ uintptr_t SyscallManager::GetRawOffsetByRva(IMAGE_SECTION_HEADER *SectionHeader, uintptr_t Sections, uintptr_t FileSize, uintptr_t Rva)
+ {
+ IMAGE_SECTION_HEADER *Header = GetSectionByRva(SectionHeader, Sections, Rva);
+
+ if(!Header)
+ return 0;
+
+ uintptr_t Delta = Rva - Header->VirtualAddress;
+ uintptr_t Offset = Header->PointerToRawData + Delta;
+
+ // Sanity check, otherwise this would crash on versions below Windows 10...
+ // for whatever reason..
+ if(Offset >= FileSize)
+ return 0;
+
+ return Offset;
+ }
+
+ IMAGE_SECTION_HEADER *SyscallManager::GetSectionByRva(IMAGE_SECTION_HEADER *SectionHeader, uintptr_t Sections, uintptr_t Rva)
+ {
+ IMAGE_SECTION_HEADER *Header = SectionHeader;
+
+ for(size_t i{}; i < Sections; ++i, ++Header)
+ {
+ uintptr_t VirtualAddress = Header->VirtualAddress;
+ uintptr_t AddressBounds = VirtualAddress + Header->SizeOfRawData;
+
+ if(Rva >= VirtualAddress && Rva < AddressBounds)
+ return Header;
+ }
+
+ return nullptr;
+ }
+
+ // Sick macros, retard.
+#define GetRvaPointer(Rva) (Buffer + GetRawOffsetByRva(SectionHeader, SectionCount, FileSize, Rva))
+
+ bool SyscallManager::Start()
+ {
+ // Read contents of NTDLL.
+ ByteArray Ntdll = GetNtdllFromDisk();
+
+ if(Ntdll.empty())
+ return false;
+
+ uint8_t *Buffer = Ntdll.data();
+ size_t FileSize = Ntdll.size();
+
+ // Ghetto check to see if the file is a valid PE.
+ if(*(uint16_t*)Buffer != IMAGE_DOS_SIGNATURE)
+ return false;
+
+ // Read PE headers.
+ IMAGE_DOS_HEADER *DosHeader = (IMAGE_DOS_HEADER *)Buffer;
+ IMAGE_NT_HEADERS *NtHeaders = (IMAGE_NT_HEADERS *)(Buffer + DosHeader->e_lfanew);
+
+ uint64_t SectionCount = NtHeaders->FileHeader.NumberOfSections;
+
+ // Read the first section header.
+ IMAGE_SECTION_HEADER *SectionHeader = (IMAGE_SECTION_HEADER *)(Buffer + DosHeader->e_lfanew + sizeof IMAGE_NT_HEADERS);
+
+ if(!SectionHeader)
+ return false;
+
+ uintptr_t ExportRva = NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
+ uintptr_t ExportSize = NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
+ uintptr_t ExportRaw = GetRawOffsetByRva(SectionHeader, SectionCount, FileSize, ExportRva);
+
+ if(!ExportRva || !ExportSize || !ExportRaw)
+ return false;
+
+ // Now let's parse the export directory.
+ IMAGE_EXPORT_DIRECTORY *ExportDirectory = (IMAGE_EXPORT_DIRECTORY *)(Buffer + ExportRaw);
+
+ uint32_t *Functions = (uint32_t *)GetRvaPointer(ExportDirectory->AddressOfFunctions);
+ uint16_t *Ordinals = (uint16_t *)GetRvaPointer(ExportDirectory->AddressOfNameOrdinals);
+ uint32_t *Names = (uint32_t *)GetRvaPointer(ExportDirectory->AddressOfNames);
+
+ if(!Functions || !Ordinals || !Names)
+ return false;
+
+
+ for(uint32_t n{}; n < ExportDirectory->NumberOfNames; ++n)
+ {
+ uint32_t NameRva = Names[n];
+ uint32_t FunctionRva = Functions[Ordinals[n]];
+
+ uintptr_t NameRawOffset = GetRawOffsetByRva(SectionHeader, SectionCount, FileSize, NameRva);
+ uintptr_t FunctionRawOffset = GetRawOffsetByRva(SectionHeader, SectionCount, FileSize, FunctionRva);
+
+ // We've found a syscall.
+ uint8_t *Opcodes = (uint8_t *)(Buffer + FunctionRawOffset);
+
+ if(!memcmp(Opcodes, "\x4C\x8B\xD1\xB8", 4))
+ {
+ uint32_t SyscallIndex = *(uint32_t *)(Buffer + FunctionRawOffset + 4);
+
+ // Get hash of syscall name.
+ char *SyscallName = (char *)(Buffer + NameRawOffset);
+ uint64_t SyscallNameHash = fnv::hash_runtime(SyscallName);
+
+ // Emplace the syscall in the syscall map.
+ m_Syscalls[SyscallNameHash].SetIndex(SyscallIndex);
+ }
+ }
+
+ if(m_Syscalls.empty())
+ return false;
+
+ return true;
+ }
+} \ No newline at end of file
diff --git a/csgo-loader/csgo-module/Security/SyscallManager.hpp b/csgo-loader/csgo-module/Security/SyscallManager.hpp
new file mode 100644
index 0000000..d8981e9
--- /dev/null
+++ b/csgo-loader/csgo-module/Security/SyscallManager.hpp
@@ -0,0 +1,77 @@
+#pragma once
+
+#include <windows.h>
+#include <winternl.h>
+#include <cstdint>
+#include <algorithm>
+#include <map>
+#include <fstream>
+#include <vector>
+#include <iterator>
+
+#include <Security/FnvHash.hpp>
+
+using ByteArray = std::vector<uint8_t>;
+
+namespace Wrapper
+{
+ // A stub used for our syscalls.
+ class SyscallStub
+ {
+ // The shellcode which executes a low latency system call.
+ uint8_t m_Shellcode[11] = {
+ 0x4C, 0x8B, 0xD1, // mov r10, rcx
+ 0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, [syscall index]
+ 0x0F, 0x05, // syscall
+ 0xC3
+ };
+ public:
+ // Constructors.
+ SyscallStub() = default;
+
+ // Sets the syscall index.
+ void SetIndex(uint32_t Index);
+
+ __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
+ {
+ // Reading NTDLL from disk because it cannot be modified
+ // due to restrictions put in place by PatchGuard.
+ ByteArray GetNtdllFromDisk();
+
+ // Container for all syscall stubs.
+ std::map<uint64_t, SyscallStub> m_Syscalls;
+
+ // Helper functions.
+ uintptr_t GetRawOffsetByRva(IMAGE_SECTION_HEADER *SectionHeader, uintptr_t Sections, uintptr_t FileSize, uintptr_t Rva);
+ IMAGE_SECTION_HEADER *GetSectionByRva(IMAGE_SECTION_HEADER *SectionHeader, uintptr_t Sections, uintptr_t Rva);
+
+ public:
+ // Initialises the syscall manager, dumping all the
+ // syscall indices.
+ bool Start();
+
+ // Finds a syscall by hash.
+ template < typename T >
+ T Find(uint64_t Hash)
+ {
+ uint64_t Syscall = m_Syscalls[Hash].Get();
+
+ if(!Syscall)
+ return T{};
+
+ return (T)m_Syscalls[Hash].Get();
+ }
+ };
+
+ using SyscallManagerPtr = std::unique_ptr<SyscallManager>;
+}
+
+extern Wrapper::SyscallManagerPtr Syscalls; \ No newline at end of file
diff --git a/csgo-loader/csgo-module/csgo-module.vcxproj b/csgo-loader/csgo-module/csgo-module.vcxproj
new file mode 100644
index 0000000..cc2f6a4
--- /dev/null
+++ b/csgo-loader/csgo-module/csgo-module.vcxproj
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="FuckMSVC|Win32">
+ <Configuration>FuckMSVC</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="FuckMSVC|x64">
+ <Configuration>FuckMSVC</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <VCProjectVersion>15.0</VCProjectVersion>
+ <ProjectGuid>{3A767D6A-B6D0-4D39-92B6-62FD4537F3BD}</ProjectGuid>
+ <RootNamespace>csgomodule</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='FuckMSVC|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='FuckMSVC|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='FuckMSVC|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='FuckMSVC|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <IncludePath>$(SolutionDir)shared\include;$(ProjectDir);$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
+ <LibraryPath>$(SolutionDir)shared\lib;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64</LibraryPath>
+ <OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)build\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <IncludePath>$(SolutionDir)shared\include;$(ProjectDir);$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
+ <LibraryPath>$(SolutionDir)shared\lib;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64</LibraryPath>
+ <OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)build\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='FuckMSVC|x64'">
+ <IncludePath>$(SolutionDir)shared\include;$(ProjectDir);$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
+ <LibraryPath>$(SolutionDir)shared\lib;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64</LibraryPath>
+ <OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
+ <IntDir>$(SolutionDir)build\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <ConformanceMode>true</ConformanceMode>
+ <PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='FuckMSVC|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <ConformanceMode>true</ConformanceMode>
+ <PreprocessorDefinitions>_WINSOCK_DEPRECATED_NO_WARNINGS;DEBUG;WIN32_LEAN_AND_MEAN;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ <ConformanceMode>true</ConformanceMode>
+ <PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;DEBUG;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='FuckMSVC|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="Module.cpp" />
+ <ClCompile Include="Networking\TCPClient.cpp" />
+ <ClCompile Include="Security\Encryption.cpp" />
+ <ClCompile Include="Security\SyscallManager.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="Module.hpp" />
+ <ClInclude Include="Networking\TCPClient.hpp" />
+ <ClInclude Include="Security\Encryption.hpp" />
+ <ClInclude Include="Security\FnvHash.hpp" />
+ <ClInclude Include="Security\SyscallManager.hpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/csgo-loader/csgo-module/csgo-module.vcxproj.filters b/csgo-loader/csgo-module/csgo-module.vcxproj.filters
new file mode 100644
index 0000000..2d62a91
--- /dev/null
+++ b/csgo-loader/csgo-module/csgo-module.vcxproj.filters
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="Module.cpp" />
+ <ClCompile Include="Networking\TCPClient.cpp">
+ <Filter>Networking</Filter>
+ </ClCompile>
+ <ClCompile Include="Security\Encryption.cpp">
+ <Filter>Security</Filter>
+ </ClCompile>
+ <ClCompile Include="Security\SyscallManager.cpp">
+ <Filter>Security</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="Module.hpp" />
+ <ClInclude Include="Networking\TCPClient.hpp">
+ <Filter>Networking</Filter>
+ </ClInclude>
+ <ClInclude Include="Security\Encryption.hpp">
+ <Filter>Security</Filter>
+ </ClInclude>
+ <ClInclude Include="Security\FnvHash.hpp">
+ <Filter>Security</Filter>
+ </ClInclude>
+ <ClInclude Include="Security\SyscallManager.hpp">
+ <Filter>Security</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="Security">
+ <UniqueIdentifier>{5c3d9ea2-e561-435a-b858-e71f87afe818}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Networking">
+ <UniqueIdentifier>{bc2e1992-5068-4c22-842f-8f6bf028f0d1}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project> \ 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 2f30e7f..0351f27 100644
--- a/csgo-loader/csgo-server/Login/RemoteLogin.cpp
+++ b/csgo-loader/csgo-server/Login/RemoteLogin.cpp
@@ -13,7 +13,20 @@ namespace Login
// Epic direct casts :---DDDD
m_Header = *(RemoteLoginHeader *)&RawLoginHeader[0];
- return true;
+
+ printf("[ => ] User attempting login: %s\n", m_Header.m_Username);
+ printf("[ => ] User HWID: %llx\n", m_Header.m_HardwareId);
+
+ RemoteLoginResponse Response = GetLoginResponse();
+
+ printf("[ => ] User response: %02x\n", Response);
+
+ if(Response & ACCESS_AUTHORISED || Response & ACCESS_SPECIAL_USER)
+ return true;
+
+ printf("[ => ] Login for user %s was rejected!\n", m_Header.m_Username);
+
+ return false;
}
RemoteLoginResponse RemoteLoginServer::GetLoginResponse()
@@ -32,9 +45,6 @@ namespace Login
if(strcmp(m_Header.m_Password, "betapassword"))
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.
@@ -43,7 +53,7 @@ namespace Login
}
// TODO: Check if the HWID is present in DB.
- if(m_Header.m_HardwareId != 0x2F769B06FA897376)
+ if(m_Header.m_HardwareId != 0xd33a13f59ae35130)
return RemoteLoginResponse::INVALID_HARDWARE;
// TODO: Check if the user has a subscription.
diff --git a/csgo-loader/csgo-server/Networking/TCPServer.hpp b/csgo-loader/csgo-server/Networking/TCPServer.hpp
index a29a796..9459136 100644
--- a/csgo-loader/csgo-server/Networking/TCPServer.hpp
+++ b/csgo-loader/csgo-server/Networking/TCPServer.hpp
@@ -24,6 +24,7 @@ namespace Networking
SOCKET m_Socket;
Wrapper::Encryption m_Encryption;
char m_IpAddress[32];
+
public:
// Initialiser for TCPConnection class.
TCPConnection(SOCKET Connection, const char *IpAddress, Wrapper::Encryption &RSA) :
@@ -54,6 +55,8 @@ namespace Networking
{
return m_Encryption.GetKey();
}
+
+ char *GetIpAddress() { return m_IpAddress; }
};
// Basic TCP server. Supports custom connection handling (pass a lambda to the handler list).
diff --git a/csgo-loader/csgo-server/RemoteCode/RemoteInjectionServer.cpp b/csgo-loader/csgo-server/RemoteCode/RemoteInjectionServer.cpp
deleted file mode 100644
index fd3efc0..0000000
--- a/csgo-loader/csgo-server/RemoteCode/RemoteInjectionServer.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include <RemoteCode/RemoteInjectionServer.hpp>
diff --git a/csgo-loader/csgo-server/RemoteCode/RemoteInjectionServer.hpp b/csgo-loader/csgo-server/RemoteCode/RemoteInjectionServer.hpp
deleted file mode 100644
index b8659ff..0000000
--- a/csgo-loader/csgo-server/RemoteCode/RemoteInjectionServer.hpp
+++ /dev/null
@@ -1,62 +0,0 @@
-#pragma once
-
-#include <windows.h>
-#include <cstdint>
-#include <vector>
-
-using ByteArray = std::vector<uint8_t>;
-
-namespace RemoteCode
-{
- // Used for TransactionStart
- using ImportedModule = char[64];
- using ImportList = std::vector<ImportedModule>;
-
- // Used for TransactionContinue
- struct ExportedFunction
- {
- // I've never seen modules / functions with names
- // that were larger than 64 characters.
- char m_Module[64];
- char m_Function[64];
-
- // Address of exported module / function
- uintptr_t m_ModuleAddress;
- uintptr_t m_FunctionAddress;
- };
-
- using ExportList = std::vector<ExportedFunction>;
-
- // Used for TransactionCommit
- struct RemoteInjectionHeader
- {
- // Used to decrypt the cheat header (first 1000 bytes of image sent back).
- uint8_t m_HeaderKey;
-
- // Used to call entrypoint/TLS callbacks.
- uintptr_t m_EntryPoint;
- uintptr_t m_TlsDirectory;
- };
-
- struct RemoteInjectionCode
- {
- RemoteInjectionHeader m_Header;
-
- // Actual injection code.
- ByteArray m_Code;
- };
-
- class RemoteInjectionServer
- {
- public:
- // Receive hash of selected cheat.
- // Reply with size of image to allocate.
- ByteArray Start(ByteArray &Response);
-
- // Receive client header, send over list of imported functions
- ByteArray TransactionStart(ByteArray &Response);
-
- // Receive list of modules & export addresses
- ByteArray TransactionContinue(ByteArray &Response);
- };
-} \ No newline at end of file
diff --git a/csgo-loader/csgo-server/Server.cpp b/csgo-loader/csgo-server/Server.cpp
index f822753..e0f1455 100644
--- a/csgo-loader/csgo-server/Server.cpp
+++ b/csgo-loader/csgo-server/Server.cpp
@@ -1,15 +1,96 @@
#include <Server.hpp>
-void ConnectionHandler(Networking::TCPConnection &Connection) {
- Login::RemoteLoginServer LoginServer;
+// 'M1' -> cl request
+// 'M2' -> mod request
+// 'M3' -> ban request
- ByteArray LoginHeader = Connection.ReceiveBytes();
-
- if(!LoginServer.Start(LoginHeader))
- return;
+namespace Handler
+{
+ void OnClientConnection(Networking::TCPConnection &Connection)
+ {
+ printf("[ !! ] Client at %s requested connection!\n", Connection.GetIpAddress());
+
+ // Initialize login server for the client.
+ Login::RemoteLoginServer LoginServer;
+
+ ByteArray LoginHeader = Connection.ReceiveBytes();
+
+ // Invalid login header.
+ if(!LoginServer.Start(LoginHeader))
+ return;
+
+ printf("[ !! ] Received login header from %s!\n", Connection.GetIpAddress());
+
+ // Reply with server header.
+ ByteArray LoginReply = LoginServer.GetResponse();
+ Connection.SendBytes(LoginReply);
- ByteArray LoginReply = LoginServer.GetResponse();
- Connection.SendBytes(LoginReply);
+ ByteArray LoginReplyEcho = Connection.ReceiveBytes();
+
+ if(LoginReply.size() != LoginReplyEcho.size())
+ {
+ printf("[ !! ] Echo from %s invalid, dropping connection!", Connection.GetIpAddress());
+ return;
+ }
+
+ RemoteCode::FileReader File;
+
+ if(!File.Start("csgo-module.dll"))
+ return;
+
+ // Send them the loader module to inject the cheat.
+ printf("[ !! ] Sending latest loader module!\n");
+
+ ByteArray RawLdrModule;
+ RawLdrModule.insert(
+ RawLdrModule.begin(),
+ (uint8_t *)File,
+ (uint8_t *)(File + File.GetFileLength())
+ );
+
+ Connection.SendBytes(RawLdrModule);
+ }
+
+ void OnModuleConnection(Networking::TCPConnection &Connection)
+ {
+ // The output of this function will be verbose by default.
+ printf("[ !! ] Module hello from %s!\n", Connection.GetIpAddress());
+ }
+
+ void OnBanReqConnection(Networking::TCPConnection &Connection)
+ {
+ // Use for forum IP-ban purposes or whatever..
+ printf("[ !! ] Client at %s requested ban!\n", Connection.GetIpAddress());
+
+ // TODO: Ban user?
+ }
+
+ void OnReceiveConnection(Networking::TCPConnection &Connection)
+ {
+ ByteArray Header = Connection.ReceiveRawBytes();
+
+ if(Header.empty())
+ {
+ printf("[ !! ] Client at %s sent malformed request!\n", Connection.GetIpAddress());
+ return;
+ }
+
+ uint32_t HeaderCode = *(uint32_t *)&Header[0];
+
+ switch(HeaderCode)
+ {
+ case CLIENT_HEADER: // "MB1"
+ OnClientConnection(Connection); break;
+ case MODULE_HEADER: // "MB2"
+ OnModuleConnection(Connection); break;
+ case BANREQ_HEADER: // "MB3";
+ OnBanReqConnection(Connection); break;
+
+ // Drop any malformed clients.
+ default:
+ printf("[ !! ] Client at %s sent malformed request!\n", Connection.GetIpAddress());
+ }
+ }
}
int __stdcall WinMain(HINSTANCE, HINSTANCE, char*, int)
@@ -25,7 +106,7 @@ int __stdcall WinMain(HINSTANCE, HINSTANCE, char*, int)
if(Result)
{
// Attach our connection handler.
- Server += ConnectionHandler;
+ Server += Handler::OnReceiveConnection;
// Accept any incoming connections.
for(;;)
diff --git a/csgo-loader/csgo-server/Server.hpp b/csgo-loader/csgo-server/Server.hpp
index af07bb0..90def2a 100644
--- a/csgo-loader/csgo-server/Server.hpp
+++ b/csgo-loader/csgo-server/Server.hpp
@@ -5,6 +5,10 @@
// PLEASE UPDATE THEM ACCORDINGLY.
#define SERVER_PORT 0xF2C // Hexadecimal representation of the server port.
+#define CLIENT_HEADER 0x4D42310A
+#define MODULE_HEADER 0x4D42320A
+#define BANREQ_HEADER 0x4D42330A
+
// Core functionality
#include <Networking/TCPServer.hpp>
#include <Networking/WebSocket.hpp>
@@ -13,7 +17,19 @@
#include <Login/RemoteLogin.hpp>
#include <RemoteCode/FileReader.hpp>
-#include <RemoteCode/RemoteInjectionServer.hpp>
+//#include <RemoteCode/RemoteInjectionServer.hpp>
+
+// Let's separate up the connection handlers :)
+namespace Handler
+{
+ // Branches
+ void OnClientConnection(Networking::TCPConnection &Connection);
+ void OnModuleConnection(Networking::TCPConnection &Connection);
+ void OnBanReqConnection(Networking::TCPConnection &Connection);
+
+ // Default handler
+ void OnReceiveConnection(Networking::TCPConnection &Connection);
+}
// It looked nasty in Server.cpp, so I'm putting it here.
namespace Utils
diff --git a/csgo-loader/csgo-server/csgo-server.vcxproj b/csgo-loader/csgo-server/csgo-server.vcxproj
index ad924f6..c702cbb 100644
--- a/csgo-loader/csgo-server/csgo-server.vcxproj
+++ b/csgo-loader/csgo-server/csgo-server.vcxproj
@@ -31,7 +31,6 @@
<ClCompile Include="Networking\TCPServer.cpp" />
<ClCompile Include="Networking\WebSocket.cpp" />
<ClCompile Include="RemoteCode\FileReader.cpp" />
- <ClCompile Include="RemoteCode\RemoteInjectionServer.cpp" />
<ClCompile Include="Security\Encryption.cpp" />
<ClCompile Include="Server.cpp" />
</ItemGroup>
@@ -40,7 +39,6 @@
<ClInclude Include="Networking\TCPServer.hpp" />
<ClInclude Include="Networking\WebSocket.hpp" />
<ClInclude Include="RemoteCode\FileReader.hpp" />
- <ClInclude Include="RemoteCode\RemoteInjectionServer.hpp" />
<ClInclude Include="Security\Encryption.hpp" />
<ClInclude Include="Security\FnvHash.hpp" />
<ClInclude Include="Server.hpp" />
diff --git a/csgo-loader/csgo-server/csgo-server.vcxproj.filters b/csgo-loader/csgo-server/csgo-server.vcxproj.filters
index 0480d6d..b0c12d7 100644
--- a/csgo-loader/csgo-server/csgo-server.vcxproj.filters
+++ b/csgo-loader/csgo-server/csgo-server.vcxproj.filters
@@ -31,9 +31,6 @@
<ClCompile Include="RemoteCode\FileReader.cpp">
<Filter>RemoteCode</Filter>
</ClCompile>
- <ClCompile Include="RemoteCode\RemoteInjectionServer.cpp">
- <Filter>RemoteCode</Filter>
- </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Security\Encryption.hpp">
@@ -51,9 +48,6 @@
<ClInclude Include="RemoteCode\FileReader.hpp">
<Filter>RemoteCode</Filter>
</ClInclude>
- <ClInclude Include="RemoteCode\RemoteInjectionServer.hpp">
- <Filter>RemoteCode</Filter>
- </ClInclude>
<ClInclude Include="Security\FnvHash.hpp">
<Filter>Security</Filter>
</ClInclude>