-
Member
Object Manager Help!
Hello!
I used to use Glider alot when I was younger, and then HonorBuddy too after. I wrote profiles back in the day, but never got into the making-a-bot part of it. Now that my programming career has come a long way and that I have started playing classic again, my passion has been reignited! I would like to make a bot eventually, but I am still learning step by step.
So far I was able to find & read the player name, guid & target guid.
I was able to find these through CheatEngine and the build-44400 offsets posted on this forum (ty!). I can also retrieve them and marshal them correctly in the code.
Now, however, I would like to iterate through the object manager and say, collect every guid, or something like that. I have checked what feels like every post on this forum referencing "entities", "object manager", and many more, but I can't seem to get it working...
- Am I using offsets correctly? Shouldnt, say, the GUID of the first object in the object manager, be:
Code:
process.MainModule.BaseAddress + 0x2CFF7E8 + 0x1B8 + 0x58
Code:
process.MainModule.BaseAddress + ObjectManagerOffset + CurrentObjectOffset + GuidOffset
Code:
var process = Process.GetProcessesByName("WowClassic")[0];
var processHandle = OpenProcess(PROCESS_VM_READ, false, process.Id);
var wow_address = process.MainModule.BaseAddress;
var player_name = ReadNullTerminatedString(processHandle, wow_address + 0x2BFA7E8, 64);
var player_guid = ReadUInt64(processHandle, wow_address + 0x2BFA7D0);
var player_target_guid = ReadUInt64(processHandle, wow_address + 0x2DDA500);
var address_object_manager = wow_address + 0x2CFF7E8;
var address_object_manager_current_obj = address_object_manager + 0x1B8;
var address_object_manager_next_obj = address_object_manager_current_obj + 0x70;
while (address_object_manager_next_obj.ToInt64() % 2 == 0 && address_object_manager_next_obj != IntPtr.Zero)
{
var guid = ReadUInt64(processHandle, address_object_manager_next_obj + 0x58);
address_object_manager_next_obj += 0x70;
}
I am sure I am missing something trivial, but I can't seem to figure it out!
Ty in advance <3!
-
Active Member
You may not be subtracting 400000 from the base address.
many offsets that are published here suggest this
-
Member
Dont know how it implemented in Classic TBC, but seems it must be as:
var address_object_manager = StaticClientConnection+ 0x2CFF7E8 or wow_address + StaticClientConnection + 0x2CFF7E8
Try to find StaticClientConnection offset or as Hrap said, remove wow_address
-
Member
From this thread https://www.ownedcore.com/forums/wor...w-classic.html (Object Manager traversal (WoW classic))
objManagerAddress = this.basePointer.Read<int>(ObjManager);
Are you sure that you have correct ObjManager (0x2CFF7E
pointer?
-
Contributor
Last edited by ChrisIsMe; 11-01-2023 at 04:58 PM.
no war
-
Elite User
Avid Ailurophile


-
Post Thanks / Like - 1 Thanks
m3ht_t (1 members gave Thanks to Razzue for this useful post)
-
Member
First of all, thank you for taking the time guys! I don't post often in forums and would rather figure things out by myself, so it's nice to see you taking the time 
Alright so, my copy pasta was made AFTER I fiddled with the code and tried, amongst other things, other offsets. The offset I am using for the object manager is indeed the correct one: 0x2C65910.
@Razzue
I would like to traverse the object manager in the most basic way, with the least amount of dependencies. I just want to prove to myself it works first. That said, I am confused by your traversal:
Code:
var ptrArray = NT.ReadArray<IntPtr>(NT.Read<IntPtr>(managerBase + 0x8), maxCount);
Does that actually traverse the pointer chain? Or is there an array of pointer in the object manager structure? Was it not a linked-list?
My understanding was that, at address "process base address + object manager offset + first element offset", I would be getting a pointer pointing to the next element in the linked-list. Afterwards, the next element pointer would be accessed at address pointed to at offset 0x70. The traversal would end when that address' value was 0. The properties would be accessed by adding a property offset, such as GUID at 0x58, to the current element's address and marshalling what's at that address to the correct type, such as a uint128 for the GUID.
Last edited by painhippo; 07-12-2022 at 04:14 PM.
-
Elite User
Avid Ailurophile


Originally Posted by
painhippo
First of all,
thank you for taking the time guys! I don't post often in forums and would rather figure things out by myself, so it's nice to see you taking the time
Alright so, my copy pasta was made AFTER I fiddled with the code and tried, amongst other things, other offsets. The offset I am using for the object manager is indeed the correct one: 0x2C65910.
@
Razzue
I would like to traverse the object manager in the most basic way, with the least amount of dependencies. I just want to prove to myself it works first. That said, I am confused by your traversal:
Code:
var ptrArray = NT.ReadArray<IntPtr>(NT.Read<IntPtr>(managerBase + 0x8), maxCount);
Does that actually traverse the pointer chain? Or is there an array of pointer in the object manager structure? Was it not a linked-list?
My understanding was that, at address "process base address + object manager offset + first element offset", I would be getting a pointer pointing to the next element in the linked-list. Afterwards, the next element pointer would be accessed at address pointed to at offset 0x70. The traversal would end when that address' value was 0. The properties would be accessed by adding a property offset, such as GUID at 0x58, to the current element's address and marshalling what's at that address to the correct type, such as a uint128 for the GUID.
The "read array" is just a quicker way of doing
var ArrayPtr = NT.Read<IntPtr>(managerBase+ 0x
for (var i = 0; i < MaxCount; i ++)
{
var entryPtr= NT.Read<IntPtr>(managerBase+ (0x8 * i));
while(IntPtr.Zero != entryPtr)
entryPtr = NT.Read<IntPtr>(entryPtr + 0x0);
}
I strongly recommend looking at all this in cheatengine or reclass, as you'll see exactly how the object manager stores stuff. 
The "How to traverse object manager" thread is also outdated. Neither classic (TBC/SOM) use that method anymore.

"May all your bacon burn"

-
Member
Originally Posted by
Razzue
Why are you using the old object manager pointer when I post updated ones nearly every patch?
Also: Copy paste able (Well mostly, I use Nt memory calls and have started reading object manager/name caches as arrays first.)
Code:
var managerBase = NT.Read<IntPtr>(GameBase + 0x2CAD910);
lock (_lock)
{
var count = _objects.Count;
var curCount = NT.Read<int>(managerBase + 0x10);
var maxCount = NT.Read<int>(managerBase + 0x0);
var ptrArray = NT.ReadArray<IntPtr>(NT.Read<IntPtr>(managerBase + 0x8), maxCount);
for (var i = 0; i < maxCount; i++)
{
var ptr = ptrArray[i];
if (ptr == IntPtr.Zero) continue;
do
{
var entry = NT.Read<IntPtr>(ptr + 0x18);
if (entry == IntPtr.Zero) continue;
var guid = NT.Read<GUID>(entry + 0x18);
var type = NT.Read<byte>(entry + 0x10);
if ( type > 13 || guid.IsEmpty()) continue;
if (_objects.ContainsKey(guid))_objects[guid].Updated = true;
else _objects.Add(guid, new ObjectEntry(entry, guid));
ptr = NT.Read<IntPtr>(ptr + 0x0);
}while (IntPtr.Zero != ptr);
}
}
This code will infinite loop if any of the if's inside the do ... while is true or am I missing something ?
Also, have some offsets changed (appart from manager base ?). I'm infinite looping when trying this (even with the if's removed)
-
-
Member
Originally Posted by
Razzue
Did you update the offsets as the posted ones on this are for MONTHS ago?

Can confirm it still works just fine 🤷*♂️
I updated the manager base offset, have the other changed ?
I'm getting the max and current count right so that's fine but something is wrong with the iteration of entries.
I admit I didn't wanna dive into RE yet and just wanted a quick mess around the object list. I couldn't find info related to the layout or the offsets of entries in game objects.
-
-
Member
Originally Posted by
Razzue
So entity array is a linked list :
Array: (IntPtr)Manager base + 0x8;
Then you could do :
for(var I = 0; I < MaxCount; I++)
{
var firstPointer = (IntPtr)Array + (0x8 * I);
while(firstPointer != IntPtr.Zero)
{
var secondPointer = (IntPtr)firstPointer+ 0x18;
var guid = (GUID) secondPointer+ 0x18;
// 'Second Pointer' is the actual entity base address.
firstPointer= (IntPtr) firstPointer+ 0x0;
}
}
Sorry for formatting, on mobile :P
Thank you very much, working now. It makes way more sense to me explained this way, I think I got confused at first with your read array function on how the array worked.