In my experience with wow, Memory Scanning to find offsets, etc is only limited in usefulness. To get the real understanding of wow, one needs to do some actual reverse engineering.
I'll walk you guys through how to get the ID of the current player. The function in wow is called ClntObjMgrGetActivePlayer.
Since wow uses Lua, it makes things worlds easier to find functions. In this case I will use GetPlayerMapPosition simply because it was the first function that came up in IDA strings window =). Double clicking on the string gives is this:
Code:
.rdata:00887220 aGetplayermappo db 'GetPlayerMapPosition',0 ; DATA XREF: .data:00B76FA0o
Following the refence gives us:
Code:
.data:00B76FA0 dd offset aGetplayermappo ; "GetPlayerMapPosition"
.data:00B76FA4 dd offset sub_4AFDD0
following sub_4AFDD0 we get
Code:
.text:004AFDD0 sub_4AFDD0 proc near ; DATA XREF: .data:00B76FA4o
.text:004AFDD0
.text:004AFDD0 var_1C = qword ptr -1Ch
.text:004AFDD0 var_10 = dword ptr -10h
.text:004AFDD0 var_C = dword ptr -0Ch
.text:004AFDD0 var_8 = dword ptr -8
.text:004AFDD0 var_4 = dword ptr -4
.text:004AFDD0 arg_0 = dword ptr 8
.text:004AFDD0
.text:004AFDD0 push ebp
.text:004AFDD1 mov ebp, esp
.text:004AFDD3 sub esp, 10h
.text:004AFDD6 push esi
.text:004AFDD7 mov esi, [ebp+arg_0]
.text:004AFDDA push 1
.text:004AFDDC push esi
.text:004AFDDD call sub_70E7B0
.text:004AFDE2 add esp, 8
.text:004AFDE5 test eax, eax
.text:004AFDE7 jnz short loc_4AFDFE
.text:004AFDE9 push offset aUsageGetplayer ; "Usage: GetPlayerMapPosition(\"player\")"
.text:004AFDEE push esi
.text:004AFDEF call sub_70FF00
.text:004AFDF4 add esp, 8
.text:004AFDF7 xor eax, eax
.text:004AFDF9 pop esi
.text:004AFDFA mov esp, ebp
.text:004AFDFC pop ebp
.text:004AFDFD retn
.text:004AFDFE ; ---------------------------------------------------------------------------
.text:004AFDFE
.text:004AFDFE loc_4AFDFE: ; CODE XREF: sub_4AFDD0+17j
.text:004AFDFE fldz
.text:004AFE00 push 0
.text:004AFE02 push 1
.text:004AFE04 fst [ebp+var_4]
.text:004AFE07 push esi
.text:004AFE08 fstp [ebp+var_8]
.text:004AFE0B call sub_70E930
.text:004AFE10 push eax ; Str1
.text:004AFE11 call sub_53C500
.text:004AFE16 add esp, 10h
.text:004AFE19 mov [ebp+var_10], eax
.text:004AFE1C mov [ebp+var_C], edx
.text:004AFE1F call ClntObjMgrGetActivePlayer
.text:004AFE24 cmp [ebp+var_10], eax
.text:004AFE27 jnz short loc_4AFE2E
.text:004AFE29 cmp [ebp+var_C], edx
.text:004AFE2C jz short loc_4AFE4E
.text:004AFE2E
.text:004AFE2E loc_4AFE2E: ; CODE XREF: sub_4AFDD0+57j
.text:004AFE2E lea eax, [ebp+var_10]
.text:004AFE31 push eax
.text:004AFE32 call sub_4B4F30
.text:004AFE37 add esp, 4
.text:004AFE3A test eax, eax
.text:004AFE3C jnz short loc_4AFE4E
.text:004AFE3E lea ecx, [ebp+var_10]
.text:004AFE41 push ecx
.text:004AFE42 call sub_4B6BF0
.text:004AFE47 add esp, 4
.text:004AFE4A test eax, eax
.text:004AFE4C jz short loc_4AFE66
.text:004AFE4E
.text:004AFE4E loc_4AFE4E: ; CODE XREF: sub_4AFDD0+5Cj
.text:004AFE4E ; sub_4AFDD0+6Cj
.text:004AFE4E mov ecx, [ebp+var_C]
.text:004AFE51 lea edx, [ebp+var_8]
.text:004AFE54 push edx
.text:004AFE55 mov edx, [ebp+var_10]
.text:004AFE58 lea eax, [ebp+var_4]
.text:004AFE5B push eax
.text:004AFE5C push ecx
.text:004AFE5D push edx
.text:004AFE5E call sub_4AEDC0
.text:004AFE63 add esp, 10h
.text:004AFE66
.text:004AFE66 loc_4AFE66: ; CODE XREF: sub_4AFDD0+7Cj
.text:004AFE66 fld [ebp+var_4]
.text:004AFE69 sub esp, 8
.text:004AFE6C fstp [esp+1Ch+var_1C]
.text:004AFE6F push esi ; int
.text:004AFE70 call sub_70EAE0
.text:004AFE75 fld [ebp+var_8]
.text:004AFE78 add esp, 4
.text:004AFE7B fstp [esp+1Ch+var_1C]
.text:004AFE7E push esi ; int
.text:004AFE7F call sub_70EAE0
.text:004AFE84 add esp, 0Ch
.text:004AFE87 mov eax, 2
.text:004AFE8C pop esi
.text:004AFE8D mov esp, ebp
.text:004AFE8F pop ebp
.text:004AFE90 retn
.text:004AFE90 sub_4AFDD0 endp
Now at this point we should know that somewhere in this function, it has to get a pointer to the player object, otherwise how else will it find the position of the player? So what we can do is follow the functions in this code to see what they look like. From experience I know that the sub_70xxxx functions are lua api calls. The first interesting function we see is this:
Code:
.text:0053C500 ; int __cdecl sub_53C500(char *Str1)
.text:0053C500 sub_53C500 proc near ; CODE XREF: sub_49CD80+22p
.text:0053C500 ; sub_49CE20+46p ...
.text:0053C500
.text:0053C500 var_8 = dword ptr -8
.text:0053C500 var_4 = dword ptr -4
.text:0053C500 Str1 = dword ptr 8
.text:0053C500
.text:0053C500 push ebp
.text:0053C501 mov ebp, esp
.text:0053C503 sub esp, 8
.text:0053C506 mov ecx, [ebp+Str1]
.text:0053C509 xor eax, eax
.text:0053C50B push eax ; char
.text:0053C50C mov [ebp+var_8], eax
.text:0053C50F mov [ebp+var_4], eax
.text:0053C512 lea eax, [ebp+var_8]
.text:0053C515 push eax ; int
.text:0053C516 push ecx ; Str1
.text:0053C517 call sub_53B620
.text:0053C51C mov eax, [ebp+var_8]
.text:0053C51F mov edx, [ebp+var_4]
.text:0053C522 add esp, 0Ch
.text:0053C525 mov esp, ebp
.text:0053C527 pop ebp
.text:0053C528 retn
.text:0053C528 sub_53C500 endp
Lets trace that call and we see a really interesting function which appears to take an 8 byte value by reference (determined after analysis).
That function has a bunch of strcmp calls that look something like this:
Code:
.text:0053B66A push 6 ; MaxCount
.text:0053B66C push offset aPlayer_0 ; "player"
.text:0053B671 push edi ; Str1
.text:0053B672 mov [ebp+var_58], edi
.text:0053B6A4 push 3 ; MaxCount
.text:0053B6A6 push offset aPet_1 ; "pet"
.text:0053B6AB push edi ; Str1
.text:0053B6AC call sub_63A480
.text:0053B6E9 push 6 ; MaxCount
.text:0053B6EB push offset aTarget ; "target"
.text:0053B6F0 push edi ; Str1
.text:0053B6F1 call sub_63A480
From this it appears that we want to follow the logic when "player" is passed to this function. Following the logic is a tough problem here, but eventually you will see a qword value placed on the stack and then used after the function call like so:
Code:
.text:0053C517 call sub_53B620
.text:0053C51C mov eax, [ebp+var_8]
.text:0053C51F mov edx, [ebp+var_4]
So in this case, it might be safe to say that somewhere, we've already see our target function!
Now lets return back to the 1st function, and lets look at this code:
Code:
.text:004AFE11 call sub_53C500
.text:004AFE16 add esp, 10h
.text:004AFE19 mov [ebp+var_10], eax
.text:004AFE1C mov [ebp+var_C], edx
.text:004AFE1F call ClntObjMgrGetActivePlayer
.text:004AFE24 cmp [ebp+var_10], eax
.text:004AFE27 jnz short loc_4AFE2E
.text:004AFE29 cmp [ebp+var_C], edx
.text:004AFE2C jz short loc_4AFE4E
Since I have it labeled here, it's easy to see our target function, what else gives it away is that the logic here is comparing the return value of this function with the return value of sub_53C500! Which if they are equal, it will go to this branch:
Code:
.text:004AFE4E loc_4AFE4E: ; CODE XREF: sub_4AFDD0+5Cj
.text:004AFE4E ; sub_4AFDD0+6Cj
.text:004AFE4E mov ecx, [ebp+var_C]
.text:004AFE51 lea edx, [ebp+var_8]
.text:004AFE54 push edx
.text:004AFE55 mov edx, [ebp+var_10]
.text:004AFE58 lea eax, [ebp+var_4]
.text:004AFE5B push eax
.text:004AFE5C push ecx
.text:004AFE5D push edx
.text:004AFE5E call sub_4AEDC0
.text:004AFE63 add esp, 10h
Looking at sub_4AEDC0 we can see a string reference to WorldMap.cpp, it appears that The ID we retrieved earlier is passed to a different function that returns a pointer in EAX. Stay tuned for analysis of this function because this is the one that is useful!