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

简介: #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 <st


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

    }



目录
相关文章
|
2月前
|
C++
析构造函数就是为了释放内存,就是在局部指针消失前释放内存,拷贝构造函数就是以构造函数为模块,在堆里面新开一块,同一个变量在堆里面的地址
本文讨论了C++中构造函数和析构函数的作用,特别是它们在管理动态内存分配和释放中的重要性,以及如何正确地实现拷贝构造函数以避免内存泄漏。
40 2
|
7月前
|
存储 C++
webserver--Buffer类实现内存缓冲区读写(全代码)
webserver--Buffer类实现内存缓冲区读写(全代码)
|
4月前
|
easyexcel Java 关系型数据库
阿里巴巴-EasyExcel 基于Java的简单、省内存的读写Excel
该文章主要介绍了在Java应用中如何使用EasyExcel技术完成对Excel文件的导入和导出操作,包括环境搭建、基本概念、快速入门、进阶操作和综合应用等内容,并提供了相关代码示例和注意事项。
 阿里巴巴-EasyExcel 基于Java的简单、省内存的读写Excel
|
5月前
|
NoSQL Redis C++
c++开发redis module问题之在复杂的Redis模块中,特别是使用第三方库或C++开发时,接管内存统计有哪些困难
c++开发redis module问题之在复杂的Redis模块中,特别是使用第三方库或C++开发时,接管内存统计有哪些困难
|
5月前
|
监控 Python
paramiko 模块 ---Python脚本监控当前系统的CPU、内存、根目录、IP地址等信息
paramiko 模块 ---Python脚本监控当前系统的CPU、内存、根目录、IP地址等信息
|
6月前
|
Java 程序员 Linux
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
51 0
高并发服务优化篇:详解一次由读写锁引起的内存泄漏
JVM相关的异常,一直是一线研发比较头疼的问题。因为对于业务代码,JVM的运行基本算是黑盒,当异常发生时,较难直观地看到和找到问题所在,这也是我们一直要研究其内部逻辑的原因。
|
7月前
|
存储 程序员
【汇编】内存的读写与地址空间、寄存器及数据存储
【汇编】内存的读写与地址空间、寄存器及数据存储
642 1
【汇编】内存的读写与地址空间、寄存器及数据存储
|
7月前
|
存储 Java C#
C# | 使用Memory<T>高效地读写内存数据
Memory<T>是什么? 它是一种可变大小、可读写的内存块,可以安全地暴露给用户代码进行操作。 为什么要使用Memory<T>? 使用它有许多好处。最主要的是善用它可以提高代码的性能。因为Memory<T>是可变的,所以我们可以直接在内存中操作数据,而不需要进行额外的拷贝操作。 使用Memory<T>还可以减少垃圾回收的压力,因为我们不需要创建新的对象来存储数据。 Memory<T>还可以与Span<T>和ReadOnlySpan<T>类型一起使用,这些类型可以方便地对数据进行访问和操作。
121 0
|
存储 索引 Windows
驱动开发:内核物理内存寻址读写
在某些时候我们需要读写的进程可能存在虚拟内存保护机制,在该机制下用户的`CR3`以及`MDL`读写将直接失效,从而导致无法读取到正确的数据,本章我们将继续研究如何实现物理级别的寻址读写。首先,驱动中的物理页读写是指在驱动中直接读写物理内存页(而不是虚拟内存页)。这种方式的优点是它能够更快地访问内存,因为它避免了虚拟内存管理的开销,通过直接读写物理内存,驱动程序可以绕过虚拟内存的保护机制,获得对系统中内存的更高级别的访问权限。
7075 1