在内存中创建功能

时间:2014-11-11 05:00:40

标签: c++ memory function-pointers

我最近在课堂上学到了函数指针,我想知道你是否可以为一个程序分配的内存块分配一个函数指针,用汇编命令填充内存块(操作码的十六进制值),然后调用使用函数指针的内存块。

我对功能指针知之甚少,但我猜你不能在内存中的任何地方分配它们,他们需要指向一个函数。如果这是真的,你怎么能在内存中创建一个函数来调用?这甚至可能吗?

这是我输入的一些代码来展示这个概念。我使用了各种操作码值来查看是否有任何工作,并且0x90(NOP)有时没有破坏它(但是其他时间也是这样),而0xC3(ret)总是打破它。

#include <stdlib.h> //for malloc
#include <cstring> //for memcpy

int main() //program entry
{
    void(*test)() = NULL; //create function pointer, initialize to NULL
    void* hold_address = (void*)malloc(100); //allocate memory, save the address it returns in a dummy pointer
    int asm_commands[] = {0x90}; //create array of assembly commands, hex values
    memcpy(hold_address, asm_commands, sizeof(asm_commands)); //copy the array into the reserved memory
    test = (void(*)())hold_address; //set the function pointer to start of the allocated memory
    test(); //call the function, crashes here
    return 0; //exit the program
}

3 个答案:

答案 0 :(得分:2)

你可以做你描述的事情。但是,使用malloc()分配的内存可能没有代码执行权限 - 具体取决于您的平台。

分配可执行内存的方式因操作系统而异。在Linux上,选中mmap。在Windows上,请参阅VirtualAlloc

答案 1 :(得分:2)

几点:

  • 您的asm_commands[]可能应该是unsigned char(或uint8_t) - 因此,您将复制3个NUL / 0字符以及{0x90 1}}

  • 某些操作系统不允许您在已经分配给malloc()的内存中执行指令 - 他们会使用SIGSEGV或类似内容 - 这样做是为了防止某些堆栈溢出和其他hackery的类型

  • 我建议您编写一个实际的函数void f() { },并使用g++ -S或编译器提供的内容查看为其生成的操作码,因为您可能需要做的不仅仅是{ {1}}正确返回(例如弹出某些寄存器)

    • 如果&#34;克隆&#34;来自实际C ++函数的指令可以帮助您开始使用调整后的asm函数,也要对位置相关的代码保持警惕......您不能只是复制函数内的数据和代码地址,因为它们不会在内部malloced地区。位置无关代码(PIC)使用相对寻址操作码来避免这种情况......这就是你需要写的东西。

答案 2 :(得分:1)

函数调用比这更复杂。

您必须至少修改基指针。我建议你看一下函数调用的反汇编并尝试模仿它