rendered paste body#include <Windows.h>#ifndef _DEBUG#define DLLNAME "CellAOLauncher.dll"#else#define DLLNAME "CellAOLauncher.dbg.dll"#endif#define FUNCOM_KEY_PUBLIC "9c32cc23d559ca90fc31be72df817d0e124769e809f936bc14360ff4bed758f260a0d596584eacbbc2b88bdd410416163e11dbf62173393fbc0c6fefb2d855f1a03dec8e9f105bbad91b3437d8eb73fe2f44159597aa4053cf788d2f9d7012fb8d7c4ce3876f7d6cd5d0c31754f4cd96166708641958de54a6def5657b9f2e92"#define FUNCOM_KEY_PRIME "eca2e8c85d863dcdc26a429a71a9815ad052f6139669dd659f98ae159d313d13c6bf2838e10a69b6478b64a24bd054ba8248e8fa778703b418408249440b2c1edd28853e240d8a7e49540b76d120d3b1ad2878b1b99490eb4a2a5e84caa8a91cecbdb1aa7c816e8be343246f80c637abc653b893fd91686cf8d32d6cfe5f2a6f"#define FUNCOM_KEY_GENERATOR "5"// The Private Key here is for reference purposes only#define CELLAO_KEY_PRIVATE "7ad852c6494f664e8df21446285ecd6f400cf20e1d872ee96136d7744887424b"#define CELLAO_KEY_PUBLIC "26b5a3b4ac1177f24a2d9de44bafef477ff23ef1cb5f646919b1be26516053030b65d5afb60cef6f49de539958ba0b7922a099319b8016a8673cb27a696ae4b60fdece25ddcdad42e7f0056b87fc35687fe033b242e17e960d79806fd46c4a79cbc64f558660a50cabc1c242dace70de6af452e3433f97e30e202567f187de70"// We keep the same prime and generator as funcom uses for simplicity sake. Although the launcher does support changing both#define CELLAO_KEY_PRIME "eca2e8c85d863dcdc26a429a71a9815ad052f6139669dd659f98ae159d313d13c6bf2838e10a69b6478b64a24bd054ba8248e8fa778703b418408249440b2c1edd28853e240d8a7e49540b76d120d3b1ad2878b1b99490eb4a2a5e84caa8a91cecbdb1aa7c816e8be343246f80c637abc653b893fd91686cf8d32d6cfe5f2a6f"#define CELLAO_KEY_GENERATOR "5"int match(unsigned char *memory, unsigned char *matchone, unsigned char *matchtwo, unsigned long max){ if (IsBadReadPtr(memory, max)) return 0; /* * Yes i know this is hackish, however since the strings are so long it is unlikely * that it will fail, and it is faster this way. Also the strings are checked later * a second time in findkeys() after this matches it. So there is no risk doing this. * -- NV */ while(max--) { if ((*memory != *matchone) && (*memory != *matchtwo)) return 0; matchone++; matchtwo++; memory++; } return 1;}unsigned long fixprotect(void *ptr, unsigned long size){ MEMORY_BASIC_INFORMATION mbi; VirtualQuery(ptr, &mbi, sizeof(mbi)); switch(mbi.Protect & 0xFF) { case PAGE_EXECUTE: case PAGE_EXECUTE_READ: case PAGE_EXECUTE_READWRITE: case PAGE_EXECUTE_WRITECOPY: mbi.Protect = PAGE_EXECUTE_READWRITE; break; case PAGE_NOACCESS: case PAGE_READONLY: case PAGE_READWRITE: case PAGE_WRITECOPY: mbi.Protect = PAGE_READWRITE; break; } VirtualProtect(ptr, size, mbi.Protect, &mbi.Protect); return mbi.Protect;}void findkeys(unsigned char *base, unsigned long size){ unsigned char *ptr; unsigned long remaining; unsigned long oldprotect; ptr = base; remaining = size; while (remaining >= min(sizeof(FUNCOM_KEY_PUBLIC), sizeof(FUNCOM_KEY_PRIME))) { if (match(ptr, FUNCOM_KEY_PUBLIC, FUNCOM_KEY_PRIME, min(sizeof(FUNCOM_KEY_PUBLIC), sizeof(FUNCOM_KEY_PRIME)))) { if (!memcmp(ptr, FUNCOM_KEY_PUBLIC, sizeof(FUNCOM_KEY_PUBLIC))) { oldprotect = fixprotect(ptr, sizeof(CELLAO_KEY_PUBLIC)); memcpy(ptr, CELLAO_KEY_PUBLIC, sizeof(CELLAO_KEY_PUBLIC)); VirtualProtect(ptr, sizeof(FUNCOM_KEY_PUBLIC), oldprotect, &oldprotect); ptr += sizeof(FUNCOM_KEY_PUBLIC) - 1; remaining -= sizeof(FUNCOM_KEY_PUBLIC) - 1; } else if (!memcmp(ptr, FUNCOM_KEY_PRIME, sizeof(FUNCOM_KEY_PRIME))) { oldprotect = fixprotect(ptr, sizeof(FUNCOM_KEY_PRIME)); memcpy(ptr, CELLAO_KEY_PRIME, sizeof(CELLAO_KEY_PRIME)); VirtualProtect(ptr, sizeof(FUNCOM_KEY_PRIME), oldprotect, &oldprotect); ptr += sizeof(FUNCOM_KEY_PRIME) - 1; remaining -= sizeof(FUNCOM_KEY_PRIME) - 1; } else { MessageBox(0, "Danger, Will Robinson.\nThis should not happen!", "CellAO Launcher", MB_ICONEXCLAMATION); ExitProcess(0); } } ptr++; remaining--; }}BOOL WINAPI execv_Hook(const char *cmdname, const char *const *argv){ STARTUPINFO si; PROCESS_INFORMATION pi; HANDLE hKernel; void *dllname; char *buffer; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); buffer = malloc(1024); strcpy_s(buffer, 1024, *argv++); while(*argv != NULL) { strcat_s(buffer, 1024, " "); strcat_s(buffer, 1024, *argv); argv++; } if (!CreateProcess(cmdname, buffer, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) { MessageBox(0, "Failed to load Client.exe!", "CellAO Launcher", MB_ICONEXCLAMATION); ExitProcess(1); } hKernel = GetModuleHandle("Kernel32.dll"); dllname = VirtualAllocEx(pi.hProcess, NULL, sizeof(DLLNAME), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(pi.hProcess, dllname, DLLNAME, sizeof(DLLNAME), NULL); if (CreateRemoteThread(pi.hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel, "LoadLibraryA"), dllname, 0, NULL) == NULL) { MessageBox(0, "Failed to create remote thread in Client.exe.\nPlease check Anti-Virus software/etc that could be preventing this", "CellAO Launcher", MB_ICONEXCLAMATION); } CloseHandle(hKernel); ResumeThread(pi.hThread); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); free(buffer); ExitProcess(0); return 0;}void InstallHook(){ void *hModule; PIMAGE_DOS_HEADER pDosHeader; PIMAGE_NT_HEADERS pNTHeaders; PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor; PIMAGE_THUNK_DATA pThunkData; void *origexecv; hModule = LoadLibrary("msvcr71.dll"); origexecv = GetProcAddress(hModule, "_execv"); pDosHeader = (void*)GetModuleHandle(NULL); if( IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER))) return; if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) return; pNTHeaders = (PIMAGE_NT_HEADERS)((unsigned long)pDosHeader + (unsigned long)pDosHeader->e_lfanew); if (IsBadReadPtr(pNTHeaders, sizeof(IMAGE_NT_HEADERS))) return; if (pNTHeaders->Signature != IMAGE_NT_SIGNATURE) return; pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((unsigned long)pDosHeader + (unsigned long)(pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)); if (pImportDescriptor == (PIMAGE_IMPORT_DESCRIPTOR)pNTHeaders) return; while(pImportDescriptor->Name) { if (!_stricmp((char*)pDosHeader + pImportDescriptor->Name, "msvcr71.dll")) { // Found msvcr71.dll Thunks pThunkData = (PIMAGE_THUNK_DATA)((unsigned long)pDosHeader + (unsigned long)pImportDescriptor->FirstThunk); while(pThunkData->u1.Function) { if((unsigned long)pThunkData->u1.Function == (unsigned long)origexecv) { unsigned long oldprotect; oldprotect = fixprotect(&pThunkData->u1.Function, 4); pThunkData->u1.Function = (unsigned long)execv_Hook; VirtualProtect(&pThunkData->u1.Function, 4, oldprotect, &oldprotect); break; } pThunkData++; } break; } pImportDescriptor++; }}BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD dwReason, PVOID lpReserved){ switch(dwReason) { case DLL_PROCESS_ATTACH: { SYSTEM_INFO si; MEMORY_BASIC_INFORMATION mbi; void *current; GetSystemInfo(&si); current = si.lpMinimumApplicationAddress; while (current < si.lpMaximumApplicationAddress) { VirtualQuery(current, &mbi, sizeof(mbi)); current = mbi.BaseAddress; if ((mbi.State & MEM_COMMIT) && (mbi.Type & MEM_IMAGE)) { findkeys(current, mbi.RegionSize); } current = (void*)((unsigned long)current + mbi.RegionSize); } InstallHook(); break; } case DLL_PROCESS_DETACH: break; } return TRUE;}