C ++注入一个DLL,你需要线程吗?

时间:2016-04-07 08:12:16

标签: c++ multithreading dll

我对它有点新意,我还不完全理解线程术语,尽管我知道如何创建一个线程并运行多个线程的程序。我想知道的是,当你创建一个dll文件(c ++)并将其注入一个进程(比方说gamehacking)时。你需要在dll文件中创建线程,还是不能工作?经过我的理解,主线程将从主机进程运行吗?或者它是如何工作的?

4 个答案:

答案 0 :(得分:1)

这取决于您计划使用DLL实现的目标。如果该特定DLL具有一些静态函数/实用程序类,它只需要输入,进行一些计算/处理并生成输出,那么就不需要在这里进行线程化。

但是,如果该DLL要在套接字上侦听或写入文件或执行需要某些并行性的实际工作,那么您可能希望在该DLL中创建线程。

基本上你必须要理解这个DLL完成的任务。 DLL可以在编译期间作为普通库链接,也可以根据您的需要/用例在运行时动态加载。

要回答你的问题,

Would you need to create threads in the dll file, or is that not going to work?

答:并非总是如此。您需要创建线程来完成某项任务。话虽这么说,但事实并非如此。在没有任何线程的情况下在进程内运行DLL是完全可行的。

After my understanding the main thread will be running from the host process right? Or how does it work?

答:没错:没错。您运行的任何进程,默认情况下都会有一个线程。如果您的应用程序很简单,可以由单个线程处理,那么这是一个祝福。跟上它:)

答案 1 :(得分:0)

每个进程至少有一个线程。当该过程开始时,可​​以将一堆函数或库链接到该进程的内存空间。这就是dll是什么。与直接链接到二进制文件相比的优点是库只需要存在于文件系统中的一个位置,而存储器中的一个位置被多个进程使用。它是一种链接技术,类似于Linux中使用的.so文件。它与线程无关。

答案 2 :(得分:0)

  

你需要在dll文件中创建线程,还是不起作用?

加载不包含可运行代码的DLL将没有任何意义。也就是说,有两种方法可以运行DLL代码:

  • 加载DLL时,它有机会运行一些初始化代码

  • 在初始化期间,可能会:

    • 启动一个或多个线程,这些线程可以继续运行 - 也许正在观察某些触发某些操作的事件

    • 注册来自操作系统或应用程序的回调,例如设置信号处理程序,击键处理程序,任何类型的事件处理程序....

  • 它可能包含程序将动态查找并运行的函数,将您的DLL代码误认为程序附带的那些函数的原始版本

哪些适合您的需求完全取决于您的DLL尝试实现的目标,以及实现它的技术必要性。例如,如果要查看某些内存以获得特定内容,然后进一步修改它,则可能只需要在您的DLL中调用OS警报服务调用的函数,如果找不到触发内存内容,则重置自己以后再次关闭。但是,触发器可能存在文件,共享内存服务,正在创建的套接字等。

  

经过我的理解,主线程将从主机进程运行吗?或者它是如何工作的?

是 - 在进程内启动的线程 - 包括任何DLL初始化例程 - 也在此过程中。有一些库函数可能会创建其他进程 - 例如fork,popen,system - 可能包含自己的线程。

答案 3 :(得分:0)

由于你专门引用了注入 DLL,我还为你提供了一些输入。

首先,让我们确保线程,流程和模块的概念是清晰的。

线程基本上是代码运行的直接环境。诸如处理器寄存器和堆栈变量的当前状态(例如,函数中的局部变量,在大多数情况下,以及执行当前所在的代码中的位置)都属于一个线程。还有其他资源通常具有线程亲和性,例如windows。它在很大程度上取决于所讨论的资源是否以及它们具有何种线程关联性。

让我们假设你写了一个简单的hello world程序。它将在一个线程中运行,该线程从头到尾遍历您的程序并打印" Hello World"。现在让我们假设您想要编写一个程序,该程序慢慢地写入" Hello World",每秒一个字符,但同时下载文件。然后你可以创建第二个线程,并有一个线程输出" Hello World"慢慢地,一个线程下载文件。这意味着执行可以并行发生,具有不同的本地状态 - 一个线程当前位于printHelloWorld函数内,一个线程位于downloadFile内。

进程基本上是一个或多个线程的容器。它将它们捆绑在一个使用相同虚拟内存的共享环境中(这意味着例如代码中的全局变量可以从所有线程访问,但这需要仔细同步以避免竞争条件)并共享资源,例如文件句柄进程中的线程创建。因此,您之前的hello-world-and-download程序将在1个进程中拥有2个线程,例如共享控制台,并在任务管理器中看作一个实体。

模块是一个包含可执行代码的文件(在大多数情况下),并且被加载到进程中。通常,在一个进程中有一个EXE文件和几个DLL文件作为模块加载。 DLL文件和EXE文件在技术上几乎相同,但EXE文件是进程启动的基础,DLL文件是指导出某些功能的库,可供其他模块使用。因为我说模块被加载到进程中,这意味着一个模块可以被进程中的所有线程访问,并且它没有自己的线程关联 - 在我们前面的例子中,当第二个线程下载文件时,它可能正在调用HTTP网络DLL,其代码将在第二个线程中运行。 Windows中有许多模块自动加载到每个进程中,而其他模块可能是由编译器的某些功能加载的。

好的,回到你的问题:

  

你需要在dll文件中创建线程吗?...

本身,使用DLL与是否需要创建新线程无关。这取决于你想要做什么 - 如果你需要与其他正在运行的代码并行执行一些耗时的任务,那么你需要为它创建一个新的线程,否则就没有必要。

  

[...]或者那不起作用?

如上所述,可以创建新线程,如果你愿意(它可以工作),但使用DLL并不是必需的。

  

根据我的理解,主线程将从主机进程运行吗?

主机进程的主线程 当然将在主机进程中。 (虽然技术上没有"主线程",因为让进程中的第一个线程创建第二个线程然后终止是完全有效的,所以只有第二个线程将再次运行,你通常在整个过程的生命周期中都有第一个线程,在这种情况下你可以把它称为主线程#34;然而,在当前运行的代码所在的模块中,将取决于线程目前正在做什么。

让我回到"注入":先前的答案似乎已经假设更多"正常"您的DLL刚刚链接到程序并且意图由它加载的环境。在这种情况下,您的DLL初始化例程(在模块加载到进程时自动运行)将在"主线程"中运行,可能在进程的实际工作之前开始。

但是,注入DLL时情况会有所不同。这取决于你如何进行注射:

  • 如果通过修改主机EXE的imports表来注入DLL,那么你的DLL将加载" normal"我刚才说的方式。因此,您可以期望您的初始化例程在此过程中运行。启动,在主线程中。
  • 如果您使用AppInit_DLLs注册表项注入DLL,它将是相同的。
  • 同样的事情,如果您通过启动挂起的主机进程注入DLL,然后编写存根以将DLL加载到进程'内存并使用SetThreadContext指向它的指令指针。
  • 如果您通过使用LoadLibrary在目标进程内远程调用CreateRemoteThread来注入DLL,那么,顾名思义,您正在创建新线程在过程中。在这个线程中,LoadLibrary将加载你的DLL并调用你的初始化例程,所以在这种情况下,你的初始化例程确实会在"主线程"以外的新线程中运行。