how to find ObjectManagerPtr version/built menu

Shout-Out

User Tag List

Results 1 to 10 of 10
  1. #1
    wineggdrop's Avatar Sergeant
    Reputation
    1
    Join Date
    Feb 2013
    Posts
    38
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    how to find ObjectManagerPtr version/built

    every new built/patch,we need to get the new offset,any data pattern to get the ObjectManagerPtr offset via memory search?

    how to find ObjectManagerPtr version/built
  2. #2
    KillerJohn's Avatar TurboHUD HUDmaster CoreCoins Purchaser Authenticator enabled
    Reputation
    3696
    Join Date
    Jul 2012
    Posts
    2,532
    Thanks G/R
    46/3338
    Trade Feedback
    0 (0%)
    Mentioned
    16 Post(s)
    Tagged
    0 Thread(s)
    I wrote a little snippet for this. The main goal is to check all addresses around the "last" ObjectManager offset and walk the path to your local actor. If you found it, that address is the new ObjectManager.
    The offsets relative to ObjectManager are well known and available from public sources (check DarthTon's framework) so I don't bother posting them here

    Code:
            private void FindInMemory_ObjectManager(int CurrentObjectManager_address, uint MyCurrentCharacterSNO)
            {
                int start_address = 1024 * 1024 * 0;
                int end_address = CurrentObjectManager_address * 2;
    
                for (int i = start_address; i <= end_address; i += 4)
                {
                    if (i % (1024 * 1024 * 5) == 0) Trace.WriteLine("@ " + (i / 1024 / 1024).ToString() + " MB");
                    if (i == CurrentObjectManager_address)
                    {
                        Trace.WriteLine("here we are...");
                    }
    
                    int ObjectManagerPtr = MR.ReadInt(i);
                    if (ObjectManagerPtr < 0) continue;
    
                    int ObjectManagerStoragePtr = ObjectManagerPtr + ObjectManager_ofs__storage;
    
                    int ObjectManagerStorageDataPtr = MR.ReadInt(ObjectManagerStoragePtr + ObjectManagerStorage_ofs__data);
                    if (ObjectManagerStorageDataPtr <= 0) continue;
    
                    int ObjectManagerStorageLocalPtr = MR.ReadInt(ObjectManagerStoragePtr + ObjectManagerStorage_ofs__local);
                    if (ObjectManagerStorageLocalPtr <= 0) continue;
    
                    int MyPlayerIndex = MR.ReadInt(ObjectManagerStorageLocalPtr);
                    if (MyPlayerIndex != 0) continue;
    
                    uint MyActorID = MR.ReadUInt(ObjectManagerStorageDataPtr + MyPlayerIndex * 0x8590 + 0x58 + 0x8 );
                    if ((MyActorID == 0) || (MyActorID == uint.MaxValue)) continue;
    
                    // ACD
                    int tmp = MR.ReadInt(ObjectManagerStoragePtr + ObjectManagerStorage_ofs__acds);
                    int container_ofs = MR.ReadInt(tmp);
                    tmp = MR.ReadInt(container_ofs + 0x148 ); //container.List, double pointer
                    int acd_data_start_ofs = MR.ReadInt(tmp); //container.List
                    acd_sizeof = MR.ReadInt(container_ofs + 0x104); //container.SizeOf
                    int acd_count_ofs = container_ofs + 0x108; //container.Count
                    int acd_bitshift = MR.ReadInt(container_ofs + 0x18C); //container.Bits
    
                    //actors
                    container_ofs = MR.ReadInt(ObjectManagerStoragePtr + ObjectManagerStorage_ofs__actors);
                    tmp = MR.ReadInt(container_ofs + 0x148 ); //container.List, double pointer
                    int actor_data_start_ofs = MR.ReadInt(tmp);
                    actor_sizeof = MR.ReadInt(container_ofs + 0x104); //container.SizeOf
                    int actor_count_ofs = container_ofs + 0x108; //container.Count
                    int actor_bitshift = MR.ReadInt(container_ofs + 0x18C); //container.Bits
    
                    int MyActorIndex = (int)(MyActorID & 0xFFFF);
                    int MyActorAddress = actor_data_start_ofs + (MyActorIndex & ((1 << actor_bitshift) - 1)) * actor_sizeof + 4 * (MyActorIndex >> actor_bitshift);
                    if (MyActorAddress <= 0) continue;
    
                    uint MyAcdID = MR.ReadUInt(MyActorAddress + actor_ofs__acd_id);
                    if ((MyAcdID == 0) || (MyAcdID == uint.MaxValue)) continue;
    
                    int MyACDIndex = (int)(MyAcdID & 0xFFFF);
                    int MyACDAddress = acd_data_start_ofs + (MyACDIndex & ((1 << acd_bitshift) - 1)) * acd_sizeof + 4 * (MyACDIndex >> acd_bitshift);
                    if (MyACDAddress <= 0) continue;
    
                    uint SNO = MR.ReadUInt(MyACDAddress + acd_ofs__sno);
                    if (SNO != MyCurrentCharacterSNO) continue;
    
                    Log("m3mread", "objectmanager candidate: 0x" + i.ToString("X") + "(current: 0x" + CurrentObjectManager_address.ToString("X") + ")");
                }            
            }
    Last edited by KillerJohn; 03-13-2013 at 07:06 AM.
    Do not send me private messages unless it is absolutely necessary or the content is sensitive or when I ask you to do that...

  3. #3
    wineggdrop's Avatar Sergeant
    Reputation
    1
    Join Date
    Feb 2013
    Posts
    38
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    thx,I get the idea.you try to scan the memory and see which address comes out with the most likely valid data.good for me to start

  4. #4
    enigma32's Avatar Legendary
    Reputation
    912
    Join Date
    Jan 2013
    Posts
    551
    Thanks G/R
    4/738
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here's some really old code I have that has so far never failed at finding an updated address. Can't remember exactly where I got the required information to implement it, and I have no idea what OP codes it translates to so don't ask

    Code:
    private readonly static byte[] ObjectManagerPattern = new byte[] {
        0x8B, 0x00, 0x00, 0x00, 0x00, 0x00,
        0xC7, 0x00, 0x00, 0x03, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
    
    
    private readonly static byte[] ObjectManagerPatternMask = new byte[] {
        0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
        0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
    
    
    private static int FindPattern(byte[] data, byte[] pattern, byte[] mask)
    {
        for (int i = 0; i < data.Length; i++)
        {
            bool match = true;
            for (int n = 0; n < pattern.Length; n++)
            {
                if ((mask[n] & data[i + n]) != (mask[n] & pattern[n]))
                {
                    match = false;
                    break;
                }
            }
            if (match)
            {
                return i;
            }
        }
        return 0;
    }
    
    
    public Engine(Process process)
    {
        Process = process;
        Memory = process.GetProcessMemory();
    
    
        byte[] module = Process.GetMainModuleMemory();
        ObjectManagerPtrPtr = new IntPtr(BitConverter.ToInt32(
            module,
            FindPattern(module, ObjectManagerPattern, ObjectManagerPatternMask) + 2));
    }

  5. #5
    iamclint's Avatar Master Sergeant
    Reputation
    14
    Join Date
    Aug 2012
    Posts
    84
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    you could always use ida pro and patch diff

  6. #6
    wineggdrop's Avatar Sergeant
    Reputation
    1
    Join Date
    Feb 2013
    Posts
    38
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I would try to learn ida.thx for the help

  7. #7
    wineggdrop's Avatar Sergeant
    Reputation
    1
    Join Date
    Feb 2013
    Posts
    38
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by enigma32 View Post
    Here's some really old code I have that has so far never failed at finding an updated address. Can't remember exactly where I got the required information to implement it, and I have no idea what OP codes it translates to so don't ask

    Code:
    private readonly static byte[] ObjectManagerPattern = new byte[] {
        0x8B, 0x00, 0x00, 0x00, 0x00, 0x00,
        0xC7, 0x00, 0x00, 0x03, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
    
    
    private readonly static byte[] ObjectManagerPatternMask = new byte[] {
        0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
        0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
    
    
    private static int FindPattern(byte[] data, byte[] pattern, byte[] mask)
    {
        for (int i = 0; i < data.Length; i++)
        {
            bool match = true;
            for (int n = 0; n < pattern.Length; n++)
            {
                if ((mask[n] & data[i + n]) != (mask[n] & pattern[n]))
                {
                    match = false;
                    break;
                }
            }
            if (match)
            {
                return i;
            }
        }
        return 0;
    }
    
    
    public Engine(Process process)
    {
        Process = process;
        Memory = process.GetProcessMemory();
    
    
        byte[] module = Process.GetMainModuleMemory();
        ObjectManagerPtrPtr = new IntPtr(BitConverter.ToInt32(
            module,
            FindPattern(module, ObjectManagerPattern, ObjectManagerPatternMask) + 2));
    }

    I use your code and get the ObjectManager address at 0xe6060d

    Data at 0x18939c4 = {0x00,0xBE,0x40,0x07,0xCC,0x68,0xF0,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
    and the code "if ((mask[n] & data[i + n]) != (mask[n] & pattern[n]))" wouldn't match the above data.
    did I do anything wrong?
    Last edited by wineggdrop; 03-14-2013 at 10:58 PM.

  8. #8
    boredevil's Avatar Active Member
    Reputation
    46
    Join Date
    Feb 2008
    Posts
    166
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Looks like you got the concept wrong. Pattern finding normally means find a piece of code not find some data that belongs to a class.
    I will try to give you a little headstart with ida.

    I will use the "ida style" text patterns that look like "E9 ? ? ? ? C8 ?". ? represents a wildcard. you could also write "E9 ?? ?? ?? ?? C8 ??" it´s both the same

    Make a new folder, and copy your Diablo III.exe and ijl15.dll in it.
    Open ida, and drag the exe in it. Select Pe-File and hit ok.
    Now grab a cup of coffee and wait, till Ida finished analyzing it.

    The IDA View-A window should now be active in graph view. Switch to Disassembly view by hitting SPACE
    Go to the Menu Options->General and set Number of opcode bytes to 10.

    now hit G and jump to address 0x00E60580. That´s the function that Allocates the Object Manager.

    you should see the function it this representation:
    address of instruction - bytecode of instruction - text representation of instruction
    Code:
    .text:00E60580                               sub_E60580      proc near               ; DATA XREF: .data:016AAA74o
    .text:00E60580 53                                            push    ebx
    .text:00E60581 56                                            push    esi
    .text:00E60582 57                                            push    edi
    .text:00E60583 6A 01                                         push    1
    .text:00E60585 33 FF                                         xor     edi, edi
    .text:00E60587 57                                            push    edi
    .text:00E60588 6A 04                                         push    4
    .text:00E6058A 68 88 09 00 00                                push    988h   // size of Object Manager
    .text:00E6058F E8 8C 16 1B 00                                call    sub_1011C20    // memory allocation Function
    .text:00E60594 83 C4 10                                      add     esp, 10h
    .text:00E60597 A3 C4 39 89 01                                mov     dword_18939C4, eax // pObjMgr
    .text:00E6059C 8B F0                                         mov     esi, eax
    .text:00E6059E E8 DD 08 1C 00                                call    sub_1020E80
    .text:00E605A3 8B 1D 0C 72 43 01                             mov     ebx, ds:TlsGetValue
    .text:00E605A9 89 06                                         mov     [esi], eax
    .text:00E605AB 89 7E 04                                      mov     [esi+4], edi
    .text:00E605AE 89 7E 08                                      mov     [esi+8], edi
    .text:00E605B1 A1 C4 39 89 01                                mov     eax, dword_18939C4
    .text:00E605B6 89 78 18                                      mov     [eax+18h], edi
    .text:00E605B9 8B 0D C4 39 89 01                             mov     ecx, dword_18939C4
    .text:00E605BF C7 81 E4 03 00 00 FF FF FF FF                 mov     dword ptr [ecx+3E4h], 0FFFFFFFFh
    .text:00E605C9 8B 15 C4 39 89 01                             mov     edx, dword_18939C4
    .text:00E605CF 89 BA E0 03 00 00                             mov     [edx+3E0h], edi
    .text:00E605D5 A1 C4 39 89 01                                mov     eax, dword_18939C4
    .text:00E605DA 89 B8 0C 04 00 00                             mov     [eax+40Ch], edi
    .text:00E605E0 8B 0D 10 BC 6A 01                             mov     ecx, dwTlsIndex
    .text:00E605E6 8B 35 C4 39 89 01                             mov     esi, dword_18939C4
    .text:00E605EC 51                                            push    ecx             ; dwTlsIndex
    .text:00E605ED 81 C6 8C 07 00 00                             add     esi, 78Ch
    .text:00E605F3 FF D3                                         call    ebx ; TlsGetValue
    .text:00E605F5 8B 10                                         mov     edx, [eax]
    .text:00E605F7 C7 42 04 01 00 00 00                          mov     dword ptr [edx+4], 1
    .text:00E605FE A1 10 BC 6A 01                                mov     eax, dwTlsIndex
    .text:00E60603 50                                            push    eax             ; dwTlsIndex
    .text:00E60604 FF D3                                         call    ebx ; TlsGetValue
    .text:00E60606 8B 08                                         mov     ecx, [eax]
    .text:00E60608 6A 01                                         push    1
    .text:00E6060A 57                                            push    edi
    .text:00E6060B 6A 04                                         push    4
    .text:00E6060D 68 A4 18 00 00                                push    18A4h
    .text:00E60612 89 31                                         mov     [ecx], esi
    .text:00E60614 E8 07 16 1B 00                                call    sub_1011C20
    .text:00E60619 8B 15 C4 39 89 01                             mov     edx, dword_18939C4
    .text:00E6061F 89 82 84 07 00 00                             mov     [edx+784h], eax
    .text:00E60625 A1 C4 39 89 01                                mov     eax, dword_18939C4
    .text:00E6062A 8B 88 84 07 00 00                             mov     ecx, [eax+784h]
    .text:00E60630 51                                            push    ecx
    .text:00E60631 E8 AA F0 D2 FF                                call    sub_B8F6E0
    .text:00E60636 83 C4 14                                      add     esp, 14h
    .text:00E60639 5F                                            pop     edi
    .text:00E6063A 5E                                            pop     esi
    .text:00E6063B 5B                                            pop     ebx
    .text:00E6063C C3                                            retn
    .text:00E6063C                               sub_E60580      endp
    Now about Creating patterns.
    You need to create a pattern that will only be found once in the whole client and still be valid after a patch.
    Let´s start with the function itself. Things that are most likely not changing between patches go into your pattern.
    Things that are going to change (addresses, offsets and maybe arguments) are added as wildcards.
    Code:
    .text:00E60580 53                                            push    ebx         // 53 - unlikely to change
    .text:00E60581 56                                            push    esi         // 56 - unlikely to change
    .text:00E60582 57                                            push    edi         // 57 - unlikely to change
    .text:00E60583 6A 01                                         push    1           // 6a ? - 1 may change. so wildcard it
    .text:00E60585 33 FF                                         xor     edi, edi    // 33 FF - unlikely to change
    .text:00E60587 57                                            push    edi         // 57 
    .text:00E60588 6A 04                                         push    4           // 6A ?
    .text:00E6058A 68 88 09 00 00                                push    988h        // 68 ? ? ? ? // size of ObjMgr can change -> wildcard
    The resulting pattern is: "53 56 57 6A ? 33 FF 57 6A ? 68 ? ? ? ?"
    Let´s test if it is unique. Menu->Search->sequence of bytes. enter the pattern and don´t forget to check "find all occurances"
    If it´s unique great. else add a few more instructions to the pattern
    DWORD addrFunctionAllocObjMgr = addrPattern.
    DWORD sizeofObjMgr = *(DWORD*) (addrPattern + 11)


    Now to the ObjMgrPtr
    Code:
    .text:00E6058A 68 88 09 00 00                                push    988h               // 68 ? ? ? ? // size of Object Manager
    .text:00E6058F E8 8C 16 1B 00                                call    sub_1011C20        // E8 ? ? ? ?// memory allocation Function
    .text:00E60594 83 C4 10                                      add     esp, 10h           // 83 C4 ?
    .text:00E60597 A3 C4 39 89 01                                mov     dword_18939C4, eax // A3 ? ? ? ?// pObjMgr
    .text:00E6059C 8B F0                                         mov     esi, eax           // 8B F0
    Pattern: "68 ? ? ? ? E8 ? ? ? ? 83 C4 ? A3 ? ? ? ? 8B F0"
    DWORD sizeofObjMgr = *(DWORD*) (addrPattern + 1)
    DWORD pObjMgr = *(DWORD*) (addrPattern + 14)

    i hope you got the concept.
    If you want to make your life easyer, you can google for "SigMaker Ida" it´s a plugin that either creates pattern for the selected code or tries to create the shortest possible pattern that brings you to the position of your mouse. It´s not idiot proof and you sometimes have to add a few wildcards to it´s output but still makes things easyer.

    Searching patterns by hand sucks. Counting bytes like (addrPattern + 14) also sucks. So here is my script finds patterns and sets itemnames:

    Code:
    #!/usr/bin/python2.6
    
    
    
    #############################################
    #
    # Configure
    #
    #
    
    # set to True to automatically rename items
    renameMatches = True
    
    # edit if different output is needed. or you want to log to file
    def formatLogLine( function, name ):
        return hex(function).upper() + "\t" + name + "\n"
    
    
        
        
    #############################################
    #
    # Code
    #
    #
    
    Message("\n######################\n")
    Message("Starting Patternfinder\n\n")
        
    #set search range to the segment the cursor is currently in
    ea = ScreenEA()
    eaStart = SegStart(ea)
    eaEnd = SegEnd(ea)
    
    # Find Pattern
    # name          obvious
    # pattern       ida style pattern to be searched
    # numSkipInstr  number of instructions to step forward/backward     
    # numOperant    number of operant that contains the desired value. -1 if you just need the code address 
    def FindPattern( name, pattern, numSkipInstr = 0, numOperant = -1 ):
    
        # find the pattern
        addr = idaapi.find_binary(eaStart, eaEnd, pattern , 16,1)
        
        if addr > 0 and numSkipInstr != 0:
            # step x instructions for/backwards
            for i in range(0, numSkipInstr):
                if numSkipInstr > 0:
                    addr = NextHead(addr,eaEnd)
                else:
                    addr = PrevHead(addr)
        
        res = addr
        if addr > 0 and numOperant != -1:
            # extraxt operant value
            res = GetOperandValue(addr, numOperant)
    
            
        if res > 0:
            Message( formatLogLine( res, name ))
            
            if renameMatches == True:
                if MakeName(res,name) == False:
                    MakeComm(addr,name)
        else:
            Message( "Failed to find Pattern " + name + "\n")
        return
    
    
    
    FindPattern("D3::AllocObjMgr", "53 56 57 6A ? 33 FF 57 6A 04 68 ? ? ? ?", 0, -1);
    FindPattern("D3::AllocObjMgr", "53 56 57 6A 01 33 FF 57 6A 04 68 ? ? ? ?");
    
    FindPattern("sizeOfObjMgr", "68 ? ? ? ? E8 ? ? ? ? 83 C4 ? A3 ? ? ? ? 8B F0", 0, 0)
    FindPattern("D3::AllocateMemory", "68 ? ? ? ? E8 ? ? ? ? 83 C4 ? A3 ? ? ? ? 8B F0", 1, 0)
    FindPattern("pObjMgr", "68 ? ? ? ? E8 ? ? ? ? 83 C4 ? A3 ? ? ? ? 8B F0", 3, 0)
    FindPattern("pObjMgr", "68 ? ? ? ? E8 ? ? ? ? 83 C4 ? A3 ? ? ? ? 8B F0", 3, 0)
    will: find the pattern -> travel 3 instructions forward -> read the value of the instruction's arg0
    just hit ctrl + F7 copy/paste the script and run it.
    Last edited by boredevil; 05-09-2013 at 04:57 PM.

  9. #9
    wineggdrop's Avatar Sergeant
    Reputation
    1
    Join Date
    Feb 2013
    Posts
    38
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    thx for the detail

  10. #10
    enigma32's Avatar Legendary
    Reputation
    912
    Join Date
    Jan 2013
    Posts
    551
    Thanks G/R
    4/738
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks a lot for the detailed description boredevil! I've worked quite a bit with IDA, but for Diablo I haven't found much use of it. This however gives me plenty of ideas to play around with

Similar Threads

  1. [Help] How to find WoW version as pointer?
    By Jadd in forum WoW Memory Editing
    Replies: 3
    Last Post: 08-23-2008, 06:19 AM
  2. How to downgrade your version of WoW (ex: 2.1.x to 2.0.12)
    By srb25x in forum World of Warcraft Guides
    Replies: 3
    Last Post: 06-06-2007, 02:29 PM
  3. How to find a bot who work...
    By tamipop in forum World of Warcraft General
    Replies: 4
    Last Post: 02-19-2007, 08:14 PM
  4. How To: Find put ur IP address by clicking on an icon
    By ttttllllrrrr in forum Community Chat
    Replies: 1
    Last Post: 01-27-2007, 08:47 PM
  5. How to find a get a rogue stealthed -- Warlock only
    By koalaz2004 in forum World of Warcraft Exploits
    Replies: 5
    Last Post: 08-26-2006, 10:53 AM
All times are GMT -5. The time now is 04:45 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search