【发布时间】:2016-07-18 20:56:54
【问题描述】:
我知道我可以通过引用复制该函数,但我想了解以下产生段错误的代码中发生了什么。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int return0()
{
return 0;
}
int main()
{
int (*r0c)(void) = malloc(100);
memcpy(r0c, return0, 100);
printf("Address of r0c is: %x\n", r0c);
printf("copied is: %d\n", (*r0c)());
return 0;
}
这是我认为应该起作用的心智模型。
进程拥有分配给 r0c 的内存。我们正在从return0对应的数据段复制数据,复制成功。
我认为取消引用函数指针与调用函数指针指向的数据段相同。如果是这种情况,那么指令指针应该移动到对应于 r0c 的数据段,其中将包含函数 return0 的指令。 return0对应的二进制代码不包含任何依赖于return0地址的跳转或函数调用,所以它应该只是返回0并恢复ip...... 100字节对于函数指针当然足够了,0xc3很好在 r0c 的范围内(在字节 11 处)。
那么为什么会出现分段错误?这是对 C 函数指针语义的误解,还是有一些我不知道的防止自我修改代码的安全功能?
【问题讨论】:
-
printf("Address of r0c is: %x\n", r0c);定义不明确。 -
某事告诉我,整个事情没有很好地定义。
-
首先,函数(代码)驻留在标记为可执行的内存段中。分配的数据没有如此标记,特别是如果您的系统正在使用 DEP(数据执行保护)。如果您希望执行数据段中的代码,您需要弄清楚如何将该数据标记为可执行。其次,
memcpy(r0c, return0, 100);可能是从内存末尾以外的地方进行复制。第三,很可能包含代码的内存位置受到保护,无法访问。 -
用 gcc 和参数 -Wall -Wpedantic -std=c11 编译它会给出几个警告。听听你的编译器。
-
memcpy(r0c, return0, 100);是一个问题,因为return0不能很好地转换为void*。
标签: c pointers self-modifying