Code:
// ReadHealth.cpp
// This was cobbled together from the information in posts made by kosacid, gononono64 and zamba1587 from ownedcore.
// Sources:
// http://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-memory-editing/319172-guide-how-make-wow-bot-complete-newbs.html
// http://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-memory-editing/331072-guide-how-create-wow-bot-using-autoit-memory-reading.html
// http://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-memory-editing/369580-field-dumper.html
// http://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-memory-editing/336013-guides-starting-point-newbs.html
#include "stdafx.h"
#include <Windows.h>
#include <TlHelp32.h>
// Helper function to get the dynamic base address of a module given the PID and module name.
DWORD dwGetModuleBaseAddress(DWORD dwProcessIdentifier, const TCHAR *lpszModuleName)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessIdentifier);
DWORD dwModuleBaseAddress = 0;
if(hSnapshot != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 ModuleEntry32 = {0};
ModuleEntry32.dwSize = sizeof(MODULEENTRY32);
if(Module32First(hSnapshot, &ModuleEntry32))
{
do
{
if(_tcscmp(ModuleEntry32.szModule, lpszModuleName) == 0)
{
dwModuleBaseAddress = (DWORD)ModuleEntry32.modBaseAddr;
break;
}
}
while(Module32Next(hSnapshot, &ModuleEntry32));
}
CloseHandle(hSnapshot);
}
return dwModuleBaseAddress;
}
int _tmain(int argc, _TCHAR* argv[])
{
// Descriptor Structures
// Gratefully leached from: http://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-memory-editing/347720-wow-4-3-4-15595-info-dump-thread.html
enum eObjectFields
{
OBJECT_FIELD_GUID = 0x0,
OBJECT_FIELD_DATA = 0x2,
OBJECT_FIELD_TYPE = 0x4,
OBJECT_FIELD_ENTRY = 0x5,
OBJECT_FIELD_SCALE_X = 0x6,
OBJECT_FIELD_PADDING = 0x7,
OBJECT_END = 0x8
};
enum eUnitFields
{
UNIT_FIELD_CHARM = OBJECT_END + 0x0,
UNIT_FIELD_SUMMON = OBJECT_END + 0x2,
UNIT_FIELD_CRITTER = OBJECT_END + 0x4,
UNIT_FIELD_CHARMEDBY = OBJECT_END + 0x6,
UNIT_FIELD_SUMMONEDBY = OBJECT_END + 0x8,
UNIT_FIELD_CREATEDBY = OBJECT_END + 0xA,
UNIT_FIELD_TARGET = OBJECT_END + 0xC,
UNIT_FIELD_CHANNEL_OBJECT = OBJECT_END + 0xE,
UNIT_CHANNEL_SPELL = OBJECT_END + 0x10,
UNIT_FIELD_BYTES_0 = OBJECT_END + 0x11,
UNIT_FIELD_HEALTH = OBJECT_END + 0x12,
UNIT_FIELD_POWER1 = OBJECT_END + 0x13, // A.K.A. Mana
UNIT_FIELD_POWER2 = OBJECT_END + 0x14,
UNIT_FIELD_POWER3 = OBJECT_END + 0x15,
UNIT_FIELD_POWER4 = OBJECT_END + 0x16,
UNIT_FIELD_POWER5 = OBJECT_END + 0x17,
UNIT_FIELD_MAXHEALTH = OBJECT_END + 0x18,
UNIT_FIELD_MAXPOWER1 = OBJECT_END + 0x19,
UNIT_FIELD_MAXPOWER2 = OBJECT_END + 0x1A,
UNIT_FIELD_MAXPOWER3 = OBJECT_END + 0x1B,
UNIT_FIELD_MAXPOWER4 = OBJECT_END + 0x1C,
UNIT_FIELD_MAXPOWER5 = OBJECT_END + 0x1D,
UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER = OBJECT_END + 0x1E,
UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER = OBJECT_END + 0x23,
UNIT_FIELD_LEVEL = OBJECT_END + 0x28,
UNIT_FIELD_FACTIONTEMPLATE = OBJECT_END + 0x29,
UNIT_VIRTUAL_ITEM_SLOT_ID = OBJECT_END + 0x2A,
UNIT_FIELD_FLAGS = OBJECT_END + 0x2D,
UNIT_FIELD_FLAGS_2 = OBJECT_END + 0x2E,
UNIT_FIELD_AURASTATE = OBJECT_END + 0x2F,
UNIT_FIELD_BASEATTACKTIME = OBJECT_END + 0x30,
UNIT_FIELD_RANGEDATTACKTIME = OBJECT_END + 0x32,
UNIT_FIELD_BOUNDINGRADIUS = OBJECT_END + 0x33,
UNIT_FIELD_COMBATREACH = OBJECT_END + 0x34,
UNIT_FIELD_DISPLAYID = OBJECT_END + 0x35,
UNIT_FIELD_NATIVEDISPLAYID = OBJECT_END + 0x36,
UNIT_FIELD_MOUNTDISPLAYID = OBJECT_END + 0x37,
UNIT_FIELD_MINDAMAGE = OBJECT_END + 0x38,
UNIT_FIELD_MAXDAMAGE = OBJECT_END + 0x39,
UNIT_FIELD_MINOFFHANDDAMAGE = OBJECT_END + 0x3A,
UNIT_FIELD_MAXOFFHANDDAMAGE = OBJECT_END + 0x3B,
UNIT_FIELD_BYTES_1 = OBJECT_END + 0x3C,
UNIT_FIELD_PETNUMBER = OBJECT_END + 0x3D,
UNIT_FIELD_PET_NAME_TIMESTAMP = OBJECT_END + 0x3E,
UNIT_FIELD_PETEXPERIENCE = OBJECT_END + 0x3F,
UNIT_FIELD_PETNEXTLEVELEXP = OBJECT_END + 0x40,
UNIT_DYNAMIC_FLAGS = OBJECT_END + 0x41,
UNIT_MOD_CAST_SPEED = OBJECT_END + 0x42,
UNIT_MOD_CAST_HASTE = OBJECT_END + 0x43,
UNIT_CREATED_BY_SPELL = OBJECT_END + 0x44,
UNIT_NPC_FLAGS = OBJECT_END + 0x45,
UNIT_NPC_EMOTESTATE = OBJECT_END + 0x46,
UNIT_FIELD_STAT0 = OBJECT_END + 0x47,
UNIT_FIELD_STAT1 = OBJECT_END + 0x48,
UNIT_FIELD_STAT2 = OBJECT_END + 0x49,
UNIT_FIELD_STAT3 = OBJECT_END + 0x4A,
UNIT_FIELD_STAT4 = OBJECT_END + 0x4B,
UNIT_FIELD_POSSTAT0 = OBJECT_END + 0x4C,
UNIT_FIELD_POSSTAT1 = OBJECT_END + 0x4D,
UNIT_FIELD_POSSTAT2 = OBJECT_END + 0x4E,
UNIT_FIELD_POSSTAT3 = OBJECT_END + 0x4F,
UNIT_FIELD_POSSTAT4 = OBJECT_END + 0x50,
UNIT_FIELD_NEGSTAT0 = OBJECT_END + 0x51,
UNIT_FIELD_NEGSTAT1 = OBJECT_END + 0x52,
UNIT_FIELD_NEGSTAT2 = OBJECT_END + 0x53,
UNIT_FIELD_NEGSTAT3 = OBJECT_END + 0x54,
UNIT_FIELD_NEGSTAT4 = OBJECT_END + 0x55,
UNIT_FIELD_RESISTANCES = OBJECT_END + 0x56,
UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE = OBJECT_END + 0x5D,
UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE = OBJECT_END + 0x64,
UNIT_FIELD_BASE_MANA = OBJECT_END + 0x6B,
UNIT_FIELD_BASE_HEALTH = OBJECT_END + 0x6C,
UNIT_FIELD_BYTES_2 = OBJECT_END + 0x6D,
UNIT_FIELD_ATTACK_POWER = OBJECT_END + 0x6E,
UNIT_FIELD_ATTACK_POWER_MOD_POS = OBJECT_END + 0x6F,
UNIT_FIELD_ATTACK_POWER_MOD_NEG = OBJECT_END + 0x70,
UNIT_FIELD_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x71,
UNIT_FIELD_RANGED_ATTACK_POWER = OBJECT_END + 0x72,
UNIT_FIELD_RANGED_ATTACK_POWER_MOD_POS = OBJECT_END + 0x73,
UNIT_FIELD_RANGED_ATTACK_POWER_MOD_NEG = OBJECT_END + 0x74,
UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x75,
UNIT_FIELD_MINRANGEDDAMAGE = OBJECT_END + 0x76,
UNIT_FIELD_MAXRANGEDDAMAGE = OBJECT_END + 0x77,
UNIT_FIELD_POWER_COST_MODIFIER = OBJECT_END + 0x78,
UNIT_FIELD_POWER_COST_MULTIPLIER = OBJECT_END + 0x7F,
UNIT_FIELD_MAXHEALTHMODIFIER = OBJECT_END + 0x86,
UNIT_FIELD_HOVERHEIGHT = OBJECT_END + 0x87,
UNIT_FIELD_MAXITEMLEVEL = OBJECT_END + 0x88,
UNIT_FIELD_PADDING = OBJECT_END + 0x89,
UNIT_END = OBJECT_END + 0x8A
};
// Offsets
// Gratefully leached from: http://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-memory-editing/347720-wow-4-3-4-15595-info-dump-thread.html
const DWORD dwDescriptorOffset = 0xC; // From Vandra. Source: http://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-memory-editing/347720-wow-4-3-4-15595-info-dump-thread-4.html#post2248388
const DWORD CurMgrPointer = 0x9BE7E0;
const DWORD CurMgrOffset = 0x463C;
const DWORD NextObject = 0x3C;
const DWORD FirstObject = 0xC0;
const DWORD LocalGUID = 0xC8;
const DWORD dwObjectTypeOffset = 0x14; // This value and the one below were dug out of replies in the info dump threads and are also in the gononono64 and zamba1587 guides.
const DWORD dwObjectGuidOffset = 0x30;
// Variables
UINT64 playerGUID, uObjGUID;
DWORD dObjectManager, dReadObject, dObjType, dPlayerObject = 0;
DWORD dwPlayerHealth, dwPlayerMana, dwPlayerDescrip, dwPID = 0;
// Check to see if there is an instance running
HWND window = FindWindow(0, _T("World of Warcraft"));
if( window == 0 ){
printf("Window not found! There doesn't appear to be an instance of WoW running.\n");
return -1;
}
GetWindowThreadProcessId(window, &dwPID);
DWORD baseAddr = dwGetModuleBaseAddress(dwPID, _T("Wow.exe"));
HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ, FALSE, dwPID);
if (hProcess == NULL)
{
printf("OpenProcess failed with error code %d\n", GetLastError());
return -1;
}
printf("Attached to process ID: %d\n", dwPID);
// Locate the object manager
BOOL bRead = ReadProcessMemory(hProcess, reinterpret_cast <void *>(baseAddr + CurMgrPointer), &dObjectManager, 4, 0);
bRead = ReadProcessMemory(hProcess, reinterpret_cast <void *>(dObjectManager + CurMgrOffset), &dObjectManager, 4, 0);
printf("Address of object manager: %x\n", dObjectManager);
// Get the GUID of the player
// This is 64bit so we read 8 bytes
bRead = ReadProcessMemory(hProcess, reinterpret_cast <void *>(dObjectManager + LocalGUID), &playerGUID, 8, 0);
// Find the player object by GUID search
bRead = ReadProcessMemory(hProcess, reinterpret_cast <void *>(dObjectManager + FirstObject), &dReadObject, 4, 0);
bRead = ReadProcessMemory(hProcess, reinterpret_cast<void *>(dReadObject + dwObjectTypeOffset), &dObjType, 4, 0);
while ((dObjType > 0) && (dObjType < 8))
{
ReadProcessMemory(hProcess, reinterpret_cast<void *> (dReadObject + dwObjectGuidOffset), &uObjGUID, 8, 0);
if ( uObjGUID == playerGUID)
{
dPlayerObject = dReadObject;
printf("Player object found.\n");
}
bRead = ReadProcessMemory(hProcess, reinterpret_cast<void *>(dReadObject + NextObject), &dReadObject, 4, 0);
bRead = ReadProcessMemory(hProcess, reinterpret_cast<void *>(dReadObject + dwObjectTypeOffset), &dObjType, 4, 0);
}
if (dPlayerObject == 0)
{
printf("Player object not found.\n");
CloseHandle(hProcess);
return -1;
}
// Read the address for the descriptor belonging to the player object
bRead = ReadProcessMemory(hProcess, reinterpret_cast<void *>(dPlayerObject + dwDescriptorOffset), &dwPlayerDescrip, 4, 0);
printf("Reading health and mana. Press C to stop.\n");
while(1)
{
// Check for key press to abort
if(GetAsyncKeyState(0x43)) break;
// Read player health
bRead = ReadProcessMemory(hProcess, reinterpret_cast<void *>(dwPlayerDescrip + UNIT_FIELD_HEALTH*sizeof(DWORD)), &dwPlayerHealth, 4, 0);
// Read player mana
bRead = ReadProcessMemory(hProcess, reinterpret_cast<void *>(dwPlayerDescrip + UNIT_FIELD_POWER1*sizeof(DWORD)), &dwPlayerMana, 4, 0);
printf("Player Health: %d\n", dwPlayerHealth);
printf("Player Mana: %d\n", dwPlayerMana);
Sleep(1000);
}
CloseHandle(hProcess);
return 0;
}
This was written using Visual C++ Express with precompiled headers and unicode enabled.