Last active
September 24, 2022 17:26
-
-
Save kvanbere/5350146 to your computer and use it in GitHub Desktop.
Semi-Generic CRC Bypass for MapleStory
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Semi-Generic CRC Bypass for MapleStory | |
Other uncredited authors for ideas/methods/concepts etc. | |
*/ | |
#include <Windows.h> | |
static LPVOID lpvImgStart, lpvImgEnd, lpvMemBackup; | |
static const LPVOID lpvCrc1 = reinterpret_cast<const LPVOID>(0x00D11BF4); // CRC 1 & 2 are codecaves | |
static const LPVOID lpvCrc2 = reinterpret_cast<const LPVOID>(0x013EFF13); | |
static const LPVOID lpvCrc2Ret = reinterpret_cast<LPBYTE>(lpvCrc2) + 5; | |
static const LPVOID lpvCrc3 = reinterpret_cast<const LPVOID>(0x01300565); // CRC3 is easier hooked w/ a jump redirection | |
static const LPVOID lpvCrc3Ret = reinterpret_cast<const LPVOID>(0x012F6A6F); | |
static const LPVOID lpvCrc1Start = reinterpret_cast<LPBYTE>(lpvCrc1) - 3 - 1; // 3 bytes incase of DWORD-tesselating landing, 1 extra because of jl | |
static const LPVOID lpvCrc1End = reinterpret_cast<const LPBYTE>(lpvCrc1) + 5 + 1; // size of overwritten instructions, 1 extra because of jg | |
static const LPVOID lpvCrc2Start = reinterpret_cast<LPBYTE>(lpvCrc2) - 3 - 1; | |
static const LPVOID lpvCrc2End = reinterpret_cast<const LPBYTE>(lpvCrc2) + 7 + 1; | |
// CRC1 scans the entire module code section | |
void __declspec(naked) Crc1 (void) | |
{ | |
__asm | |
{ | |
cmp ecx, [lpvImgStart] | |
jl l_original | |
cmp ecx, [lpvImgEnd] | |
jg l_original | |
sub ecx, lpvImgStart | |
add ecx, lpvMemBackup | |
l_original: | |
// Original code start | |
mov dl, [ecx] | |
add dl, 1 | |
// Original code end | |
ret | |
} | |
} | |
// CRC2 scans the entire module code section | |
void __declspec(naked) Crc2 (void) | |
{ | |
__asm | |
{ | |
cmp ebx, [lpvImgStart] | |
jl l_original | |
cmp ebx, [lpvImgEnd] | |
jg l_original | |
sub ebx, lpvImgStart | |
add ebx, lpvMemBackup | |
l_original: | |
// Original code start | |
add al, [ebx] | |
pop ebx | |
push bx | |
mov bh, 0x41 | |
// Original code end | |
jmp lpvCrc2Ret | |
} | |
} | |
// CRC3 scans CRC1, CRC2 and many important but unvirtualized code sectors | |
void __declspec(naked) Crc3 (void) | |
{ | |
__asm | |
{ | |
cmp edx, lpvCrc1Start | |
jl l_nobypass | |
cmp edx, lpvCrc1End | |
jg l_nobypass | |
jmp l_bypass | |
l_nobypass: | |
cmp edx, lpvCrc2Start | |
jl l_ret | |
cmp edx, lpvCrc2End | |
jg l_ret | |
jmp l_bypass | |
l_bypass: | |
sub edx, lpvImgStart | |
add edx, lpvMemBackup | |
l_ret: | |
push [edx] | |
jmp lpvCrc3Ret | |
} | |
} | |
BOOL OnProcessAttach (HINSTANCE hinstDLL) | |
{ | |
HMODULE g_hMSInst = GetModuleHandle(NULL); | |
IMAGE_NT_HEADERS* nthBase = reinterpret_cast<IMAGE_NT_HEADERS*>(reinterpret_cast<PBYTE>(g_hMSInst) + PIMAGE_DOS_HEADER(g_hMSInst)->e_lfanew); | |
DWORD dwImageSize = nthBase->OptionalHeader.SizeOfImage; | |
lpvImgStart = reinterpret_cast<PBYTE>(g_hMSInst); | |
lpvImgEnd = reinterpret_cast<PBYTE>(lpvImgStart) + dwImageSize; | |
if (!(lpvMemBackup = malloc(dwImageSize))) | |
return FALSE; | |
CopyMemory(lpvMemBackup, lpvImgStart, dwImageSize); | |
auto WriteInlineJumpCall = [](bool bJump, LPVOID lpvAddress, LPVOID lpvDestination, size_t nNops) | |
{ | |
DWORD fOldProtect; | |
size_t nPatchSize = nNops + 5; | |
VirtualProtect(lpvAddress, nPatchSize, PAGE_EXECUTE_READWRITE, &fOldProtect); | |
FillMemory(lpvAddress, nPatchSize, 0x90); | |
*reinterpret_cast<LPBYTE>(lpvAddress) = (bJump ? 0xE9 : 0xE8); // E9 = long rel jmp, E8 = long rel call | |
*reinterpret_cast<PDWORD>(reinterpret_cast<LPBYTE>(lpvAddress) + 1) = reinterpret_cast<DWORD>(lpvDestination) - reinterpret_cast<DWORD>(lpvAddress) - 5; | |
VirtualProtect(lpvAddress, nPatchSize, fOldProtect, &fOldProtect); | |
}; | |
WriteInlineJumpCall(false, lpvCrc1, &Crc1, 0); | |
WriteInlineJumpCall(true, lpvCrc2, &Crc2, 2); | |
WriteInlineJumpCall(true, lpvCrc3, &Crc3, 2); | |
return TRUE; | |
} | |
BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) | |
{ | |
// For blocking application of patches: | |
// return (fdwReason == DLL_PROCESS_ATTACH ? OnProcessAttach(hinstDLL) : FALSE); | |
if (fdwReason == DLL_PROCESS_ATTACH) | |
{ | |
DisableThreadLibraryCalls(hinstDLL); | |
HANDLE hAttachThread; | |
if (!(hAttachThread = CreateThread(NULL, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(&OnProcessAttach), hinstDLL, NULL, NULL))) | |
return FALSE; | |
CloseHandle(hAttachThread); | |
return TRUE; | |
} | |
return FALSE; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How did you manage to attach a debugger to MS? I keep having trouble, even if I mask OllyDbg and use phantom + strong. Any tips?