2013-04-27 64 views
4

假设我想将一个DLL注入一个想要每隔250毫秒编辑地址A值的进程。我需要使用DllMain,对吧?问题是我不允许在DllMain中等待。所以我将不得不创建一个线程?或者是否没有绕过限制?我会如何去做这件事?DLL注入的最佳实践?

另外,使用DLL注入来编辑应用程序的内存使用EXE有什么好处吗?

另外,CreateThread中的堆栈大小应该是多少?如果它太小或太大会怎样?我如何知道我需要多少?

回答

5

从您的描述看来,您已经知道如何让目标进程加载您的DLL。如果我的假设是正确的,那么答案很简单:从DLLMain创建一个线程并在线程中实现您的逻辑。只要你的代码遵守下面列出的规则,你应该没问题。

这个document描述了DLLMain能做什么和不能做什么以及为什么。

如记录,你永远不应该从内部的DllMain执行下列任务:

  • 调用LoadLibrary或LoadLibraryEx(直接或间接)。 这可能会导致死锁或崩溃。
  • 与其他线程同步。这可能导致死锁。
  • 获取正在等待获取加载程序 锁的代码拥有的同步对象。这可能导致死锁。
  • 使用CoInitializeEx初始化COM线程。在某些情况下,该函数可以调用 LoadLibraryEx。
  • 调用注册表函数。这些函数在Advapi32.dll中实现。如果Advapi32.dll没有在您的DLL之前初始化,该DLL可以访问未初始化的内存并导致进程崩溃。
  • 调用CreateProces。创建一个进程可以加载另一个DLL。
  • 调用ExitThread。在DLL分离期间退出线程可能会导致再次获取加载程序锁定,从而导致死锁或崩溃。
  • 调用CreateThread。如果您不与其他线程同步,创建一个线程可以工作,但这是有风险的。
  • 创建一个命名管道或其他命名对象(仅限Windows 2000)。在Windows 2000中,命名对象由终端服务DLL提供。如果此DLL未初始化,对DLL的调用可能会导致进程崩溃。
  • 使用动态C运行时(CRT)中的内存管理功能。如果CRT DLL没有初始化,调用这些函数会导致进程崩溃。
  • 在User32.dll或Gdi32.dll中调用函数。某些函数加载另一个DLL,可能无法初始化。
  • 使用托管代码。

以下任务是安全的范围内的DllMain执行:

  • 初始化静态数据结构和成员在编译时。
  • 创建并初始化同步对象
  • 分配内存和初始化动态数据结构(避免上面列出的功能。)
  • 设置线程本地存储(TLS)。
  • 打开,读取和写入文件。
  • Kernel32.dll中的调用函数(上面列出的函数除外)。
  • 将全局指针设置为NULL,推迟动态成员的初始化。在Microsoft Windows Vista™中,您可以使用一次性初始化函数来确保在多线程环境中仅执行一次代码块。

你的第二个问题对我来说不太清楚。要将代码注入到另一个进程中,您必须从某处(浏览器,exe或其他任何地方)启动,然后写入目标进程内存以加载您的DLL。