[Help] Read Playername menu

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 15 of 23
  1. #1
    1814's Avatar Active Member
    Reputation
    21
    Join Date
    Mar 2008
    Posts
    67
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [Help] Read Playername

    Hi,
    anyone can help me with Reading the name from an Player Object.
    ATM Im trying it like Shynd did
    Code:
        static string GetPlayerName(IntPtr hProcess, uint player)
        {
          //read the object's GUID from obj+0x30 (again, pretty basic)
          UInt64 GUID = Memory.ReadUInt64(hProcess, (player + 0x30));
     
          //some sort of list index
          int var1 = Memory.ReadInt(hProcess, (0x00D4C4F8 + 0x24));
          if (var1 == -1)
            return "Unknown Player";
     
          //here we're getting the pointer to the start of the linked list
          int var2 = Memory.ReadInt(hProcess, (0x00D4C4F8 + 0x1C));
          var1 &= (int)GUID;
          var1 += var1 * 2;
          var1 = (var2 + (var1 * 4) + 4);
          var1 = Memory.ReadInt(hProcess, (var1 + 4));
     
          //iterate through the linked list until the current entry has
          //the same GUID as the object whose name we want
          while (Memory.ReadInt(hProcess, var1) != (int)GUID)
          {
            int var3 = Memory.ReadInt(hProcess, (0x00D4C4F8 + 0x1C));
            var2 = (int)GUID;
            var2 &= Memory.ReadInt(hProcess, (0x00D4C4F8 + 0x24));
            var2 += var2 * 2;
            var2 = Memory.ReadInt(hProcess, (var3 + (var2 * 4)));
            var2 += var1;
            var1 = Memory.ReadInt(hProcess, (var2 + 4));
          }
     
          //now that we have the correct entry in the linked list,
          //read its name from entry+0x20
          return Memory.ReadString(hProcess, (var1 + 0x20), 40);
        }
    But it does not find code does not work : (((var1/var2 are -1 )

    Can anyone help me?

    P.S The Guid is 100 % correct ^-^

    [Help] Read Playername
  2. #2
    Shynd's Avatar Contributor
    Reputation
    97
    Join Date
    May 2008
    Posts
    393
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The offsets that I threw in there need to be updated for the current patch. I am not sure that I have time to do it, at the moment. Let me check my other projects when I get home to see if I ever updated them or not and I'll get back to you.

  3. #3
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1356
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It would be a lot easier to use the VMT. Function 42 from memory. Or if you REALLY want to use the cache you can update the offsets yourself by jumping into that function in IDA and reversing it. It retrives player names the same way (via the cache).

  4. #4
    RoKFenris's Avatar Member
    Reputation
    16
    Join Date
    Jun 2008
    Posts
    69
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Already reversed it. Shynd's blog was helpful, although in the end I ended up reversing the function in IDA; Shynd's code was too confuse to follow
    BTW, these are the current pointers, although for retail they should only be valid until next tuesday.

    Code:
    static const unsigned long nameStorePtr        = 0x00D29BA8 + 0x8;  // Player name database
    static const unsigned long nameMaskOffset      = 0x024;  // Offset for the mask used with GUID to select a linked list
    static const unsigned long nameBaseOffset      = 0x01c;  // Offset for the start of the name linked list
    static const unsigned long nameStringOffset    = 0x020;  // Offset to the C string in a name structure
    
    
    bool getPlayerName(const GUID guid, String * const name)
    {
      unsigned long mask, base, offset, current, shortGUID, testGUID;
      peek(nameStorePtr + nameMaskOffset, &mask);
      peek(nameStorePtr + nameBaseOffset, &base);
    
      shortGUID = guid & 0xffffffff;  // Only half the guid is used to check for a hit
      if (mask == 0xffffffff) {*name = ""; return false;}
      offset = 12 * (mask & shortGUID);  // select the appropriate linked list
      peek(base + offset + 8, &current);  // first element
      peek(base + offset, &offset)  // this plus 4 is the offset for the next element
      if (current == 0 or (current & 0x1)) {*name = ""; return false;}
      peek(current, &testGUID)
      while (testGUID != shortGUID)
      {
        peek(current + offset + 4, &current);
        if (current == 0 or (current & 0x1)) {*name = ""; return false;}
        peek(current, &testGUID)
      }
      return peekString(current + nameStringOffset, name);
    }
    As for the structure of the name cache itself, it's a group of linked lists (currently 64). The correct one is selected based on the least significant bits (currently 10) of the GUID. It's a cool trick to really speed up the linked list lookup if you have a lot of elements and a way to reliably distribute them among the different lists.

  5. #5
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1356
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by RoKFenris View Post
    Already reversed it. Shynd's blog was helpful, although in the end I ended up reversing the function in IDA; Shynd's code was too confuse to follow
    BTW, these are the current pointers, although for retail they should only be valid until next tuesday.

    Code:
    static const unsigned long nameStorePtr        = 0x00D29BA8 + 0x8;  // Player name database
    static const unsigned long nameMaskOffset      = 0x024;  // Offset for the mask used with GUID to select a linked list
    static const unsigned long nameBaseOffset      = 0x01c;  // Offset for the start of the name linked list
    static const unsigned long nameStringOffset    = 0x020;  // Offset to the C string in a name structure
    
    
    bool getPlayerName(const GUID guid, String * const name)
    {
      unsigned long mask, base, offset, current, shortGUID, testGUID;
      peek(nameStorePtr + nameMaskOffset, &mask);
      peek(nameStorePtr + nameBaseOffset, &base);
    
      shortGUID = guid & 0xffffffff;  // Only half the guid is used to check for a hit
      if (mask == 0xffffffff) {*name = ""; return false;}
      offset = 12 * (mask & shortGUID);  // select the appropriate linked list
      peek(base + offset + 8, &current);  // first element
      peek(base + offset, &offset)  // this plus 4 is the offset for the next element
      if (current == 0 or (current & 0x1)) {*name = ""; return false;}
      peek(current, &testGUID)
      while (testGUID != shortGUID)
      {
        peek(current + offset + 4, &current);
        if (current == 0 or (current & 0x1)) {*name = ""; return false;}
        peek(current, &testGUID)
      }
      return peekString(current + nameStringOffset, name);
    }
    As for the structure of the name cache itself, it's a group of linked lists (currently 64). The correct one is selected based on the least significant bits (currently 10) of the GUID. It's a cool trick to really speed up the linked list lookup if you have a lot of elements and a way to reliably distribute them among the different lists.
    Very nicely done.

  6. #6
    bigtimt's Avatar Active Member
    Reputation
    41
    Join Date
    Mar 2008
    Posts
    100
    Thanks G/R
    2/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    or you can do it with my ProcessASM library i wrote(i have a new version wrote up so syntax is a bit different)

    Code:
    public this as ProcessASM
    
    public function GetObjectName(byval BaseAddress as int32) as string
            With this
                .AddLine("mov EDX, [0x00D43318]")   //Start UpdateCurMgr
                .AddLine("mov EDX, [EDX+0x2218]")
                .AddLine("FS mov EAX, [0x2C]")
                .AddLine("mov EAX, [EAX]")
                .AddLine("add EAX, 8")
                .AddLine("mov [EAX], EDX") // End UpdateCurMgr
                .AddLine("mov ecx, " & BaseAddress)
                .AddLine("mov eax, 0x005EC8F0")
                .AddLine("call eax")
            End With
    
            return ReadString(this.Execute())
    end sub

  7. #7
    1814's Avatar Active Member
    Reputation
    21
    Join Date
    Mar 2008
    Posts
    67
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by RoKFenris View Post
    Already reversed it. Shynd's blog was helpful, although in the end I ended up reversing the function in IDA; Shynd's code was too confuse to follow
    BTW, these are the current pointers, although for retail they should only be valid until next tuesday.

    Code:
    static const unsigned long nameStorePtr        = 0x00D29BA8 + 0x8;  // Player name database
    static const unsigned long nameMaskOffset      = 0x024;  // Offset for the mask used with GUID to select a linked list
    static const unsigned long nameBaseOffset      = 0x01c;  // Offset for the start of the name linked list
    static const unsigned long nameStringOffset    = 0x020;  // Offset to the C string in a name structure
    
    
    bool getPlayerName(const GUID guid, String * const name)
    {
      unsigned long mask, base, offset, current, shortGUID, testGUID;
      peek(nameStorePtr + nameMaskOffset, &mask);
      peek(nameStorePtr + nameBaseOffset, &base);
    
      shortGUID = guid & 0xffffffff;  // Only half the guid is used to check for a hit
      if (mask == 0xffffffff) {*name = ""; return false;}
      offset = 12 * (mask & shortGUID);  // select the appropriate linked list
      peek(base + offset + 8, &current);  // first element
      peek(base + offset, &offset)  // this plus 4 is the offset for the next element
      if (current == 0 or (current & 0x1)) {*name = ""; return false;}
      peek(current, &testGUID)
      while (testGUID != shortGUID)
      {
        peek(current + offset + 4, &current);
        if (current == 0 or (current & 0x1)) {*name = ""; return false;}
        peek(current, &testGUID)
      }
      return peekString(current + nameStringOffset, name);
    }
    As for the structure of the name cache itself, it's a group of linked lists (currently 64). The correct one is selected based on the least significant bits (currently 10) of the GUID. It's a cool trick to really speed up the linked list lookup if you have a lot of elements and a way to reliably distribute them among the different lists.
    Thanks : )

    It works ^-^
    *kiss

    +Rep

  8. #8
    Robske's Avatar Contributor
    Reputation
    305
    Join Date
    May 2007
    Posts
    1,062
    Thanks G/R
    3/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by RoKFenris View Post
    Already reversed it. Shynd's blog was helpful, although in the end I ended up reversing the function in IDA; Shynd's code was too confuse to follow
    BTW, these are the current pointers, although for retail they should only be valid until next tuesday.

    Code --

    As for the structure of the name cache itself, it's a group of linked lists (currently 64). The correct one is selected based on the least significant bits (currently 10) of the GUID. It's a cool trick to really speed up the linked list lookup if you have a lot of elements and a way to reliably distribute them among the different lists.
    Thanks, this helped alot but could you tell me where/how I could find the 3.0.2 offsets (Mask, Base, String)

    My knowledge of reverse engineering is close to none btw

    I have ported your code to AutoIt, this is the result: (Atleast I tried)
    Code:
    ;Get the name of the player when given an object.
    ;This function does not check if the object is actually a player object (type 4)
    ;Credit to RokFenris (http://www.mmowned.com/forums/wow-memory-editing/174671-help-read-playername.html)
    Func GetPlayerName($object)
    	;Variables
    	local $nameStorePtr=0x00D29BA8 + 0x8	; Player name database (updated for 3.0.2)
    	local $nameMaskOffset=0x024				; offset for the mask used with GUID to select a linked list
    	local $nameBaseOffset=0x01c				; offset for the start of the named linked list
    	local $nameStringOffset=0x020			; offset to the C string in a name structure
    	
    	$GUID=_ReadProcess($Handle, ($object+0x30), "uint64")
    	
    	$mask=_ReadProcess($Handle, ($nameStorePtr+$nameMaskOffset), "uint")
    	$base=_ReadProcess($Handle, ($nameStorePtr+$nameBaseOffset), "uint")
    	
    	$shortGUID = $GUID & 0xffffffff		; Only half of the GUID is used to check for a hit
    	if ($mask==0xffffffff) Then
    		$name=""
    		return False
    	EndIf
    	
    	$offset = 12 * ($mask&$shortGUID)								; Select the linked list
    	$current = _ReadProcess($Handle, ($base+$offset+8), "uint")	;first element in the list
    	$offset = _ReadProcess($Handle, ($base+$offset), "uint") 		;this +4 is the offset for the next element
    	if ($current==0 or ($current & 0x1)) Then
    		$name=""
    		return False
    	EndIf
    	$testGUID=_ReadProcess($Handle, ($current))
    	while ($testGUID<>$shortGUID)
    		$current=_ReadProcess($Handle, ($current+$offset+4))
    		if ($current==0 or ($current&0x1)) Then
    			$name=""
    			return False
    		EndIf
    		$testGUID=_ReadProcess($Handle, ($current))
    	WEnd
    	return _ReadProces($Handle, ($current+$nameStringOffset), "char[40]")
    EndFunc
    Last edited by Robske; 10-19-2008 at 03:04 PM.

  9. #9
    RoKFenris's Avatar Member
    Reputation
    16
    Join Date
    Jun 2008
    Posts
    69
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Robske007a View Post
    Thanks, this helped alot but could you tell me where/how I could find the 3.0.2 offsets (Mask, Base, String)
    Look at the post http://www.mmowned.com/forums/wow-me...addresses.html . It's on the first post.
    The offsets have not changed, you just need the new Player name database
    pointer.

  10. #10
    Cypher's Avatar Kynox's Sister's Pimp
    Reputation
    1356
    Join Date
    Apr 2006
    Posts
    5,368
    Thanks G/R
    0/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Heads up to anyone reading the playername via the VMT. Function has moved to position 47 (assuming 0-based numbering).

  11. #11
    1814's Avatar Active Member
    Reputation
    21
    Join Date
    Mar 2008
    Posts
    67
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Cypher View Post
    Heads up to anyone reading the playername via the VMT. Function has moved to position 47 (assuming 0-based numbering).
    yay! I will get flamed by cypher ^-^
    Could you explain how to call that function?

  12. #12
    Nesox's Avatar ★ Elder ★
    Reputation
    1280
    Join Date
    Mar 2007
    Posts
    1,238
    Thanks G/R
    0/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by 1814 View Post
    yay! I will get flamed by cypher ^-^
    Could you explain how to call that function?
    this way works it's what bigtimt posted but i updated it also using his ProcessASM library for the asm.


    Code:
                ProcessASM WowASM = new ProcessASM( processID );
                
                //get the adress of the call for vmt 47 (get object name)?
                uint GetObjectNameVMT47 = Memory.ReadUInt(hProcess,
                (Memory.ReadUInt(hProcess, obj) + (47 * 4)));
    
                WowASM.AddLine("mov EDX, [0x011C8248]");   //Start UpdateCurMgr
                WowASM.AddLine("mov EDX, [EDX+0x285C]");
                WowASM.AddLine("FS mov EAX, [0x2C]");
                WowASM.AddLine("mov EAX, [EAX]");
                WowASM.AddLine("add EAX, 8");
                WowASM.AddLine("mov [EAX], EDX"); // End UpdateCurMgr
    
                WowASM.AddLine("mov ecx, " + "0x" + obj.ToString("X"));
                WowASM.AddLine("mov eax, 0x" + GetObjectNameVMT47.ToString("X") + "");
                WowASM.AddLine("call eax");
                WowASM.AddLine("retn");
    
                return Memory.ReadString(hProcess, WowASM.Execute(), 64);
    btw. im trying to get Interact to work VMT fuction 34 this is what's ive come up with so far.
    Code:
    ProcessASM WowASM = new ProcessASM(processID);
    
                //get the adress of the call for vmt 34 (Interact)
                uint VMT34 = Memory.ReadUInt(hProcess,
                (Memory.ReadUInt(hProcess, obj) + (34 * 4)));
    
                WowASM.AddLine("mov EDX, [0x011C8248]");   //Start UpdateCurMgr
                WowASM.AddLine("mov EDX, [EDX+0x285C]");
                WowASM.AddLine("FS mov EAX, [0x2C]");
                WowASM.AddLine("mov EAX, [EAX]");
                WowASM.AddLine("add EAX, 8");
                WowASM.AddLine("mov [EAX], EDX"); // End UpdateCurMgr
    
                WowASM.AddLine("mov ecx, " + "0x" + obj.ToString("X"));
                WowASM.AddLine("mov eax, 0x" + VMT34.ToString("X") + "");
                WowASM.AddLine("call eax");
                WowASM.AddLine("retn");
    
                WowASM.Execute();
    but nothing happens when i call the function. anyone who know's or could point out what im doing wrong?
    Last edited by Nesox; 10-20-2008 at 02:23 PM.

  13. #13
    Robske's Avatar Contributor
    Reputation
    305
    Join Date
    May 2007
    Posts
    1,062
    Thanks G/R
    3/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by RoKFenris View Post
    Look at the post http://www.mmowned.com/forums/wow-me...addresses.html . It's on the first post.
    The offsets have not changed, you just need the new Player name database
    pointer.
    Updated the memory adress but it still doesn't work, obviously -->

    I've found the problem to be in my port to autoit, after further analysing your code I found that I had misinterpreted the "&" symbol (seeing as I have zero experience with C) and I don't know any replacement for it in AutoIt.

    So instead of copying your code like a brainless monkey, could you help me out on the theory? Please correct me if I'm wrong:

    - I have the GUID of a player object. ($curObj+0x30)
    - I have access to the playernames (0x011AC3B8 + 0x, I have the idea that this list contains a GUID, the corresponding name and some other info at certain offsets.

    So in order to get the name that goes with the current GUID I have to:
    - Follow the pointer 0x011AC3B8 + 0x8, add the offset to the first GUID (0x01c ?) and compare it with mine.
    If they are equal, I read the offset to the name (0x020 ?) and exit the loop
    If they aren't, I add the offset to the next GUID (+0x01c ?)

    Please do correct me if I made any horrible mistakes.

    (Cypher is allowed to flame me into deep depression though)

  14. #14
    Shynd's Avatar Contributor
    Reputation
    97
    Join Date
    May 2008
    Posts
    393
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Where you see & use AutoIt's BitAND function.

  15. #15
    RoKFenris's Avatar Member
    Reputation
    16
    Join Date
    Jun 2008
    Posts
    69
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Robske007a View Post
    So instead of copying your code like a brainless monkey, could you help me out on the theory? Please correct me if I'm wrong:

    - I have the GUID of a player object. ($curObj+0x30)
    - I have access to the playernames (0x011AC3B8 + 0x, I have the idea that this list contains a GUID, the corresponding name and some other info at certain offsets.
    Here you are wrong. [0x011AC3B8 + 0x8] is not the address of a pointer, it is the start of a structure with information on how to select among a whole lot of linked lists (i believe 64 currently). The two important things in this structure are located at offsets 0x24 (the mask used to select the right list, which for valid values doubles as the number of lists minus 1) and 0x1c (this is the pointer to the structure that holds the linked lists themselves).

    BTW, I wrote 0x011AC3B8 + 0x8, instead of 0x011AC3C0, because 0x011AC3B8 is the one pointer you will find if you search the WoW executable. Just a trick to remember how to find the pointer next time I have to update it.

    The structure at [ [0x011AC3B8 + 0x8] + 0x1c] starts with an integer that is the offset of the next element pointer in each linked list element minus 4, and then at offset 0x8 starts the linked list pointer array, each pointer 12 bytes after the previous.

    Each linked list element starts with half the GUID, and have the string pointer at offset 0x20 and the next element pointer at the offset mentioned in the previous paragraph.

    Believe me, my code should be about the simplest way of navigating this structure. If you can't understand it, I don't think you will be able to write something to get the names of the other players without injecting

    Originally Posted by Robske007a View Post
    So in order to get the name that goes with the current GUID I have to:
    - Follow the pointer 0x011AC3B8 + 0x8, add the offset to the first GUID (0x01c ?) and compare it with mine.
    If they are equal, I read the offset to the name (0x020 ?) and exit the loop
    If they aren't, I add the offset to the next GUID (+0x01c ?)

    Please do correct me if I made any horrible mistakes.
    Yeah, as I explained before, this is an horrible mistake The data is stored in a reasonably more complex way than you thought, in order to cut down on the lookup time.

Page 1 of 2 12 LastLast

Similar Threads

  1. Need help reading Memory, Writing too memory
    By Neer in forum Programming
    Replies: 0
    Last Post: 08-17-2009, 12:11 PM
  2. Need help, read please!
    By elwarcrafta in forum World of Warcraft General
    Replies: 5
    Last Post: 07-30-2008, 01:00 PM
  3. Replies: 3
    Last Post: 07-10-2008, 05:05 AM
  4. [help] reading chat pane (for zeppelin arrivals)
    By korknob in forum WoW Memory Editing
    Replies: 2
    Last Post: 05-17-2008, 06:00 AM
All times are GMT -5. The time now is 03:41 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search