OK, I downloaded the latest NA CShell and it works perfectly fine.
Lets do it step-by-step:
1. Running the sigscan will result in:
Code:
dwTmp = cMisc.FindPattern(dwCShellEntryPoint, dwCShellCodeSize, (PBYTE)"\x83\xC4\x0C\x88\x5E\x3F\xA1\x00\x00\x00\x00\x8B\x08\x8B\x51\x18", "xxxxxxx????xxxxx");
//dwTmp will result in 0x371CA1D0
2. Adding the offset to reach our wanted Virtual Function:
Code:
dwAdrTbl[24] = dwTmp + 0x70; //dwAdrTbl[24] will result in 0x371CA240 => [LEA EAX, 0xADDRESS]
dwJumpbackGetSfxMgr = dwAdrTbl[24] + 0x6; //dwJumpbackGetSfxMgr will result in 0x371CA246 => [RETN]
sfxMgrECXOffset = (DWORD)*(DWORD*)(dwAdrTbl[24] + 0x2); //sfxMgrECXOffset will result in 0x1EFA8 => Offset to EAX
3. Hooking the virtual to get ECX so we can add our already read offset to the base address:
Code:
ReadProcessMemory(GetCurrentProcess(), (void*)cMisc.dwAdrTbl[24], &origGetSFXMgrbytes, 6, 0); //Backup Original bytes e.g. memory
cMisc.CreateDetour((PBYTE)dwAdrTbl[24], (PBYTE)hkVGetSfxMgr, 6); //Hook the function
4. Reading ECX register value to get base address:
Code:
__declspec(naked) HRESULT WINAPI hkVGetSfxMgr()
{
__asm pushad; //Save register
__asm MOV cMisc.sfxMgrECXPointer, ECX //Copy ECX (our basepointer) in a variable so we can use it in the hack later
__asm popad; //Reload saved register
//__asm LEA EAX, DWORD PTR DS:[ECX + 0x24B28] //Do the actual code we had overwritten with our hook
//Notice: You can see that the offset is clearly old, but you also know that we saved it already so no need to re-update it all the time
//Seems like I forgot to change this, it would crash, use instead:
__asm LEA EAX, DWORD PTR DS:[ECX + cMisc.sfxMgrECXOffset] //Will work on every update now
__asm JMP dwJumpbackGetSfxMgr //Jump back to the RETN instruction of the virtual
}
5. Use these informations:
Now that we have all the informations lets use them!
Code:
if(!detouredGetSFXMgr && cMisc.sfxMgrECXPointer != NULL)
{
cMisc.memcpy_s((void*)cMisc.dwAdrTbl[24], (void*)cMisc.origGetSFXMgrbytes, 6); //Unpatch the hook (Unhook) so we cant be trapped by an HackShield
detouredGetSFXMgr = true;
}
pSFXMgr = (cSFXMgr*)(cMisc.sfxMgrECXPointer + cMisc.sfxMgrECXOffset);
This works for every virtual function, and you can easily catch the function also in class, without hooking:
Code:
for(int i = 0; i < 120; i++)
{
//We're gonna try 120 virtual functions and see if they are SFXMgr :)
//If yes, we're gonna call it and be happy
if(*(DWORD*)(pGameClientShell + 0x4 * i) == dwAdrTbl[24])
{
//This should be our virtual, just call it and get in return our lovely sfxMgr.
//IDK if this method works, try it if you have time and like experimenting
}
}
All in all, you can see 2 strings referring to our address:
Code:
SetServerVar End
CCBAGameClientShell
You will find the function manually from there
Have fun!