简体   繁体   English

在C ++中将字符串转换为函数

[英]Converting a string into a function in c++

I have been looking for a way to dynamically load functions into c++ for some time now, and I think I have finally figure it out. 一段时间以来,我一直在寻找一种将函数动态加载到c ++中的方法,我想我终于找到了答案。 Here is the plan: 这是计划:

  1. Pass the function as a string into C++ (via a socket connection, a file, or something). 将函数作为字符串传递给C ++(通过套接字连接,文件或其他方式)。
  2. Write the string into file. 将字符串写入文件。
  3. Have the C++ program compile the file and execute it. 让C ++程序编译该文件并执行它。 If there are any errors, catch them and return it. 如果有任何错误,请抓住并返回。
  4. Have the newly executed program with the new function pass the memory location of the function to the currently running program. 让具有新功能的新执行程序将功能的存储位置传递给当前正在运行的程序。
  5. Save the location of the function to a function pointer variable (the function will always have the same return type and arguments, so this simplifies the declaration of the pointer). 将函数的位置保存到函数指针变量中(该函数将始终具有相同的返回类型和参数,因此这简化了指针的声明)。
  6. Run the new function with the function pointer. 使用函数指针运行新函数。

The issue is that after step 4, I do not want to keep the new program running since if I do this very often, many running programs will suck up threads. 问题是,在第4步之后,我不想保持新程序的运行,因为如果我经常这样做,那么许多正在运行的程序都会占用线程。 Is there some way to close the new program, but preserve the memory location where the new function is stored? 有什么方法可以关闭新程序,但保留存储新功能的内存位置? I do not want it being overwritten or made available to other programs while it is still in use. 我不希望它在使用过程中被覆盖或提供给其他程序使用。

If you guys have any suggestions for the other steps as well, that would be appreciated as well. 如果您对其他步骤也有任何建议,也将不胜感激。 There might be other libraries that do things similar to this, and it is fine to recommend them, but this is the approach I want to look into — if not for the accomplishment of it, then for the knowledge of knowing how to do so. 可能还有其他类似的库,推荐它们是可以的,但这是我要研究的方法-如果不是为了实现它,而是为了知道如何做。

Edit: I am aware of dynamically linked libraries. 编辑:我知道动态链接的库。 This is something I am largely looking into to gain a better understanding of how things work in C++. 为了更好地理解C ++的工作方式,我主要在研究这一点。

I can't see how this can work. 我看不到它如何工作。 When you run the new program it'll be a separate process and so any addresses in its process space have no meaning in the original process. 当您运行新程序时,它将是一个单独的过程,因此其过程空间中的任何地址在原始过程中均无意义。

And not just that, but the code you want to call doesn't even exist in the original process, so there's no way to call it in the original process. 不仅如此,您要调用的代码甚至在原始过程中都不存在 ,因此无法在原始过程中调用它。

As Nick says in his answer, you need either a DLL/shared library or you have to set up some form of interprocess communication so the original process can send data to the new process to be operated on by the function in question and then sent back to the original process. 正如Nick在他的回答中所说,您需要一个DLL /共享库,或者必须建立某种形式的进程间通信,以便原始进程可以将数据发送到新进程以由相关函数进行操作,然后再发送回去。到原始过程。

How about a Dynamic Link Library ? 动态链接库怎么样?

These can be linked/unlinked/replaced at runtime. 这些可以在运行时链接/取消链接/替换。

Or, if you really want to communicated between processes, you could use a named pipe . 或者,如果您确实想在进程之间进行通信,则可以使用命名管道

edit - you can also create named shared memory . 编辑 -您还可以创建命名的共享内存

for the step 4. we can't directly pass the memory location(address) from one process to another process because the two process use the different virtual memory space. 对于第4步,我们无法将内存位置(地址)从一个进程直接传递到另一进程,因为这两个进程使用不同的虚拟内存空间。 One process can't use memory in other process. 一个进程不能在其他进程中使用内存。 So you need create a shared memory through two processes. 因此,您需要通过两个过程来创建共享内存。 and copy your function to this memory, then you can close the newly process. 并将功能复制到此内存中,然后可以关闭新进程。 for shared memory, if in windows, looks Creating Named Shared Memory http://msdn.microsoft.com/en-us/library/windows/desktop/aa366551(v=vs.85).aspx 对于共享内存,如果在Windows中,则显示“创建命名的共享内存” http://msdn.microsoft.com/zh-cn/library/windows/desktop/aa366551(v=vs.85).aspx

after that, you still create another memory space to copy function to it again. 之后,您仍然创建另一个存储空间以将功能再次复制到该存储空间。 The idea is that the normal memory allocated only has read/write properties, if execute the programmer on it, the CPU will generate the exception. 想法是分配的普通内存仅具有读/写属性,如果在其上执行编程器,CPU将生成异常。

So, if in windows, you need use VirtualAlloc to allocate the memory with the flag,PAGE_EXECUTE_READWRITE ( http://msdn.microsoft.com/en-us/library/windows/desktop/aa366887(v=vs.85).aspx ) 因此,如果在Windows中,则需要使用VirtualAlloc来分配带有标志PAGE_EXECUTE_READWRITE的内存( http://msdn.microsoft.com/zh-cn/library/windows/desktop/aa366887(v=vs.85).aspx

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

After copy the function to address , you can call the function in address , but need be very careful to keep the stack balance. 将函数复制到address ,可以在address调用函数,但是需要非常小心以保持堆栈平衡。

Dynamic library are best suited for your problem. 动态库最适合您的问题。 Also forget about launching a different process, it's another problem by itself, but in addition to the post above, provided that you did the virtual alloc correctly, just call your function within the same "loadder", then you shouldn't have to worry since you will be running the same RAM size bound stack. 另外,也不必考虑启动一个不同的进程,这本身就是另一个问题,但是除了上面的文章,只要您正确地执行了虚拟分配,只需在同一“加载程序”中调用函数即可,那么您不必担心因为您将运行相同的RAM大小绑定堆栈。

The real problems are: 真正的问题是:

1 - Compiling the function you want to load, offline from the main program. 1-从主程序离线编译要加载的功能。

2 - Extract the relevant code from the binary produced by the compiler. 2-从编译器生成的二进制文件中提取相关代码。

3 - Load the string. 3-加载字符串。

1 and 2 require deep understanding of the entire compiler suite, including compiler flag options, linker, etc ... not just the IDE's push buttons ... 1和2需要对整个编译器套件有深刻的了解,包括编译器标志选项,链接器等...而不仅仅是IDE的按钮...

If you are OK, with 1 and 2, you should know why using a std::string or anything but pure char *, is an harmfull. 如果可以,请使用1和2,您应该知道为什么使用std :: string或除纯char *之外的其他任何方式都是有害的。

I could continue the entire story but it definitely deserve it's book, since this is Hacker/Cracker way of doing things I strongly recommand to the normal user the use of dynamic library, this is why they exists. 我可以继续讲整个故事,但绝对值得一读,因为这是Hacker / Cracker的处理方式,因此我强烈建议普通用户使用动态库,这就是它们存在的原因。

Usually we call this code injection ... 通常我们称这种代码注入为...

Basically it is forbidden by any modern operating system to access something for exceution after the initial loading has been done for sake of security, so we must fall back to OS wide validated dynamic libraries. 基本上,任何现代操作系统都为安全起见,在初始加载完成后,禁止任何东西来执行某些操作,因此,我们必须使用经过OS验证的动态库。

That's said, one you have valid compiled code, if you realy want to achieve that effect you must load your function into memory then define it as executable ( clear the NX bit ) in a system specific way. 就是说,您有一个有效的编译代码,如果您确实想实现这种效果,则必须将函数加载到内存中,然后以系统特定的方式将其定义为可执行文件(清除NX位)。

But let's be clear, your function must be code position independant and you have no help from the dynamic linker in order to resolve symbol ... that's the hard part of the job. 但是请清楚一点,您的函数必须与代码位置无关,并且动态链接程序也没有帮助来解析符号……这是工作的难点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM