好吧,我正在使用CreateRemoteThread/LoadLibrary“技巧”将一些代码注入另一个进程。
我最终得到了一个线程ID,并且我选择了一个带有我选择的DLL的进程。至少在理论上,DLL目前没有做任何事情,所以验证这有点棘手。暂时我愿意仅靠信仰接受它。此外,在我朝这个方向努力之前,需要回答这个问题。
基本上,你不能阻止DllMain。但是,所有我必须与远程线程进行通信的是它的id。这实际上是为了阻止PostThreadMessage / GetMessage的恶作剧。我可以在DllMain中启动另一个线程,但我无法将其id传回给创建线程,也无法将另一个线程的id传递给远程线程。
简而言之,如果我在流程中创建远程线程,我应该如何与原始流程进行通信?
答案 0 :(得分:6)
步骤零;注入的DLL应该有一个入口点,我们称之为Init()
,它将LPCWSTR
作为其单个参数并返回int
;即与LoadLibrary()
相同的签名,因此与线程起始函数地址同等有效...
第一步;使用加载库和远程线程注入。在注入的DLL DLLMain()
中不做任何事情。存储返回的HMODULE
作为注入线程的退出代码,这是注入的DLL的HMODULE
和返回值LoadLibrary()
。
注意 如果/DYNAMICBASE
和ASLR(地址空间布局随机化)被启用,则这不再是x64上的可靠方法x64上的{1}}大于HMODULE
返回的DWORD
值,地址空间的变化意味着GetThreadExitCode()
的值小到不足以适应进入HMODULE
。请参阅下面的评论和链接的问题(此处),了解如何使用共享内存来传达DWORD
第二步;使用LoadLibrary将注入的DLL加载到正在执行注入的进程中。然后在地址空间中找到HMODULE
入口点的偏移量,并从中减去地址空间中注入的DLL的Init()
。您现在具有HMODULE
函数的相对偏移量。获取目标进程中注入的DLL的Init()
(即您在第一步中保存的值),并将HMODULE
的相对地址添加到其中。现在,您的目标流程中的地址为Init()
。
第三步;使用您用来调用Init()
的相同“远程线程”方法在目标进程中调用Init()
。你可以将一个字符串传递给Init()调用,这可以是你想要的任何东西。
我倾向于传递一个唯一的字符串键,我将其用作命名管道名称的一部分。 Injected DLL和注入过程现在都知道命名管道的名称,您可以在它们之间进行通信。 LoadLibrary()
函数不是Init()
,并且不会受到影响DLLMain()
的限制(因为它不是从DLLMain()
内调用等),所以你可以做正常的东西。一旦注入的DLL和注入过程通过命名管道连接,您就可以根据需要来回传递命令和数据结果。由于您将LoadLibrary
函数传递给字符串,因此您可以确保命名管道对于此注入过程的特定实例是唯一的,并且此特定注入的DLL意味着您可以同时运行多个注入过程实例每个进程都可以注入多个目标进程,所有这些通信通道都是唯一且可控的。
答案 1 :(得分:1)
您没有远程进程中线程的线程ID,因为当您的模块成功加载到进程的地址空间时,用于加载dll的线程将退出。
您可以轻松使用正常的进程间通信方法,如命名节/管道/创建命名窗口/等。与你的“注射”过程沟通。