jeudi 6 mars 2014

[Source] Mac-OSX memory editing topic




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.


PHP Code:







#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 pidvoidaddrsize_tsize

{     

    
assert(*size != || 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 pidvoidaddrunsigned chardatasize_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(ptxtdatadsize); 


    
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)dsize0VM_PROT_READ VM_PROT_WRITE VM_PROT_ALL); 


    
kret vm_write(task, (vm_address_t)addr, (pointer_t)ptxtdataCunt); 


    return 
kret




mach_error_t setpage_exec(void *address)  



    
mach_error_t err err_none

    
vm_size_t pageSize


    
host_page_sizemach_host_self(), &pageSize ); 

    
uintptr_t page = (uintptr_t)address & ~(uintptr_t)(pageSize-1); 

    
int e err_none


    
|= mprotect((void *)pagepageSizePROT_EXEC PROT_READ); 

    
|= msync((void *)pagepageSizeMS_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 getAddressOfLibrarycharlibraryPath 



    const 
struct mach_headermh


    
int n _dyld_image_count(); 


    
int i 0

    for( 
0ni++ ) 

    { 

        
mh _dyld_get_image_header(i); 

        if( 
mh->filetype != MH_DYLIB ){ continue; } 


        const 
charimageName _dyld_get_image_name(i); 

        
printf("%s\n",imageName); 

        if( 
strcmp(imageNamelibraryPath) == 

        { 

            
struct segment_command_64seg

            
struct load_commandcmd

            
cmd = (struct load_command*)((char*)mh sizeof(struct mach_header_64)); 


            
int j 0

            for( 
0mh->ncmdsj++ ) 

            { 

                if( 
cmd->cmd == LC_SEGMENT_64 

                { 

                    
seg = (struct segment_command_64*)cmd

                    if( 
strcmp(seg->segnameSEG_TEXT) == 

                    { 

                        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(charlibpathchar symbol



    
voidhlib dlopen(libpathRTLD_NOW); 

    
voidfuncaddr64 dlsym(hlibsymbol);  

    return (
unsigned long long)funcaddr64





#pragma mark processes  

int32_t procpid (charprocname



    
pid_t pid

    
int j

    
kinfo_proc proclist

    
size_t procCount


    
getprocessList(&proclist, &procCount); 


    for (
0procCount +1j++) { 

        if (
strcmp(proclist[j].kp_proc.p_commprocname) == )  

                    
pid proclist[j].kp_proc.p_pid

    } 


    
free(proclist); 

    return 
pid




static 
int getprocessList(kinfo_proc **procListsize_t *procCount



    
int                 err

    
kinfo_proc *        result

    
int                 done

    static const 
int    name[] = { CTL_KERNKERN_PROCKERN_PROC_ALL}; 


    
size_t              length


    
assertprocList != 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

                     
NULL0); 

        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

                         
NULL0); 

            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 == && ! done); 



    if (
err != && result != NULL) { 

        
free(result); 

        
result NULL

    } 

    *
procList result

    if (
err == 0) { 

        *
procCount length sizeof(kinfo_proc); 

    } 


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


    return 
err
















Aucun commentaire:

Enregistrer un commentaire