机器码运行

#include                                                                                            
#include 
#include 
#include 
#include 

/*
首先我们要知道生成的所谓机器码到底是神马东西。一行看上去只是处理几个数字的代码,蕴含着的就是机器码。

unsigned char[] macCode = {0x48, 0x8b, 0x07};
macCode对应的汇编指令就是:

mov    (%rdi),%rax
其实可以看出机器码就是比特流,所以将它加载进内存并不困难。而问题是应该如何执行。

好啦。下面我们就模拟一下执行新生成的机器码的过程。一个求和函数的机器码:

long add(long num) {
  return num + 1;
}

//对应的机器码
0x48, 0x83, 0xc0, 0x01,           
0xc3 

动态的在内存上创建函数之前,我们需要在内存上分配空间。具体到模拟动态创建函数,其实就是将对应的机器码映射到内存空间中。这里我们使用c语言做实验,利用mmap函数来实现这一点。
头文件	
    #include     
    #include 
定义函数	
    void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offsize)
函数说明	
    mmap()用来将某个文件内容映射到内存中,对该内存区域的存取即是直接对该文件内容的读写。


代表映射区域的保护方式,有下列组合:

    PROT_EXEC  映射区域可被执行;
    PROT_READ  映射区域可被读取;
    PROT_WRITE  映射区域可被写入;
*/

//分配内存
void* create_space(size_t size) {
    void* ptr = mmap(0, size,
            PROT_READ | PROT_WRITE | PROT_EXEC,
            MAP_PRIVATE | MAP_ANON,
            -1, 0);   
    return ptr;
}
/*
这样我们就获得了一块分配给我们存放代码的空间。下一步就是实现一个方法将机器码,也就是比特流拷贝到分配给我们的那块空间上去。使用memcpy即可。
*/
//在内存中创建函数
void copy_code_2_space(unsigned char* m) {
    unsigned char macCode[] = {
        0x48, 0x83, 0xc0, 0x01,
        c3 
    };
    memcpy(m, macCode, sizeof(macCode));
}

//main 声明一个函数指针TestFun用来指向我们的求和函数在内存中的地址
int main(int argc, char** argv) {                                                                                              
    const size_t SIZE = 1024;
    typedef long (*TestFun)(long);
    void* addr = create_space(SIZE);
    copy_code_2_space(addr);
    TestFun test = addr;
    int result = test(1);
    printf("result = %d\n", result); 
    return 0;
}

/*
编译并且运行看一下结果:

//编译
gcc testFun.c
//运行
./a.out 1 

result = 2

*/

IOS封了内存(或者堆)的可执行权限,所以需要提权才能运行。

你可能感兴趣的:(机器码运行)