This is not finished, but a work in progress. Maybe it will give you some ideas. Or maybe you can help :)
I don't know very much about the ObjectManager / CurMgr, w/e, (the linked list of dynamic objects in the game), so this is how I tried to learn more. Most people use a static pointer to find the bjectManager then a couple of offsets/pointers it hasto find the first object..but I don't know how to that :| So I went with something I did know..my .Health :D
Entire Process
Try to get the memory address for the LocalPlayer.BaseAddress (ie. to read your own health, position etc)
How: There is code in wow.exe that writes to the health address (duh. to update your health when uget hit etc)
This code uses LocalPlayer.BaseAddress + HealthOffset = some value , and LocalPlayer.BaseAddress is
stored in a register! So, the plan is, make a codecave in wow.exe, then write a "jmp" command to where
wow.exe updates our health..and our code-cave will copy the register to some pre-known location where
we can read it from our bot.exe as soon as the codecave gets run (1/10 of a second).
Step 1. Open Cheat Engine
Step 2. Find LocalPlayer.Health Address - There are 2 actually, it should only take 1-2 "Decreased value" scans to find it. them*.
Step 3. I chose the first one. Right click on it and select "Find out what accesses this address"
This will tell us the parts of code in wow.exe that read our health
The first result I get is 0x5B534B who's asm code is mov eax, [ecx+000011CC]
I checked eax..it's my health value. so on a hunch ecx = .BaseAddress and 11CC = health offset
I repeated the process with an enemy npc..scanned for it's health, attacked, scanned again
Checked what "accessed that address*" and it was the same line that did mine! 0x5b534b !
So now I'm pretty sure it's some loop updating all Unit's health and ecx = unit.base and 11cc = health_offset
Step 4. Use a codecave and detour wow.exe at 0x5B534B (which I made a FindPattern() for btw ;) , copy register ecx,
clean-up wow.exe (put original code back at 0x5b534b instead of our JMP {codecave} code), and return back to wow.exe
at 0x5b534b for normal execution <--all of this is critical, or stack gets corrupt and wow crashes.
I'm using OpenProcess() and VirtualAllocEx() to get some free ram inside wow.exe to store to code cave
I'm using WriteProcessMemory() from inside my bot.exe to write the "jmp {codecave}" into wow.exe @ 0x5b534b
I'm using a .dll i found here at ownedcore.com called fasmdll_managed.dll to convert asm instructions to byte code. Credits due.
I write the jmp asm code myself. (why? fasm kept giving me errors..and good exercise? in case i want to make my own/part of assembler)
Pseudocode {
wowCodeLoc = FindPattern("..byte_pattern..") = 5b534b
codeCaveLocation = VirtualAlloc(wowHandle,0,200,COMMIT,EXECUTE_READWRITE)
registerRtnValueLoc = codeCaveLocation + 100 'will store value of register, ecx, so we can read it from our .exe using ReadProcessMemory()
originalAsmLoc = codeCaveLocation + 180 'original wow.exe asm
jmpCommand = 'E9' + relative offset from wow.5b534b to CodeCaveLoc + codeCaveCode.LengthInBytes, in reverse order
(example: codeCaveLoc = 0x88123456 so reversed bytes would be 56 34 12 88
so jump command = E9,56,34,12,88 , but it has to be relative (this is how jmp works?) so you subtract CodeCaveLoc and 0x5b534b
0x88123456 - 0x5b534b - codeCave.LengthInBytes = some number. reverse bytes and put 'E9' in front of it and it's a jmp instruction
back into wow.exe so it can continue normal execution.
CopyOrigAsmToCodeCave()
WriteAsmToCodeCave (
mov registerRtnValueLoc , ecx
mov wowCodeLoc, [originalAsmLoc] 'restore 0x5b534b, 4 bytes
mov wowCodeLoc + 4, [originalAsmLoc +4] 'restore 0x5b534b + 4, 4 bytes
jmp 0x5B534B
)
VirtualProtectEx(wow,0x5B534B, 8) ' make sure the memory isn't read only! needs to be execute_read_write
WriteProcessMemory(wow,registerRtnValueLoc, 12345678) ' so we can check for this and know if wow.exe wrote to it yet
JmpCommand2 = "jmp" + to codecave == "jmp" + codecave-currentAddress == "jmp codeCaveLoc-0x5b534b" // to jump to code-cave
WriteProcessMemory(wow,0x5B534B, jmpCommand2)
Do Until ReadProcessMemory(wow,registerRtnvalue) <> 12345678
application.doEvents
//todo: If _timeLapse.Seconds > 10 Return Fail. Hasn't happened yet..wow always crashes.
Loop
Dim rtnPointer as Intptr = ReadProcessMemory(registerRtnValueLoc)
LocalPlayer.baseAddress = rtnPointer
}
---------------------------------------so in my code it would look something like
IntPtr targetLoc = FindPattern("LP_Health")
LocalPlayer.baseAddress = CodeCave().CopyRegister(targetLoc,"ecx")
once i get this working I'll try to learn more about the curMgr and unit structure.
If people want, I can do a step by step, w/ screenshots. or someone should tell me if I'm headed down the wrong road. Thanks.