| @@ -80,6 +80,8 @@ auto generateMicropatchArrayPattern = xorstr("48 89 5C 24 ?? 48 89 74 24 ?? 48 8 | |||||
| auto generateMicropatchArrayBackupPattern = xorstr("48 8D 54 24 ?? E8 ?? ?? ?? ?? 48 8D 55 60"); | auto generateMicropatchArrayBackupPattern = xorstr("48 8D 54 24 ?? E8 ?? ?? ?? ?? 48 8D 55 60"); | ||||
| auto getNewsItemsPattern = xorstr("48 89 ?? ?? ?? 48 89 ?? ?? ?? 48 89 ?? ?? ?? 48 89 ?? ?? ?? 55 41 ?? 41 ?? 41 ?? 41 ?? 48 8D ?? ?? ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? ?? 8D"); | auto getNewsItemsPattern = xorstr("48 89 ?? ?? ?? 48 89 ?? ?? ?? 48 89 ?? ?? ?? 48 89 ?? ?? ?? 55 41 ?? 41 ?? 41 ?? 41 ?? 48 8D ?? ?? ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? ?? 8D"); | ||||
| auto FGbxSparkModuleStartupModulePattern = xorstr("40 53 48 83 EC 50 48 8B D9 48 89 0D"); | auto FGbxSparkModuleStartupModulePattern = xorstr("40 53 48 83 EC 50 48 8B D9 48 89 0D"); | ||||
| auto onMicropatchesReceivedPattern = xorstr("48 89 5C 24 ?? 48 89 74 24 ?? 55 57 41 55 41 56 41 57 48 8D 6C 24 ?? 48 81 EC ?? ?? ?? ?? 48 63 51 08"); | |||||
| auto areMicropatchesDifferentPattern = xorstr("48 89 5C 24 ?? 55 56 57 48 83 EC 20 C7 02"); | |||||
| // + 0x33 | // + 0x33 | ||||
| auto parseJSONString = xorstr("40 55 53 56 57 48 8D 6C 24 ?? 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 45 10 48 8B D9"); | auto parseJSONString = xorstr("40 55 53 56 57 48 8D 6C 24 ?? 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 45 10 48 8B D9"); | ||||
| @@ -91,6 +93,8 @@ auto reallocPattern = xorstr("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B | |||||
| CRITICAL_SECTION critsec; | CRITICAL_SECTION critsec; | ||||
| static bool isInInternalMode = false; | |||||
| // | // | ||||
| //std::string startReceiveHotfixes_Pattern = xorstr("48 63 81 c4 00 00 00 83 f8 06 77 49 4c 8d 05"); | //std::string startReceiveHotfixes_Pattern = xorstr("48 63 81 c4 00 00 00 83 f8 06 77 49 4c 8d 05"); | ||||
| //// | //// | ||||
| @@ -644,6 +648,9 @@ tGenerateMicropatchArray oGenerateMicropatchArray = NULL; | |||||
| typedef void* (__fastcall* tParseJSONString)(void** jsonReader, const FString* text); | typedef void* (__fastcall* tParseJSONString)(void** jsonReader, const FString* text); | ||||
| tParseJSONString oParseJSONString = NULL; | tParseJSONString oParseJSONString = NULL; | ||||
| typedef bool(__fastcall* tAreMicropatchesDifferent)(TArray<FMicropatch>* micropatches, void* severity); | |||||
| tAreMicropatchesDifferent oAreMicropatchesDifferent = NULL; | |||||
| FSparkModule** pSparkModule = NULL; | FSparkModule** pSparkModule = NULL; | ||||
| @@ -720,6 +727,16 @@ void* hkParseJSONString(void** reader, FString* text) { | |||||
| } | } | ||||
| json j; | json j; | ||||
| char buffer[256] = { 0 }; | char buffer[256] = { 0 }; | ||||
| if (ModdedHotfixes == 0 && TotalHotfixes == 0) { | |||||
| delete ws; | |||||
| #ifdef _WIN32 | |||||
| WSACleanup(); | |||||
| #endif | |||||
| if (oParseJSONString) | |||||
| return oParseJSONString(reader, text); | |||||
| return NULL; | |||||
| } | |||||
| sprintf(buffer, "%I64u/%I64u", ModdedHotfixes, TotalHotfixes); | sprintf(buffer, "%I64u/%I64u", ModdedHotfixes, TotalHotfixes); | ||||
| j["eventName"] = "getNews"; | j["eventName"] = "getNews"; | ||||
| @@ -774,7 +791,7 @@ void* hkParseJSONString(void** reader, FString* text) { | |||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||
| WSACleanup(); | WSACleanup(); | ||||
| #endif | #endif | ||||
| std::cout << modified.ToString() << std::endl; | |||||
| //std::cout << modified.ToString() << std::endl; | |||||
| if (oParseJSONString) { | if (oParseJSONString) { | ||||
| void* result = oParseJSONString(reader, text); | void* result = oParseJSONString(reader, text); | ||||
| return result; | return result; | ||||
| @@ -997,17 +1014,17 @@ static Curl_Write_Data* currentCurlWriteData = NULL; | |||||
| size_t __stdcall hkWriteCallback(char* ptr, size_t size, size_t dataSize, void* userdata) { | size_t __stdcall hkWriteCallback(char* ptr, size_t size, size_t dataSize, void* userdata) { | ||||
| size_t writeSize = oWrite_Callback(ptr, size, dataSize, userdata); | size_t writeSize = oWrite_Callback(ptr, size, dataSize, userdata); | ||||
| currentCurlWriteData = (Curl_Write_Data*)userdata; | |||||
| std::string currentURL = currentCurlWriteData->RequestURL.ToString(); | |||||
| if (currentURL.find("verification") != std::string::npos && currentURL.find("discovery") != std::string::npos) { | |||||
| std::cout << "Need to get and alter response here" << std::endl; | |||||
| /*static std::string moddedHotfixes = getMicropatchString(); | |||||
| currentCurlWriteData->Body->Content.ResizeGrow(currentCurlWriteData->Body->Content.Count, moddedHotfixes.size(), 1); | |||||
| strcpy(currentCurlWriteData->Body->Content.Data, &moddedHotfixes.data()[0]); | |||||
| currentCurlWriteData->Body->Content.Max = moddedHotfixes.size(); | |||||
| currentCurlWriteData->Body->Content.Count = moddedHotfixes.size();*/ | |||||
| std::cout << "" << std::endl; | |||||
| } | |||||
| //currentCurlWriteData = (Curl_Write_Data*)userdata; | |||||
| //std::string currentURL = currentCurlWriteData->RequestURL.ToString(); | |||||
| //if (currentURL.find("verification") != std::string::npos && currentURL.find("discovery") != std::string::npos) { | |||||
| // std::cout << "Need to get and alter response here" << std::endl; | |||||
| // /*static std::string moddedHotfixes = getMicropatchString(); | |||||
| // currentCurlWriteData->Body->Content.ResizeGrow(currentCurlWriteData->Body->Content.Count, moddedHotfixes.size(), 1); | |||||
| // strcpy(currentCurlWriteData->Body->Content.Data, &moddedHotfixes.data()[0]); | |||||
| // currentCurlWriteData->Body->Content.Max = moddedHotfixes.size(); | |||||
| // currentCurlWriteData->Body->Content.Count = moddedHotfixes.size();*/ | |||||
| // std::cout << "" << std::endl; | |||||
| //} | |||||
| return writeSize; | return writeSize; | ||||
| } | } | ||||
| @@ -1038,56 +1055,61 @@ bool startLogging = false; | |||||
| DWORD __stdcall hkCurl_Easy_SetOpt(void* curlHandle, long option, void* parameter) | DWORD __stdcall hkCurl_Easy_SetOpt(void* curlHandle, long option, void* parameter) | ||||
| { | { | ||||
| DWORD result; | DWORD result; | ||||
| /*result = oCurl_Easy_SetOpt(curlHandle, option, parameter);*/ | |||||
| EnterCriticalSection(&critsec); | |||||
| result = oCurl_Easy_SetOpt(curlHandle, option, parameter); | |||||
| if (!isInInternalMode) { | |||||
| EnterCriticalSection(&critsec); | |||||
| result = oCurl_Easy_SetOpt(curlHandle, CURLOPT_PROXY, const_cast<char*>((proxyURLA + proxyPort).c_str())); | |||||
| if (result != CURLE_OK) { | |||||
| std::cout << "Failed to set proxy. Errorcode: " << result << std::endl; | |||||
| } | |||||
| result = oCurl_Easy_SetOpt(curlHandle, CURLOPT_PROXY, const_cast<char*>((proxyURLA + proxyPort).c_str())); | |||||
| if (result != CURLE_OK) { | |||||
| std::cout << "Failed to set proxy. Errorcode: " << result << std::endl; | |||||
| } | |||||
| result = oCurl_Easy_SetOpt(curlHandle, CURLOPT_ERRORBUFFER, errbuf); | |||||
| if (result != CURLE_OK) { | |||||
| std::cout << "Failed to set errorbuffer. Errorcode: " << result << std::endl; | |||||
| } | |||||
| result = oCurl_Easy_SetOpt(curlHandle, CURLOPT_ERRORBUFFER, errbuf); | |||||
| if (result != CURLE_OK) { | |||||
| std::cout << "Failed to set errorbuffer. Errorcode: " << result << std::endl; | |||||
| } | |||||
| if (option == CURLOPT_SSL_VERIFYHOST) { | |||||
| parameter = (void*)0L; | |||||
| result = oCurl_Easy_SetOpt(curlHandle, option, parameter); | |||||
| } | |||||
| else if (option == CURLOPT_SSL_VERIFYPEER) { | |||||
| parameter = (void*)0L; | |||||
| result = oCurl_Easy_SetOpt(curlHandle, option, parameter); | |||||
| } | |||||
| else if (option == CURLOPT_USE_SSL) { | |||||
| parameter = (void*)CURLUSESSL_TRY; | |||||
| result = oCurl_Easy_SetOpt(curlHandle, option, parameter); | |||||
| } | |||||
| else if (option == CURLOPT_WRITEFUNCTION) { | |||||
| std::cout << "Write data func at: 0x" << std::hex << parameter << std::endl; | |||||
| if (option == CURLOPT_SSL_VERIFYHOST) { | |||||
| parameter = (void*)0L; | |||||
| result = oCurl_Easy_SetOpt(curlHandle, option, parameter); | |||||
| } | |||||
| else if (option == CURLOPT_SSL_VERIFYPEER) { | |||||
| parameter = (void*)0L; | |||||
| result = oCurl_Easy_SetOpt(curlHandle, option, parameter); | |||||
| } | |||||
| else if (option == CURLOPT_USE_SSL) { | |||||
| parameter = (void*)CURLUSESSL_TRY; | |||||
| result = oCurl_Easy_SetOpt(curlHandle, option, parameter); | |||||
| } | |||||
| else if (option == CURLOPT_WRITEFUNCTION) { | |||||
| //std::cout << "Write data func at: 0x" << std::hex << parameter << std::endl; | |||||
| oWrite_Callback = (tWrite_Callback)parameter; | |||||
| parameter = &hkWriteCallback; | |||||
| hookedWriteCallback = true; | |||||
| result = oCurl_Easy_SetOpt(curlHandle, option, parameter); | |||||
| } | |||||
| else if (option == CURLOPT_READFUNCTION) { | |||||
| std::cout << "Read data func at: 0x" << std::hex << parameter << std::endl; | |||||
| result = oCurl_Easy_SetOpt(curlHandle, option, parameter); | |||||
| } | |||||
| else if (option == CURLOPT_CAINFO) { | |||||
| result = CURLE_OK; | |||||
| } | |||||
| else { | |||||
| result = oCurl_Easy_SetOpt(curlHandle, option, parameter); | |||||
| } | |||||
| oWrite_Callback = (tWrite_Callback)parameter; | |||||
| parameter = &hkWriteCallback; | |||||
| hookedWriteCallback = true; | |||||
| result = oCurl_Easy_SetOpt(curlHandle, option, parameter); | |||||
| } | |||||
| else if (option == CURLOPT_READFUNCTION) { | |||||
| //std::cout << "Read data func at: 0x" << std::hex << parameter << std::endl; | |||||
| result = oCurl_Easy_SetOpt(curlHandle, option, parameter); | |||||
| } | |||||
| else if (option == CURLOPT_CAINFO) { | |||||
| result = CURLE_OK; | |||||
| } | |||||
| else { | |||||
| result = oCurl_Easy_SetOpt(curlHandle, option, parameter); | |||||
| } | |||||
| LeaveCriticalSection(&critsec); | |||||
| LeaveCriticalSection(&critsec); | |||||
| } | |||||
| return result; | return result; | ||||
| } | } | ||||
| bool __fastcall hkAreMicropatchesDifferent(TArray<FMicropatch>* micropatches, void* severity) { | |||||
| return true; | |||||
| } | |||||
| void hkGenerateMicropatchArray(void* someTMap, TArray<FMicropatch>* outPatches) { | void hkGenerateMicropatchArray(void* someTMap, TArray<FMicropatch>* outPatches) { | ||||
| if (oGenerateMicropatchArray) { | if (oGenerateMicropatchArray) { | ||||
| oGenerateMicropatchArray(someTMap, outPatches); | oGenerateMicropatchArray(someTMap, outPatches); | ||||
| @@ -1195,9 +1217,9 @@ void hkGetNewsItems(void* newsWidget) { | |||||
| if (*pSparkModule) { | if (*pSparkModule) { | ||||
| if ((*pSparkModule)->SparkNewsService && (*pSparkModule)->SparkNewsService->NewsItems.Data != NULL) { | if ((*pSparkModule)->SparkNewsService && (*pSparkModule)->SparkNewsService->NewsItems.Data != NULL) { | ||||
| for (int i = 0; i < (*pSparkModule)->SparkNewsService->NewsItems.Count; ++i) { | |||||
| /*for (int i = 0; i < (*pSparkModule)->SparkNewsService->NewsItems.Count; ++i) { | |||||
| std::cout << (*pSparkModule)->SparkNewsService->NewsItems.Data[i].NewsText.ToString() << std::endl; | std::cout << (*pSparkModule)->SparkNewsService->NewsItems.Data[i].NewsText.ToString() << std::endl; | ||||
| } | |||||
| }*/ | |||||
| } | } | ||||
| } | } | ||||
| if (oGetNewsItems) { | if (oGetNewsItems) { | ||||
| @@ -1344,17 +1366,11 @@ DWORD WINAPI MainThread(LPVOID param) | |||||
| } | } | ||||
| std::cout << "Found 5/7 Patterns" << std::endl; | std::cout << "Found 5/7 Patterns" << std::endl; | ||||
| /*uintptr_t generateMicropatchArray = PatternScan::FindSignature(NULL, generateMicropatchArrayPattern.crypt_get()); | |||||
| while (generateMicropatchArray == NULL) { | |||||
| generateMicropatchArray = PatternScan::FindSignature(NULL, generateMicropatchArrayPattern.crypt_get()); | |||||
| Sleep(50); | |||||
| }*/ | |||||
| std::cout << "Found 6/7 Patterns" << std::endl; | |||||
| /*uintptr_t getNewsItems = PatternScan::FindSignature(NULL, getNewsItemsPattern.crypt_get()); | |||||
| while (getNewsItems == NULL) { | |||||
| getNewsItems = PatternScan::FindSignature(NULL, getNewsItemsPattern.crypt_get()); | |||||
| Sleep(50); | |||||
| }*/ | |||||
| uintptr_t areMicropatchesDifferentAddress = PatternScan::FindSignature(NULL, areMicropatchesDifferentPattern.crypt_get()); | |||||
| while (areMicropatchesDifferentAddress == NULL) { | |||||
| areMicropatchesDifferentAddress = PatternScan::FindSignature(NULL, areMicropatchesDifferentPattern.crypt_get()); | |||||
| Sleep(100); | |||||
| } | |||||
| uintptr_t sparkModuleAddress = PatternScan::FindSignature(NULL, FGbxSparkModuleStartupModulePattern.crypt_get()); | uintptr_t sparkModuleAddress = PatternScan::FindSignature(NULL, FGbxSparkModuleStartupModulePattern.crypt_get()); | ||||
| while (sparkModuleAddress == NULL) { | while (sparkModuleAddress == NULL) { | ||||
| @@ -1366,15 +1382,7 @@ DWORD WINAPI MainThread(LPVOID param) | |||||
| pSparkModule = reinterpret_cast<FSparkModule**>(sparkModuleAddress + sparkSingletonOffset + 7); | pSparkModule = reinterpret_cast<FSparkModule**>(sparkModuleAddress + sparkSingletonOffset + 7); | ||||
| /*uintptr_t parseJSONStringAddress = PatternScan::FindSignature(NULL, parseJSONString.crypt_get()); | |||||
| while (parseJSONStringAddress == NULL) { | |||||
| parseJSONStringAddress = PatternScan::FindSignature(NULL, parseJSONString.crypt_get()); | |||||
| Sleep(50); | |||||
| } | |||||
| parseJSONStringAddress += 0x33; | |||||
| int32_t parseJSONStringOffset = *(int32_t*)(parseJSONStringAddress + 1); | |||||
| parseJSONStringAddress = parseJSONStringAddress + parseJSONStringOffset + 5;*/ | |||||
| std::cout << "Found 7/7 Patterns" << std::endl; | std::cout << "Found 7/7 Patterns" << std::endl; | ||||
| /*uintptr_t fsparkmanagerctor = PatternScan::FindSignature(NULL, sparkManagerCtorPattern.c_str()); | /*uintptr_t fsparkmanagerctor = PatternScan::FindSignature(NULL, sparkManagerCtorPattern.c_str()); | ||||
| @@ -1415,14 +1423,10 @@ DWORD WINAPI MainThread(LPVOID param) | |||||
| Sleep(200); | Sleep(200); | ||||
| while (MH_CreateHookEx((LPVOID)curl_easy_getinfo, &hkCurl_Easy_GetInfo, &oCurl_Easy_GetInfo) != MH_OK) | while (MH_CreateHookEx((LPVOID)curl_easy_getinfo, &hkCurl_Easy_GetInfo, &oCurl_Easy_GetInfo) != MH_OK) | ||||
| Sleep(200); | Sleep(200); | ||||
| while (MH_CreateHookEx((LPVOID)areMicropatchesDifferentAddress, &hkAreMicropatchesDifferent, &oAreMicropatchesDifferent) != MH_OK) | |||||
| Sleep(200); | |||||
| std::cout << "Placed 5/7 hooks" << std::endl; | std::cout << "Placed 5/7 hooks" << std::endl; | ||||
| /*while (MH_CreateHookEx((LPVOID)generateMicropatchArray, &hkGenerateMicropatchArray, &oGenerateMicropatchArray) != MH_OK) | |||||
| Sleep(200);*/ | |||||
| std::cout << "Placed 6/7 hooks" << std::endl; | |||||
| /*while (MH_CreateHookEx((LPVOID)getNewsItems, &hkGetNewsItems, &oGetNewsItems) != MH_OK) | |||||
| Sleep(200); */ | |||||
| /*while (MH_CreateHookEx((LPVOID)parseJSONStringAddress, &hkParseJSONString, &oParseJSONString) != MH_OK) | |||||
| Sleep(200);*/ | |||||
| std::cout << "Placed 7/7 hooks" << std::endl; | std::cout << "Placed 7/7 hooks" << std::endl; | ||||
| while (MH_EnableHook(MH_ALL_HOOKS) != MH_OK) { | while (MH_EnableHook(MH_ALL_HOOKS) != MH_OK) { | ||||
| Sleep(200); | Sleep(200); | ||||
| @@ -1435,8 +1439,67 @@ DWORD WINAPI MainThread(LPVOID param) | |||||
| struct ArgStruct { | struct ArgStruct { | ||||
| const char dllPath[MAX_PATH]; | const char dllPath[MAX_PATH]; | ||||
| int portNumber; | int portNumber; | ||||
| bool boolValue; | |||||
| }; | }; | ||||
| // TODO: Send log messages on success/errors | |||||
| extern "C" __declspec(dllexport) DWORD __stdcall ToggleOperationalMode(ArgStruct* argStruct) | |||||
| { | |||||
| EnterCriticalSection(&critsec); | |||||
| static uintptr_t generateMicropatchArray; | |||||
| while (generateMicropatchArray == NULL) { | |||||
| generateMicropatchArray = PatternScan::FindSignature(NULL, generateMicropatchArrayPattern.crypt_get()); | |||||
| Sleep(50); | |||||
| } | |||||
| static uintptr_t getNewsItems; | |||||
| while (getNewsItems == NULL) { | |||||
| getNewsItems = PatternScan::FindSignature(NULL, getNewsItemsPattern.crypt_get()); | |||||
| Sleep(50); | |||||
| } | |||||
| static uintptr_t parseJSONStringAddress; | |||||
| while (parseJSONStringAddress == NULL) { | |||||
| parseJSONStringAddress = PatternScan::FindSignature(NULL, parseJSONString.crypt_get()); | |||||
| if (parseJSONStringAddress != NULL) { | |||||
| parseJSONStringAddress += 0x33; | |||||
| int32_t parseJSONStringOffset = *(int32_t*)(parseJSONStringAddress + 1); | |||||
| parseJSONStringAddress = parseJSONStringAddress + parseJSONStringOffset + 5; | |||||
| } | |||||
| Sleep(50); | |||||
| } | |||||
| // Hook or unhook | |||||
| if (argStruct->boolValue && !isInInternalMode) { | |||||
| MH_STATUS hookStatus = MH_CreateHookEx((LPVOID)generateMicropatchArray, &hkGenerateMicropatchArray, &oGenerateMicropatchArray); | |||||
| if (hookStatus == MH_ERROR_ALREADY_CREATED || hookStatus == MH_OK) { | |||||
| hookStatus = MH_EnableHook((LPVOID)generateMicropatchArray); | |||||
| } | |||||
| hookStatus = MH_CreateHookEx((LPVOID)getNewsItems, &hkGetNewsItems, &oGetNewsItems); | |||||
| if (hookStatus == MH_ERROR_ALREADY_CREATED || hookStatus == MH_OK) { | |||||
| hookStatus = MH_EnableHook((LPVOID)getNewsItems); | |||||
| } | |||||
| hookStatus = MH_CreateHookEx((LPVOID)parseJSONStringAddress, &hkParseJSONString, &oParseJSONString); | |||||
| if (hookStatus == MH_ERROR_ALREADY_CREATED || hookStatus == MH_OK) { | |||||
| hookStatus = MH_EnableHook((LPVOID)parseJSONStringAddress); | |||||
| } | |||||
| isInInternalMode = true; | |||||
| } | |||||
| else if (!argStruct->boolValue && isInInternalMode) { | |||||
| while (MH_DisableHook((LPVOID)generateMicropatchArray) != MH_OK) | |||||
| Sleep(200); | |||||
| while (MH_DisableHook((LPVOID)getNewsItems) != MH_OK) | |||||
| Sleep(200); | |||||
| while (MH_DisableHook((LPVOID)parseJSONStringAddress) != MH_OK) | |||||
| Sleep(200); | |||||
| while (MH_ApplyQueued() != MH_OK) | |||||
| Sleep(200); | |||||
| isInInternalMode = false; | |||||
| } | |||||
| LeaveCriticalSection(&critsec); | |||||
| return TRUE; | |||||
| } | |||||
| extern "C" __declspec(dllexport) DWORD __stdcall InitFunc(ArgStruct * argstruct) | extern "C" __declspec(dllexport) DWORD __stdcall InitFunc(ArgStruct * argstruct) | ||||
| { | { | ||||
| EnterCriticalSection(&critsec); | EnterCriticalSection(&critsec); | ||||