I'm am trying to get myself a another grinding bot working after a few years. I found that a couple of things have changed in WoW Classic, and I can't find good information on the recent client.
What I managed to do so far:
- dumped wow memory using scylla
- found object manager by searching for "Object manager list status" string with IDA
- by inspecting the code around "Object manager list status", I was able to iterate through "active objects" (as a string suggests)
Where I am stuck at:
- I am confused about how to properly iterate through objects, there seem to be different ways
- where to find the unit descriptor, object type, object guid, unit position, health etc.
- ida fails to completely understand the dumped binary, for example "UnitHealth" and nearly all other lua API procedures seemed to be messed up
Do you guuys have any recent information? I'll be sharing my information along the journey.
In IDA find the UnitHealth function, followd the first branch -> follow the second function -> follow the first function.
This function is a whole bunch of string compares ("targt", "player", "pet", ...), follow the branch with the "target" string compare, and you will find the target guid.
This is how I can count active objects. Seems to work (at least I get a reasonable number which changes when I walk around in the game), but I missing any offsets into the object, e.g. for guid or unit attributes. Any help?
Code:
Int64 objMgr = memoryReader.Read<Int64>(offsets.objectManager + imageOffset);
Int64 first = memoryReader.Read<Int64>(objMgr + 0x120);
Int64 current = first;
uint activeObjectCount = 0;
while (true)
{
current = memoryReader.Read<Int64>(current);
if (current == first) break;
activeObjectCount++;
}
I would also appreciate some tips on how to analyze the obfuscated code!
Did some memory scanning trying to find the target guid in one of the active objects, and I found two offsets that seem to return the
guid of an object. The two guids do not always match though, this might be due to some stale objects beeing in the list?
Code:
uint activeObjectCount = 0;
while (true)
{
current = memoryReader.Read<Int64>(current);
if (current == first) break;
activeObjectCount++;
var entry = memoryReader.Read<IntPtr>(current + 0xf8);
var guid0 = memoryReader.Read<Guid>(entry + 0x0);
var guid1 = memoryReader.Read<Guid>(current - 0x50);
System.Console.WriteLine("Guid 0: " + guid0 + (guid1.Equals(targetGuid) ? "<-" : ""));
System.Console.WriteLine("Guid 1: " + guid1 + (guid1.Equals(targetGuid) ? "<-" : ""));
}
It seems like your guid1 is what I used. This is how I grabbed it.
First aggregate the wowobjects.
Code:
var current = Marshal.ReadIntPtr(objMngr + (nint)Offsets.ObjectManager.FirstObject);
var first = current;
while (current != IntPtr.Zero)
{
list.Add(new WoWObject(current - 0x68));
current = Marshal.ReadIntPtr(current);
if (current == first)
{
break;
}
}
Then you will find the Guid at wowobject + 0x18. (128 bit)
For example "mov some_register, [rbp + some_value]". My understanding is, that IDA thinks that in example below, "+18h" is not a function parameter? Does anyone have an idea what's going on and how to fix this?
Nothings really changed in classics object manager, all the code I have posted for classic wow is 100% still valid and usable.
Also, why manually count active objects? Manager + 0x10 == active objects. Manager + 0x120 = enum vis objects offset, so you can just loop read 0x0 from there (subtract 0x68 from read pointer to get entity pointer)