想象一下,我正在做这样的事情:
void *p = malloc (1000); *((char*)p) = some_opcode; *((char*)p+1) = another_opcode; // for the sake of the example: the opcodes are ok .... etc...
如何定义一个函数指针来调用p,好像它是一个函数?(我使用的是VC++ 2008 express).
谢谢
实际上,malloc可能不会削减它.在Windows上,您可能需要调用类似[VirtualAlloc](http://msdn.microsoft.com/en-us/library/aa366887 ( VS.85).aspx)的内容才能获得可执行的内存页面.
从小开始:
void main(void) { char* p = (char*)VirtualAlloc(NULL, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE); p[0] = (char)0xC3; // ret typedef void (*functype)(); functype func = (functype)p; (*func)(); }
使用代码的下一步是保留EBP寄存器.这是一个练习.:-)
写完之后,我用malloc运行它,它也有效.这可能是因为我在Windows 2000 Server上运行管理员帐户.其他版本的Windows实际上可能需要VirtualAlloc调用.谁知道.
评论的空间不够.Joe_Muc是对的.你不应该将代码填入由malloc
或获得的内存中new
.如果更改Windows分配的页面的页面属性,则会遇到问题.
这不是问题,因为使用VirtualAlloc()并且相关的WIn32 API非常简单:调用VirtualAlloc()并将其设置flProtect
为[PAGE_EXECUTE_READWRITE][2]
请注意,您可能应该执行三个分配,一个保护页面,代码所需的页面,然后是另一个保护页面.这将为您提供一些不良代码保护.
还使用结构化异常处理来包装对生成的代码的调用.
接下来,Windows X86 ABI(调用约定)没有很好的文档记录(我知道,我看过).有一些信息在这里,这里,这里 看到的东西如何工作是看编译器生成代码的最好方法.这很容易用\FA
开关(有四个).
您可以在此处找到64位调用约定.
此外,您仍然可以在此处获取Microsoft的宏汇编程序MASM.我建议在MASM中编写机器代码并查看其输出,然后让机器代码生成器执行类似的操作.
英特尔和AMD的处理器手册都是很好的参考 - 如果你没有它们就可以获得它们.
如果你有正确的操作码,调用就像转换为函数指针并调用它一样简单.
typedef void (*voidFunc)(); char *p = malloc (1000); p[0] = some_opcode; p[1] = another_opcode; // for the sake of the example: the opcodes are ok p[n] = // return opcode... ((voidFunc)p)();
请注意,除非您将页面标记为可执行文件,否则您的处理器可能无法执行堆上生成的代码.