From 5722ea462205aebd91fbcf355300f748b4da480b Mon Sep 17 00:00:00 2001 From: ChrisMiuchiz Date: Tue, 10 Sep 2019 19:28:59 -0400 Subject: [PATCH 1/9] Start refactoring for update --- CallbackManager/main.cpp | 416 ------------------------------------ CubeModLauncher/Process.cpp | 43 ++++ CubeModLauncher/Process.h | 24 +++ CubeModLauncher/crc.cpp | 68 ++++++ CubeModLauncher/crc.h | 7 + CubeModLauncher/main.cpp | 89 ++++++++ CubeModLauncher/main.h | 7 + main.cpp | 117 ---------- 8 files changed, 238 insertions(+), 533 deletions(-) delete mode 100644 CallbackManager/main.cpp create mode 100644 CubeModLauncher/Process.cpp create mode 100644 CubeModLauncher/Process.h create mode 100644 CubeModLauncher/crc.cpp create mode 100644 CubeModLauncher/crc.h create mode 100644 CubeModLauncher/main.cpp create mode 100644 CubeModLauncher/main.h delete mode 100644 main.cpp diff --git a/CallbackManager/main.cpp b/CallbackManager/main.cpp deleted file mode 100644 index bdb877a..0000000 --- a/CallbackManager/main.cpp +++ /dev/null @@ -1,416 +0,0 @@ -#include "main.h" -#include -#define no_shenanigans __attribute__((noinline)) __declspec(dllexport) -#define MakeCallback(callbackName, callbackReturnType, registrarFunctionName, vectorName)\ - typedef callbackReturnType (__stdcall *callbackName)( ... );\ - std::vector vectorName;\ - extern "C" void DLL_EXPORT registrarFunctionName(callbackName func){\ - vectorName.push_back(func);\ - } - -UINT_PTR base; - -//Chat Events -MakeCallback(ChatEventCallback, bool, RegisterChatEventCallback, chat_event_callbacks); -bool DLL_EXPORT HandleChatEvent(wchar_t buf[], unsigned int msg_size){ - bool cancelChatDisplay = false; - wchar_t msg[1024] = { 0 }; - memcpy(msg, buf, msg_size * 2); //the message should be null terminated - for (ChatEventCallback func : chat_event_callbacks){ - bool cancel = func(msg, msg_size); - if (cancel){ - cancelChatDisplay = true; - } - } - return cancelChatDisplay; -} -DWORD HandleChatEvent_ptr = (DWORD)&HandleChatEvent; - -_declspec(naked) void DLL_EXPORT ASMHandleMessage(){ - - asm("mov eax, [_base]"); - asm("add eax, 0x36B1C8"); - asm("mov eax, [eax]"); //eax points to gamecontroller - asm("mov eax, dword ptr [eax + 0x800A14]"); //eax points to ChatWidget - asm("mov eax, dword ptr [eax + 0x178]"); //get message size - asm("push eax"); - - asm("lea eax, [ebp - 0x128 + 0x4]"); - asm("mov eax, [eax]"); //get message - asm("push eax"); - - asm("call [_HandleChatEvent_ptr]"); - - asm("cmp eax, 0"); //message ptr - asm("je 0f"); - - asm("1:"); - asm("mov ecx, [_base]"); //jump to end - asm("add ecx, 0x7E6BF"); - asm("jmp ecx"); - - - asm("0:"); //exit normally - asm("mov eax, [_base]"); //jump back - asm("add eax, 0x7E621"); - asm("cmp dword ptr [edi + 0x8006CC], 0"); //original comparison - asm("jmp eax"); -} - -//Zone Loaded -MakeCallback(ZoneLoadedCallback, void, RegisterZoneLoadedCallback, zone_loaded_callbacks); -void __stdcall no_shenanigans HandleZoneLoaded(unsigned int zone_ptr){ - for (ZoneLoadedCallback func : zone_loaded_callbacks){ - func(zone_ptr); - } -} -DWORD HandleZoneLoaded_ptr = (DWORD)&HandleZoneLoaded; - -unsigned int ASMHandleZoneLoaded_JMP_back; -_declspec(naked) void DLL_EXPORT ASMHandleZoneLoaded(){ - asm("pushad"); - - asm("push eax"); - asm("call [_HandleZoneLoaded_ptr]"); - - asm("popad"); - - asm("mov ecx, [ebx]"); //Original code - asm("add ecx, 0x800D44"); - - asm("jmp [_ASMHandleZoneLoaded_JMP_back]"); -} - - -//Zone Destructed -MakeCallback(ZoneDeleteCallback, void, RegisterZoneDeleteCallback, zone_delete_callbacks); -void __stdcall no_shenanigans HandleZoneDelete(unsigned int zone_ptr){ - for (ZoneDeleteCallback func : zone_delete_callbacks){ - func(zone_ptr); - } -} -DWORD HandleZoneDelete_ptr = (DWORD)&HandleZoneDelete; - -unsigned int ASMHandleZoneDelete_JMP_back; -_declspec(naked) void DLL_EXPORT ASMHandleZoneDelete(){ - asm("pushad"); - - asm("push ecx"); //Zone ptr - asm("call [_HandleZoneDelete_ptr]"); - - asm("popad"); - - asm("push ebp"); //Original code - asm("mov ebp, esp"); - asm("push esi"); - asm("mov esi, ecx"); - - asm("jmp [_ASMHandleZoneDelete_JMP_back]"); -} - -//Check M3. returning -1 means force disable. 0 means act as normal. 1 means force enable -MakeCallback(DodgeAttemptCheckCallback, int, RegisterDodgeAttemptCheckCallback, dodge_attempt_check_callbacks); -int __stdcall no_shenanigans HandleDodgeAttemptCheck(unsigned int attempting_to_dodge){ - int need_to_dodge = 0; - for (DodgeAttemptCheckCallback func : dodge_attempt_check_callbacks){ - unsigned int need_to_dodge_2 = func(attempting_to_dodge); - if (need_to_dodge_2 != 0){ - need_to_dodge = need_to_dodge_2; - } - } - return need_to_dodge; -} -DWORD HandleDodgeAttemptCheck_ptr = (DWORD)&HandleDodgeAttemptCheck; - -unsigned int ASMM3Check_JMP_back; -_declspec(naked) void DLL_EXPORT ASMM3Check(){ - asm("movss dword ptr [esp+0x18], xmm6"); //original code - asm("movss dword ptr [esp+0x80], xmm6"); - - asm("push ebx"); - asm("push eax"); - - asm("push ebx"); - asm("call [_HandleDodgeAttemptCheck_ptr]"); - - - asm("mov ebx, eax"); //result - - asm("cmp ebx, -1"); - asm("je 0f"); //Disable - - asm("cmp ebx, 0"); - asm("je 1f"); //Do nothing - - //Enable - asm("pop ebx"); - asm("pop eax"); - asm("mov ebx, 0"); - asm("jmp [_ASMM3Check_JMP_back]"); - - asm("0:"); //Disable - asm("pop ebx"); - asm("pop eax"); - asm("mov ebx, 1"); - asm("jmp [_ASMM3Check_JMP_back]"); - - asm("1:"); //Do nothing - asm("pop eax"); - asm("pop ebx"); - asm("jmp [_ASMM3Check_JMP_back]"); -} - -//Check M1. returning -1 means force disable. 0 means act as normal. 1 means force enable -MakeCallback(PrimaryAttackAttemptCheckCallback, int, RegisterPrimaryAttackAttemptCheckCallback, primary_attack_attempt_callbacks); -int __stdcall no_shenanigans HandlePrimaryAttackAttemptCheck(unsigned int attempting_to_attack){ - int need_to_attack = 0; - for (PrimaryAttackAttemptCheckCallback func : primary_attack_attempt_callbacks){ - unsigned int need_to_attack_2 = func(attempting_to_attack); - if (need_to_attack_2 != 0){ - need_to_attack = need_to_attack_2; - } - } - return need_to_attack; -} -DWORD HandlePrimaryAttackAttemptCheck_ptr = (DWORD)&HandlePrimaryAttackAttemptCheck; - -unsigned int ASMM1Check_JMP_Enable; -unsigned int ASMM1Check_JMP_Disable; -_declspec(naked) void DLL_EXPORT ASMM1Check(){ - asm("push eax"); - - asm("movzx eax, byte ptr [edi+0x4]"); - asm("push eax"); - asm("call [_HandlePrimaryAttackAttemptCheck_ptr]"); - - asm("cmp eax, -1"); - asm("je 0f"); //Disable - - asm("cmp eax, 0"); - asm("je 1f"); //Do nothing - - //Enable - asm("pop eax"); - asm("jmp [_ASMM1Check_JMP_Enable]"); - - asm("0:"); //Disable - asm("pop eax"); - asm("jmp [_ASMM1Check_JMP_Disable]"); - - asm("1:"); //Do nothing - asm("pop eax"); - asm("cmp byte ptr [edi+0x4], 0"); //original code - asm("jz 2f"); - asm("jmp [_ASMM1Check_JMP_Enable]"); - - asm("2:"); //the disable option from original code - asm("jmp [_ASMM1Check_JMP_Disable]"); //Can't do this with jz -} - -//Check abilities. returning -1 means force disable. 0 means act as normal. 1 means force enable -//I don't know why you would want to enable this, but for consistency it will be like this. -MakeCallback(AbilityAttackAttemptCheckCallback, int, RegisterAbilityAttackAttemptCheckCallback, ability_attack_attempt_callbacks); -int __stdcall no_shenanigans HandleAbilityAttackAttemptCheck(unsigned int attempting_to_attack, unsigned int keyNumber){ - int need_to_attack = 0; - for (AbilityAttackAttemptCheckCallback func : ability_attack_attempt_callbacks){ - unsigned int need_to_attack_2 = func(attempting_to_attack, keyNumber); - if (need_to_attack_2 != 0){ - need_to_attack = need_to_attack_2; - } - } - return need_to_attack; -} -DWORD HandleAbilityAttackAttemptCheck_ptr = (DWORD)&HandleAbilityAttackAttemptCheck; - -unsigned int ASMAbilitiesCheck_JMP_Back; -_declspec(naked) void DLL_EXPORT ASMAbilitiesCheck(){ - asm("push eax"); - - - asm("push esi"); //keyNumber - asm("movzx eax, byte ptr [edi+esi+0x4]"); //attempting to attack - asm("push eax"); - asm("call [_HandleAbilityAttackAttemptCheck_ptr]"); - - asm("cmp eax, -1"); - asm("je 0f"); //Disable - - asm("cmp eax, 0"); //Do nothing - asm("je 1f"); - - //Enable - asm("mov eax, 1"); - asm("cmp eax, 0"); - asm("pop eax"); - asm("jmp [_ASMAbilitiesCheck_JMP_Back]"); - - asm("0:"); //Disable - asm("mov eax, 0"); - asm("cmp eax, 0"); - asm("pop eax"); - asm("jmp [_ASMAbilitiesCheck_JMP_Back]"); - - asm("1:"); //Do nothing - asm("cmp byte ptr [edi+esi+0x4], 0"); //original code - asm("pop eax"); - asm("jmp [_ASMAbilitiesCheck_JMP_Back]"); -} - - - - - -//Packets -MakeCallback(PacketCallback, int, RegisterPacketCallback, packet_callbacks); -int __stdcall no_shenanigans HandlePacket(unsigned int packet_ID, unsigned int socket_ptr){ - int handled = 0; - for (PacketCallback func : packet_callbacks){ - unsigned int handled_2 = func(packet_ID, socket_ptr); - if (handled_2 != 0){ - handled = handled_2; - } - } - return handled; -} -DWORD HandlePacket_ptr = (DWORD)&HandlePacket; - - -unsigned int ASMHandlePacket_Invalid_Packet_JMP; -unsigned int ASMHandlePacket_Valid_Packet_JMP; -unsigned int ASMHandlePacket_Already_Handled_JMP; -_declspec(naked) void __declspec(dllexport) ASMHandlePacket(){ - asm("pushad"); - - asm("push [ebp-0x11D8]"); //socket - asm("push [ebp-0x1220]"); //Packet ID - asm("call [_HandlePacket_ptr]"); - - asm("cmp eax, 0"); - asm("je 0f"); //The packet was not handled - - asm("popad"); //The packet WAS handled - asm("mov cl, [ebp-0x11D1]"); - asm("jmp [_ASMHandlePacket_Already_Handled_JMP]"); - - asm("0:"); //The packet was not handled - asm("popad"); - asm("mov eax, [ebp-0x1220]");//original code - asm("cmp eax, 0xF"); - asm("ja 1f"); - asm("jmp [_ASMHandlePacket_Valid_Packet_JMP]"); - - asm("1:"); - asm("jmp [_ASMHandlePacket_Invalid_Packet_JMP]"); - -} - -//ready to send a packet -MakeCallback(ReadyToSendCallback, void, RegisterReadyToSendCallback, ready_to_send_callbacks); -void __stdcall no_shenanigans HandleReadyToSend(SOCKET s){ - for (ReadyToSendCallback func : ready_to_send_callbacks){ - func(s); - } -} -DWORD HandleReadyToSend_ptr = (DWORD)&HandleReadyToSend; - -unsigned int ASMHandleReadyToSend_JMP_Back; -void no_shenanigans ASMHandleReadyToSend(){ - asm("pushad"); - - asm("mov eax, [edi]"); //GameController - asm("push dword ptr [eax+0x8006CC]"); //socket - asm("call [_HandleReadyToSend_ptr]"); - - asm("popad"); - - asm("push 0"); //original code - asm("push 4"); //len - asm("lea eax, [ebp-0x2444]"); - - asm("jmp [_ASMHandleReadyToSend_JMP_Back]"); - - -} - -//Finish crafting -MakeCallback(FinishCraftingCallback, void, RegisterFinishCraftingCallback, finish_crafting_callbacks); -void __stdcall no_shenanigans HandleFinishCrafting(){ - for (FinishCraftingCallback func : finish_crafting_callbacks){ - func(); - } -} -DWORD HandleFinishCrafting_ptr = (DWORD)&HandleFinishCrafting; - -unsigned int ASMHandleFinishCrafting_JMP_Back; -void no_shenanigans ASMHandleFinishCrafting(){ - asm("pushad"); - - asm("call [_HandleFinishCrafting_ptr]"); - - asm("popad"); - - asm("mov ecx, [ebp-0xC]"); //original code - asm("mov dword ptr fs:[0], ecx"); - - asm("jmp [_ASMHandleFinishCrafting_JMP_Back]"); - - -} - - -void WriteJMP(BYTE* location, BYTE* newFunction){ - DWORD dwOldProtection; - VirtualProtect(location, 5, PAGE_EXECUTE_READWRITE, &dwOldProtection); - location[0] = 0xE9; //jmp - *((DWORD*)(location + 1)) = (DWORD)(( (unsigned INT32)newFunction - (unsigned INT32)location ) - 5); - VirtualProtect(location, 5, dwOldProtection, &dwOldProtection); -} - - -extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - base = (UINT_PTR)GetModuleHandle(NULL); - switch (fdwReason) - { - case DLL_PROCESS_ATTACH: - //Chat - WriteJMP((BYTE*)(base + 0x7E61A), (BYTE*)&ASMHandleMessage); - - //Zone Load - ASMHandleZoneLoaded_JMP_back = base + 0x6ACDE; - WriteJMP((BYTE*)(base + 0x6ACD6), (BYTE*)&ASMHandleZoneLoaded); - - //Zone Delete - ASMHandleZoneDelete_JMP_back = base + 0x224766; - WriteJMP((BYTE*)(base + 0x224760), (BYTE*)&ASMHandleZoneDelete); - - //Check M3 - ASMM3Check_JMP_back = base + 0xA6CD2; - WriteJMP((BYTE*)(base + 0xA6CC3), (BYTE*)&ASMM3Check); - - //Check M1 - ASMM1Check_JMP_Enable = base + 0x9BF82; - ASMM1Check_JMP_Disable = base + 0x9BFC8; - WriteJMP((BYTE*)(base + 0x9BF7C), (BYTE*)&ASMM1Check); - - //Check abilities - ASMAbilitiesCheck_JMP_Back = base + 0x9B63A; - WriteJMP((BYTE*)(base + 0x9B635), (BYTE*)&ASMAbilitiesCheck); - - //Handle packet - ASMHandlePacket_Already_Handled_JMP = base + 0x6D0E3; - ASMHandlePacket_Invalid_Packet_JMP = base + 0x6D0DD; - ASMHandlePacket_Valid_Packet_JMP = base + 0x6B8B0; - WriteJMP((BYTE*)(base + 0x6B8A7), (BYTE*)&ASMHandlePacket); - - //Ready to send packet - ASMHandleReadyToSend_JMP_Back = base + 0x69C92; - WriteJMP((BYTE*)(base + 0x69C88), (BYTE*)&ASMHandleReadyToSend); - - ASMHandleFinishCrafting_JMP_Back = base + 0x70D6B; - WriteJMP((BYTE*)(base + 0x70D61), (BYTE*)&ASMHandleFinishCrafting); - - break; - } - return true; -} diff --git a/CubeModLauncher/Process.cpp b/CubeModLauncher/Process.cpp new file mode 100644 index 0000000..3a18f2a --- /dev/null +++ b/CubeModLauncher/Process.cpp @@ -0,0 +1,43 @@ +#include "Process.h" + +#include + +using namespace std; + +Process::Process(string path) +{ + this->path = path; + ZeroMemory(&si, sizeof(si)); + ZeroMemory(&pi, sizeof(pi)); +} + +Process::~Process() +{ + //dtor +} + +bool Process::InjectDLL(string dllName) { + LPVOID load_library = (LPVOID) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "LoadLibraryA"); + LPVOID remote_string = (LPVOID) VirtualAllocEx(pi.hProcess, NULL, strlen(dllName.c_str()) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + WriteProcessMemory(pi.hProcess, remote_string, dllName.c_str(), strlen(dllName.c_str()) + 1, NULL); + HANDLE thread = CreateRemoteThread(pi.hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE) load_library, remote_string, CREATE_SUSPENDED, NULL); + ResumeThread(thread); + return true; +} +bool Process::Create() { + return CreateProcess(NULL, + "Cube.exe", + NULL, + NULL, + true, + CREATE_SUSPENDED, + NULL, + NULL, + &si, + &pi); +} + +void Process::Run() { + ResumeThread(pi.hThread); + CloseHandle(pi.hProcess); +} diff --git a/CubeModLauncher/Process.h b/CubeModLauncher/Process.h new file mode 100644 index 0000000..e7a1db6 --- /dev/null +++ b/CubeModLauncher/Process.h @@ -0,0 +1,24 @@ +#ifndef PROCESS_H +#define PROCESS_H + +#include +#include +class Process +{ + public: + Process(std::string path); + virtual ~Process(); + bool InjectDLL(std::string dllName); + bool Create(); + void Run(); + + protected: + + private: + std::string path; + STARTUPINFO si; + PROCESS_INFORMATION pi; + +}; + +#endif // PROCESS_H diff --git a/CubeModLauncher/crc.cpp b/CubeModLauncher/crc.cpp new file mode 100644 index 0000000..b69c3b3 --- /dev/null +++ b/CubeModLauncher/crc.cpp @@ -0,0 +1,68 @@ +#include "crc.h" +#include + +unsigned int crc32_table[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +unsigned int crc32_buf(const char* buf, unsigned long len) +{ + unsigned int crc = ~0; + while (len--) + crc = crc32_table[(crc ^ *buf++) & 0xFF] ^ (crc >> 8); + return crc ^ ~0; +} + +unsigned int crc32_file(const char* fileName){ + FILE* file = fopen(fileName, "rb"); + fseek(file, 0, SEEK_END); + int fileSize = ftell(file); + char* fileContents = new char[fileSize]; + fread(fileContents, 1, fileSize, file); + fclose(file); + int result = crc32_buf(fileContents, fileSize); + delete[] fileContents; + return result; +} diff --git a/CubeModLauncher/crc.h b/CubeModLauncher/crc.h new file mode 100644 index 0000000..7b72c1f --- /dev/null +++ b/CubeModLauncher/crc.h @@ -0,0 +1,7 @@ +#ifndef CRC_H +#define CRC_H + +unsigned int crc32_buf(const char* buf, unsigned long len); +unsigned int crc32_file(const char* fileName); + +#endif // CRC_H diff --git a/CubeModLauncher/main.cpp b/CubeModLauncher/main.cpp new file mode 100644 index 0000000..818c668 --- /dev/null +++ b/CubeModLauncher/main.cpp @@ -0,0 +1,89 @@ +#include "main.h" +#include +#include +#include +#include "Process.h" +#include "crc.h" + +#define CUBE_VERSION "1.0.0-0" +#define CUBE_CRC 0x00000000 + +using namespace std; + +bool FileExists(const char* fileName) { + DWORD dwAttrib = GetFileAttributes(fileName); + return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); +} + +int main() +{ + vector modDLLs; + + //Cube world is obviously required + if (!FileExists("Cube.exe")){ + printf("Cube World not found.\n"); + Sleep(1000); + return 1; + } + + unsigned int checksum = crc32_file("Cube.exe"); + if (checksum != CUBE_CRC){ + printf("Cube World was found, but it is not version %s.\n" + "(Found CRC %08X, expected %08X)\n" + "Please update your game.\n", + CUBE_VERSION, checksum, CUBE_CRC); + printf("Press enter to exit.\n"); + cin.ignore(); + return 1; + } + + //The callback manager is required. + if ( !FileExists("CallbackManager.dll") ){ + printf("Callback manager not found.\n"); + Sleep(1000); + return 1; + } + + modDLLs.push_back( std::string("CallbackManager.dll") ); + + Process process("Cube.exe"); + + //Create game in suspended state + printf("Starting Cube.exe...\n\n"); + if (!process.Create()) + { + printf("Failed to create process: %lu", GetLastError()); + return 1; + } + else { + printf("Cube.exe was successfully started.\n\n"); + } + + //Find mods + HANDLE hFind; + WIN32_FIND_DATA data; + + CreateDirectory("Mods", NULL); + hFind = FindFirstFile("Mods\\*.dll", &data); + if (hFind != INVALID_HANDLE_VALUE) { + do { + modDLLs.push_back( std::string("Mods\\") + data.cFileName); + } while (FindNextFile(hFind, &data)); + FindClose(hFind); + } + + + //Inject DLLs + vector threads; + for (string S_DLLName : modDLLs){ + printf("Loading %s\n", S_DLLName.c_str()); + process.InjectDLL(S_DLLName); + } + + process.Run(); + + printf("\nAll available mods have been loaded.\n"); + Sleep(1500); + + return 0; +} diff --git a/CubeModLauncher/main.h b/CubeModLauncher/main.h new file mode 100644 index 0000000..8225de5 --- /dev/null +++ b/CubeModLauncher/main.h @@ -0,0 +1,7 @@ +#ifndef MAIN_H_INCLUDED +#define MAIN_H_INCLUDED + +bool FileExists(char* fileName); +int main(); + +#endif // MAIN_H_INCLUDED diff --git a/main.cpp b/main.cpp deleted file mode 100644 index 7403bea..0000000 --- a/main.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include -#include -#include - - -using namespace std; - -bool FileExists(LPCTSTR szPath) -{ - DWORD dwAttrib = GetFileAttributes(szPath); - return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); -} - -int main() -{ - vector modDLLs; - - //Cube world is obviously required - if (!FileExists("Cube.exe")){ - printf("Cube World not found.\n"); - Sleep(1000); - return 1; - } - - FILE *file = fopen("Cube.exe", "rb"); - fseek(file, 0, SEEK_END); - int fileSize = ftell(file); - fclose(file); - - const int CUBE_SIZE = 3885568; - if (fileSize != CUBE_SIZE){ - printf("Cube World was found, but it is not version 0.1.1. Please update your game.\n"); - printf("Press enter to exit.\n"); - cin.ignore(); - return 1; - } - - - - - //The callback manager is required. - if ( !FileExists("CallbackManager.dll") ){ - printf("Callback manager not found.\n"); - Sleep(1000); - return 1; - } - - modDLLs.push_back( std::string("CallbackManager.dll") ); - const char MOD_PATH[] = "Mods\\*.dll"; - STARTUPINFO si; - PROCESS_INFORMATION pi; - ZeroMemory(&si, sizeof(si)); - ZeroMemory(&pi, sizeof(pi)); - CreateDirectory("Mods", NULL); - - //Create game in suspended state - printf("Starting Cube.exe...\n\n"); - if (!CreateProcess(NULL, - "Cube.exe", - NULL, - NULL, - true, - CREATE_SUSPENDED, - NULL, - NULL, - &si, - &pi)) - { - printf("Failed to create process: %lu", GetLastError()); - return 1; - } - else { - printf("Cube.exe was successfully started.\n\n"); - } - - - //Find mods - HANDLE hFind; - WIN32_FIND_DATA data; - - hFind = FindFirstFile(MOD_PATH, &data); - if (hFind != INVALID_HANDLE_VALUE) { - do { - modDLLs.push_back( std::string("Mods\\") + data.cFileName); - } while (FindNextFile(hFind, &data)); - FindClose(hFind); - } - - - //Inject DLLs - vector threads; - for (string S_DLLName : modDLLs){ - printf("Loading %s\n", S_DLLName.c_str()); - - LPVOID load_library = (LPVOID) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "LoadLibraryA"); - LPVOID remote_string = (LPVOID) VirtualAllocEx(pi.hProcess, NULL, strlen(S_DLLName.c_str()) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - - WriteProcessMemory(pi.hProcess, remote_string, S_DLLName.c_str(), strlen(S_DLLName.c_str()) + 1, NULL); - - HANDLE thread = CreateRemoteThread(pi.hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE) load_library, remote_string, CREATE_SUSPENDED, NULL); - threads.push_back(thread); - ResumeThread(thread); - } - - ResumeThread(pi.hThread); - CloseHandle(pi.hProcess); - - printf("\nAll available mods have been loaded.\n"); - Sleep(1500); -// -// -// WaitForSingleObject(pi.hThread, INFINITE); -// for (HANDLE thread : threads){ -// CloseHandle(thread); -// } - return 0; -} From 710a699df95e608bccb466f0de049b1055487347 Mon Sep 17 00:00:00 2001 From: ChrisMiuchiz Date: Wed, 11 Sep 2019 19:55:52 -0400 Subject: [PATCH 2/9] Working on 64 bit cw --- CubeModLauncher/Process.cpp | 2 +- CubeModLauncher/crc.cpp | 8 +++++++- CubeModLauncher/main.cpp | 5 +++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CubeModLauncher/Process.cpp b/CubeModLauncher/Process.cpp index 3a18f2a..1dd0b57 100644 --- a/CubeModLauncher/Process.cpp +++ b/CubeModLauncher/Process.cpp @@ -26,7 +26,7 @@ bool Process::InjectDLL(string dllName) { } bool Process::Create() { return CreateProcess(NULL, - "Cube.exe", + (char*)path.c_str(), NULL, NULL, true, diff --git a/CubeModLauncher/crc.cpp b/CubeModLauncher/crc.cpp index b69c3b3..48247a3 100644 --- a/CubeModLauncher/crc.cpp +++ b/CubeModLauncher/crc.cpp @@ -57,12 +57,18 @@ unsigned int crc32_buf(const char* buf, unsigned long len) unsigned int crc32_file(const char* fileName){ FILE* file = fopen(fileName, "rb"); + fseek(file, 0, SEEK_END); int fileSize = ftell(file); - char* fileContents = new char[fileSize]; + char* fileContents = new char[fileSize+1]; + + fseek(file, 0, SEEK_SET); fread(fileContents, 1, fileSize, file); fclose(file); + int result = crc32_buf(fileContents, fileSize); + delete[] fileContents; + return result; } diff --git a/CubeModLauncher/main.cpp b/CubeModLauncher/main.cpp index 818c668..ce6fde3 100644 --- a/CubeModLauncher/main.cpp +++ b/CubeModLauncher/main.cpp @@ -6,7 +6,7 @@ #include "crc.h" #define CUBE_VERSION "1.0.0-0" -#define CUBE_CRC 0x00000000 +#define CUBE_CRC 0x6AFF99F7 using namespace std; @@ -38,13 +38,14 @@ int main() } //The callback manager is required. - if ( !FileExists("CallbackManager.dll") ){ + /*if ( !FileExists("CallbackManager.dll") ){ printf("Callback manager not found.\n"); Sleep(1000); return 1; } modDLLs.push_back( std::string("CallbackManager.dll") ); + */ Process process("Cube.exe"); From a78fe0572e1a3378811dbaae89b892fbc6847716 Mon Sep 17 00:00:00 2001 From: ChrisMiuchiz Date: Wed, 11 Sep 2019 21:45:36 -0400 Subject: [PATCH 3/9] working on cube 64 --- CubeModLauncher/main.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/CubeModLauncher/main.cpp b/CubeModLauncher/main.cpp index ce6fde3..efbcd95 100644 --- a/CubeModLauncher/main.cpp +++ b/CubeModLauncher/main.cpp @@ -6,7 +6,7 @@ #include "crc.h" #define CUBE_VERSION "1.0.0-0" -#define CUBE_CRC 0x6AFF99F7 +#define CUBE_CRC 0xDC91320A using namespace std; @@ -18,7 +18,6 @@ bool FileExists(const char* fileName) { int main() { vector modDLLs; - //Cube world is obviously required if (!FileExists("Cube.exe")){ printf("Cube World not found.\n"); @@ -75,16 +74,15 @@ int main() //Inject DLLs - vector threads; for (string S_DLLName : modDLLs){ printf("Loading %s\n", S_DLLName.c_str()); process.InjectDLL(S_DLLName); } - process.Run(); - printf("\nAll available mods have been loaded.\n"); Sleep(1500); + process.Run(); + Sleep(3000); return 0; } From a7f0179897d9b91e6fee851b06eb1709b1f03f3c Mon Sep 17 00:00:00 2001 From: ChrisMiuchiz Date: Thu, 12 Sep 2019 20:41:28 -0400 Subject: [PATCH 4/9] working --- CubeModLauncher/main.cpp | 47 +++++++++++----------------------------- CubeModLoader/main.cpp | 33 ++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 34 deletions(-) create mode 100644 CubeModLoader/main.cpp diff --git a/CubeModLauncher/main.cpp b/CubeModLauncher/main.cpp index efbcd95..cd74fdd 100644 --- a/CubeModLauncher/main.cpp +++ b/CubeModLauncher/main.cpp @@ -15,18 +15,16 @@ bool FileExists(const char* fileName) { return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); } -int main() -{ - vector modDLLs; +int main() { //Cube world is obviously required - if (!FileExists("Cube.exe")){ + if (!FileExists("Cube.exe")) { printf("Cube World not found.\n"); Sleep(1000); return 1; } unsigned int checksum = crc32_file("Cube.exe"); - if (checksum != CUBE_CRC){ + if (checksum != CUBE_CRC) { printf("Cube World was found, but it is not version %s.\n" "(Found CRC %08X, expected %08X)\n" "Please update your game.\n", @@ -36,52 +34,33 @@ int main() return 1; } - //The callback manager is required. - /*if ( !FileExists("CallbackManager.dll") ){ + //Inject our dll + if ( !FileExists("CubeModLoader.dll") ) { printf("Callback manager not found.\n"); Sleep(1000); return 1; } - modDLLs.push_back( std::string("CallbackManager.dll") ); - */ - Process process("Cube.exe"); //Create game in suspended state printf("Starting Cube.exe...\n\n"); - if (!process.Create()) - { + if (!process.Create()) { printf("Failed to create process: %lu", GetLastError()); return 1; - } - else { + } else { printf("Cube.exe was successfully started.\n\n"); } - //Find mods - HANDLE hFind; - WIN32_FIND_DATA data; + process.InjectDLL( std::string("CubeModLoader.dll") ); - CreateDirectory("Mods", NULL); - hFind = FindFirstFile("Mods\\*.dll", &data); - if (hFind != INVALID_HANDLE_VALUE) { - do { - modDLLs.push_back( std::string("Mods\\") + data.cFileName); - } while (FindNextFile(hFind, &data)); - FindClose(hFind); - } + // Need to give the loader some time to work + // This is a horrible thing and probably will result in a race condition please help me + Sleep(250); - - //Inject DLLs - for (string S_DLLName : modDLLs){ - printf("Loading %s\n", S_DLLName.c_str()); - process.InjectDLL(S_DLLName); - } - - printf("\nAll available mods have been loaded.\n"); - Sleep(1500); + // Let Cube World run! process.Run(); + Sleep(3000); return 0; diff --git a/CubeModLoader/main.cpp b/CubeModLoader/main.cpp new file mode 100644 index 0000000..99ce1d8 --- /dev/null +++ b/CubeModLoader/main.cpp @@ -0,0 +1,33 @@ +#include +#include +#include + +using namespace std; + +extern "C" __declspec(dllexport) BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { + switch (fdwReason) { + case DLL_PROCESS_ATTACH: + MessageBoxA(0, "hello!", "DLL Message", MB_OK | MB_ICONINFORMATION); + + vector modDLLs; + + //Find mods + HANDLE hFind; + WIN32_FIND_DATA data; + + CreateDirectory("Mods", NULL); + hFind = FindFirstFile("Mods\\*.dll", &data); + if (hFind != INVALID_HANDLE_VALUE) { + do { + modDLLs.push_back( std::string("Mods\\") + data.cFileName); + } while (FindNextFile(hFind, &data)); + FindClose(hFind); + } + + // We should be loaded into the application's address space, so we can just LoadLibraryA + for (std::string modName : modDLLs) { + LoadLibraryA(modName.c_str()); + } + } + return true; +} From 89da8bb31a761e8d2267cfbf6f85e966cce58e76 Mon Sep 17 00:00:00 2001 From: ChrisMiuchiz Date: Sat, 14 Sep 2019 15:24:12 -0400 Subject: [PATCH 5/9] cube --- CubeModLoader/DLL.cpp | 16 +++++++ CubeModLoader/DLL.h | 28 +++++++++++ CubeModLoader/main.cpp | 105 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 143 insertions(+), 6 deletions(-) create mode 100644 CubeModLoader/DLL.cpp create mode 100644 CubeModLoader/DLL.h diff --git a/CubeModLoader/DLL.cpp b/CubeModLoader/DLL.cpp new file mode 100644 index 0000000..47995af --- /dev/null +++ b/CubeModLoader/DLL.cpp @@ -0,0 +1,16 @@ +#include "DLL.h" +#include + +DLL::DLL(std::string fileName) { + this->fileName = fileName; + this->handle = nullptr; +} + +HMODULE DLL::Load() { + this->handle = LoadLibraryA(this->fileName.c_str()); + return this->handle; +} + +DLL::~DLL() { + //dtor +} diff --git a/CubeModLoader/DLL.h b/CubeModLoader/DLL.h new file mode 100644 index 0000000..8ed837b --- /dev/null +++ b/CubeModLoader/DLL.h @@ -0,0 +1,28 @@ +#ifndef DLL_H +#define DLL_H +#include +#include + +class DLL +{ + public: + std::string fileName; + HMODULE handle; + + FARPROC ModInitialize; + FARPROC ModMajorVersion; + FARPROC ModMinorVersion; + + // Callbacks + FARPROC HandleNumber; + + DLL(std::string fileName); + HMODULE Load(); + virtual ~DLL(); + + protected: + + private: +}; + +#endif // DLL_H diff --git a/CubeModLoader/main.cpp b/CubeModLoader/main.cpp index 99ce1d8..bb2df0b 100644 --- a/CubeModLoader/main.cpp +++ b/CubeModLoader/main.cpp @@ -1,15 +1,95 @@ #include #include #include +#include "DLL.h" + +#define MOD_MAJOR_VERSION 1 +#define MOD_MINOR_VERSION 1 + + +#define no_optimize __attribute__((optimize("O0"))) + +#define MUST_IMPORT(dllname, name)\ +dllname->name = GetProcAddress(dllname->handle, #name);\ + if (!dllname->name) {\ + printf("%s does not export " #name ".\n", dllname->fileName.c_str());\ + exit(1);\ + } + +#define IMPORT(dllname, name)\ +dllname->name = GetProcAddress(dllname->handle, #name); + using namespace std; +void* base; +vector modDLLs; + +void WriteFarJMP(void* source, void* destination) { + DWORD dwOldProtection; + VirtualProtect(source, 14, PAGE_EXECUTE_READWRITE, &dwOldProtection); + char* location = (char*)source; + + // Far jump + *((UINT16*)&location[0]) = 0x25FF; + + // mode + *((UINT32*)&location[2]) = 0x00000000; + + *((UINT64*)&location[6]) = (UINT64)destination; + + VirtualProtect(location, 14, dwOldProtection, &dwOldProtection); +} + + + +// Example handler +void NumberHandler(int number) { + for (DLL* dll: modDLLs) { + if (dll->HandleNumber) { + ((void(*)(int))dll->HandleNumber)(number); + } + } +} +void* NumberHandler_ptr = (void*)&NumberHandler; + +void* ASMNumberHandler_jmpback; +char ASMNumberHandler_formatstring[] = "%d...\n"; +void no_optimize ASMNumberHandler() { + asm("call rax \n" + "mov eax, [rbp-4] \n" + "push rax\n push rcx\n push rdx\n push r8\n push r9\n push r10\n push r11\n" + + "sub rsp, 0x20 \n" + "mov ecx, eax \n" + "call [NumberHandler_ptr] \n" + "add rsp, 0x20 \n" + + "pop r11\n pop r10\n pop r9\n pop r8\n pop rdx\n pop rcx\n pop rax\n" + + "mov edx, eax \n" + "lea rcx, [ASMNumberHandler_formatstring] \n" + "jmp [ASMNumberHandler_jmpback]" + ); +} +void SetupNumberHandler() { + WriteFarJMP(base+0x1597, (void*)&ASMNumberHandler); + ASMNumberHandler_jmpback = (void*)base+0x15A5; +} + + +void SetupHandlers() { + SetupNumberHandler(); +} + extern "C" __declspec(dllexport) BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: - MessageBoxA(0, "hello!", "DLL Message", MB_OK | MB_ICONINFORMATION); + base = GetModuleHandle(NULL); - vector modDLLs; + SetupHandlers(); + + MessageBoxA(0, "hello!", "DLL Message", MB_OK | MB_ICONINFORMATION); //Find mods HANDLE hFind; @@ -19,15 +99,28 @@ extern "C" __declspec(dllexport) BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD hFind = FindFirstFile("Mods\\*.dll", &data); if (hFind != INVALID_HANDLE_VALUE) { do { - modDLLs.push_back( std::string("Mods\\") + data.cFileName); + // We should be loaded into the application's address space, so we can just LoadLibraryA + DLL* dll = new DLL(string("Mods\\") + data.cFileName); + dll->Load(); + modDLLs.push_back(dll); } while (FindNextFile(hFind, &data)); FindClose(hFind); } - // We should be loaded into the application's address space, so we can just LoadLibraryA - for (std::string modName : modDLLs) { - LoadLibraryA(modName.c_str()); + + // Find all the functions the mods may export + for (DLL* dll: modDLLs) { + MUST_IMPORT(dll, ModMajorVersion); + MUST_IMPORT(dll, ModMinorVersion); + MUST_IMPORT(dll, ModInitialize); + IMPORT(dll, HandleNumber); } + + // Run Initialization routines on all mods + for (DLL* dll: modDLLs) { + ((void(*)())dll->ModInitialize)(); + } + } return true; } From 176c0b95ebc36dbd83e16bc26e7aed4abd368d43 Mon Sep 17 00:00:00 2001 From: ChrisMiuchiz Date: Sat, 14 Sep 2019 19:59:24 -0400 Subject: [PATCH 6/9] 64 --- CubeModLoader/DLL.cpp | 3 +++ CubeModLoader/DLL.h | 1 + CubeModLoader/main.cpp | 28 ++++++++++++++++++++++++++-- README.md | 8 ++++---- 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/CubeModLoader/DLL.cpp b/CubeModLoader/DLL.cpp index 47995af..0b0d939 100644 --- a/CubeModLoader/DLL.cpp +++ b/CubeModLoader/DLL.cpp @@ -8,6 +8,9 @@ DLL::DLL(std::string fileName) { HMODULE DLL::Load() { this->handle = LoadLibraryA(this->fileName.c_str()); + if (!this->handle) { + printf("%s %d\n", this->fileName.c_str(), GetLastError()); + } return this->handle; } diff --git a/CubeModLoader/DLL.h b/CubeModLoader/DLL.h index 8ed837b..3ae853b 100644 --- a/CubeModLoader/DLL.h +++ b/CubeModLoader/DLL.h @@ -9,6 +9,7 @@ class DLL std::string fileName; HMODULE handle; + FARPROC ModPreInitialize; FARPROC ModInitialize; FARPROC ModMajorVersion; FARPROC ModMinorVersion; diff --git a/CubeModLoader/main.cpp b/CubeModLoader/main.cpp index bb2df0b..5f93bed 100644 --- a/CubeModLoader/main.cpp +++ b/CubeModLoader/main.cpp @@ -102,23 +102,47 @@ extern "C" __declspec(dllexport) BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD // We should be loaded into the application's address space, so we can just LoadLibraryA DLL* dll = new DLL(string("Mods\\") + data.cFileName); dll->Load(); + printf("Loaded %s\n", dll->fileName.c_str()); modDLLs.push_back(dll); } while (FindNextFile(hFind, &data)); FindClose(hFind); } + // Find all the functions the mods may export for (DLL* dll: modDLLs) { MUST_IMPORT(dll, ModMajorVersion); MUST_IMPORT(dll, ModMinorVersion); - MUST_IMPORT(dll, ModInitialize); + MUST_IMPORT(dll, ModPreInitialize); + IMPORT(dll, ModInitialize); IMPORT(dll, HandleNumber); } + // Ensure version compatibility + for (DLL* dll: modDLLs) { + int majorVersion = ((int(*)())dll->ModMajorVersion)(); + int minorVersion = ((int(*)())dll->ModMinorVersion)(); + if (majorVersion != MOD_MAJOR_VERSION) { + printf("%s has major version %d but requires %d.\n", dll->fileName.c_str(), majorVersion, MOD_MAJOR_VERSION); + exit(1); + } + + if (minorVersion > MOD_MINOR_VERSION) { + printf("%s has minor version %d but requires %d or lower.\n", dll->fileName.c_str(), minorVersion, MOD_MINOR_VERSION); + exit(1); + } + } + // Run Initialization routines on all mods for (DLL* dll: modDLLs) { - ((void(*)())dll->ModInitialize)(); + ((void(*)())dll->ModPreInitialize)(); + } + + for (DLL* dll: modDLLs) { + if (dll->ModInitialize) { + ((void(*)())dll->ModInitialize)(); + } } } diff --git a/README.md b/README.md index a849a6d..ab82499 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,6 @@ Supports injecting Cube World mods. DLLs must go in a folder called "Mods". -If something doesn't work, make sure you have the latest release for the launcher and all your mods, along with Cube World. - -If you need to update Cube World, you can use this: https://github.com/ChrisMiuchiz/CubeWorld-Cracker - ## Installing Get the latest executable from Releases and place it in the same folder as Cube.exe @@ -13,3 +9,7 @@ https://github.com/ChrisMiuchiz/Cube-World-Mod-Launcher/releases ## Installing Mods A "Mods" folder should be created in the same folder as Cube.exe, and mods should be installed by moving them into the Mods folder. + + + +building flags: -m64 -masm=intel -static-libgcc -static-libstdc++ From 102f05644747c9c637dc226349f816d3d872299b Mon Sep 17 00:00:00 2001 From: ChrisMiuchiz Date: Mon, 16 Sep 2019 21:24:20 -0400 Subject: [PATCH 7/9] c u b e --- CubeModLoader/DLL.cpp | 3 +- CubeModLoader/callbacks/NumberHandler.h | 33 +++++++++++++++++++++ CubeModLoader/main.cpp | 39 +------------------------ CubeModLoader/main.h | 12 ++++++++ 4 files changed, 48 insertions(+), 39 deletions(-) create mode 100644 CubeModLoader/callbacks/NumberHandler.h create mode 100644 CubeModLoader/main.h diff --git a/CubeModLoader/DLL.cpp b/CubeModLoader/DLL.cpp index 0b0d939..fcfa6d1 100644 --- a/CubeModLoader/DLL.cpp +++ b/CubeModLoader/DLL.cpp @@ -9,7 +9,8 @@ DLL::DLL(std::string fileName) { HMODULE DLL::Load() { this->handle = LoadLibraryA(this->fileName.c_str()); if (!this->handle) { - printf("%s %d\n", this->fileName.c_str(), GetLastError()); + printf("Could not load %s: %d\n", this->fileName.c_str(), GetLastError()); + exit(1); } return this->handle; } diff --git a/CubeModLoader/callbacks/NumberHandler.h b/CubeModLoader/callbacks/NumberHandler.h new file mode 100644 index 0000000..8ed1fca --- /dev/null +++ b/CubeModLoader/callbacks/NumberHandler.h @@ -0,0 +1,33 @@ +// Example handler +void NumberHandler(int number) { + for (DLL* dll: modDLLs) { + if (dll->HandleNumber) { + ((void(*)(int))dll->HandleNumber)(number); + } + } +} +void* NumberHandler_ptr = (void*)&NumberHandler; + +void* ASMNumberHandler_jmpback; +char ASMNumberHandler_formatstring[] = "%d...\n"; +void no_optimize ASMNumberHandler() { + asm("call rax \n" + "mov eax, [rbp-4] \n" + "push rax\n push rcx\n push rdx\n push r8\n push r9\n push r10\n push r11\n" + + "sub rsp, 0x20 \n" + "mov ecx, eax \n" + "call [NumberHandler_ptr] \n" + "add rsp, 0x20 \n" + + "pop r11\n pop r10\n pop r9\n pop r8\n pop rdx\n pop rcx\n pop rax\n" + + "mov edx, eax \n" + "lea rcx, [ASMNumberHandler_formatstring] \n" + "jmp [ASMNumberHandler_jmpback]" + ); +} +void SetupNumberHandler() { + WriteFarJMP(base+0x1597, (void*)&ASMNumberHandler); + ASMNumberHandler_jmpback = (void*)base+0x15A5; +} diff --git a/CubeModLoader/main.cpp b/CubeModLoader/main.cpp index 5f93bed..728724c 100644 --- a/CubeModLoader/main.cpp +++ b/CubeModLoader/main.cpp @@ -41,42 +41,7 @@ void WriteFarJMP(void* source, void* destination) { VirtualProtect(location, 14, dwOldProtection, &dwOldProtection); } - - -// Example handler -void NumberHandler(int number) { - for (DLL* dll: modDLLs) { - if (dll->HandleNumber) { - ((void(*)(int))dll->HandleNumber)(number); - } - } -} -void* NumberHandler_ptr = (void*)&NumberHandler; - -void* ASMNumberHandler_jmpback; -char ASMNumberHandler_formatstring[] = "%d...\n"; -void no_optimize ASMNumberHandler() { - asm("call rax \n" - "mov eax, [rbp-4] \n" - "push rax\n push rcx\n push rdx\n push r8\n push r9\n push r10\n push r11\n" - - "sub rsp, 0x20 \n" - "mov ecx, eax \n" - "call [NumberHandler_ptr] \n" - "add rsp, 0x20 \n" - - "pop r11\n pop r10\n pop r9\n pop r8\n pop rdx\n pop rcx\n pop rax\n" - - "mov edx, eax \n" - "lea rcx, [ASMNumberHandler_formatstring] \n" - "jmp [ASMNumberHandler_jmpback]" - ); -} -void SetupNumberHandler() { - WriteFarJMP(base+0x1597, (void*)&ASMNumberHandler); - ASMNumberHandler_jmpback = (void*)base+0x15A5; -} - +#include "callbacks/NumberHandler.h" void SetupHandlers() { SetupNumberHandler(); @@ -108,8 +73,6 @@ extern "C" __declspec(dllexport) BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD FindClose(hFind); } - - // Find all the functions the mods may export for (DLL* dll: modDLLs) { MUST_IMPORT(dll, ModMajorVersion); diff --git a/CubeModLoader/main.h b/CubeModLoader/main.h new file mode 100644 index 0000000..59a404a --- /dev/null +++ b/CubeModLoader/main.h @@ -0,0 +1,12 @@ +#ifndef MAIN_H +#define MAIN_H + +#include "DLL.h" +#include +#define no_optimize __attribute__((optimize("O0"))) +using namespace std; +vector modDLLs; +void* base; +void WriteFarJMP(void* source, void* destination); + +#endif // MAIN_H From 66b0adfffb1e12fe6638c89fa5f2a7cadd3bd6e4 Mon Sep 17 00:00:00 2001 From: ChrisMiuchiz Date: Sat, 21 Sep 2019 13:12:00 -0400 Subject: [PATCH 8/9] Working for beta, added chat callback --- CubeModLauncher/main.cpp | 78 ++++++++++++++++++------- CubeModLauncher/main.h | 3 +- CubeModLoader/DLL.h | 2 +- CubeModLoader/callbacks/NumberHandler.h | 33 ----------- CubeModLoader/main.cpp | 9 ++- 5 files changed, 66 insertions(+), 59 deletions(-) delete mode 100644 CubeModLoader/callbacks/NumberHandler.h diff --git a/CubeModLauncher/main.cpp b/CubeModLauncher/main.cpp index cd74fdd..6720f87 100644 --- a/CubeModLauncher/main.cpp +++ b/CubeModLauncher/main.cpp @@ -5,8 +5,13 @@ #include "Process.h" #include "crc.h" -#define CUBE_VERSION "1.0.0-0" -#define CUBE_CRC 0xDC91320A +#define CUBE_VERSION "0.9.1-0" +#define CUBE_PACKED_CRC 0x8B2EE791 +#define CUBE_UNPACKED_CRC 0xC2845E38 + +#define MODLOADER_CRC 0x5858F9D7 + +#define CUBE_EXECUTABLE "cubeworld.exe" using namespace std; @@ -15,41 +20,72 @@ bool FileExists(const char* fileName) { return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); } -int main() { - //Cube world is obviously required - if (!FileExists("Cube.exe")) { - printf("Cube World not found.\n"); - Sleep(1000); - return 1; +int Bail(int result){ + printf("Press enter to exit.\n"); + cin.ignore(); + return result; +} + +int main(int argc, char** argv) { + bool testMode = false; + if (argc >= 2 && !strcmp(argv[1], "test")) { + testMode = true; + printf("Test mode enabled. CRC checks will be bypassed.\n"); } - unsigned int checksum = crc32_file("Cube.exe"); - if (checksum != CUBE_CRC) { + //Cube world is obviously required + if (!FileExists(CUBE_EXECUTABLE)) { + printf("%s not found.\n", CUBE_EXECUTABLE); + return Bail(1); + } + + unsigned int checksum = crc32_file(CUBE_EXECUTABLE); + + if (testMode) { + printf("%s CRC: %08X\n", CUBE_EXECUTABLE, checksum); + } + + // Check if the game is still packed + if (checksum == CUBE_PACKED_CRC && !testMode) { + printf("Cube World was found, but it is not unpacked.\n" + "Use Steamless to unpack %s.\n", CUBE_EXECUTABLE); + return Bail(1); + } + + + if (checksum != CUBE_UNPACKED_CRC && !testMode) { printf("Cube World was found, but it is not version %s.\n" "(Found CRC %08X, expected %08X)\n" "Please update your game.\n", - CUBE_VERSION, checksum, CUBE_CRC); - printf("Press enter to exit.\n"); - cin.ignore(); - return 1; + CUBE_VERSION, checksum, CUBE_UNPACKED_CRC); + return Bail(1); } //Inject our dll if ( !FileExists("CubeModLoader.dll") ) { - printf("Callback manager not found.\n"); - Sleep(1000); - return 1; + printf("CubeModLoader.dll not found.\n"); + return Bail(1); } - Process process("Cube.exe"); + unsigned int loaderChecksum = crc32_file("CubeModLoader.dll"); + if (loaderChecksum != MODLOADER_CRC && !testMode) { + printf("CubeModLoader.dll is the wrong version (%08X)\n", loaderChecksum); + return Bail(1); + } + + if (testMode) { + printf("CubeModLoader.dll CRC: %08X\n", loaderChecksum); + } + + Process process(CUBE_EXECUTABLE); //Create game in suspended state - printf("Starting Cube.exe...\n\n"); + printf("Starting %s...\n\n", CUBE_EXECUTABLE); if (!process.Create()) { printf("Failed to create process: %lu", GetLastError()); - return 1; + return Bail(1); } else { - printf("Cube.exe was successfully started.\n\n"); + printf("%s was successfully started.\n\n", CUBE_EXECUTABLE); } process.InjectDLL( std::string("CubeModLoader.dll") ); diff --git a/CubeModLauncher/main.h b/CubeModLauncher/main.h index 8225de5..b204edf 100644 --- a/CubeModLauncher/main.h +++ b/CubeModLauncher/main.h @@ -2,6 +2,7 @@ #define MAIN_H_INCLUDED bool FileExists(char* fileName); -int main(); +int Bail(int result); +int main(int argc, char** argv); #endif // MAIN_H_INCLUDED diff --git a/CubeModLoader/DLL.h b/CubeModLoader/DLL.h index 3ae853b..5881351 100644 --- a/CubeModLoader/DLL.h +++ b/CubeModLoader/DLL.h @@ -15,7 +15,7 @@ class DLL FARPROC ModMinorVersion; // Callbacks - FARPROC HandleNumber; + FARPROC HandleChat; DLL(std::string fileName); HMODULE Load(); diff --git a/CubeModLoader/callbacks/NumberHandler.h b/CubeModLoader/callbacks/NumberHandler.h deleted file mode 100644 index 8ed1fca..0000000 --- a/CubeModLoader/callbacks/NumberHandler.h +++ /dev/null @@ -1,33 +0,0 @@ -// Example handler -void NumberHandler(int number) { - for (DLL* dll: modDLLs) { - if (dll->HandleNumber) { - ((void(*)(int))dll->HandleNumber)(number); - } - } -} -void* NumberHandler_ptr = (void*)&NumberHandler; - -void* ASMNumberHandler_jmpback; -char ASMNumberHandler_formatstring[] = "%d...\n"; -void no_optimize ASMNumberHandler() { - asm("call rax \n" - "mov eax, [rbp-4] \n" - "push rax\n push rcx\n push rdx\n push r8\n push r9\n push r10\n push r11\n" - - "sub rsp, 0x20 \n" - "mov ecx, eax \n" - "call [NumberHandler_ptr] \n" - "add rsp, 0x20 \n" - - "pop r11\n pop r10\n pop r9\n pop r8\n pop rdx\n pop rcx\n pop rax\n" - - "mov edx, eax \n" - "lea rcx, [ASMNumberHandler_formatstring] \n" - "jmp [ASMNumberHandler_jmpback]" - ); -} -void SetupNumberHandler() { - WriteFarJMP(base+0x1597, (void*)&ASMNumberHandler); - ASMNumberHandler_jmpback = (void*)base+0x15A5; -} diff --git a/CubeModLoader/main.cpp b/CubeModLoader/main.cpp index 728724c..30ee23d 100644 --- a/CubeModLoader/main.cpp +++ b/CubeModLoader/main.cpp @@ -19,6 +19,9 @@ dllname->name = GetProcAddress(dllname->handle, #name);\ #define IMPORT(dllname, name)\ dllname->name = GetProcAddress(dllname->handle, #name); +#define PUSH_ALL "push rax\npush rbx\npush rcx\npush rdx\npush rsi\npush rdi\npush rbp\npush r8\npush r9\npush r10\npush r11\npush r12\npush r13\npush r14\npush r15\n" +#define POP_ALL "pop r15\npop r14\npop r13\npop r12\npop r11\npop r10\npop r9\npop r8\npop rbp\npop rdi\npop rsi\npop rdx\npop rcx\npop rbx\npop rax\n" + using namespace std; @@ -41,10 +44,10 @@ void WriteFarJMP(void* source, void* destination) { VirtualProtect(location, 14, dwOldProtection, &dwOldProtection); } -#include "callbacks/NumberHandler.h" + #include "callbacks/ChatHandler.h" void SetupHandlers() { - SetupNumberHandler(); + SetupChatHandler(); } extern "C" __declspec(dllexport) BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { @@ -79,7 +82,7 @@ extern "C" __declspec(dllexport) BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD MUST_IMPORT(dll, ModMinorVersion); MUST_IMPORT(dll, ModPreInitialize); IMPORT(dll, ModInitialize); - IMPORT(dll, HandleNumber); + IMPORT(dll, HandleChat); } // Ensure version compatibility From 357d7fde4b58d23d79ac4d001490db8ee6490d9a Mon Sep 17 00:00:00 2001 From: ChrisMiuchiz Date: Sun, 22 Sep 2019 19:17:15 -0400 Subject: [PATCH 9/9] prepare c u b e --- CubeModLoader/callbacks/ChatHandler.h | 47 +++++++++++++++++++++++++++ CubeModLoader/main.cpp | 17 +++++++--- README.md | 14 ++++++-- 3 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 CubeModLoader/callbacks/ChatHandler.h diff --git a/CubeModLoader/callbacks/ChatHandler.h b/CubeModLoader/callbacks/ChatHandler.h new file mode 100644 index 0000000..ac33dc8 --- /dev/null +++ b/CubeModLoader/callbacks/ChatHandler.h @@ -0,0 +1,47 @@ +int ChatHandler(wchar_t* msg) { + for (DLL* dll: modDLLs) { + if (dll->HandleChat) { + if ( ((int(*)(wchar_t*))dll->HandleChat)(msg) ){ + return 1; + } + } + } + return 0; +} +void* ChatHandler_ptr = (void*)&ChatHandler; + +void* ASMChatHandler_jmpback; +void* ASMChatHandler_bail; +void no_optimize ASMChatHandler() { + asm(PUSH_ALL + + "mov rcx, rsi \n" // The message + + PREPARE_STACK + + "call [ChatHandler_ptr] \n" + + RESTORE_STACK + + // Did the handler return true? + "test al, al \n" + "jnz bail \n" + + POP_ALL + + // original code + "mov qword ptr [rbp+0x98], 7 \n" + "mov [rbp+0x90], r15 \n" + "jmp [ASMChatHandler_jmpback] \n" + + + "bail: \n" + POP_ALL + "jmp [ASMChatHandler_bail]" + ); +} +void SetupChatHandler() { + WriteFarJMP(base+0x87611, (void*)&ASMChatHandler); + ASMChatHandler_jmpback = (void*)base+0x87624; + ASMChatHandler_bail = (void*)base+0x879B2; +} diff --git a/CubeModLoader/main.cpp b/CubeModLoader/main.cpp index 30ee23d..2c80307 100644 --- a/CubeModLoader/main.cpp +++ b/CubeModLoader/main.cpp @@ -12,7 +12,7 @@ #define MUST_IMPORT(dllname, name)\ dllname->name = GetProcAddress(dllname->handle, #name);\ if (!dllname->name) {\ - printf("%s does not export " #name ".\n", dllname->fileName.c_str());\ + Popup("Error", "%s does not export " #name ".\n", dllname->fileName.c_str());\ exit(1);\ } @@ -22,6 +22,9 @@ dllname->name = GetProcAddress(dllname->handle, #name); #define PUSH_ALL "push rax\npush rbx\npush rcx\npush rdx\npush rsi\npush rdi\npush rbp\npush r8\npush r9\npush r10\npush r11\npush r12\npush r13\npush r14\npush r15\n" #define POP_ALL "pop r15\npop r14\npop r13\npop r12\npop r11\npop r10\npop r9\npop r8\npop rbp\npop rdi\npop rsi\npop rdx\npop rcx\npop rbx\npop rax\n" +#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" + using namespace std; @@ -50,6 +53,12 @@ void SetupHandlers() { SetupChatHandler(); } +void Popup(char* title, char* format, ... ){ + char msg[512] = {0}; + sprintf(msg, format); + MessageBoxA(0, msg, title, MB_OK | MB_ICONINFORMATION); +} + extern "C" __declspec(dllexport) BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: @@ -57,8 +66,6 @@ extern "C" __declspec(dllexport) BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD SetupHandlers(); - MessageBoxA(0, "hello!", "DLL Message", MB_OK | MB_ICONINFORMATION); - //Find mods HANDLE hFind; WIN32_FIND_DATA data; @@ -90,12 +97,12 @@ extern "C" __declspec(dllexport) BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD int majorVersion = ((int(*)())dll->ModMajorVersion)(); int minorVersion = ((int(*)())dll->ModMinorVersion)(); if (majorVersion != MOD_MAJOR_VERSION) { - printf("%s has major version %d but requires %d.\n", dll->fileName.c_str(), majorVersion, MOD_MAJOR_VERSION); + Popup("Error", "%s has major version %d but requires %d.\n", dll->fileName.c_str(), majorVersion, MOD_MAJOR_VERSION); exit(1); } if (minorVersion > MOD_MINOR_VERSION) { - printf("%s has minor version %d but requires %d or lower.\n", dll->fileName.c_str(), minorVersion, MOD_MINOR_VERSION); + Popup("Error", "%s has minor version %d but requires %d or lower.\n", dll->fileName.c_str(), minorVersion, MOD_MINOR_VERSION); exit(1); } } diff --git a/README.md b/README.md index ab82499..51aaa6a 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,21 @@ Supports injecting Cube World mods. DLLs must go in a folder called "Mods". ## Installing -Get the latest executable from Releases and place it in the same folder as Cube.exe +Get the latest executable from Releases and place it in the same folder as cubeworld.exe https://github.com/ChrisMiuchiz/Cube-World-Mod-Launcher/releases ## Installing Mods -A "Mods" folder should be created in the same folder as Cube.exe, and mods should be installed by moving them into the Mods folder. +A "Mods" folder should be created in the same folder as cubeworld.exe, and mods should be installed by moving them into the Mods folder. +## Preparing cubeworld.exe +Since Cube World is using SteamStub obfuscation, you need to remove the obfuscation using [Steamless](https://github.com/atom0s/Steamless). -building flags: -m64 -masm=intel -static-libgcc -static-libstdc++ + +## Building the launcher or mods +This project will only ever support GCC. This program will not even build using MSVC, not only because the inline assembly syntax is different, but because support for inline assembly was removed for x86-64. + +All mods MUST include cwmods.h from [cwsdk](https://github.com/ChrisMiuchiz/CWSDK) to function. + +Compiler/Linker flags: `-m64 -masm=intel -static -static-libgcc -static-libstdc++`