Linux下如何执行buffer中的一段代码
2024-10-31 18:10:36

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

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

test.S的内容为:

1
2
3
4
5
6
7
8
9
10
11
12
.code64
.align 0x1000
.text
.global test
.type test, @function

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

main.c的内容为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#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文件为:

1
2
3
4
5
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)

运行结果如下:

1
2
execute assembly successfully
execute buffer successfully, end here

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

1
display /20i $pc