取消引用 C 中的函数指针以访问 CODE 内存
Dereferencing function pointers in C to access CODE memory
我们这里处理的是C。我只是有这个想法,想知道是否有可能访问内存中存储函数的点,比如 foo
并将函数的内容复制到内存中的另一个点。具体来说,我正在尝试使以下内容起作用:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void foo(){
printf("Hello World");
}
int main(){
void (*bar)(void) = malloc(sizeof foo);
memcpy(&bar, &foo, sizeof foo);
bar();
return 0;
}
但是运行它给出了总线错误:Bus error: 10
。我正在尝试将函数 foo
的内容复制到内存 bar
的 space 中,然后执行新创建的函数 bar
。
无非是想看看这样的事情是否可能,揭示C语言的复杂性。我没有考虑它有什么实际用途。
我正在寻找使它起作用的指导,或者以其他方式被告知为什么它不起作用
EDIT 查看一些答案并学习 read、write 和可执行 内存,我突然意识到可以通过写入可执行内存在 C 中动态创建函数。
使用标准 C,您尝试做的是实现定义的行为,并且无法移植。在给定的平台上,您也许能够完成这项工作。
记忆malloc
给你的通常是不可执行的。跳到那里会导致总线错误 (SIGBUS
)。假设你在一个类似 POSIX 的系统上,或者使用 mmap
为函数分配内存和导致内存区域可执行的标志,或者使用 mprotect
将区域标记为可执行.
您还需要更加小心您提供的内存量,您不能简单地获取函数的大小并期望它是函数的长度,sizeof
并非旨在提供这种功能。您需要使用其他方法找出函数长度。
在现代桌面上,虚拟内存管理器会妨碍您。内存区域有三种访问类型:read、write和execute。在代码段只有 execute 权限的系统上,memcpy
将因总线错误而失败。在更典型的情况下,只有代码段具有 execute 权限,您可以复制函数,但不能复制 运行,因为包含 bar
的内存区域将没有 执行 权限。
此外,确定函数的大小也存在问题。考虑以下程序
void foo( int *x )
{
printf( "x:(%zu %zu) ", sizeof x, sizeof *x );
}
int main( void )
{
int x = 0;
foo( &x );
printf( "foo:(%zu %zu)\n", sizeof foo, sizeof *foo );
}
在我的系统上,输出是 x:(8 4) foo:(1 1)
,表示获取 sizeof
函数指针或函数本身不受支持。
我们这里处理的是C。我只是有这个想法,想知道是否有可能访问内存中存储函数的点,比如 foo
并将函数的内容复制到内存中的另一个点。具体来说,我正在尝试使以下内容起作用:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void foo(){
printf("Hello World");
}
int main(){
void (*bar)(void) = malloc(sizeof foo);
memcpy(&bar, &foo, sizeof foo);
bar();
return 0;
}
但是运行它给出了总线错误:Bus error: 10
。我正在尝试将函数 foo
的内容复制到内存 bar
的 space 中,然后执行新创建的函数 bar
。
无非是想看看这样的事情是否可能,揭示C语言的复杂性。我没有考虑它有什么实际用途。
我正在寻找使它起作用的指导,或者以其他方式被告知为什么它不起作用
EDIT 查看一些答案并学习 read、write 和可执行 内存,我突然意识到可以通过写入可执行内存在 C 中动态创建函数。
使用标准 C,您尝试做的是实现定义的行为,并且无法移植。在给定的平台上,您也许能够完成这项工作。
记忆malloc
给你的通常是不可执行的。跳到那里会导致总线错误 (SIGBUS
)。假设你在一个类似 POSIX 的系统上,或者使用 mmap
为函数分配内存和导致内存区域可执行的标志,或者使用 mprotect
将区域标记为可执行.
您还需要更加小心您提供的内存量,您不能简单地获取函数的大小并期望它是函数的长度,sizeof
并非旨在提供这种功能。您需要使用其他方法找出函数长度。
在现代桌面上,虚拟内存管理器会妨碍您。内存区域有三种访问类型:read、write和execute。在代码段只有 execute 权限的系统上,memcpy
将因总线错误而失败。在更典型的情况下,只有代码段具有 execute 权限,您可以复制函数,但不能复制 运行,因为包含 bar
的内存区域将没有 执行 权限。
此外,确定函数的大小也存在问题。考虑以下程序
void foo( int *x )
{
printf( "x:(%zu %zu) ", sizeof x, sizeof *x );
}
int main( void )
{
int x = 0;
foo( &x );
printf( "foo:(%zu %zu)\n", sizeof foo, sizeof *foo );
}
在我的系统上,输出是 x:(8 4) foo:(1 1)
,表示获取 sizeof
函数指针或函数本身不受支持。