调用另一个进程加载的 DLL 中的函数

Posted

技术标签:

【中文标题】调用另一个进程加载的 DLL 中的函数【英文标题】:Calling functions in a DLL loaded by another process 【发布时间】:2011-07-08 22:51:11 【问题描述】:

我有一个注入到另一个进程的 DLL,但我希望能够从我的应用程序中调用该 DLL 上的导出。我在其他地方读到你必须使用 SendMessage API,但我不知道该怎么做。有没有关于如何做到这一点的示例代码?

【问题讨论】:

您可以直接从您的应用程序中使用导出,无需链接或加载该 DLL。 DLL 就是这样工作的,真的。它可能在您的进程的地址空间中具有不同的地址,但它们将是完全相同的页面。这就是为什么 DLL 也有自己的堆(而不仅仅是使用应用程序的堆)的原因。 【参考方案1】:

虽然无法直接调用另一个进程中的函数,但您可以通过几个步骤和 Windows API 轻松地间接调用。

    从自己的进程中获取LoadLibraryGetProcAddress的地址。 kernel32.dll 应该在每个进程中加载​​到相同的地址,因此您可以依赖它们存在于您要注入的进程中 创建一个struct,它将包含您要传递给函数的所有参数,该函数将调用另一个进程中的函数(因为CreateRemoteThread 只能将一个参数传递给函数,所以我们将使用它传递一个指向结构的指针)至少包含成员函数指针来保存LoadLibraryGetProcAddress的地址 通过VirtualAllocEx为远程进程中的结构分配足够的内存,然后用WriteProcessMemory填充正确的信息 编写一个函数,获取指向您编写的struct 的指针,该函数使用LoadLibrary/GetProcAddress 调用您想要的函数。请记住使用 pointers 指向要传递函数的结构中的那些函数,而不是名称。 在远程进程中分配足够的内存来保存带有VirtualAllocEx 的函数,确保传递VAXPAGE_EXECUTE_READWRITE 标志以便它可以保存可执行代码 通过Read/WriteProcessMemory从你的进程读写函数代码到另一个进程 使用CreateRemoteThread调用远程进程中的函数(在VirtualAllocEx返回的地址)。

确保您传递给函数的所有数据都存储在结构内和/或驻留在远程进程的地址空间中(使用VirtualAllocEx/WriteProcessMemory 获取它。

它可能看起来有点复杂,但实际上并没有那么复杂。如果您需要一些帮助,请随时在评论中提问。

【讨论】:

“这个”进程和另一个进程的位数不同(32/64 位)的情况如何?有没有办法从这个进程中的 GetProcAddress() 返回值中找出它在另一个具有不同位数的进程中会是什么?【参考方案2】:

一般来说,您不能直接调用另一个进程中的函数。但是,您可以使用一些解决方法。

首先,如果您知道导出的地址(很多时候并非如此),并且您调用的函数使用__stdcall 调用约定,将指针大小的整数作为参数,并返回一个 DWORD,您可以使用CreateRemoteThread 在远程进程的线程中执行它。这通常用于运行LoadLibrary 以将DLL 注入目标进程,因为LoadLibrary 在给定计算机上的所有进程上加载到相同地址。

否则,您注入的 DLL 将需要与调用它的进程进行某种 RPC。例如,您可以让注入的 DLL 在其 DLL_PROCESS_ATTACH 处理程序中生成一个线程,该线程又连接到命名管道,或通过 COM 或其他方式连接到主进程。

【讨论】:

我刚刚查看了命名管道,这将满足我的需求。谢谢!【参考方案3】:

SendMessage 需要一个窗口句柄(隐藏或可见),以及与之关联的消息泵,它可以处理自定义消息。与 UAC/Windows-7 一样,应用程序的完整性级别可能会阻止其他应用程序从其他完整性低的进程发送/发布消息。

最好有另一个线程等待这些自定义消息。为此,您可以使用管道(命名或未命名)、套接字、邮槽、共享内存(以及用于触发的互斥体/事件)。其他进程将使用相同的协议发送消息。

但在实现这种自定义消息/协议/IPC 机制之前,我建议您先确定确切的需求。

【讨论】:

以上是关于调用另一个进程加载的 DLL 中的函数的主要内容,如果未能解决你的问题,请参考以下文章

什么是动态链接库

mfc HackerTools远程线程注入

反射式DLL注入--方法

逆向学习-DLL注入

如何查找加载到进程中的DLL及其位置等

dll被加载后线程的问题