Skip to content

Instantly share code, notes, and snippets.

@kvanbere
Last active September 24, 2022 17:26
Show Gist options
  • Save kvanbere/5350146 to your computer and use it in GitHub Desktop.
Save kvanbere/5350146 to your computer and use it in GitHub Desktop.
Semi-Generic CRC Bypass for MapleStory
/*
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;
}
@mach-kernel
Copy link

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment