0

一段时间以来,我一直在寻找一种将函数动态加载到 c++ 中的方法,我想我终于弄明白了。这是计划:

  1. 将函数作为字符串传递给 C++(通过套接字连接、文件或其他方式)。
  2. 将字符串写入文件。
  3. 让 C++ 程序编译该文件并执行它。如果有任何错误,抓住它们并返回它。
  4. 让新执行的带有新函数的程序将函数的内存位置传递给当前正在运行的程序。
  5. 将函数的位置保存到函数指针变量中(函数将始终具有相同的返回类型和参数,因此这简化了指针的声明)。
  6. 使用函数指针运行新函数。

问题是在第 4 步之后,我不想让新程序继续运行,因为如果我经常这样做,许多正在运行的程序会占用线程。有什么方法可以关闭新程序,但保留存储新函数的内存位置?我不希望它在仍在使用时被覆盖或提供给其他程序。

如果你们对其他步骤也有任何建议,那也将不胜感激。可能还有其他库做类似的事情,推荐它们很好,但这是我想要研究的方法——如果不是为了完成它,那么是为了知道如何去做。

编辑:我知道动态链接库。这是我主要研究的内容,以更好地了解 C++ 中的工作原理。

4

5 回答 5

6

我看不出这是如何工作的。当您运行新程序时,它将是一个单独的进程,因此其进程空间中的任何地址在原始进程中都没有意义。

不仅如此,你要调用的代码甚至在原进程中都不存在,所以在原进程中也没有办法调用它。

正如尼克在他的回答中所说,您需要一个 DLL/共享库,或者您必须设置某种形式的进程间通信,以便原始进程可以将数据发送到新进程以由相关函数操作,然后发回到原来的过程。

于 2012-05-28T00:30:16.367 回答
3

动态链接库怎么样?

这些可以在运行时链接/取消链接/替换。

或者,如果您真的想在进程之间进行通信,您可以使用命名管道

编辑- 您还可以创建命名共享内存

于 2012-05-28T00:28:43.267 回答
2

动态库最适合您的问题。也忘了启动一个不同的进程,这本身就是另一个问题,但除了上面的帖子,只要你正确地做了虚拟分配,只需在同一个“加载器”中调用你的函数,那么你不必担心因为您将运行相同的 RAM 大小绑定堆栈。

真正的问题是:

1 - 从主程序离线编译要加载的函数。

2 - 从编译器生成的二进制文件中提取相关代码。

3 - 加载字符串。

1 和 2 需要深入了解整个编译器套件,包括编译器标志选项、链接器等……而不仅仅是 IDE 的按钮……

如果你没问题,使用 1 和 2,你应该知道为什么使用 std::string 或除纯字符 * 之外的任何东西是有害的。

我可以继续整个故事,但它绝对值得一书,因为这是 Hacker/Cracker 做事的方式,我强烈建议普通用户使用动态库,这就是它们存在的原因。

于 2012-05-28T03:23:56.087 回答
2

对于步骤 4。我们不能直接将内存位置(地址)从一个进程传递给另一个进程,因为这两个进程使用不同的虚拟内存空间。一个进程不能在其他进程中使用内存。所以你需要通过两个进程创建一个共享内存。并将您的功能复制到此内存中,然后您可以关闭新进程。对于共享内存,如果在 Windows 中,请查看创建命名共享内存 http://msdn.microsoft.com/en-us/library/windows/desktop/aa366551(v=vs.85).aspx

之后,您仍然创建另一个内存空间以再次将功能复制到它。这个想法是分配的普通内存只有读/写属性,如果在上面执行程序员,CPU会产生异常。

因此,如果在 Windows 中,您需要使用 VirtualAlloc 使用标志 PAGE_EXECUTE_READWRITE 分配内存(http://msdn.microsoft.com/en-us/library/windows/desktop/aa366887(v=vs.85).aspx )

void* address = NULL;
address= VirtualAlloc(NULL,
        sizeof(emitcode),
        MEM_COMMIT|MEM_RESERVE,
        PAGE_EXECUTE_READWRITE);

将函数复制到 后address,就可以调用 中的函数address,但需要非常小心保持堆栈平衡。

于 2012-05-28T00:48:19.993 回答
0

通常我们称这种代码注入...

基本上,为了安全起见,任何现代操作系统都禁止在初始加载完成后访问某些内容以进行执行,因此我们必须回退到操作系统范围内经过验证的动态库。

也就是说,你有有效的编译代码,如果你真的想达到这个效果,你必须将你的函数加载到内存中,然后以系统特定的方式将它定义为可执行文件(清除 NX 位)。

但是让我们明确一点,您的函数必须与代码位置无关,并且动态链接器无法帮助您解析符号……这是工作的难点。

于 2018-08-21T15:49:29.657 回答