diff --git a/CubeModLoader/CMakeLists.txt b/CubeModLoader/CMakeLists.txt new file mode 100644 index 0000000..3e7025c --- /dev/null +++ b/CubeModLoader/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required (VERSION 3.8) +project(project_CubeModLoader) +add_library (CubeModLoader SHARED + crc.cpp + DLL.cpp + main.cpp + mutex.cpp) \ No newline at end of file diff --git a/CubeModLoader/GenerateProjectCMake.py b/CubeModLoader/GenerateProjectCMake.py new file mode 100644 index 0000000..08aac33 --- /dev/null +++ b/CubeModLoader/GenerateProjectCMake.py @@ -0,0 +1,19 @@ +from pathlib import Path +import os + +path = os.path.dirname(os.path.realpath(__file__)) +_, folderName = os.path.split(path) + +files = list(Path(path).glob('*.cpp')) + +for filename in files: + print(filename) + +lines = [ +'cmake_minimum_required (VERSION 3.8)', +'project(project_%s)' % folderName, +'add_library (%s SHARED \n %s)' % (folderName, '\n '.join([str(x)[len(path)+1:].replace('\\', '/') for x in files])) + ] + +with open(os.path.join(path, 'CMakeLists.txt'), 'w') as f: + f.write('\n'.join(lines)) diff --git a/CubeModLoader/callbacks/ChatHandler.h b/CubeModLoader/callbacks/ChatHandler.h index d6f223c..7f7823d 100644 --- a/CubeModLoader/callbacks/ChatHandler.h +++ b/CubeModLoader/callbacks/ChatHandler.h @@ -1,4 +1,4 @@ -int ChatHandler(wchar_t* msg) { +extern "C" int ChatHandler(wchar_t* msg) { for (DLL* dll: modDLLs) { if (dll->HandleChat) { if ( ((int(*)(wchar_t*))dll->HandleChat)(msg) ){ @@ -8,18 +8,18 @@ int ChatHandler(wchar_t* msg) { } return 0; } -void* ChatHandler_ptr = (void*)&ChatHandler; -void* ASMChatHandler_jmpback; -void* ASMChatHandler_bail; -void no_optimize ASMChatHandler() { - asm(PUSH_ALL +GETTER_VAR(void*, ASMChatHandler_jmpback); +GETTER_VAR(void*, ASMChatHandler_bail); +void ASMChatHandler() { + asm(".intel_syntax \n" + PUSH_ALL "mov rcx, rbx \n" // The message PREPARE_STACK - "call [ChatHandler_ptr] \n" + "call ChatHandler \n" RESTORE_STACK @@ -33,16 +33,16 @@ void no_optimize ASMChatHandler() { "mov qword ptr [rbp+0x88], 7 \n" "mov [rbp+0x80], r12 \n" "mov [rbp+0x70], r12w \n" - "jmp [ASMChatHandler_jmpback] \n" + DEREF_JMP(ASMChatHandler_jmpback) "bail: \n" POP_ALL - "jmp [ASMChatHandler_bail]" + DEREF_JMP(ASMChatHandler_bail) ); } void SetupChatHandler() { - WriteFarJMP(base+0x97198, (void*)&ASMChatHandler); - ASMChatHandler_jmpback = (void*)base+0x971B0; - ASMChatHandler_bail = (void*)base+0x9777A; + WriteFarJMP(Offset(base, 0x97198), (void*)&ASMChatHandler); + ASMChatHandler_jmpback = Offset(base, 0x971B0); + ASMChatHandler_bail = Offset(base, 0x9777A); } diff --git a/CubeModLoader/callbacks/CheckInventoryFullHandler.h b/CubeModLoader/callbacks/CheckInventoryFullHandler.h index 2ff96e7..3a00d94 100644 --- a/CubeModLoader/callbacks/CheckInventoryFullHandler.h +++ b/CubeModLoader/callbacks/CheckInventoryFullHandler.h @@ -1,4 +1,4 @@ -int CheckInventoryFullHandler(void* player, void* item) { +extern "C" int CheckInventoryFullHandler(void* player, void* item) { for (DLL* dll: modDLLs) { if (dll->HandleCheckInventoryFull) { if ( int result = ((int(*)(void*, void*))dll->HandleCheckInventoryFull)(player, item) ){ @@ -8,15 +8,15 @@ int CheckInventoryFullHandler(void* player, void* item) { } return 0; } -void* CheckInventoryFullHandler_ptr = (void*)&CheckInventoryFullHandler; -void* ASMCheckInventoryFullHandler_jmpback; -void* ASMCheckInventoryFullHandler_retn; -void no_optimize ASMCheckInventoryFullHandler() { - asm(PUSH_ALL +GETTER_VAR(void*, ASMCheckInventoryFullHandler_jmpback); +GETTER_VAR(void*, ASMCheckInventoryFullHandler_retn); +__attribute__((naked)) void ASMCheckInventoryFullHandler() { + asm(".intel_syntax \n" + PUSH_ALL PREPARE_STACK - "call [CheckInventoryFullHandler_ptr] \n" + "call CheckInventoryFullHandler \n" RESTORE_STACK @@ -37,22 +37,22 @@ void no_optimize ASMCheckInventoryFullHandler() { "push r14 \n" "push r15 \n" "sub rsp, 0x20 \n" - "jmp [ASMCheckInventoryFullHandler_jmpback] \n" + DEREF_JMP(ASMCheckInventoryFullHandler_jmpback) "1: \n" //full POP_ALL "xor al,al \n" - "jmp [ASMCheckInventoryFullHandler_retn] \n" + DEREF_JMP(ASMCheckInventoryFullHandler_retn) "2: \n" //not POP_ALL "mov al,1 \n" - "jmp [ASMCheckInventoryFullHandler_retn] \n" + DEREF_JMP(ASMCheckInventoryFullHandler_retn) ); } void SetupCheckInventoryFullHandler() { - WriteFarJMP(base+0x50670, (void*)&ASMCheckInventoryFullHandler); - ASMCheckInventoryFullHandler_jmpback = (void*)base+0x5067F; - ASMCheckInventoryFullHandler_retn = (void*)base+0x507A0; + WriteFarJMP(Offset(base, 0x50670), (void*)&ASMCheckInventoryFullHandler); + ASMCheckInventoryFullHandler_jmpback = Offset(base, 0x5067F); + ASMCheckInventoryFullHandler_retn = Offset(base, 0x507A0); } diff --git a/CubeModLoader/callbacks/P2PRequestHandler.h b/CubeModLoader/callbacks/P2PRequestHandler.h index 18cde89..e6e7e33 100644 --- a/CubeModLoader/callbacks/P2PRequestHandler.h +++ b/CubeModLoader/callbacks/P2PRequestHandler.h @@ -1,4 +1,4 @@ -int P2PRequestHandler(long long steamID) { +extern "C" int P2PRequestHandler(long long steamID) { for (DLL* dll: modDLLs) { if (dll->HandleP2PRequest) { if ( int result = ((int(*)(long long))dll->HandleP2PRequest)(steamID) ){ @@ -8,19 +8,19 @@ int P2PRequestHandler(long long steamID) { } return 0; } -void* P2PRequestHandler_ptr = (void*)&P2PRequestHandler; -void* ASMP2PRequestHandler_jmpback; -void* ASMP2PRequestHandler_block; -void* ASMP2PRequestHandler_allow; -void no_optimize ASMP2PRequestHandler() { - asm(PUSH_ALL +GETTER_VAR(void*, ASMP2PRequestHandler_jmpback); +GETTER_VAR(void*, ASMP2PRequestHandler_block); +GETTER_VAR(void*, ASMP2PRequestHandler_allow); +void ASMP2PRequestHandler() { + asm(".intel_syntax \n" + PUSH_ALL "mov rcx, [rdi] \n" //incoming steam id PREPARE_STACK - "call [P2PRequestHandler_ptr] \n" + "call P2PRequestHandler \n" RESTORE_STACK @@ -42,21 +42,21 @@ void no_optimize ASMP2PRequestHandler() { "mov rax, [rcx] \n" "call qword ptr [rax+0x18] \n" - "jmp [ASMP2PRequestHandler_jmpback] \n" + DEREF_JMP(ASMP2PRequestHandler_jmpback) "1: \n" //block POP_ALL - "jmp [ASMP2PRequestHandler_block] \n" + DEREF_JMP(ASMP2PRequestHandler_block) "2: \n" //allow POP_ALL - "jmp [ASMP2PRequestHandler_allow] \n" + DEREF_JMP(ASMP2PRequestHandler_allow) ); } void SetupP2PRequestHandler() { - WriteFarJMP(base+0x9F6DF, (void*)&ASMP2PRequestHandler); - ASMP2PRequestHandler_jmpback = (void*)base+0x9F6ED; - ASMP2PRequestHandler_block = (void*)base+0x9F7A6; - ASMP2PRequestHandler_allow = (void*)base+0x9F783; + WriteFarJMP(Offset(base, 0x9F6DF), (void*)&ASMP2PRequestHandler); + ASMP2PRequestHandler_jmpback = Offset(base, 0x9F6ED); + ASMP2PRequestHandler_block = Offset(base, 0x9F7A6); + ASMP2PRequestHandler_allow = Offset(base, 0x9F783); } diff --git a/CubeModLoader/main.cpp b/CubeModLoader/main.cpp index 16caf6d..bc48972 100644 --- a/CubeModLoader/main.cpp +++ b/CubeModLoader/main.cpp @@ -18,11 +18,11 @@ using namespace std; -void* base; // Module base -vector modDLLs; // Every mod we've loaded -HMODULE hSelf; // A handle to ourself, to prevent being unloaded -void** initterm_eReference; // A pointer-pointer to a function which is run extremely soon after starting, or after being unpacked -void* initterm_e; // A pointer to that function +global void* base; // Module base +global vector modDLLs; // Every mod we've loaded +global HMODULE hSelf; // A handle to ourself, to prevent being unloaded +global void** initterm_eReference; // A pointer-pointer to a function which is run extremely soon after starting, or after being unpacked +GETTER_VAR(void*, initterm_e); // A pointer to that function #include "callbacks/ChatHandler.h" #include "callbacks/P2PRequestHandler.h" @@ -38,7 +38,7 @@ void SetupHandlers() { // Handles injecting callbacks and the mods bool already_loaded_mods = false; mutex already_loaded_mods_mtx; -void StartMods() { +extern "C" void StartMods() { char msg[256] = {0}; already_loaded_mods_mtx.lock(); @@ -110,34 +110,33 @@ void StartMods() { if (hSelf) PrintLoadedMods(); return; } -void* StartMods_ptr = (void*)&StartMods; - -void no_optimize ASMStartMods() { - asm(PUSH_ALL +void ASMStartMods() { + asm(".intel_syntax \n" + PUSH_ALL PREPARE_STACK // Initialize mods and callbacks - "call [StartMods_ptr] \n" + "call StartMods \n" RESTORE_STACK POP_ALL // Run initterm_e properly this time. - "jmp [initterm_e] \n" + DEREF_JMP(initterm_e) ); } void PatchFreeImage(){ // Patch FreeImage, because Windows 8 and higher do not work properly with it. DWORD oldProtect; - void* patchaddr = (void*)GetModuleHandleA("FreeImage.dll") + 0x1E8C4E; + void* patchaddr = Offset(GetModuleHandleA("FreeImage.dll"), 0x1E8C4E); VirtualProtect((LPVOID)patchaddr, 9, PAGE_EXECUTE_READWRITE, &oldProtect); memset(patchaddr, 0x90, 9); VirtualProtect((LPVOID)patchaddr, 9, oldProtect, &oldProtect); - patchaddr += 0x14; + patchaddr = Offset(patchaddr, 0x14); VirtualProtect((LPVOID)patchaddr, 14, PAGE_EXECUTE_READWRITE, &oldProtect); memset(patchaddr, 0x90, 14); VirtualProtect((LPVOID)patchaddr, 14, oldProtect, &oldProtect); @@ -145,7 +144,7 @@ void PatchFreeImage(){ void PatchInitterm_ePtr() { // Get ** to initterm_e - initterm_eReference = (void**)(base + 0x42CBD8); + initterm_eReference = (void**)(Offset(base, 0x42CBD8)); initterm_e = *initterm_eReference; @@ -184,6 +183,10 @@ void WriteFarJMP(void* source, void* destination) { VirtualProtect(location, 14, dwOldProtection, &dwOldProtection); } +void* Offset(void* x1, uint64_t x2) { + return (void*)((char*)x1 + x2); +} + bool already_initialized = false; mutex already_initialized_mtx; extern "C" __declspec(dllexport) BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { diff --git a/CubeModLoader/main.h b/CubeModLoader/main.h index 2154d4b..f7ed1e6 100644 --- a/CubeModLoader/main.h +++ b/CubeModLoader/main.h @@ -28,6 +28,22 @@ dllname->name = GetProcAddress(dllname->handle, #name); #define PREPARE_STACK "mov rax, rsp \n and rsp, 0xFFFFFFFFFFFFFFF0 \n push rax \n sub rsp, 0x28 \n" #define RESTORE_STACK "add rsp, 0x28 \n pop rsp \n" +#define GETTER_VAR(vartype, varname)\ + static __attribute__((used)) vartype varname;\ + extern "C" vartype Get_##varname(){return varname;} + +#define DEREF_JMP(varname)\ + "sub rsp, 8 \n"\ + "push rax \n"\ + "call Get_"#varname" \n"\ + "mov [rsp+8], rax \n"\ + "pop rax \n"\ + "ret \n" + +#define global static __attribute__((used)) + +void* Offset(void* x1, uint64_t x2); +