Read Attributes OOP menu

User Tag List

Results 1 to 13 of 13
  1. #1
    DrGonzo's Avatar Contributor
    Reputation
    144
    Join Date
    Jun 2009
    Posts
    132
    Thanks G/R
    0/59
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Read Attributes OOP

    Trying to read attributes of an ACDActor out of process, hit a snag - doesn't seem to be returning the correct data.

    Code:
    unsigned long readAttribute(unsigned long attributeTable, int attributeKey)
    {
    	int unk = 0;
    	ReadProcessMemory(hProcess,(LPCVOID)(attributeTable+0x38), &unk, 4, 0);
    	int hash = 0;
    	ReadProcessMemory(hProcess,(LPCVOID)(attributeTable+0xC8), &hash, 4, 0);
    
    	int v4 = (unk + 4 * (hash & (attributeKey ^ (attributeKey >> 16))));
    	ReadProcessMemory(hProcess,(LPCVOID)(v4), &v4, 4, 0);
      
    	if ( v4 )
    	{
    		while (1)
    		//*(_DWORD *)(v4 + 4) != attributeKey )
    		{
    		  //v4 = *(_DWORD *)v4;
    			int key = 0;
    			ReadProcessMemory(hProcess,(LPCVOID)(v4+0x4), &key, 4, 0);
    			if (key == attributeKey)
    				break;
    			ReadProcessMemory(hProcess,(LPCVOID)(v4), &v4, 4, 0);
    		  if ( !v4 )
    			goto LABEL_6;
    		}
    		//sub_85DEA0(attributeTable, attributeKey);
    		attributeKey = attributeKey;
    	}
    LABEL_6:
    	int unk2 = 0;
    	ReadProcessMemory(hProcess,(LPCVOID)(attributeTable+0x10), &unk2, 4, 0);
    	int unk3 = 0;
    	ReadProcessMemory(hProcess,(LPCVOID)(unk2+0x8), &unk3, 4, 0);
    	int unk4 = 0;
    	ReadProcessMemory(hProcess,(LPCVOID)(unk2+0x418), &unk4, 4, 0);
    
    	int hash2 = attributeKey ^ (attributeKey >> 16);
    	int v5 = 0;
    	ReadProcessMemory(hProcess,(LPCVOID)(unk3 + 4 * (unk4 & (hash2))), &v5, 4, 0);
    	//v5 = *(_DWORD *)(unk3 + 4 * (unk4 & (v3 ^ (v3 >> 16))));
      
    	int result = 0;
    	if ( v5 )
    	{
    		while (1)
    			//*(_DWORD *)(v5 + 4) != attributeKey )
    		{
    			int key = 0;
    			ReadProcessMemory(hProcess,(LPCVOID)(v5+0x4), &key, 4, 0);
    			if (key == attributeKey)
    				break;
    			ReadProcessMemory(hProcess,(LPCVOID)(v5), &v5, 4, 0);
    		  if ( !v5 )
    			goto LABEL_9;
    		}
    		ReadProcessMemory(hProcess,(LPCVOID)(v5+8), &result, 4, 0);
    		return result;
    	}
    	else
    	{
    		LABEL_9:
    		int unk5 = (4 * 10 * (attributeKey & 0xFFF));
    		int v7 = 0;
    		ReadProcessMemory(hProcess,(LPCVOID)(0x15494EC+unk5), &v7, 4, 0);
    		return v7;
    		//v7 = dword_15494EC[10 * (attributeKey & 0xFFF)];
    		//result = a1;
    		//*(_DWORD *)a1 = v7;
    	}
    	return result;
    }
    Based on int __cdecl sub_85E130(int a1, int attributeTable, signed int attributeCategory), called from getInt.
    I looked through sub_12C1BB0, which led me to think the attribute keys/index would be '10' for strength but this is returning 0 and I'm seeing other, larger negative keys being used/referenced in code and breakpoints (-4019 being one).

    Can someone point me in the right direction?

    Read Attributes OOP
  2. #2
    BitHacker's Avatar Master Sergeant
    Reputation
    13
    Join Date
    May 2012
    Posts
    114
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In case someone isn't sitting next to idapro while looking at this post here is the function 85E130.

    Code:
    int __cdecl sub_85E130(int a1, int a2, signed int a3)
    {
      signed int v3; // eax@1
      int v4; // ecx@1
      int v5; // ecx@6
      int v6; // ecx@9
      int result; // eax@9
    
      v3 = a3;
      v4 = *(_DWORD *)(*(_DWORD *)(a2 + 56) + 4 * (*(_DWORD *)(a2 + 200) & (a3 ^ (a3 >> 16))));
      if ( v4 )
      {
        while ( *(_DWORD *)(v4 + 4) != a3 )
        {
          v4 = *(_DWORD *)v4;
          if ( !v4 )
            goto LABEL_6;
        }
        sub_85DEA0(a2, a3);
        v3 = a3;
      }
    LABEL_6:
      v5 = *(_DWORD *)(*(_DWORD *)(*(_DWORD *)(a2 + 16) + 8)
                     + 4 * (*(_DWORD *)(*(_DWORD *)(a2 + 16) + 1048) & (v3 ^ (v3 >> 16))));
      if ( v5 )
      {
        while ( *(_DWORD *)(v5 + 4) != v3 )
        {
          v5 = *(_DWORD *)v5;
          if ( !v5 )
            goto LABEL_9;
        }
        result = a1;
        *(_DWORD *)a1 = *(_DWORD *)(v5 + 8);
      }
      else
      {
    LABEL_9:
        v6 = dword_15494EC[10 * (v3 & 0xFFF)];
        result = a1;
        *(_DWORD *)a1 = v6;
      }
      return result;
    }
    I don't understand why your looking at sub_12C1BB0 its not referenced in the above function?

    Your forgetting a parameter?
    unsigned long readAttribute(unsigned long attributeTable, int attributeKey)

    Its suppose to be setup for 3? is it not?
    Wouldn't that mess with how parameters are passed to the function and this explains why your getting the wrong data?
    Inside the function that calls 0085E130:
    Code:
    0085E2BD   8B4D 0C          MOV ECX,DWORD PTR SS:[EBP+C]
    0085E2C0   51               PUSH ECX
    0085E2C1   50               PUSH EAX
    0085E2C2   8D55 FC          LEA EDX,DWORD PTR SS:[EBP-4]
    0085E2C5   52               PUSH EDX
    0085E2C6   E8 65FEFFFF      CALL Diablo_I.0085E130
    0085E2CB   8B45 FC          MOV EAX,DWORD PTR SS:[EBP-4]
    Edited: per wrong info...

    -Bit_Hacker
    Last edited by BitHacker; 05-23-2012 at 07:20 PM.

  3. #3
    MaiN's Avatar Elite User
    Reputation
    335
    Join Date
    Sep 2006
    Posts
    1,047
    Thanks G/R
    0/10
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by BitHacker View Post
    In case someone isn't sitting next to idapro while looking at this post here is the function 85E130.
    ..snip..


    I didn't check it all, but I noticed two things quickly:
    1. Dereferencing the address 200 (da fuq - no.. just.. no)
    2. Calling a right shift of 16 a multiplication of 2^16. You mixed them around, that is a division by 2^16.

    I think Hex-Rays got the signature wrong - because memory will never be allocated at 200.

    EDIT: Yes, I know you can technically allocate the first page (from 0x0 to 0x1000) of memory. But you have to call NtAllocateVirtualMemory and.. why would you do that, really.
    Last edited by MaiN; 05-23-2012 at 05:23 PM.
    [16:15:41] Cypher: caus the CPU is a dick
    [16:16:07] kynox: CPU is mad
    [16:16:15] Cypher: CPU is all like
    [16:16:16] Cypher: whatever, i do what i want

  4. #4
    BitHacker's Avatar Master Sergeant
    Reputation
    13
    Join Date
    May 2012
    Posts
    114
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    MaiN,

    Thanks shit...
    Shifting left by n bits on a signed or unsigned binary number has the effect of multiplying it by 2n. Shifting right by n bits on an unsigned binary number has the effect of dividing it by 2n (rounding towards 0).

    I Forgot I just went with what I had in my head... damn it....

    I tried...

    IN ORDER TO LEARN YOU GOTTA FAIL... SO AT LEAST I'M TRYING


    I've been re-looking at the values and these are the values passed into the function below:

    0085E2BD 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+C]
    0085E2C0 51 PUSH ECX
    0085E2C1 50 PUSH EAX
    0085E2C2 8D55 FC LEA EDX,DWORD PTR SS:[EBP-4]
    0085E2C5 52 PUSH EDX
    0085E2C6 E8 65FEFFFF CALL Diablo_I.0085E130
    0085E2CB 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]

    a1 = 0018FDA8 ( Decimal 7853056 ) ( Big Endian 00 00 D4 77 ) ( Little Endian 77 D4 00 00 )
    a2 = 1EB18000 ( Decimal 7853056 ) ( Big Endian 00 00 D4 77 ) ( Little Endian 77 D4 00 00 )
    a3 = 16D ( Decimal 365 )

    v4 = *(_DWORD *)(*(_DWORD *)(a2 + 56) + 4 * (*(_DWORD *)(a2 + 200) & (a3 ^ (a3 >> 16))));
    Anyone want to walk thru it with me? With the values specified? ( Its ok, I will get it myself :P )
    found out a1 and a2 are the same.... but at different addresses...

    Ok now, I can proceed with understanding the function..


    a2 = 1EB18000

    I'm not understanding this part... Below:
    a2 = 1EB18000 + 56

    The alignment of 56 is fine, it divides by 4 fine its equal to 14.

    it adds 56 to the address then dereferences it?

    Then the same with this:
    a2 = 1EB18000 + 200

    The alignment of 200 is fine, it divides by 4 fine its equal to 50.

    FearAndLawyering,
    That's your problem I think. a1, a2 are the same... but when your using two parameters in your function..
    Its not recognizing which one to use. there the same structure with different data..


    *(_DWORD *)(a2 + 56) + 4
    This is adding 56 to the actual virtual memory address then De-referencing it. Then adding 4 to the value correct?

    and same with this
    *(_DWORD *)(a2 + 200)
    This is adding 200 to the actual virtual memory address then De-referencing it. Grabbing the value then using the bitwise (AND) operator with the outcome of ( a3 ^(a3 >> 16)).

    After all that there multiplied together. To form the final pointer that gets de-referenced again. Final value output is put into v4.


    -Bit_Hacker
    Last edited by BitHacker; 05-23-2012 at 08:41 PM.

  5. #5
    DrGonzo's Avatar Contributor
    Reputation
    144
    Join Date
    Jun 2009
    Posts
    132
    Thanks G/R
    0/59
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    sub_12C1BB0 is the function that sets up the different attribute types as pointed out in other threads.

    I omitted a1 because it is only used for holding the return value, which im going to ret instead. It is set to the guid of the attribute class. a2 is a ptr to that attribute class and at that address is the guid, which is why they appear to be the same thing.

    *(_DWORD *)(a2 + 56) + 4
    This is adding 56 to the actual virtual memory address then De-referencing it. Then adding 4 to the value correct?
    It's adding 4 * the value of the rest of the statement, not just + 4.

  6. #6
    BitHacker's Avatar Master Sergeant
    Reputation
    13
    Join Date
    May 2012
    Posts
    114
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    FearAndLawyering,

    I'm I looking at this right now?

    Code:
    0085E2BD   8B4D 0C          MOV ECX,DWORD PTR SS:[EBP+C]
    0085E2C0   51               PUSH ECX
    0085E2C1   50               PUSH EAX
    0085E2C2   8D55 FC          LEA EDX,DWORD PTR SS:[EBP-4]
    0085E2C5   52               PUSH EDX
    0085E2C6   E8 65FEFFFF      CALL Diablo_I.0085E130
    0085E2CB   8B45 FC          MOV EAX,DWORD PTR SS:[EBP-4]
    
    a1 = 0018FC7C ( Decimal 7853056 ) ( Big Endian 00 00 D4 77 ) ( Little Endian 77 D4 00 00 )
    a2 = 1EB18000 ( Decimal 7853056 ) ( Big Endian 00 00 D4 77 ) ( Little Endian 77 D4 00 00 )
    a3 = 0000016D ( Decimal 365 )
    
    v4 = *(_DWORD *)( *(_DWORD *)(a2 + 56) + 4 * ( *(_DWORD *)(a2 + 200) & ( a3 ^ (a3 >> 16) ) ) );
    
    --------------------------------------------------------------------------------------------------
    
    So, lets start understanding this:
    v4 = *(_DWORD *)( *(_DWORD *)(a2 + 56) + 4 * ( *(_DWORD *)(a2 + 200) & ( a3 ^ (a3 >> 16) ) ) );
    a3 gets SAR which is a automatic shift right that uses its sign bit to fill.
    a3 = 0000016D
    a3 >> 16 = 00000000
    
    --------------------------------------------------------------------------------------------------
    
    We have:
    v4 = *(_DWORD *)( *(_DWORD *)(a2 + 56) + 4 * ( *(_DWORD *)(a2 + 200) & ( a3 ^ (00000000) ) ) );
    
    a3 = 0000016D
    0000016D ^ 00000000 = 0001 0110 1101
    
    Bit Level:
    0001 0110 1101 ^
    0000 0000 0000 
    ---------------
    0001 0110 1101
    
    --------------------------------------------------------------------------------------------------
    
    Then we have:
    v4 = *(_DWORD *)( *(_DWORD *)(a2 + 56) + 4 * ( *(_DWORD *)(a2 + 200) & ( 0000016D ^ (00000000) ) ) );
    
    Which becomes:
    v4 = *(_DWORD *)( *(_DWORD *)(a2 + 56) + 4 * ( *(_DWORD *)(a2 + 200) & 0000016D ) );
    a2 = 1EB18000
    a2 + 200 = 1EB18200
    
    --------------------------------------------------------------------------------------------------
    
    Then:
    v4 = *(_DWORD *)( *(_DWORD *)(a2 + 56) + 4 * ( *(_DWORD *)(1EB18200) & 0000016D ) );
    The value at 1EB18200 is 00000000
    
    So:
    v4 = *(_DWORD *)( *(_DWORD *)(a2 + 56) + 4 * ( 00000000 & 0000016D ) );
    
    Bit Level:
    0000 0000 0000 &
    0001 0110 1101
    ----------------
    0000 0000 0000
    
    --------------------------------------------------------------------------------------------------
    
    So we have:
    v4 = *(_DWORD *)( *(_DWORD *)(a2 + 56) + 4 * 00000000 );
    a2 = 1EB18000
    a2 + 56 = 1EB18056
    
    So we have now...
    v4 = *(_DWORD *)( *(_DWORD *)(1EB18056) + 4 * 00000000 );
    The value at 1EB18056 is 00000000
    
    So we have..
    v4 = *(_DWORD *)( 00000000 + 4 * 00000000 );
    
    Then we can add 4:
    v4 = *(_DWORD *)( 00000004 * 00000000 );
    4 * 0 = 0
    
    v4 = 00000000
    
    ---------------------------------------------------------------------------------------------------
    
    so looking at our while loop...
    
      while ( *(_DWORD *)(v4 + 4) != a3 )
        {
          v4 = *(_DWORD *)v4;
          if ( !v4 )
            goto LABEL_6;
        }
        sub_85DEA0(a2, a3);
        v3 = a3;
    
    v4 is 00000000 + 4 = 00000004
    
    Basically the if(v4) is never true so the while loop will not even be reached....But if it did.
    
    while ( 00000004 != 0000016D )
    {
        // Do loop
    }
    Here is EAX param 2 or a2
    Code:
    1EB18000     77D40000    00000001    00000001    FFFFFFFF
    1EB18010     1993002C    19930454    FFFFFFFF    03592BF0
    1EB18020     03592BF0    00000001    03531520    00000001
    1EB18030     1AC3E59C    00000000    1EB18044    00000000
    1EB18040     00000020    00000000    00000000    00000000
    1EB18050     00000000    00000000    00000000    00000000
    1EB18060     00000000    00000000    00000000    00000000
    1EB18070     00000000    00000000    00000000    00000000
    1EB18080     00000000    00000000    00000000    00000000
    1EB18090     00000000    00000000    00000000    00000000
    1EB180A0     00000000    00000000    00000000    00000000
    1EB180B0     00000000    00000000    00000000    00000000
    1EB180C0     00000000    00000000    0000001F    00000000
    1EB180D0     00000001    00000000    1AC3E59C    00000000
    1EB180E0     1EB180EC    00000000    00000020    00000000
    1EB180F0     00000000    00000000    00000000    00000000
    1EB18100     00000000    00000000    00000000    00000000
    1EB18110     00000000    00000000    00000000    00000000
    1EB18120     00000000    00000000    00000000    00000000
    1EB18130     00000000    00000000    00000000    00000000
    1EB18140     00000000    00000000    00000000    00000000
    1EB18150     00000000    00000000    00000000    00000000
    1EB18160     00000000    00000000    00000000    00000000
    1EB18170     0000001F    00000000    00000001    00000000
    1EB18180     77D50001    00000000    00000000    FFFFFFFF
    1EB18190     1993087C    19930CA4    77D40000    00000000
    1EB181A0     00000000    00000000    03531520    00000001
    1EB181B0     1AC3E59C    00000000    1EB181C4    00000000
    1EB181C0     00000020    00000000    00000000    00000000
    1EB181D0     00000000    00000000    00000000    00000000
    1EB181E0     00000000    00000000    00000000    00000000
    1EB181F0     00000000    00000000    00000000    00000000
    1EB18200     00000000    00000000    00000000    00000000
    1EB18210     00000000    00000000    00000000    00000000
    1EB18220     00000000    00000000    00000000    00000000
    Here is EDX param 1 or a1:
    Code:
    0018FC7C     77D40000    0018FC90    008B4453    77D40000
    0018FC8C     FFFFF32A    0018FCD0    00981C53    FFFFF32A
    0018FC9C     1D218484    0094D597    1D218484    1D21848C
    0018FCAC     0018FD20    1D218484    1D21848C    0B034804
    0018FCBC     FFFFD8F2    00000000    FFFFFFFF    00000000
    0018FCCC     006F534A    0018FCEC    0094D8D8    00008080
    0018FCDC     1D218484    1D21848C    0018FD10    1D218494
    0018FCEC     0018FE74    0094E2F6    00000001    1D218484
    0018FCFC     1D21848C    0018FD10    0511D200    00000001
    0018FD0C     0511D200    00000000    00000000    000006ED
    0018FD1C     000003E5    00000000    00000000    000006ED
    0018FD2C     000003E5    07A68008    00F11849    00000000
    0018FD3C     00000000    00000000    000006ED    000003E5
    0018FD4C     1D218494    00000001    00000001    00000001
    0018FD5C     0B791511    0018FD9C    00A823E5    00000000
    0018FD6C     00000000    00A823E5    44A62AAB    00000000
    0018FD7C     00000000    3F800000    3F800000    00000000
    0018FD8C     0018FE08    44794000    0018FDB8    00A8241F
    0018FD9C     44A62000    0018FE08    FFFFFFFF    000000DE
    0018FDAC     00000000    0000060F    000003E5    0018FDF4
    0018FDBC     0094C9CB    0018FDD4    0018FE08    0018FDE4
    0018FDCC     0018FDD4    3FE3A07B    00000000    00000000
    0018FDDC     000006ED    000003E5    00000000    00000000
    0018FDEC     3F800000    3F800000    0018FE30    0097D672
    0018FDFC     0018FE08    0018FE18    00A827B4    00000000
    0018FE0C     00000000    1DABA000    0000007F    0018FE2C
    0018FE1C     00B97262    00000000    07A81610    1DABA000
    0018FE2C     0018FE70    009818DE    00000000    0511D200
    0018FE3C     0511D200    BF800576    00000000    00000000
    0018FE4C     BF800000    BF800576    00000000    0018FE6C
    0018FE5C     00ADDE49    00000000    B3000000    00000003
    0018FE6C     0018FEA8    0B791605    0018FEA8    0094EAE1
    0018FE7C     3D8C6C51    00000001    00000000    00000000
    0018FE8C     00000001    00000003    00000000    00000000
    0018FE9C     00000000    1AD04690    00000003    0018FEEC
    0018FEAC     00818001    3D8C6C51    00800000    00000001
    0018FEBC     0080D92A    005841BB    0018FEDC    62616944
    0018FECC     49206F6C    00004949    72CB028D    00000000
    0018FEDC     01DD7E20    01DD1B80    01DD07D0    0B79169D
    0018FEEC     0018FEF8    0080D96F    017E3758    0018FF88
    0018FEFC     00F2CA2A    00800000    00000000    005841BB
    0018FF0C     00000005    0B7917F9    00000000    00000000
    0018FF1C     FFFDE000    00000044    005C60D8    005C6478
    0018FF2C     005C7868    00000000    00000000    00000000
    0018FF3C     00000000    00000000    00000000    00000000
    0018FF4C     00000001    00000005    00000000    FFFFFFFF
    0018FF5C     FFFFFFFF    FFFFFFFF    0018FF74    005841BB
    To make it easier, here are the values:
    1EB18150 00000000 00000000 00000000 00000000

    1EB18200 00000000 00000000 00000000 00000000

    i stepped thru the function :
    0085E326 E8 05FEFFFF CALL Diablo_I.0085E130

    And those values never change...

    Well I hope someone will respond to my findings... ???

    Basically the if(v4) is never true so the while loop will not even be reached....

    -Bit_Hacker
    Last edited by BitHacker; 05-23-2012 at 11:21 PM.

  7. #7
    matamore's Avatar Member
    Reputation
    6
    Join Date
    Dec 2008
    Posts
    13
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    there is a FAG_GUID in ACD-struct at 0x120.
    use it to get the correct FAG (FastAttribGroups) entry by
    the same method like iterating actors.
    obj_manager: 0x179FFA0, offset 0x2e8, struct size 0x2d0

    Code:
            
    public static int GetFAGPtrFromGUID(int GUID)
            {
    
                # region
    
                //0x1505498;
                //v22 = *(**TlsGetValue(dwTlsIndex) + 0xD4);
    
                int base_0 = Memory.Read<int>((IntPtr)(0x179FFA0/*0x17528C0*/), "");//0x02D2E690), "");//0x1505498), "");
                //NewObject("base_0: " + base_0.ToString("x8"));
    
                int base_1 = Memory.Read<int>((IntPtr)(base_0), "");
                //NewObject("base_1: " + base_1.ToString("x8"));
    
                int base_2 = Memory.Read<int>((IntPtr)(base_1 + 0x2E8), "");//0xD4), "");
                //NewObject("base_2: " + base_2.ToString("x8"));
    
                int base_3 = base_2;// Memory.Read<int>((IntPtr)(base_2), "");
                //NewObject("base_3: " + base_3.ToString("x8"));
    
                uint max = Memory.Read<uint>((IntPtr)(base_3 + 0x100), "");
                //NewObject("max: " + max);
    
                int size = 0x180;
    
                int result = 0;
                if (GUID == -1)
                {
                    result = 0;
                }
                else
                {
                    if ((GUID & 0xFFFF) < max)
                    {
                        //v3 = *(*(base_ + 0x148) + 4 * (GUID >> *(base_ + 0x18C))) + 0x2D0 * (GUID & ((1 << *(base_ + 0x18C)) - 1));
                        //result = ((*v3 != a2) - 1) & v3;
    
                        int _148 = Memory.Read<int>((IntPtr)(base_3 + 0x148), "");
                        int _18c = Memory.Read<int>((IntPtr)(base_3 + 0x18C), "");
                        // NewObject("0x148: " + base_2.ToString("x8"));
                        //NewObject("0x18C: " + base_3.ToString("x8"));
    
                        int a = (_148 + 4 * 0/*(GUID >> (int)_18c)*/);
                        int b = (size * (GUID & ((1 << (int)_18c) - 1)));
    
                        //int zz = ((1 << (int)base_5) - 1);
                        //NewObject("zz: " + zz.ToString("x8"));
    
                        //NewObject("a: " + a.ToString("x8"));
                        //NewObject("b: " + b.ToString("x8"));
    
                        int v3 = Memory.Read<int>((IntPtr)(a), "") + b;
                        //int v3_ = Memory.Read<int>((IntPtr)(v3), "");
    
                        //NewObject("v3: " + v3.ToString("x8"));
                        //NewObject("v3_: " + v3_.ToString("x8"));
    
                        //int c = ((v3_ != GUID) ? 1 : 0) - 1;
                        //NewObject("c: " + c.ToString("x8"));
                        result = v3 & -1;
                    }
                    else
                    {
                        result = 0;
                    }
                }
                return result;
    
    
                # endregion
    
            }

    to call the function sub_85E130:

    int __cdecl sub_85E130(int a1, int a2, signed int a3)

    dont care for a1 !
    this is the important part, where a2 is fag_ptr and a3 is attribute-index:

    Code:
      v3 = a3;
      v5 = *(*(*(a2 + 0x10) + 8) + 4 * (*(*(a2 + 0x10) + 0x418) & (v3 ^ (v3 >> 0x10u))));
      if ( v5 )
      {
        while ( *(v5 + 4) != v3 )
        {
          v5 = *v5;
          if ( !v5 )
            goto LABEL_9;
        }
        result = a1;
        *a1 = *(v5 + 8);
      }
    
      }
    where *(v5 + is "Hitpoints_Cur" for 0xFFFFF066 as attribute-index


    Code:
            private static int get_attribute(int this_, uint a2)
            {
    
                # region
    
    
                int v4; // esi@1
                int result; // eax@1
    
                //NewObject("this_: " + this_.ToString("x8"));
    
                //int v3 = this_;
                int _10 = Memory.Read<int>((IntPtr)(this_ + 0x10), "");
                //NewObject("_10: " + _10.ToString("x8"));
    
                int _418 = Memory.Read<int>((IntPtr)(_10 + 0x418), "");
                //NewObject("_418: " + _418.ToString("x8"));
    
                int _08 = Memory.Read<int>((IntPtr)(_10 + 0x8), "");
                //NewObject("_08: " + _08.ToString("x8"));
    
    
                v4 = (int)(_418 & (a2 ^ (a2 >> 0x10)));
                //NewObject("v4: " + v4.ToString("x8"));
    
                int _res = (_08 + 4 * v4);
    
                //NewObject("_res: " + _res.ToString("x8"));
    
                result = Memory.Read<int>((IntPtr)(_res), "");
                //NewObject("result: " + result.ToString("x8"));
                if (result != 0)
                {
                    while (Memory.Read<uint>((IntPtr)(result + 0x4), "") != a2)
                    {
                        int zz = Memory.Read<int>((IntPtr)(result + 0x4), "");
                        //NewObject("zz: " + zz.ToString("x8"));
                        //NewObject("result: " + result.ToString("x8"));
                        result = Memory.Read<int>((IntPtr)(result), "");
                        if (result == 0)
                        {
                            break;
                            return 0;
                            //goto LABEL_4;
                        }
                    }
                    //*(result + 8) = a3;
                }
                //NewObject("end-result: " + result.ToString("x8"));
                return result;
    
                # endregion
    
            }


    Code:
            private void button20_Click(object sender, EventArgs e)
            {
    
                int player_guid = Diablo3.Actor.GetPlayerGUID();
                int actor_ptr = Diablo3.Actor.GetActorByGUID(player_guid);
                Console.WriteLine("actor_ptr: " + actor_ptr.ToString("x8"));
                if (actor_ptr != 0)
                {
                    int acd_GUID = Memory.Read<int>((IntPtr)(actor_ptr + 4), "");
                    if (acd_GUID != -1)
                    {
                        Console.WriteLine("player_guid: " + player_guid.ToString("x8"));
                        Console.WriteLine("acd_GUID: " + acd_GUID.ToString("x8"));
    
                        int acd_ptr = Diablo3.ACD.GetACDPtrFromGUID(acd_GUID);
                        Console.WriteLine("acd_ptr: " + acd_ptr.ToString("x8"));
    
                        Diablo3.ACD acd = new Diablo3.ACD(acd_ptr);
                        Console.WriteLine("FAG_GUID: " + acd.FAG_GUID.ToString("x8"));
    
                        int fag_ptr = Diablo3.FAG.GetFAGPtrFromGUID(acd.FAG_GUID);
                        Console.WriteLine("fag_ptr: " + fag_ptr.ToString("x8"));
    
                        Diablo3.FAG fag = new Diablo3.FAG(fag_ptr);
                        float hp = fag.GetFloat("Hitpoints_Cur");
                        Console.WriteLine("hp: " + hp);
                    }
                }
            }

    Code:
        public class D3Attributes
        {
    
            static D3Attributes main;
            public static D3Attributes Main
            {
                get
                {
                    if (main == null)
                    {
                        main = new D3Attributes();
                    }
                    return main;
                }
            }
    
            # region Fields
    
            Dictionary<string, int> dict = new Dictionary<string, int>();
    
            # endregion
    
            # region Constructors
    
            public D3Attributes()
            {
                Init();
            }
    
            # endregion
    
            # region Methods
    
            private void Init()
            {
    
                int count = (0x155159C - 0x1549504) / 0x28;
                for (int i = 0; i < count; i++)
                {
                    int ptr = 0x1549504 + i * 0x28;
    
                    int name_ptr = Memory.Read<int>((IntPtr)(ptr), "");
                    string name = Memory.ReadCString((IntPtr)(name_ptr), 100, "");
                    int value = Memory.Read<int>((IntPtr)(0x15494E8 + i * 0x28), "");
    
                    dict.Add(name, value);
                    //Console.WriteLine("i: " + i + " name: " + name);
                    //Console.WriteLine("ptr " + _ptr.ToString("x8"));
                    //Console.WriteLine("value " + value.ToString("x8"));
                }
    
            }
    
            public int GetAttribute(string attribute)
            {
                if (dict.ContainsKey(attribute))
                {
                    return dict[attribute];
                }
                return -1;
            }
    
            # endregion
    
        }

    in FAG-class:

    Code:
            public int GetInt(string attribute)
            {
                int _attribute = D3Attributes.Main.GetAttribute(attribute);
                if (_attribute != -1)
                {
                    return GetInt((uint)_attribute | 0xFFFFF000);
                }
                return -1;
            }
    
            public int GetInt(uint a2)
            {
                int ret = get_attribute(this.ptr, a2);
    
                if (ret != 0)
                {
                    int return_value = Memory.Read<int>((IntPtr)(ret + 8), "");
                    //NewObject("return_value: " + return_value);
                    return return_value;
                }
                return -1;
            }
    
            public float GetFloat(string attribute)
            {
                int _attribute = D3Attributes.Main.GetAttribute(attribute);
                if (_attribute != -1)
                {
                    return GetFloat((uint)_attribute | 0xFFFFF000);
                }
                return -1;
            }
    
            public float GetFloat(uint a2)
            {
                int ret = get_attribute(this.ptr, a2);
    
                if (ret != 0)
                {
                    float return_value = Memory.Read<float>((IntPtr)(ret + 8), "");
                    //NewObject("return_value: " + return_value);
                    return return_value;
                }
                return -1;
            }
    Last edited by matamore; 05-24-2012 at 12:16 AM.

  8. #8
    BitHacker's Avatar Master Sergeant
    Reputation
    13
    Join Date
    May 2012
    Posts
    114
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    matamore,

    Thank you, we need more posts like this across the forum. Very informative.. Thank you again..

    -Bit_Hacker

  9. #9
    DrGonzo's Avatar Contributor
    Reputation
    144
    Join Date
    Jun 2009
    Posts
    132
    Thanks G/R
    0/59
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    (uint)_attribute | 0xFFFFF000
    Didn't know about that part. My code works as is. Best. Fix. Ever.

  10. #10
    Nonal2's Avatar Private
    Reputation
    1
    Join Date
    May 2012
    Posts
    3
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by matamore View Post
    there is a FAG_GUID in ACD-struct at 0x120.
    use it to get the correct FAG (FastAttribGroups) entry by
    the same method like iterating actors.
    obj_manager: 0x179FFA0, offset 0x2e8, struct size 0x2d0
    Thanks for this very informative post, Matamore.

    In case this is of use to someone, instead of using "0x179FFA0, offset 0x2e8" (now 0x017AD950, offset 0x2e8 in 9749) an alternative way to access FAG Map from ObjectManagerPtr is:
    • [[Storage + 0xC8] + 0x70] or
    • [[ manager + 0x77C + 0xC8] + 0x70]


    Code:
    	const unsigned int MANAGER_PTR = 0x15799EC; //[9558] 0x156c8cc [9749]
    	const unsigned int MANAGER_TO_STORAGE = 0x77c; //[9558][9749]
    	const unsigned int STORAGE_TO_FAG_MGR_1 = 0xC8; //[9749]
    	const unsigned int STORAGE_TO_FAG_MGR_2 = 0x70; //[9749]
    
    	unsigned int ObjectManagerAddress = getInt(MANAGER_PTR);
    	unsigned int storage = ObjectManagerAddress+MANAGER_TO_STORAGE;
    	unsigned int FAGMap = getInt(getInt(storage+STORAGE_TO_FAG_MGR_1)+STORAGE_TO_FAG_MGR_2);
    One thing that intrigues me is that when I dump content of attributes hashmap (ie. not access by key but iterate it), I find a lot of keys which are not of the form 0xFFFFFxxx, which means this hashmap is used to store something else than only attributes - or means that I cannot write an hashmap iteration correctly. Does someone know what is also stored in there ? I must admit I have not searched for .insert() operations, which may give a hint.

    Code:
    	000000B5: FFFFF24A FFFFF04A 
    	000000B6: 000010B6 000000B6 
    	000000B7: FFFFF148 075E01E9 000010B7 000000B7 
    	000000B8: FFFFF147 FFFFF047 
    	000000B9: FFFFF146 FFFFF046 076951D0 
    	000000BA: FFFFF145
    BTW I think 0x2D0 is a typo in your post (this is ACD size), as you have indeed written 0x180 in your code.
    Last edited by Nonal2; 05-31-2012 at 03:30 PM. Reason: fixed typo: too many brackets

  11. #11
    hb123220's Avatar Sergeant
    Reputation
    8
    Join Date
    Mar 2012
    Posts
    40
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Nonal2 View Post
    Thanks for this very informative post, Matamore.

    In case this is of use to someone, instead of using "0x179FFA0, offset 0x2e8" (now 0x017AD950, offset 0x2e8 in 9749) an alternative way to access FAG Map from ObjectManagerPtr is:
    • [[Storage + 0xC8] + 0x70] or
    • [[[ manager + 0x77C ] + 0xC8] + 0x70]


    Code:
    	const unsigned int MANAGER_PTR = 0x15799EC; //[9558] 0x156c8cc [9749]
    	const unsigned int MANAGER_TO_STORAGE = 0x77c; //[9558][9749]
    	const unsigned int STORAGE_TO_FAG_MGR_1 = 0xC8; //[9749]
    	const unsigned int STORAGE_TO_FAG_MGR_2 = 0x70; //[9749]
    
    	unsigned int ObjectManagerAddress = getInt(MANAGER_PTR);
    	unsigned int storage = ObjectManagerAddress+MANAGER_TO_STORAGE;
    	unsigned int FAGMap = getInt(getInt(storage+STORAGE_TO_FAG_MGR_1)+STORAGE_TO_FAG_MGR_2);
    [[0x15799EC]+0x77c] =0 ?????
    i've got FAG_GUID in ACD-struct ,,how to find out "obj_manager: 0x179FFA0, offset 0x2e8, struct size 0x2d0" for [9558]???

  12. #12
    Nonal2's Avatar Private
    Reputation
    1
    Join Date
    May 2012
    Posts
    3
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by hb123220 View Post
    [[0x15799EC]+0x77c] =0 ?????
    i've got FAG_GUID in ACD-struct ,,how to find out "obj_manager: 0x179FFA0, offset 0x2e8, struct size 0x2d0" for [9558]???
    That was a typo indeed: you can do [[ [0x15799EC] + 0x77C + 0xC8] + 0x70] (as indicated in code),
    or the other way: [ [ [ 0x017AD950 ] ] + 0x2E8 ]

    both should give same answer and point to the FAG Map. I personnally do everything starting from [0x15799EC].

  13. #13
    hb123220's Avatar Sergeant
    Reputation
    8
    Join Date
    Mar 2012
    Posts
    40
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    huge thanks,,[[ [0x15799EC] + 0x77C + 0xC8] + 0x70] works ~

Similar Threads

  1. [5.0.5 16057][OOP] Reading completed quests out of memory...
    By Tanaris4 in forum WoW Memory Editing
    Replies: 12
    Last Post: 10-13-2012, 01:14 PM
  2. [1.0.1 9558] OOP - How do I read the GUID?
    By Tanaris4 in forum Diablo 3 Memory Editing
    Replies: 9
    Last Post: 05-22-2012, 04:50 PM
  3. Understanding localized strings (how to read them OOP)
    By Tanaris4 in forum WoW Memory Editing
    Replies: 18
    Last Post: 04-12-2010, 04:04 PM
  4. Thottbot Search Engine (MATT please read)
    By Tbone in forum Community Chat
    Replies: 13
    Last Post: 11-07-2006, 06:27 AM
All times are GMT -5. The time now is 01:16 AM. 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