Deprecated: The behavior of unparenthesized expressions containing both '.' and '+'/'-' will change in PHP 8: '+'/'-' will take a higher precedence in /home/iano/public_html/tpforums-vb5/forum/includes/class_core.php on line 5842

PHP Warning: Use of undefined constant MYSQL_NUM - assumed 'MYSQL_NUM' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: Use of undefined constant MYSQL_ASSOC - assumed 'MYSQL_ASSOC' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: Use of undefined constant MYSQL_BOTH - assumed 'MYSQL_BOTH' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in ..../includes/functions_navigation.php on line 588

PHP Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in ..../includes/functions_navigation.php on line 612

PHP Warning: Use of undefined constant misc - assumed 'misc' (this will throw an Error in a future version of PHP) in ..../global.php(29) : eval()'d code(6) : eval()'d code on line 1

PHP Warning: Use of undefined constant index - assumed 'index' (this will throw an Error in a future version of PHP) in ..../global.php(29) : eval()'d code(6) : eval()'d code on line 1

PHP Warning: Use of undefined constant misc - assumed 'misc' (this will throw an Error in a future version of PHP) in ..../includes/class_bootstrap.php(1422) : eval()'d code(4) : eval()'d code on line 1

PHP Warning: Use of undefined constant index - assumed 'index' (this will throw an Error in a future version of PHP) in ..../includes/class_bootstrap.php(1422) : eval()'d code(4) : eval()'d code on line 1

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6
10.10 Address finding
Results 1 to 6 of 6

