复制内存中的函数并执行它

我想知道在C中如何将一个函数的内容复制到memroy并执行它?

我正在尝试做这样的事情:

typedef void(*FUN)(int *); char * myNewFunc; char *allocExecutablePages (int pages) { template = (char *) valloc (getpagesize () * pages); if (mprotect (template, getpagesize (), PROT_READ|PROT_EXEC|PROT_WRITE) == -1) { perror ("mprotect"); } } void f1 (int *v) { *v = 10; } // allocate enough spcae but how much ?? myNewFunc = allocExecutablePages(...) /* Copy f1 somewere else * (how? assume that i know the size of f1 having done a (nm -S foo.o)) */ ((FUN)template)(&val); printf("%i",val); 

谢谢你的回答

你似乎已经找到了关于保护标志的部分。 如果您知道函数的大小,现在您可以执行memcpy()并将f1的地址作为源地址传递。

一个很大的警告是,在许多平台上,你将无法从你正在复制的那个函数中调用任何其他函数(f1),因为相对地址被硬编码到函数的二进制代码中,并将其移动到另一个函数中位置它的内存可以使那些相对地址变坏。

这恰好起作用,因为function1和function2在内存中的大小完全相同。 对于memcopy,我们需要function2的长度,所以应该做的是:int diff =(&main – &function2);

您会注意到您可以根据自己的喜好编辑function2并保持正常工作!

顺便说一下。 不兼容g ++编译器确实吐出了从void *到int的无效转换……但实际上使用gcc它完全编译;)

修改来源:

 //Hacky solution and simple proof of concept that works for me (and compiles without warning on Mac OS X/GCC 4.2.1): //fixed the diff address to also work when function2 is variable size #include "stdio.h" #include "stdlib.h" #include "string.h" #include  int function1(int x){ return x-5; } int function2(int x){ //printf("hello world"); int k=32; int l=40; return x+5+k+l; } int main(){ int diff = (&main - &function2); printf("pagesize: %d, diff: %d\n",getpagesize(),diff); int (*fptr)(int); void *memfun = malloc(4096); if (mprotect(memfun, 4096, PROT_READ|PROT_EXEC|PROT_WRITE) == -1) { perror ("mprotect"); } memcpy(memfun, (const void*)&function2, diff); fptr = &function1; printf("native: %d\n",(*fptr)(6)); fptr = memfun; printf("memory: %d\n",(*fptr)(6) ); fptr = &function1; printf("native: %d\n",(*fptr)(6)); free(memfun); return 0; } 

输出:

Walter-Schrepperss-MacBook-Pro:cppWork wschrep $ gcc memoryFun.c Walter-Schrepperss-MacBook-Pro:cppWork wschrep $ ./a.out pagesize:4096,diff:35 native:1 memory:83 native:1

另一个值得注意的是调用printf会出现段错误,因为相对地址出错导致很可能找不到printf …

我已经在C中多次尝试过这个问题并得出结论,仅使用C语言无法实现。 我的主要刺是找到要复制的函数的长度。

标准C语言不提供任何获取函数长度的方法。 但是,可以使用汇编语言和“部分”来查找长度。 一旦找到长度,复制和执行就很容易。

最简单的解决方案是创建或定义包含该函数的链接器段。 编写汇编语言模块来计算并公开声明该段的长度。 将此常量用于函数的大小。

还有其他方法涉及设置链接器,例如预定义区域或固定位置以及复制这些位置。

在嵌入式系统中,大多数将可执行内容复制到RAM中的代码都是用汇编语言编写的。

这可能是一个黑客解决方案。 您可以在函数(要复制)之后直接创建一个虚拟变量或函数,获取该虚拟变量/函数的地址,然后使用函数地址对使用地址进行求和算术来获得函数大小吗? 这可能是可能的,因为内存是线性和有序(而不是随机)分配的。 这还可以在ANSI C便携式环境中保持function复制,而不是深入研究系统特定的汇编代码。 我觉得C很灵活,只需要思考一下。

Hacky解决方案和简单的概念certificate对我有用(并且在Mac OS X / GCC 4.2.1上没有警告就编译):

 #include "stdio.h" #include "stdlib.h" #include "string.h" #include  int function1(int x){ return x-5; } int function2(int x){ return x+5; } int main(){ int diff = (&function2 - &function1); printf("pagesize: %d, diff: %d\n",getpagesize(),diff); int (*fptr)(int); void *memfun = malloc(4096); if (mprotect(memfun, 4096, PROT_READ|PROT_EXEC|PROT_WRITE) == -1) { perror ("mprotect"); } memcpy(memfun, (const void*)&function2, diff); fptr = &function1; printf("native: %d\n",(*fptr)(6)); fptr = memfun; printf("memory: %d\n",(*fptr)(6) ); fptr = &function1; printf("native: %d\n",(*fptr)(6)); free(memfun); return 0; }