转载一份老外的 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;  

    }



目录
相关文章
|
4月前
|
存储 程序员
【汇编】内存的读写与地址空间、寄存器及数据存储
【汇编】内存的读写与地址空间、寄存器及数据存储
165 1
【汇编】内存的读写与地址空间、寄存器及数据存储
|
5月前
|
存储 Java C#
C# | 使用Memory<T>高效地读写内存数据
Memory<T>是什么? 它是一种可变大小、可读写的内存块,可以安全地暴露给用户代码进行操作。 为什么要使用Memory<T>? 使用它有许多好处。最主要的是善用它可以提高代码的性能。因为Memory<T>是可变的,所以我们可以直接在内存中操作数据,而不需要进行额外的拷贝操作。 使用Memory<T>还可以减少垃圾回收的压力,因为我们不需要创建新的对象来存储数据。 Memory<T>还可以与Span<T>和ReadOnlySpan<T>类型一起使用,这些类型可以方便地对数据进行访问和操作。
38 0
|
5月前
|
存储 安全 数据安全/隐私保护
3.2 Windows驱动开发:内核CR3切换读写内存
CR3是一种控制寄存器,它是CPU中的一个专用寄存器,用于存储当前进程的页目录表的物理地址。在x86体系结构中,虚拟地址的翻译过程需要借助页表来完成。页表是由页目录表和页表组成的,页目录表存储了页表的物理地址,而页表存储了实际的物理页框地址。因此,页目录表的物理地址是虚拟地址翻译的关键之一。在操作系统中,每个进程都有自己的地址空间,地址空间中包含了进程的代码、数据和堆栈等信息。为了实现进程间的隔离和保护,操作系统会为每个进程分配独立的地址空间。在这个过程中,操作系统会将每个进程的页目录表的物理地址存储在它自己的CR3寄存器中。当进程切换时,操作系统会修改CR3寄存器的值,从而让CPU使用新的页
62 0
3.2 Windows驱动开发:内核CR3切换读写内存
|
10月前
|
JSON 数据可视化 定位技术
python数据可视化开发(3):使用psutil和socket模块获取电脑系统信息(Mac地址、IP地址、主机名、系统用户、硬盘、CPU、内存、网络)
python数据可视化开发(3):使用psutil和socket模块获取电脑系统信息(Mac地址、IP地址、主机名、系统用户、硬盘、CPU、内存、网络)
205 0
|
11月前
|
存储
驱动开发:内核读写内存多级偏移
让我们继续在`《内核读写内存浮点数》`的基础之上做一个简单的延申,如何实现多级偏移读写,其实很简单,读写函数无需改变,只是在读写之前提前做好计算工作,以此来得到一个内存偏移值,并通过调用内存写入原函数实现写出数据的目的。以读取偏移内存为例,如下代码同样来源于本人的`LyMemory`读写驱动项目,其中核心函数为`WIN10_ReadDeviationIntMemory()`该函数的主要作用是通过用户传入的基地址与偏移值,动态计算出当前的动态地址。
85 0
|
11月前
|
存储 索引 Windows
驱动开发:内核物理内存寻址读写
在某些时候我们需要读写的进程可能存在虚拟内存保护机制,在该机制下用户的`CR3`以及`MDL`读写将直接失效,从而导致无法读取到正确的数据,本章我们将继续研究如何实现物理级别的寻址读写。首先,驱动中的物理页读写是指在驱动中直接读写物理内存页(而不是虚拟内存页)。这种方式的优点是它能够更快地访问内存,因为它避免了虚拟内存管理的开销,通过直接读写物理内存,驱动程序可以绕过虚拟内存的保护机制,获得对系统中内存的更高级别的访问权限。
6977 1
|
12月前
|
存储 C语言
内存的读写过程、现实模型及指针
内存的读写过程、现实模型及指针
116 0
内存的读写过程、现实模型及指针
|
12月前
驱动开发:内核读写内存浮点数
如前所述,在前几章内容中笔者简单介绍了`内存读写`的基本实现方式,这其中包括了`CR3切换`读写,`MDL映射`读写,`内存拷贝`读写,本章将在如前所述的读写函数进一步封装,并以此来实现驱动读写内存浮点数的目的。内存`浮点数`的读写依赖于`读写内存字节`的实现,因为浮点数本质上也可以看作是一个字节集,对于`单精度浮点数`来说这个字节集列表是4字节,而对于`双精度浮点数`,此列表长度则为8字节。
219 0
|
存储 块存储
AD2428W手册解读之模块ID和模块配置内存
AD2428W手册解读之模块ID和模块配置内存
AD2428W手册解读之模块ID和模块配置内存
|
API
驱动开发:通过内存拷贝读写内存
内核中读写内存的方式有很多,典型的读写方式有CR3读写,MDL读写,以及今天要给大家分享的内存拷贝实现读写,拷贝读写的核心是使用`MmCopyVirtualMemory`这个内核API函数实现,通过调用该函数即可很容易的实现内存的拷贝读写。
338 0
驱动开发:通过内存拷贝读写内存