Linux下如何执行buffer中的一段代码

linux中,存在一个系统调用mprotect,可以修改一段内存的权限信息,一般情况下,数据段是不可以执行的,通过mprotect,可以赋予数据段以执行权限,再将一段逻辑实现拷贝到该数据段中,通过函数指针跳转,从而执行该数据段中的代码,以下为实现部分:

两个源码文件,分别为main.c和test.S

test.S的内容为:

.code64
.align 0x1000
.text
.global test
.type test, @function

test:
    pushq   %rbp
    movq    %rsp, %rbp
    movl    $22, %eax
    popq    %rbp
    ret

main.c的内容为

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/mman.h>

int test(void);

int main()
{
    int ret;
    int (*p)(void);
    void *code;

    code = mmap(0, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    if (code == MAP_FAILED) {
        printf("mmap failed, errno is %d \n", errno);
        return -errno;
    }

    ret = mprotect(code, 0x1000, PROT_EXEC | PROT_WRITE);
    if (ret == -1) {
        printf("mprotect failed, errno is %d \n", errno);
        return -errno;
    }

    ret = test();
    if (ret != 22)
        return -EINVAL;
    puts("execute assembly successfully");

    memcpy(code, test, 0x1000);

    p = code;
    ret = p();
    if (ret != 22)
        return -EINVAL;
    puts("execute buffer successfully, end here");
    return 0;
}

编译用的cmake文件为:

cmake_minimum_required(VERSION 3.16)
project(ACM C ASM)
set(CMAKE_C_STANDARD 99)
set_source_files_properties(test.S PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp")
add_executable(ACM main.c test.S)

运行结果如下:

execute assembly successfully
execute buffer successfully, end here

gdb调试可以加入以下指令,进行查看:

display /20i $pc