Thread: 10.10 Address finding

  1. #1
    Senior Member
    Join Date
    Jan 2008
    Location
    Cambridge, England
    Posts
    725

    10.10 Address finding

    So I'm tired of releasing posts here which publish the addresses for items which I suspect no longer exist nor have any relevance, I decided it's time to try some shit out and see if I can personally work out what the values mean. I'm gonna post my results here, if anyone wants to put up any clues, please do so as all information is welcome. I will look at the existing structures, I just want to know what as many bytes as possible from this mean. Here's the list so far:

    Code:
                public UInt32 cid; // 4 bytes
                public string name; // 32 bytes
                public byte[] unknown; // 16 unknown bytes
                public UInt32 z; // 4 bytes z
                public UInt32 y; // 4 bytes y
                public UInt32 x; // 4 bytes x
                public byte[] unknown2; // 8 bytes unknown
                public UInt32 Direction; // Currently facing (0 north, 1 east, 2 south, 3 west)
                public UInt32 rnd2; // 4 more bytes of random number, really random
                public UInt32 rnd3; // 4 more bytes of random number, really random (as last)
                public UInt32 rnd4; // 4 more bytes of random, appears to be primarily 0-32
                public UInt32 rnd5; // as previous
                public UInt32 rnd6; // always 900 on npc?
                public UInt32 isWalking; // Is walking value
                public byte[] unknown1; // 12 bytes of unknown shit, last one is quite a long number (2147483748)
                public UInt32 Outfit1; // 4 byte outfit type, 129 for npc
                public UInt32 Outfit2; // 4 byte outfit type, 19 for npc
                public UInt32 Outfit3; // 4 byte outfit type, 113 for npc
                public UInt32 Outfit4; // 4 byte outfit type, 95 for npc
                public UInt32 Outfit5; // 4 byte outfit type, 115 for NPC
                public byte[] unknown2; // 24 bytes of empty values on npc...
                public UInt32 hppc; // 4 byte hppc (100 for npc and self in test)
                public UInt32 rnd7; // 4 bytes, 45 on npc...
                public UInt32 rnd8; // 4 bytes, 1 on npc...
                public byte[] unknown3; // 12 bytes unknown values
                public UInt32 rnd9; // 4 bytes, 1 on npc
                public UInt32 rnd10; // 4 byte value, 357 for npc
                public UInt32 rnd11; // 4 byte value 0
                public UInt32 rnd12; // 4 byte value 153
                public UInt32 rnd13; // 4 byte value 0
                public UInt32 rnd14; // 4 byte value 0
                public UInt32 rnd15; // 4 byte value 0
                public UInt32 rnd16; // 4 byte value 2
    Note that what I did so far is just took a random snapshot, looked at the values, linked them to the code, and now here I effectively have a struct which somewhat matches what I expect to find. Where I've put byte[] it is difficult to see why the values would be as they are, and they are groups of 4 byte 0's (e.g unknown3 is 3 sequential 4 byte integers which have the value 0).

    Time to study up and see what I can actually learn from this shit
    Last edited by XtrmJash; 07-26-2013 at 09:31 PM.

  2. #2
    Senior Member
    Join Date
    Jan 2008
    Location
    Cambridge, England
    Posts
    725
    Code:
            public static Util util;
            [DllImport("kernel32.dll")]
            public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
                [In, Out] IntPtr buffer, UInt32 size, out int lpNumberOfBytesRead);
    
            public static Structures.BattleListEntry GetBattleListEntry(int index)
            {
                int numberOfBytesRead;
                Type type = typeof(Structures.BattleListEntry);
                int size = Marshal.SizeOf(type);
                IntPtr BytesRead = Marshal.AllocHGlobal(size);
                
                ReadProcessMemory(util._Handle, (IntPtr)(BLAddress.Start + util._Base), BytesRead, (uint)size, out numberOfBytesRead);
                Structures.BattleListEntry ble = (Structures.BattleListEntry)Marshal.PtrToStructure(BytesRead, type);
                Marshal.FreeHGlobal(BytesRead);
                return ble;
            }
    So what I'm doing is initialising my util class:

    Code:
        public class Util
        {
            public Process _Tibia;
            public UInt32 _Base;
            public IntPtr _Handle;
            public Util(Process Tibia)
            {
                _Tibia = Tibia;
                _Base = (UInt32)Tibia.MainModule.BaseAddress.ToInt32();
                _Handle = Tibia.MainWindowHandle;
            }
        }
    With the first client it can find. The struct currently looks like this:

    Code:
            public struct BattleListEntry
            {
                public UInt32 cid; // 4 bytes
                public string name; // 32 bytes
                public byte[] unknown; // 16 unknown bytes
                public UInt32 z; // 4 bytes z
                public UInt32 y; // 4 bytes y
                public UInt32 x; // 4 bytes x
                public byte[] unknown2; // 8 bytes unknown
                public UInt32 direction; // Currently facing (0 north, 1 east, 2 south, 3 west)
                public UInt32 timeLastMovement; // The actual time you last moved
                public UInt32 rnd3; // Repeat of previous?
                public UInt32 rnd4; // 4 more bytes of random, appears to be primarily 0-32
                public UInt32 rnd5; // as previous
                public UInt32 rnd6; // always 900 on npc?
                public UInt32 isWalking; // Is walking value
                public byte[] unknown1; // 12 bytes of unknown shit, last one is quite a long number (2147483748)
                public UInt32 Outfit1; // 4 byte outfit type, 129 for npc
                public UInt32 Outfit2; // 4 byte outfit type, 19 for npc
                public UInt32 Outfit3; // 4 byte outfit type, 113 for npc
                public UInt32 Outfit4; // 4 byte outfit type, 95 for npc
                public UInt32 Outfit5; // 4 byte outfit type, 115 for NPC
                public byte[] unknown3; // 24 bytes of empty values on npc...
                public UInt32 hppc; // 4 byte hppc (100 for npc and self in test)
                public UInt32 rnd7; // 4 bytes, 45 on npc...
                public UInt32 rnd8; // 4 bytes, 1 on npc...
                public byte[] unknown4; // 12 bytes unknown values
                public UInt32 rnd9; // 4 bytes, 1 on npc
                public UInt32 rnd10; // 4 byte value, 357 for npc
                public UInt32 rnd11; // 4 byte value 0
                public UInt32 rnd12; // 4 byte value 153
                public UInt32 rnd13; // 4 byte value 0
                public UInt32 rnd14; // 4 byte value 0
                public UInt32 rnd15; // 4 byte value 0
                public UInt32 rnd16; // 4 byte value 2
            }
    It's throwing an access violation on this line:

    Code:
    Structures.BattleListEntry ble = (Structures.BattleListEntry)Marshal.PtrToStructure(BytesRead, type);
    Saying I tried to write to or read protected memory... I presume that's because BytesRead is inaccessible from the thread which is running the unsafe code...?

  3. #3
    Senior Member
    Join Date
    Jan 2012
    Posts
    417
    you must fix a length for all arrays within your structure, through SizeConst of MarshalAs(...).

    your creature's name hasn't a pre-fixed length and the CLR doesn't know your string is 32 bytes long, you should fix it with SizeConst = 0x20 (32 bytes) and find the right unmanaged type for this string

    after all, make sure "Marshal.SizeOf(creatureType) == 0xC0". Writing the offset of the field in the right side help a lot to see if anything is being mapped correctly.

  4. #4
    Senior Member
    Join Date
    Jan 2008
    Location
    Cambridge, England
    Posts
    725
    Quote Originally Posted by Blequi View Post
    you must fix a length for all arrays within your structure, through SizeConst of MarshalAs(...).

    your creature's name hasn't a pre-fixed length and the CLR doesn't know your string is 32 bytes long, you should fix it with SizeConst = 0x20 (32 bytes) and find the right unmanaged type for this string

    after all, make sure "Marshal.SizeOf(creatureType) == 0xC0". Writing the offset of the field in the right side help a lot to see if anything is being mapped correctly.
    Ahhh shiet, I knew I'd forgotten something hahaha. Surely using the sizeof() would analyse it properly and void the risk of the exception though?

  5. #5
    Senior Member
    Join Date
    Sep 2007
    Posts
    230
    Marshal.SizeOf also throws an exception if there is an error in the marshalling data for the structure which is probably where the exception is actually coming from, in this case is the error is the lack of MarshalAs attributes for the string and arrays to specify their native type and size. For the string you want to marshal it as an UnmanagedType.ByValTStr with a SizeConst value of 32, and the CharSet must be set to ANSI which is the default in C#. For the arrays you want ByValArray and appropriate SizeConst, and it's important to know that SizeConst is actually the number of elements/characters in the array/string and not the actual size in bytes.

  6. #6
    Senior Member
    Join Date
    Jan 2012
    Posts
    417
    looks like you want to move your code to this new approach and it's really a great step to chose.

    For a battle list-like reader, instead of allocating / freeing memory foreach creature, you should alloc the whole battle list array and just marshal the right creature.

    EDIT: and ofc, keep the battle list allocated in unmanaged memory for the lifetime of your application

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •