我一直在寻找一种方法将函数动态加载到c ++中一段时间了,我想我终于搞清楚了。这是计划:
- 将函数作为字符串传递给C ++(通过套接字连接,文件或其他东西)。
- 将字符串写入文件。
- 让C ++程序编译并执行它。如果有任何错误,请抓住并返回。
- 使用新函数新执行的程序将函数的内存位置传递给当前正在运行的程序。
- 将函数的位置保存到函数指针变量中(函数将始终具有相同的返回类型和参数,因此 这简化了指针的声明)。
- 使用函数指针运行新函数。
醇>
问题是,在第4步之后,我不想保持新程序的运行,因为如果我经常这样做,许多正在运行的程序将会吸收线程。有没有办法关闭新程序,但保留存储新功能的内存位置?我不希望它在被使用时被覆盖或提供给其他程序。
如果你们对其他步骤有任何建议,那也值得赞赏。可能还有其他库可以做与此类似的事情,可以推荐它们,但这是我想要研究的方法 - 如果不是为了完成它,那么知道如何这样做。
编辑:我知道动态链接的库。这是我正在研究的内容,以便更好地理解C ++中的工作原理。
答案 0 :(得分:6)
我看不出这是如何起作用的。当您运行新程序时,它将是一个单独的进程,因此其进程空间中的任何地址在原始进程中都没有意义。
不仅仅是这样,但是在原始流程中,您想要调用的代码甚至不存在,因此无法在原始流程中调用它。
正如尼克在他的回答中所说,您需要一个DLL /共享库,或者您必须设置某种形式的进程间通信,以便原始进程可以将数据发送到新进程以由相关函数进行操作,然后发回原来的过程。
答案 1 :(得分:3)
答案 2 :(得分: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
中调用该函数,但需要非常小心以保持堆栈平衡。
答案 3 :(得分:2)
动态库最适合您的问题。还要忘记启动一个不同的进程,它本身就是另一个问题,但除了上面的帖子之外,如果你正确地进行了虚拟分配,只需在同一个“加载器”中调用你的函数,那你就不必担心了因为你将运行相同的RAM大小绑定堆栈。
真正的问题是:
1 - 从主程序编译要加载的功能,离线。
2 - 从编译器生成的二进制文件中提取相关代码。
3 - 加载字符串。
1和2需要深入了解整个编译器套件,包括编译器标志选项,链接器等...而不仅仅是IDE的按钮......
如果你没事,1和2,你应该知道为什么使用std :: string或者除了纯char *之外的任何东西都是有害的。
我可以继续整个故事,但它绝对值得它的书,因为这是Hacker / Cracker做事的方式我强烈建议普通用户使用动态库,这就是它们存在的原因。
答案 4 :(得分:0)
通常我们称这种代码注入...
基本上,任何现代操作系统都禁止为安全起见在完成初始加载后访问某些内容,因此,我们必须使用经过OS验证的动态库。
也就是说,您有一个有效的编译代码,如果您确实想实现这种效果,则必须将函数加载到内存中,然后以系统特定的方式将其定义为可执行文件(清除NX位)。
但是要清楚一点,您的函数必须与代码位置无关,并且动态链接程序也没有帮助来解析符号...这是工作的难点。