Source Code Mac OSX Memory Editing Library

  • CSGO recently moved logic from 'client_panorama.dll' to 'client.dll', you must update all code that uses 'client_panorama.dll' and replace it with 'client.dll' or the code will not work.
Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat

NTvalk

Hacker
Meme Tier VIP
Jul 6, 2013
499
3,108
8
Hello, I created this today because I couldn't find a lot of samples/documentation on this.
Since Apple disabled ptrace() on OSX, I wasn't able to edit memory of other processes, so the only way around this is to use the kernel (mach) API.
This is just source code... If you have any questions you can ask ofc.

I also added functions to iterate through processes and libraries.


Mac OSX Memory Editing Library

C++:
#include <mach/host_info.h>
#include <mach/mach_host.h>
#include <mach/shared_region.h>
#include <mach/mach.h>
#include <mach-o/dyld.h>

#include <stdlib.h>
#include <stdio.h>
#import <dlfcn.h>

#include <assert.h>
#include <errno.h>

#include <sys/sysctl.h>
#include <sys/mman.h>

#pragma mark read and write
/* Note : buffer must be free'd manually */
unsigned char * xnu_read (int pid, void* addr, size_t* size)
{   
    assert(*size != 0 || addr != 0);
    *size = _word_align(*size);

    unsigned char *rbuffer = (unsigned char*)malloc(*size);
    if (rbuffer == 0)
        printf("Allocation error : xnu_read \n");

    mach_msg_type_number_t data_cnt;
    mach_port_t task;

    kern_return_t kernret = task_for_pid(mach_task_self(), pid, &task);
    if (kernret != KERN_SUCCESS)
        printf("Error : task_for_pid \n");

    kernret = vm_read(task, (vm_address_t)addr, *size, (vm_offset_t*)&rbuffer, &data_cnt);

    if(kernret != KERN_SUCCESS)
        free(rbuffer);

    return rbuffer;
}

int xnu_write (int pid, void* addr, unsigned char* data, size_t dsize)
{   
    assert(dsize != 0);
    assert(addr != 0);
    assert(data != 0);

    dsize = _word_align(dsize);
    unsigned char * ptxt = (unsigned char*)malloc(dsize);

    assert(ptxt != 0);
    memcpy(ptxt, data, dsize);

    mach_port_t task;
        //vm_info_region_t  regbackup;
    mach_msg_type_number_t dataCunt = dsize;

    kern_return_t kret = task_for_pid(mach_task_self(), pid, &task);

        //mach_vm_region_info(task, (vm_address_t)addr, &regbackup,0 , 0);

    /* retrieve write permision */
    vm_protect(task, (vm_address_t)addr, (vm_size_t)dsize, 0, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_ALL);

    kret = vm_write(task, (vm_address_t)addr, (pointer_t)ptxt, dataCunt);

    return kret;
}

mach_error_t setpage_exec(void *address)
{
    mach_error_t err = err_none;
    vm_size_t pageSize;

    host_page_size( mach_host_self(), &pageSize );
    uintptr_t page = (uintptr_t)address & ~(uintptr_t)(pageSize-1);
    int e = err_none;

    e |= mprotect((void *)page, pageSize, PROT_EXEC | PROT_READ);
    e |= msync((void *)page, pageSize, MS_INVALIDATE );
    if (e) {
        printf("Cannot create executable page\n");
    }

    return err;
}


size_t _word_align(size_t size)
{
    size_t rsize = 0;

    rsize = ((size % sizeof(long)) > 0) ? (sizeof(long) - (size % sizeof(long))) : 0;
    rsize += size;

    return rsize;
}

/* Mach-O format related functions */
#pragma mark macho
__uint64_t getAddressOfLibrary( char* libraryPath )
{
    const struct mach_header* mh;

    int n = _dyld_image_count();

    int i = 0;
    for( i = 0; i < n; i++ )
    {
        mh = _dyld_get_image_header(i);
        if( mh->filetype != MH_DYLIB ){ continue; }

        const char* imageName = _dyld_get_image_name(i);
        printf("%s\n",imageName);
        if( strcmp(imageName, libraryPath) == 0 )
        {
            struct segment_command_64* seg;
            struct load_command* cmd;
            cmd = (struct load_command*)((char*)mh + sizeof(struct mach_header_64));

            int j = 0;
            for( j = 0; j < mh->ncmds; j++ )
            {
                if( cmd->cmd == LC_SEGMENT_64 )
                {
                    seg = (struct segment_command_64*)cmd;
                    if( strcmp(seg->segname, SEG_TEXT) == 0 )
                    {
                        return seg->vmaddr + (__uint64_t)_dyld_get_image_vmaddr_slide(i);
                    }
                }

                cmd = (struct load_command*)((char*)cmd + cmd->cmdsize);
            }

            return _dyld_get_image_vmaddr_slide(i);
        }
    }

    return 0;
}

/* Retrieve symbol pointer at runtime */
__uint64_t getAddressOfSymbol(char* libpath, char * symbol)
{
    void* hlib = dlopen(libpath, RTLD_NOW);
    void* funcaddr64 = dlsym(hlib, symbol);
    return (unsigned long long)funcaddr64;
}


#pragma mark processes
int32_t procpid (char* procname)
{
    pid_t pid;
    int j;
    kinfo_proc * proclist;
    size_t procCount;

    getprocessList(&proclist, &procCount);

    for (j = 0; j < procCount +1; j++) {
        if (strcmp(proclist[j].kp_proc.p_comm, procname) == 0 )
                    pid = proclist[j].kp_proc.p_pid;
    }

    free(proclist);
    return pid;
}

static int getprocessList(kinfo_proc **procList, size_t *procCount)
{
    int                 err;
    kinfo_proc *        result;
    int                 done;
    static const int    name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };

    size_t              length;

    assert( procList != NULL);
        //assert(*procList == NULL);
    assert(procCount != NULL);

    *procCount = 0;

    result = NULL;
    done = 0;
    do {
        assert(result == NULL);

        length = 0;
        err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1,
                     NULL, &length,
                     NULL, 0);
        if (err == -1) {
            err = errno;
        }


        if (err == 0) {
            result = malloc(length);
            if (result == NULL) {
                err = ENOMEM;
            }
        }

        if (err == 0) {
            err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1,
                         result, &length,
                         NULL, 0);
            if (err == -1) {
                err = errno;
            }
            if (err == 0) {
                done = 1;
            } else if (err == ENOMEM) {
                assert(result != NULL);
                free(result);
                result = NULL;
                err = 0;
            }
        }
    } while (err == 0 && ! done);


    if (err != 0 && result != NULL) {
        free(result);
        result = NULL;
    }
    *procList = result;
    if (err == 0) {
        *procCount = length / sizeof(kinfo_proc);
    }

    assert( (err == 0) == (*procList != NULL) );

    return err;
}
 
Last edited by a moderator:

c5

Kim Kong Trasher
Dank Tier VIP
Dank Tier Donator
Jul 19, 2012
1,187
12,638
76
Sweet, +rep
 

ndani14

Nick
Dank Tier Donator
Nobleman
Aug 27, 2012
52
708
1
Thanks for posting this, I have never seen a Mac OSX memory class before, very cool
 
Last edited by a moderator:
Attention! Before you post:

Read the How to Ask Questions Guide
99% of questions are answered in the Beginner's Guide, do it before asking a question.

No Hack Requests. Post in the correct section.  Search the forum first. Read the rules.

How to make a good post:

  • Fill out the form correctly
  • Tell us the game name & coding language
  • Post everything we need to know to help you
  • Ask specific questions, be descriptive
  • Post errors, line numbers & screenshots
  • Post code snippets using code tags
  • If it's a large project, zip it up and attach it

If you do not comply, your post may be deleted.  We want to help, please make a good post and we will do our best to help you.

Community Mods