Hey,
I've been trying to create a simple morpher for 4.3.4, but so far I am stuck at attempting to invoke a function. From what I've researched on this forum, in order to change the appearance of a equipped item slot I have to write to the memory location that holds the item ID of that given slot and then call a function called UpdateDisplayInfo. Currently I am able to sucessfully read and write to these locations, however when attempting to invoke the said update function, my game crashes, throwing a Access Violation error. The said function should be located at the 0x5D9BD0 offset, which I have decompiled by using IDA and found out this function is of the void type, is using a thiscall calling convention and requires two int parameters. From what I've gathered these parameters should be the location of the player base object and a bool parameter to force the update. I believe the bug is not in the way I am calling the function. I was wondering whether someone more experienced could help me with my issue. I am accessing the WoW process memory internally by injecting a DLL. Here are the relevant pieces of code:
Main:
Code:
DWORD WINAPI MainThread(HMODULE hModule)
{
uintptr_t baseAddr;
uintptr_t objMgrAddr;
uintptr_t playerBaseAddr;
uintptr_t playerDescriptor;
DWORD wowBuild;
DWORD playerGUID;
DWORD playerHealth;
DWORD playerItemChest;
typedef void(__thiscall * CGUnit_C__UpdateDisplayInfo)(int arg1, int arg2);
/* Allocate a console for debugging */
AllocConsole();
FILE *fDummy;
freopen_s(&fDummy, "CONIN$", "r", stdin);
freopen_s(&fDummy, "CONOUT$", "w", stderr);
freopen_s(&fDummy, "CONOUT$", "w", stdout);
while (1)
{
if (GetAsyncKeyState(VK_END) & 1)
break;
if (GetAsyncKeyState(VK_HOME) & 1) {
system("cls");
baseAddr = reinterpret_cast<uintptr_t>(GetModuleHandle(NULL));
std::cout << "Base add: " << std::hex << baseAddr << std::endl;
wowBuild = GetWoWBuild(baseAddr);
if (wowBuild != 15595) // 4.3.4 build number
{
std::cout << "This version of WoW is not supported. Terminating." << std::endl;
break;
}
objMgrAddr = FindObjMgrAddr(baseAddr);
std::cout << "Obj Mgr Addr: " << std::hex << objMgrAddr << std::endl;
if (objMgrAddr == 0)
{
std::cout << "Object Manager couldn't be located. Terminating." << std::endl;
break;
}
playerGUID = GetPlayerGUID(objMgrAddr);
std::cout << "Player GUID: " << playerGUID << std::endl;
playerBaseAddr = GetPlayerBaseAddr(objMgrAddr, playerGUID);
std::cout << "Player base add: " << std::hex << playerBaseAddr << std::endl;
playerDescriptor = playerBaseAddr + 0xC;
playerDescriptor = *(uintptr_t*)playerDescriptor;
std::cout << "Player descriptor: " << std::hex << playerDescriptor << std::endl;
playerHealth = *(DWORD*)(playerDescriptor + 0x20 + 0x12 * 4);
std::cout << "Player health: " << std::dec << playerHealth << std::endl;
playerItemChest = *(DWORD*)(playerDescriptor + 0x20 + 0x8A * 4 + 0x10D * 4);
std::cout << "Chest ID: " << std::dec << playerItemChest << std::endl;
try
{
CGUnit_C__UpdateDisplayInfo _udi = (CGUnit_C__UpdateDisplayInfo)(baseAddr + 0x5D9BD0);
_udi(playerBaseAddr, 1); // <- Access Violation error
}
catch (...)
{
}
}
std::cout << "Terminating..." << std::endl;
fclose(fDummy);
FreeConsole();
FreeLibraryAndExitThread(hModule, 0);
return 0;
}
GetPlayerBaseAddress:
Code:
uintptr_t GetPlayerBaseAddress(uintptr_t objMgrAddress, DWORD playerGUID)
{
uintptr_t objType;
uintptr_t objGUID;
uintptr_t playerBaseAddress = objMgrAddress;
playerBaseAddress += 0xC0;
objType = *(uintptr_t*)playerBaseAddress;
objType += 0x14;
objType = *(uintptr_t*)objType;
while (objType <= 7 && objType > 0)
{
playerBaseAddress = *(uintptr_t*)playerBaseAddress;
objGUID = playerBaseAddress + 0x30;
objGUID = *(uintptr_t*)objGUID;
if (objGUID == playerGUID)
{
std::cout << "Found GUID " << std::hex << objGUID << " at " << std::hex << playerBaseAddress << std::endl;
return playerBaseAddress;
}
playerBaseAddress += 0x3C;
objType = *(uintptr_t*)playerBaseAddress;
objType += 0x14;
objType = *(uintptr_t*)objType;
}
std::cout << "Didn't find our GUID !" << std::endl;
return 0;
}
Thanks in advance.