WoW Offsets learning menu

User Tag List

Page 3 of 3 FirstFirst 123
Results 31 to 45 of 45
  1. #31
    Archos's Avatar Member Authenticator enabled
    Reputation
    2
    Join Date
    Mar 2007
    Posts
    34
    Thanks G/R
    4/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Sweann View Post
    My binary is only good for static analysis never tried to run or hook anything i just using memory reading nothing more.
    I am curious what you are using for memory reading? Not a lot of options on Apple Silicon unless you disable SIP.

    WoW Offsets learning
  2. #32
    Archos's Avatar Member Authenticator enabled
    Reputation
    2
    Join Date
    Mar 2007
    Posts
    34
    Thanks G/R
    4/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Sweann View Post
    My binary is only good for static analysis never tried to run or hook anything i just using memory reading nothing more.
    I am curious what you are using for memory reading? Not a lot of options on Apple Silicon unless you disable SIP. Personally I have been using a macOS in a UTM VM.

  3. #33
    Sweann's Avatar Active Member Authenticator enabled
    Reputation
    15
    Join Date
    Mar 2010
    Posts
    22
    Thanks G/R
    5/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You just have to change the entitlements and add the required security options like: com.apple.security.get-task-allow and resign the binary with codesign deep. And all of this is done then you don't have to disable SIP, my simple c app simply can connect and read even the Bit Slicer app. If interested i can share the XML and sign commands used.

  4. #34
    Archos's Avatar Member Authenticator enabled
    Reputation
    2
    Join Date
    Mar 2007
    Posts
    34
    Thanks G/R
    4/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Sweann View Post
    You just have to change the entitlements and add the required security options like: com.apple.security.get-task-allow and resign the binary with codesign deep. And all of this is done then you don't have to disable SIP, my simple c app simply can connect and read even the Bit Slicer app. If interested i can share the XML and sign commands used.
    That would be wonderful!

  5. #35
    Sweann's Avatar Active Member Authenticator enabled
    Reputation
    15
    Join Date
    Mar 2010
    Posts
    22
    Thanks G/R
    5/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Replace the signature and add new entitlements:
    Code:
    WOW=/World\ of\ Warcraft/_classic_era_/World\ of\ Warcraft\ Classic.app
    SIGN=hash_of_your_apple_developer_signature
    
    codesign -s $(SIGN) -f --deep --options runtime --entitlements entitlements.xml $(WOW)
    codesign -d --entitlements - --xml $(WOW)

    The entitlements.xml file contains this:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    	<dict>
    		<key>com.apple.security.cs.allow-jit</key>
    		<true/>
    		<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
    		<true/>
    		<key>com.apple.security.cs.disable-executable-page-protection</key>
    		<true/>
    		<key>com.apple.security.device.audio-input</key>
    		<true/>
    		<key>com.apple.security.get-task-allow</key>
    		<true/>
    		<key>com.apple.security.cs.debugger</key>
    		<true/>
    	</dict>
    </plist>

  6. Thanks Corthezz, Archos (2 members gave Thanks to Sweann for this useful post)
  7. #36
    Sweann's Avatar Active Member Authenticator enabled
    Reputation
    15
    Join Date
    Mar 2010
    Posts
    22
    Thanks G/R
    5/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Oh forgot the compilation part need some extras as well...

    Code:
    <?xml version="1.0" encoding="UTF-8"?>  
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">  
    <plist version="1.0">  
    <dict>  
        <key>SecTaskAccess</key>
        <array>
            <string>allowed</string>
        </array>
    </dict>  
    </plist>
    And add these parameters for cc / clang whatever:
    Code:
    ... -sectcreate __TEXT __info_plist ./Info.plist -o memscan
    And last i sign my app

    Code:
    codesign -s $(SIGN) memscan

  8. Thanks Archos (1 members gave Thanks to Sweann for this useful post)
  9. #37
    scizzydo's Avatar Contributor
    Reputation
    134
    Join Date
    Oct 2019
    Posts
    96
    Thanks G/R
    5/54
    Trade Feedback
    0 (0%)
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Archos View Post
    Here is how far I have gotten.

    Code:
    //
    //  DumpBinary.c
    //  DumpBinary
    //  Look for Object manager list status
    //  Created by Alexandre Colucci on 04.08.2016.
    //  Copyright © 2016 Alexandre Colucci. All rights reserved.
    //
    //    To compile:
    //        gcc -o DumpBinary.dylib -dynamiclib DumpBinary.c
    //
    //    To run:
    //        DYLD_INSERT_LIBRARIES=./DumpBinary.dylib /Applications/World\ of\ Warcraft/_retail_/World\ of\ Warcraft.app/Contents/MacOS/World\ of\ Warcraft
    //
    
    
    #include  <stdio.h>
    #include  <stdlib.h>
    #include  <string.h>
    
    
    #include  <mach-o/loader.h>
    #include  <mach-o/dyld.h>
    #include  <mach-o/fat.h>
    #include  <mach-o/swap.h>
    
    
    // For PATH_MAX
    #include  <sys/syslimits.h>
    
    
    const struct mach_header_64 *get_mach_header_64()
    {
        for (uint32_t i = 0; i < _dyld_image_count(); ++i)
        {
            const struct mach_header_64 *mach_header_64 = (const struct mach_header_64 *)_dyld_get_image_header(i);
            if (mach_header_64->filetype == MH_EXECUTE)
            {
                if ((mach_header_64->cputype & CPU_TYPE_ARM64) != CPU_TYPE_ARM64)
                {
                    fprintf(stderr, "[ERROR] Executable is not an ARM64 file\n");
                    exit(1);
                }
                fprintf(stderr, "[INFO] Found MH_EXECUTE Header\n");
                const char *name = _dyld_get_image_name(i);
                fprintf(stderr, "[INFO] Executable is %s\n", "ARM64");
                fprintf(stdout, "[INFO] Executable header for '%s' found.\n", name);
                return mach_header_64;
            }
        }
        return NULL;
    }
    
    
    uint8_t *get_file_from_disk(const char *path, size_t *start, size_t *size)
    {
        fprintf(stdout, "[INFO] Loading '%s' from disk.\n", path);
    
    
        FILE *file = fopen(path, "r");
        if (file == NULL)
        {
            fprintf(stderr, "[ERROR] Could not open executable path '%s'\n", path);
            exit(1);
        }
    
    
        fseek(file, 0, SEEK_END);
        long file_size = ftell(file);
        fseek(file, 0, SEEK_SET);
        *size = file_size;
    
    
        uint8_t *buffer = (uint8_t *)calloc(file_size, 1);
        if (buffer == NULL)
        {
            fclose(file);
            fprintf(stderr, "[ERROR] Could not allocate buffer\n");
            exit(1);
        }
    
    
        if (fread(buffer, 1, file_size, file) != file_size)
        {
            fclose(file);
            free(buffer);
            fprintf(stderr, "[ERROR] Could not read the file '%s' to buffer\n", path);
            exit(1);
        }
        fclose(file);
    
    
        struct fat_header *fat_header = (struct fat_header *)buffer;
        if (fat_header->magic == FAT_CIGAM || fat_header->magic == FAT_MAGIC || fat_header->magic == FAT_CIGAM_64 || fat_header->magic == FAT_MAGIC_64)
        {
            bool byteswap = fat_header->magic == FAT_CIGAM || fat_header->magic == FAT_CIGAM_64;
            if (byteswap)
    #pragma  clang diagnostic ignored "-Wdeprecated-declarations"
                swap_fat_header(fat_header, 0);
            struct fat_arch *fat_arch = (struct fat_arch *)(fat_header + 1);
            for (uint32_t i = 0; i < fat_header->nfat_arch; ++i)
            {
                if (byteswap)
                    swap_fat_arch(fat_arch, 1, 0);
    #pragma  clang diagnostic ignored "-Wdeprecated-declarations"
                bool is_arm64 = (fat_arch->cputype & CPU_TYPE_ARM64) == CPU_TYPE_ARM64;
                bool is_x86_64 = (fat_arch->cputype & CPU_TYPE_X86_64) == CPU_TYPE_X86_64;
                if (is_arm64)
                {
                    *size = fat_arch->size;
                    *start = fat_arch->offset;
                    break;
                }
                ++fat_arch;
            }
        }
    
    
        return buffer;
    }
    
    
    void __attribute__((destructor)) DumpBinaryDestructor()
    {
        char destinationPath[PATH_MAX];
        fprintf(stderr, "[INFO] Destructor CALLED\n");
        const struct mach_header_64 *mh64 = get_mach_header_64();
        if (mh64 == NULL)
        {
            fprintf(stderr, "[ERROR] Could not find the main executable\n");
            exit(1);
        }
    
    
        char executablePath[PATH_MAX];
    
    
        /*
        _NSGetExecutablePath() copies the path of the main executable into the
         buffer buf.  The bufsize parameter should initially be the size of the
         buffer.  This function returns 0 if the path was successfully copied, and
         * bufsize is left unchanged.  It returns -1 if the buffer is not large
         enough, and * bufsize is set to the size required.  Note that
         _NSGetExecutablePath() will return "a path" to the executable not a "real
         path" to the executable.  That is, the path may be a symbolic link and
         not the real file. With deep directories the total bufsize needed could
         be more than MAXPATHLEN.
        */
        uint32_t len = sizeof(executablePath);
        if (_NSGetExecutablePath(executablePath, &len) != 0)
        {
            fprintf(stderr, "[ERROR] Buffer is not large enough to copy the executable path\n");
            exit(1);
        }
    
    
        //
        // Get the canonicalized absolute path
        //
        char *canonicalPath = realpath(executablePath, NULL);
        if (canonicalPath != NULL)
        {
            strlcpy(executablePath, canonicalPath, sizeof(executablePath));
            free(canonicalPath);
        }
    
    
        fprintf(stderr, "[INFO] Found absolute path: '%s'\n", executablePath);
    
    
        size_t buffer_start = 0, buffer_size = 0;
        uint8_t *buffer = get_file_from_disk(executablePath, &buffer_start, &buffer_size);
    
    
        //
        // Loop through each section
        //
        size_t segmentOffset = sizeof(struct mach_header_64);
        fprintf(stderr, "[INFO] Commnd Size %d\n", mh64->sizeofcmds);
        for (uint32_t i = 0; i < mh64->ncmds; i++)
        {
            struct load_command *loadCommand = (struct load_command *)((uint8_t *)mh64 + segmentOffset);
            if (loadCommand->cmd == LC_SEGMENT_64)
            {
                // Found a 64-bit segment
                struct segment_command_64 *segCommand = (struct segment_command_64 *)loadCommand;
    
    
                void *sectionPtr = (void *)(segCommand + 1);
                for (uint32_t nsect = 0; nsect < segCommand->nsects; ++nsect)
                {
                    struct section_64 *section = (struct section_64 *)sectionPtr;
                    fprintf(stderr, "\t[INFO] Found the section (%s, %s)\n", section->segname, section->sectname);
                    if (strncmp(segCommand->segname, SEG_TEXT, 16) == 0)
                    {
                        fprintf(stderr, "\t[INFO] Save the unencrypted (%s, %s) section to the buffer\n", section->segname, section->sectname);
                        memcpy(buffer + section->offset, (uint8_t *)mh64 + section->offset, section->size);
                    }
    
    
                    sectionPtr += sizeof(struct section_64);
                }
            }
            segmentOffset += loadCommand->cmdsize;
        }
    start_dump:
        //
        // Create the output file
        //
        // char appendName[12] = mh64->cputype == CPU_TYPE_ARM64 ? "_Decrypted_a" : "_Decrypted_x";
        strlcpy(destinationPath, executablePath, sizeof(destinationPath));
        strlcat(destinationPath, mh64->cputype == CPU_TYPE_ARM64 ? "_Decrypted_a" : "_Decrypted_x", sizeof(destinationPath));
    
    
        fprintf(stderr, "[INFO] Creating the output file '%s'\n", destinationPath);
        FILE *destinationFile = fopen(destinationPath, "w");
    
    
        if (destinationFile == NULL)
        {
            free(buffer);
            fprintf(stderr, "[ERROR] Could create the output file '%s'\n", destinationPath);
            exit(1);
        }
    
    
        //
        // Save the data into the output file
        //
        if (fwrite(buffer + buffer_start, 1, buffer_size, destinationFile) != buffer_size)
        {
            free(buffer);
            fclose(destinationFile);
            fprintf(stderr, "[ERROR] Could not write to the output file\n");
            exit(1);
        }
    
    
        free(buffer);
        fclose(destinationFile);
        fprintf(stderr, "[INFO] Decryption completed\n");
    }
    Ended up getting ahold of an apple silicon device, and updated the script. The following in the gist appears to work fine:
    https://gist.github.com/scizzydo/cbd...1dbaeb79485883

    Added the notes for compiling it and making a universal dumper dylib out of it too. When running under rosetta it did the x86_64 side, and then the arm64 side natively. Obviously two separate binaries for the architectures...

  10. Thanks Sweann, Archos (2 members gave Thanks to scizzydo for this useful post)
  11. #38
    Archos's Avatar Member Authenticator enabled
    Reputation
    2
    Join Date
    Mar 2007
    Posts
    34
    Thanks G/R
    4/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by scizzydo View Post
    Ended up getting ahold of an apple silicon device, and updated the script. The following in the gist appears to work fine:
    macOS x86_64 executable dylib dumper . GitHub

    Added the notes for compiling it and making a universal dumper dylib out of it too. When running under rosetta it did the x86_64 side, and then the arm64 side natively. Obviously two separate binaries for the architectures...
    Well damn this is perfect. Now I need to automate the searching offsets and get patterns for mac

  12. #39
    Sweann's Avatar Active Member Authenticator enabled
    Reputation
    15
    Join Date
    Mar 2010
    Posts
    22
    Thanks G/R
    5/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Then here is my python based solution for this offset_dump.ini . GitHub

    On arm64 this is a bit tricky, because every instruction is 4 byte not like x64.

  13. #40
    Archos's Avatar Member Authenticator enabled
    Reputation
    2
    Join Date
    Mar 2007
    Posts
    34
    Thanks G/R
    4/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Sweann View Post
    Then here is my python based solution for this offset_dump.ini . GitHub

    On arm64 this is a bit tricky, because every instruction is 4 byte not like x64.
    Using he patterns in your example, I was able to find matches using Hopper.

    Screenshot 2024-03-28 at 11.45.38 PM.png

  14. #41
    Archos's Avatar Member Authenticator enabled
    Reputation
    2
    Join Date
    Mar 2007
    Posts
    34
    Thanks G/R
    4/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by scizzydo View Post
    Ended up getting ahold of an apple silicon device, and updated the script. The following in the gist appears to work fine:
    macOS x86_64 executable dylib dumper . GitHub

    Added the notes for compiling it and making a universal dumper dylib out of it too. When running under rosetta it did the x86_64 side, and then the arm64 side natively. Obviously two separate binaries for the architectures...
    I am curious if its possible to rebuild the original fat binary with the dumped binaries from each architecture. It seems that FAT binary that is dumped is fine for ARM but is not correct for x86. Hopper detects it properly but IDA does not recognize the dumped FAT binary from x86 correctly.

  15. #42
    Sweann's Avatar Active Member Authenticator enabled
    Reputation
    15
    Join Date
    Mar 2010
    Posts
    22
    Thanks G/R
    5/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Simply extract x64 binary from fat archive but here is my fast python solution for that fat_split.py . GitHub

  16. #43
    Archos's Avatar Member Authenticator enabled
    Reputation
    2
    Join Date
    Mar 2007
    Posts
    34
    Thanks G/R
    4/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Sweann View Post
    Simply extract x64 binary from fat archive but here is my fast python solution for that fat_split.py . GitHub
    Awesome! Looks how now its just a matter of building patterns for ARM.

  17. #44
    Sweann's Avatar Active Member Authenticator enabled
    Reputation
    15
    Join Date
    Mar 2010
    Posts
    22
    Thanks G/R
    5/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Now i stumbled on an issue, when server disconnects a dialog shows up anyone found a clue to detect when this window is visible?

    Asked too fast, maybe need to find frames base and iterate the frames… i think the glue is what i am searching…
    Last edited by Sweann; 3 Weeks Ago at 04:09 PM.

  18. #45
    Sweann's Avatar Active Member Authenticator enabled
    Reputation
    15
    Join Date
    Mar 2010
    Posts
    22
    Thanks G/R
    5/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    With GetMouseFocus i've identified an address (1.15.2 WoW SoD) DAT_102286ec0 + 0x1b8 and when i hovering the mouse on an element then the address points an UIObject as i see.
    And this addres + 0x10 there is a pointer for the name, and +0x148 is an another pointer which points a next element.

    But this iteration is not 100% good sometimes i saw odd number in the next element pointer and one of my created control frame not showing up.

    Found a post by @darheroc here https://www.ownedcore.com/forums/wor...ml#post4447356 mention EnumerateFrames and this uses 0xed0 as start offset.

    The odd values checked in EnumerateFrames too with "uVar3 & 1", and uses the found 0x148 offset:
    Code:
    for (; ((uVar3 & 1) == 0 && (uVar3 != 0)); uVar3 = *(ulong *)(uVar3 + 0x148)) {
    Last edited by Sweann; 3 Weeks Ago at 01:12 PM. Reason: Added extra info after few more search

Page 3 of 3 FirstFirst 123

Similar Threads

  1. [PQR] Custom wow offset?
    By cabrobas in forum WoW Memory Editing
    Replies: 2
    Last Post: 04-04-2022, 04:40 PM
  2. WoW Offsets & WPE
    By RyanoAthens in forum World of Warcraft General
    Replies: 2
    Last Post: 03-11-2014, 10:15 PM
  3. 4.0.3 Wow - Offsets
    By luciferc in forum WoW Memory Editing
    Replies: 51
    Last Post: 11-25-2010, 12:04 PM
  4. im going to use wow to learn french!
    By Ermok in forum World of Warcraft General
    Replies: 7
    Last Post: 09-10-2007, 04:02 PM
All times are GMT -5. The time now is 10:51 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