转载一份老外的 xun 内存读写模块

本文介绍了一个用于在XNU内核下进行内存读取、写入及页面权限设置的C语言程序实例。此外,还展示了如何通过Mach-O格式获取库地址和符号地址,以及如何获取指定进程ID的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


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

    }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值