Okay, so I'm working on reading WoW's memory. Answering the following questions is kind of involved but if someone would explain the process of just how you look in memory for that first object pointer (for example) it would greatly help a number of people get in to this kind of thing (so that were not constantly relying on the work of others).
I'm very noobish to it all so you can basically assume I know nothing about it. Anyway, I've been looking off of the wow memory reading framework (made by.. hypnodok?) and trying to replicate it myself to learn what the heck is going on. So I rewrote the majority of it before realizing that I didn't know what I was doing, I'm hoping someone can help me figure out what is going on with the main reading (or.. pointer.. finding?) function:
Code:
public void GetBaseOffset()
{
Program.Log("GetBaseOffset()");
IntPtr threadHandle, TEBHandle;
ThreadEntry32 threadStruct = Kernel32.CreateThreadEntry32();
ThreadBasicInformation threadbasicinfo = new ThreadBasicInformation();
UInt32 TLSSlotNumer = Kernel32.ReadUInt32(WowProcessHandle, TLSIndex,true);// gets the number of the tls-slot (usually 0) - 0 means the first tls entry points to the struct
IntPtr threadSnapshotHandle = Kernel32.CreateToolhelp32Snapshot(Kernel32.SnapshotFlags.Thread, 0); // makes a snapshot of all !! open threads#
Kernel32.Thread32First(threadSnapshotHandle, ref threadStruct);//now contains information about the first ! thread
do
{
if (threadStruct.the32OwnerProcessID == processID)//thread belongs to wow
{
threadHandle = Kernel32.OpenThread(Kernel32.ThreadAccess.QUERY_INFORMATION, false, threadStruct.th32ThreadID);//open the thread
UInt32 threadQueryResult = ntdlll.NtQueryInformationThread(threadHandle , 0, ref threadbasicinfo, (uint)Marshal.SizeOf(threadbasicinfo), IntPtr.Zero);//check for the operation's result
if (threadQueryResult == 0)//STATUS_SUCCESS
{
TEBHandle = threadbasicinfo.TebBaseAdress;// Thread Environment Block
UInt32 TLSOffset = Kernel32.ReadUInt32(WowProcessHandle, (IntPtr)((UInt32)TEBHandle + 0x2c),true);//gets the TLS_OFFSET from (teb + offset 2C)
if (TLSOffset != 0)
{
IntPtr TLSSlot = (IntPtr)Kernel32.ReadInt32(WowProcessHandle, (IntPtr)(TLSOffset + TLSSlotNumer * 4), true); // gets the tls-slot - multiplied by 4 bcaseu each tls_slot is 4 bytes long
IntPtr WowObjectPointer = (IntPtr)Kernel32.ReadInt32(WowProcessHandle, (IntPtr)((Int32)TLSSlot + 8), true); //add 8 to get the wow object pointer (this is int, not hex !)
Program.Log("Wowobject Pointer: " + WowObjectPointer);
if (WowObjectPointer != IntPtr.Zero)//discard nullpointers
{
WowFirstObjectPointer = (IntPtr)Kernel32.ReadInt32(WowProcessHandle, (IntPtr)((Int32)WowObjectPointer + 0xC), true);
Program.Log("First Object Pointer: " + WowFirstObjectPointer);
WowPlayerGUID = Kernel32.ReadUInt64(WowProcessHandle, (IntPtr)((Int32)TLSSlot + 16), true);
Program.Log("Player GUID: " + WowPlayerGUID);
WowFirstUnitPointer = GetFirstUnitPointer();
WowPlayerPointer = GetPlayerPointer();
if (!Kernel32.CloseHandle(threadHandle))
Program.Log("Failed to close thread handle. " + threadHandle);
if (!Kernel32.CloseHandle(threadSnapshotHandle))
Program.Log("Failed to close thread snapshop handle. " + threadSnapshotHandle);
}
}
else
Program.Log("TLS Offset was null");
}
}
}
while (Kernel32.Thread32Next(threadSnapshotHandle, out threadStruct) == true);
Program.Log("GetBaseOffset() done");
}
So this is just what I think is going on:
1. Get the number of the TLS slot (what does this slot tell us) and take a "Snapshot" to identify all of WoW's threads.
2. Loop through and open each thread and get... more specific information on each thread?
3. Find the Thread Environment Block base address (what the heck is this I couldnt find anything about it from msdn or google?)
4. Find the TLS offset from TEB+offset 2C? (Wheres this come from) Add some variables together and you get ur first wow object pointer, woo hoo.
Other questions...
1. Are the objects spread out among different threads or are you just looking for the thread that has the pointer to the objects?
2. The author gives this example to find the TLS-Pointer based off debugging WoW:
Code:
00774C40 A1 84AAE800 MOV EAX,DWORD PTR DS:[E8AA84] // always 0
00774C45 64:8B0D 2C000000 MOV ECX,DWORD PTR FS:[2C] // TLS-Pointer
00774C4C 8B1481 MOV EDX,DWORD PTR DS:[ECX+EAX*4]
00774C4F 8B82 10000000 MOV EAX,DWORD PTR DS:[EDX+10] // TLS-Pointer + 0x10
00774C55 C3 RETN
which one of those numbers is the TLS pointer?