我想知道是否有可能执行根本不在主程序中的代码,如果可能的话,您将如何去执行它?如果不能用c完成,可以用c ++完成吗?
我在想,如果将二进制文件导入到堆上,将指针移到寄存器int,然后尝试预测寄存器并调用指针,则可能会发生这种情况,但是我实际上并没有备用PC尝试此操作,以防出现问题。
答案 0 :(得分:0)
(更新:我可能错过了树林,因此我将首先介绍更明智的动态链接方法。请注意,此编辑之前已经接受了答案,因此请参阅分隔符下面的内容。)>
如果要在主程序之外使用代码,则操作系统通常会在其动态链接器中提供用于此目的的工具。通常,您可以在运行时加载.so
或.dll
文件。
在Linux上,您可以使用dlopen
(加载.so文件)和dlsym
(从中获取函数)来实现。这是一个虚拟插件系统的示例,其中您向load_plugin
传递了一个.so
文件的路径,并尝试从该文件运行foo_plugin_init
:
#include <stdio.h>
#include <dlfcn.h>
int load_plugin(const char* filename) {
void *handle = dlopen(filename, RTLD_LAZY); // Try to load the .so file
dlerror(); // Clear any error a previous dlsym might have reported
void (*plugin_init)() = dlsym(handle, "foo_plugin_init"); // Load the "foo_plugin_init" function
const char* error = dlerror(); // Check for errors reported by dlsym
if (error) {
fprintf(stderr, "Could not load plugin %s: %s\n", filename, error);
return 0;
}
plugin_init(); // Call the newly loaded function
return 1;
}
在Windows上,您可以使用LoadLibrary
(加载.dll文件)和GetProcAddress
(从中获取函数)执行类似的操作。用法大致相同,除了使用GetLastError
和FormatMessage
来检索结果字符串而导致的错误报告舞动更为复杂。我的Windows编程非常生锈,因此我无法轻松演示。
只要您有可执行的内存区域,就可以将其强制转换为函数指针:
void execute_memory(const void* mem) {
void (*func)() = mem;
func();
}
尽管执行此操作的方法是特定于平台的,但您可能需要首先使该内存可执行。尽管Windows使用mprotect
,但大多数操作系统都使用VirtualProtect
。
请记住,尽管此技术经常在JIT编译器中使用,但是非常很容易意外地编写带有严重安全漏洞的软件,因此,我将尽可能避免使用它。它还违反了可能存在的各种安全策略(例如DEP或grsecurity的W ^ X策略)。因此,如果您打算在实践中使用它,则应该提供一个不依赖于执行运行时生成的代码的后备。