我可以在堆上分配一个块,将其字节设置为与函数调用及其参数对应的值,然后使用函数调用和解除引用运算符来执行该序列吗?
答案 0 :(得分:4)
因此,如果我正确读到你,你想在堆上动态创建CPU汇编指令并执行它们。有点像自修改代码。理论上这是可能的,但在实践中可能不是。
问题在于堆存在于数据段中,而现在CPU /操作系统已采取措施来防止这种行为(它被称为NX位,或x86 CPU的No-eXecute位)。如果标记被标记为NX,则无法从中执行代码。这是为了阻止计算机病毒使用缓冲区溢出将可执行代码放入数据/堆/堆栈内存中,然后尝试调用程序来执行此类代码。
请注意,DLL和库是在代码段中加载的,这当然允许代码执行。
答案 1 :(得分:3)
是。 Dynamic loading和Linking还有什么用呢?还记得一些(大多数?)操作系统和一些(大多数?)连接器也是用C / C ++编写的。例如,
#include <dlfcn.h>
void* initializer = dlsym(sdl_library,"SDL_Init");
if (initializer == NULL) {
// report error ...
} else {
// cast initializer to its proper type and use
}
另外,我认为JIT(例如GNU lightning和其他人)通常会执行这些操作。
答案 2 :(得分:2)
在Windows中,例如,当它曾经非常简单时,现在很难做到。我曾经能够在C中获取一个字节数组,然后将其转换为函数指针类型来执行它......但不再是。
现在,如果可以调用Global或VirtualAlloc函数并专门请求可执行内存,则可以执行此操作。在大多数平台上,它要么完全打开,要么大规模锁定。例如,在iOS上执行此类操作非常令人头疼,如果发现,它将导致应用商店提交失败。
这里有一些奇妙的过时和硬壳代码,我做了你描述的原始内容:
https://code.google.com/p/fridgescript/source/browse/trunk/src/w32/Code/Platform_FSCompiledCode.cpp
使用https://code.google.com/p/fsassembler
中的字节你可能会注意到我需要提供平台(windows)特定的分配函数来获得一些可执行的内存:
答案 3 :(得分:0)
是的,但您必须确保内存标记为可执行文件。你如何做到这一点取决于架构。