clong
This commit is contained in:
parent
0ba9eb4078
commit
9ab01582d8
|
@ -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)
|
|
@ -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))
|
|
@ -1,4 +1,4 @@
|
||||||
int ChatHandler(wchar_t* msg) {
|
extern "C" int ChatHandler(wchar_t* msg) {
|
||||||
for (DLL* dll: modDLLs) {
|
for (DLL* dll: modDLLs) {
|
||||||
if (dll->HandleChat) {
|
if (dll->HandleChat) {
|
||||||
if ( ((int(*)(wchar_t*))dll->HandleChat)(msg) ){
|
if ( ((int(*)(wchar_t*))dll->HandleChat)(msg) ){
|
||||||
|
@ -8,18 +8,18 @@ int ChatHandler(wchar_t* msg) {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
void* ChatHandler_ptr = (void*)&ChatHandler;
|
|
||||||
|
|
||||||
void* ASMChatHandler_jmpback;
|
GETTER_VAR(void*, ASMChatHandler_jmpback);
|
||||||
void* ASMChatHandler_bail;
|
GETTER_VAR(void*, ASMChatHandler_bail);
|
||||||
void no_optimize ASMChatHandler() {
|
void ASMChatHandler() {
|
||||||
asm(PUSH_ALL
|
asm(".intel_syntax \n"
|
||||||
|
PUSH_ALL
|
||||||
|
|
||||||
"mov rcx, rbx \n" // The message
|
"mov rcx, rbx \n" // The message
|
||||||
|
|
||||||
PREPARE_STACK
|
PREPARE_STACK
|
||||||
|
|
||||||
"call [ChatHandler_ptr] \n"
|
"call ChatHandler \n"
|
||||||
|
|
||||||
RESTORE_STACK
|
RESTORE_STACK
|
||||||
|
|
||||||
|
@ -33,16 +33,16 @@ void no_optimize ASMChatHandler() {
|
||||||
"mov qword ptr [rbp+0x88], 7 \n"
|
"mov qword ptr [rbp+0x88], 7 \n"
|
||||||
"mov [rbp+0x80], r12 \n"
|
"mov [rbp+0x80], r12 \n"
|
||||||
"mov [rbp+0x70], r12w \n"
|
"mov [rbp+0x70], r12w \n"
|
||||||
"jmp [ASMChatHandler_jmpback] \n"
|
DEREF_JMP(ASMChatHandler_jmpback)
|
||||||
|
|
||||||
|
|
||||||
"bail: \n"
|
"bail: \n"
|
||||||
POP_ALL
|
POP_ALL
|
||||||
"jmp [ASMChatHandler_bail]"
|
DEREF_JMP(ASMChatHandler_bail)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
void SetupChatHandler() {
|
void SetupChatHandler() {
|
||||||
WriteFarJMP(base+0x97198, (void*)&ASMChatHandler);
|
WriteFarJMP(Offset(base, 0x97198), (void*)&ASMChatHandler);
|
||||||
ASMChatHandler_jmpback = (void*)base+0x971B0;
|
ASMChatHandler_jmpback = Offset(base, 0x971B0);
|
||||||
ASMChatHandler_bail = (void*)base+0x9777A;
|
ASMChatHandler_bail = Offset(base, 0x9777A);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
int CheckInventoryFullHandler(void* player, void* item) {
|
extern "C" int CheckInventoryFullHandler(void* player, void* item) {
|
||||||
for (DLL* dll: modDLLs) {
|
for (DLL* dll: modDLLs) {
|
||||||
if (dll->HandleCheckInventoryFull) {
|
if (dll->HandleCheckInventoryFull) {
|
||||||
if ( int result = ((int(*)(void*, void*))dll->HandleCheckInventoryFull)(player, item) ){
|
if ( int result = ((int(*)(void*, void*))dll->HandleCheckInventoryFull)(player, item) ){
|
||||||
|
@ -8,15 +8,15 @@ int CheckInventoryFullHandler(void* player, void* item) {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
void* CheckInventoryFullHandler_ptr = (void*)&CheckInventoryFullHandler;
|
|
||||||
|
|
||||||
void* ASMCheckInventoryFullHandler_jmpback;
|
GETTER_VAR(void*, ASMCheckInventoryFullHandler_jmpback);
|
||||||
void* ASMCheckInventoryFullHandler_retn;
|
GETTER_VAR(void*, ASMCheckInventoryFullHandler_retn);
|
||||||
void no_optimize ASMCheckInventoryFullHandler() {
|
__attribute__((naked)) void ASMCheckInventoryFullHandler() {
|
||||||
asm(PUSH_ALL
|
asm(".intel_syntax \n"
|
||||||
|
PUSH_ALL
|
||||||
|
|
||||||
PREPARE_STACK
|
PREPARE_STACK
|
||||||
"call [CheckInventoryFullHandler_ptr] \n"
|
"call CheckInventoryFullHandler \n"
|
||||||
|
|
||||||
RESTORE_STACK
|
RESTORE_STACK
|
||||||
|
|
||||||
|
@ -37,22 +37,22 @@ void no_optimize ASMCheckInventoryFullHandler() {
|
||||||
"push r14 \n"
|
"push r14 \n"
|
||||||
"push r15 \n"
|
"push r15 \n"
|
||||||
"sub rsp, 0x20 \n"
|
"sub rsp, 0x20 \n"
|
||||||
"jmp [ASMCheckInventoryFullHandler_jmpback] \n"
|
DEREF_JMP(ASMCheckInventoryFullHandler_jmpback)
|
||||||
|
|
||||||
|
|
||||||
"1: \n" //full
|
"1: \n" //full
|
||||||
POP_ALL
|
POP_ALL
|
||||||
"xor al,al \n"
|
"xor al,al \n"
|
||||||
"jmp [ASMCheckInventoryFullHandler_retn] \n"
|
DEREF_JMP(ASMCheckInventoryFullHandler_retn)
|
||||||
|
|
||||||
"2: \n" //not
|
"2: \n" //not
|
||||||
POP_ALL
|
POP_ALL
|
||||||
"mov al,1 \n"
|
"mov al,1 \n"
|
||||||
"jmp [ASMCheckInventoryFullHandler_retn] \n"
|
DEREF_JMP(ASMCheckInventoryFullHandler_retn)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
void SetupCheckInventoryFullHandler() {
|
void SetupCheckInventoryFullHandler() {
|
||||||
WriteFarJMP(base+0x50670, (void*)&ASMCheckInventoryFullHandler);
|
WriteFarJMP(Offset(base, 0x50670), (void*)&ASMCheckInventoryFullHandler);
|
||||||
ASMCheckInventoryFullHandler_jmpback = (void*)base+0x5067F;
|
ASMCheckInventoryFullHandler_jmpback = Offset(base, 0x5067F);
|
||||||
ASMCheckInventoryFullHandler_retn = (void*)base+0x507A0;
|
ASMCheckInventoryFullHandler_retn = Offset(base, 0x507A0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
int P2PRequestHandler(long long steamID) {
|
extern "C" int P2PRequestHandler(long long steamID) {
|
||||||
for (DLL* dll: modDLLs) {
|
for (DLL* dll: modDLLs) {
|
||||||
if (dll->HandleP2PRequest) {
|
if (dll->HandleP2PRequest) {
|
||||||
if ( int result = ((int(*)(long long))dll->HandleP2PRequest)(steamID) ){
|
if ( int result = ((int(*)(long long))dll->HandleP2PRequest)(steamID) ){
|
||||||
|
@ -8,19 +8,19 @@ int P2PRequestHandler(long long steamID) {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
void* P2PRequestHandler_ptr = (void*)&P2PRequestHandler;
|
|
||||||
|
|
||||||
void* ASMP2PRequestHandler_jmpback;
|
GETTER_VAR(void*, ASMP2PRequestHandler_jmpback);
|
||||||
void* ASMP2PRequestHandler_block;
|
GETTER_VAR(void*, ASMP2PRequestHandler_block);
|
||||||
void* ASMP2PRequestHandler_allow;
|
GETTER_VAR(void*, ASMP2PRequestHandler_allow);
|
||||||
void no_optimize ASMP2PRequestHandler() {
|
void ASMP2PRequestHandler() {
|
||||||
asm(PUSH_ALL
|
asm(".intel_syntax \n"
|
||||||
|
PUSH_ALL
|
||||||
|
|
||||||
"mov rcx, [rdi] \n" //incoming steam id
|
"mov rcx, [rdi] \n" //incoming steam id
|
||||||
|
|
||||||
PREPARE_STACK
|
PREPARE_STACK
|
||||||
|
|
||||||
"call [P2PRequestHandler_ptr] \n"
|
"call P2PRequestHandler \n"
|
||||||
|
|
||||||
RESTORE_STACK
|
RESTORE_STACK
|
||||||
|
|
||||||
|
@ -42,21 +42,21 @@ void no_optimize ASMP2PRequestHandler() {
|
||||||
"mov rax, [rcx] \n"
|
"mov rax, [rcx] \n"
|
||||||
"call qword ptr [rax+0x18] \n"
|
"call qword ptr [rax+0x18] \n"
|
||||||
|
|
||||||
"jmp [ASMP2PRequestHandler_jmpback] \n"
|
DEREF_JMP(ASMP2PRequestHandler_jmpback)
|
||||||
|
|
||||||
|
|
||||||
"1: \n" //block
|
"1: \n" //block
|
||||||
POP_ALL
|
POP_ALL
|
||||||
"jmp [ASMP2PRequestHandler_block] \n"
|
DEREF_JMP(ASMP2PRequestHandler_block)
|
||||||
|
|
||||||
"2: \n" //allow
|
"2: \n" //allow
|
||||||
POP_ALL
|
POP_ALL
|
||||||
"jmp [ASMP2PRequestHandler_allow] \n"
|
DEREF_JMP(ASMP2PRequestHandler_allow)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
void SetupP2PRequestHandler() {
|
void SetupP2PRequestHandler() {
|
||||||
WriteFarJMP(base+0x9F6DF, (void*)&ASMP2PRequestHandler);
|
WriteFarJMP(Offset(base, 0x9F6DF), (void*)&ASMP2PRequestHandler);
|
||||||
ASMP2PRequestHandler_jmpback = (void*)base+0x9F6ED;
|
ASMP2PRequestHandler_jmpback = Offset(base, 0x9F6ED);
|
||||||
ASMP2PRequestHandler_block = (void*)base+0x9F7A6;
|
ASMP2PRequestHandler_block = Offset(base, 0x9F7A6);
|
||||||
ASMP2PRequestHandler_allow = (void*)base+0x9F783;
|
ASMP2PRequestHandler_allow = Offset(base, 0x9F783);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,11 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
void* base; // Module base
|
global void* base; // Module base
|
||||||
vector <DLL*> modDLLs; // Every mod we've loaded
|
global vector <DLL*> modDLLs; // Every mod we've loaded
|
||||||
HMODULE hSelf; // A handle to ourself, to prevent being unloaded
|
global 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
|
global 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
|
GETTER_VAR(void*, initterm_e); // A pointer to that function
|
||||||
|
|
||||||
#include "callbacks/ChatHandler.h"
|
#include "callbacks/ChatHandler.h"
|
||||||
#include "callbacks/P2PRequestHandler.h"
|
#include "callbacks/P2PRequestHandler.h"
|
||||||
|
@ -38,7 +38,7 @@ void SetupHandlers() {
|
||||||
// Handles injecting callbacks and the mods
|
// Handles injecting callbacks and the mods
|
||||||
bool already_loaded_mods = false;
|
bool already_loaded_mods = false;
|
||||||
mutex already_loaded_mods_mtx;
|
mutex already_loaded_mods_mtx;
|
||||||
void StartMods() {
|
extern "C" void StartMods() {
|
||||||
char msg[256] = {0};
|
char msg[256] = {0};
|
||||||
|
|
||||||
already_loaded_mods_mtx.lock();
|
already_loaded_mods_mtx.lock();
|
||||||
|
@ -110,34 +110,33 @@ void StartMods() {
|
||||||
if (hSelf) PrintLoadedMods();
|
if (hSelf) PrintLoadedMods();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void* StartMods_ptr = (void*)&StartMods;
|
|
||||||
|
|
||||||
|
|
||||||
|
void ASMStartMods() {
|
||||||
void no_optimize ASMStartMods() {
|
asm(".intel_syntax \n"
|
||||||
asm(PUSH_ALL
|
PUSH_ALL
|
||||||
PREPARE_STACK
|
PREPARE_STACK
|
||||||
|
|
||||||
// Initialize mods and callbacks
|
// Initialize mods and callbacks
|
||||||
"call [StartMods_ptr] \n"
|
"call StartMods \n"
|
||||||
|
|
||||||
RESTORE_STACK
|
RESTORE_STACK
|
||||||
POP_ALL
|
POP_ALL
|
||||||
|
|
||||||
// Run initterm_e properly this time.
|
// Run initterm_e properly this time.
|
||||||
"jmp [initterm_e] \n"
|
DEREF_JMP(initterm_e)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PatchFreeImage(){
|
void PatchFreeImage(){
|
||||||
// Patch FreeImage, because Windows 8 and higher do not work properly with it.
|
// Patch FreeImage, because Windows 8 and higher do not work properly with it.
|
||||||
DWORD oldProtect;
|
DWORD oldProtect;
|
||||||
void* patchaddr = (void*)GetModuleHandleA("FreeImage.dll") + 0x1E8C4E;
|
void* patchaddr = Offset(GetModuleHandleA("FreeImage.dll"), 0x1E8C4E);
|
||||||
VirtualProtect((LPVOID)patchaddr, 9, PAGE_EXECUTE_READWRITE, &oldProtect);
|
VirtualProtect((LPVOID)patchaddr, 9, PAGE_EXECUTE_READWRITE, &oldProtect);
|
||||||
memset(patchaddr, 0x90, 9);
|
memset(patchaddr, 0x90, 9);
|
||||||
VirtualProtect((LPVOID)patchaddr, 9, oldProtect, &oldProtect);
|
VirtualProtect((LPVOID)patchaddr, 9, oldProtect, &oldProtect);
|
||||||
|
|
||||||
patchaddr += 0x14;
|
patchaddr = Offset(patchaddr, 0x14);
|
||||||
VirtualProtect((LPVOID)patchaddr, 14, PAGE_EXECUTE_READWRITE, &oldProtect);
|
VirtualProtect((LPVOID)patchaddr, 14, PAGE_EXECUTE_READWRITE, &oldProtect);
|
||||||
memset(patchaddr, 0x90, 14);
|
memset(patchaddr, 0x90, 14);
|
||||||
VirtualProtect((LPVOID)patchaddr, 14, oldProtect, &oldProtect);
|
VirtualProtect((LPVOID)patchaddr, 14, oldProtect, &oldProtect);
|
||||||
|
@ -145,7 +144,7 @@ void PatchFreeImage(){
|
||||||
|
|
||||||
void PatchInitterm_ePtr() {
|
void PatchInitterm_ePtr() {
|
||||||
// Get ** to initterm_e
|
// Get ** to initterm_e
|
||||||
initterm_eReference = (void**)(base + 0x42CBD8);
|
initterm_eReference = (void**)(Offset(base, 0x42CBD8));
|
||||||
|
|
||||||
initterm_e = *initterm_eReference;
|
initterm_e = *initterm_eReference;
|
||||||
|
|
||||||
|
@ -184,6 +183,10 @@ void WriteFarJMP(void* source, void* destination) {
|
||||||
VirtualProtect(location, 14, dwOldProtection, &dwOldProtection);
|
VirtualProtect(location, 14, dwOldProtection, &dwOldProtection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* Offset(void* x1, uint64_t x2) {
|
||||||
|
return (void*)((char*)x1 + x2);
|
||||||
|
}
|
||||||
|
|
||||||
bool already_initialized = false;
|
bool already_initialized = false;
|
||||||
mutex already_initialized_mtx;
|
mutex already_initialized_mtx;
|
||||||
extern "C" __declspec(dllexport) BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
|
extern "C" __declspec(dllexport) BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
|
||||||
|
|
|
@ -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 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 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);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue