C++ 调用由另一进程加载的DLL中的函数

C++ 调用由另一进程加载的DLL中的函数,c++,dll,hook,C++,Dll,Hook,我有一个DLL,我将其注入另一个进程,但我希望能够从我的应用程序调用该DLL上的导出。我在其他地方读到,您必须使用SendMessageAPI,但我不知道该怎么做。是否有关于如何执行此操作的示例代码?通常,您不能在另一个进程中直接调用函数。但是,您可以使用一些变通方法 首先,如果您知道导出的地址(通常情况下不是这样),并且您调用的函数使用\uu stdcall调用约定,将指针大小的整数作为参数,并返回DWORD,则可以使用CreateRemoteThread在远程进程的线程中执行它。这通常用于运

我有一个DLL,我将其注入另一个进程,但我希望能够从我的应用程序调用该DLL上的导出。我在其他地方读到,您必须使用SendMessageAPI,但我不知道该怎么做。是否有关于如何执行此操作的示例代码?

通常,您不能在另一个进程中直接调用函数。但是,您可以使用一些变通方法

首先,如果您知道导出的地址(通常情况下不是这样),并且您调用的函数使用
\uu stdcall
调用约定,将指针大小的整数作为参数,并返回DWORD,则可以使用
CreateRemoteThread
在远程进程的线程中执行它。这通常用于运行
LoadLibrary
将DLL注入目标进程,因为
LoadLibrary
加载到给定计算机上所有进程的相同地址中


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

虽然无法直接调用另一个进程中的函数,通过几个步骤和Windows API,您可以非常轻松地间接地完成这项工作

  • 从您自己的进程中获取
    LoadLibrary
    GetProcAddress
    的地址
    kernel32.dll
    应该在每个进程中加载到相同的地址,这样您就可以相信它们在您要注入的进程中存在
  • 创建一个
    struct
    ,该结构将保存要传递给函数的所有参数,该函数将在另一个进程中调用函数(因为
    CreateRemoteThread
    只能向函数传递一个参数,所以我们将使用它传递指向该结构的指针)它至少包含成员函数指针,用于保存
    LoadLibrary
    GetProcAddress
  • 通过
    VirtualAllocEx
    为远程进程中的结构分配足够的内存,然后使用
    WriteProcessMemory
  • 编写一个函数,用指针指向您编写的
    结构
    ,该结构使用
    LoadLibrary
    /
    GetProcAddress
    调用您想要的函数。记住在传递函数的结构中使用指向这些函数的指针,而不是名称
  • 在远程进程中分配足够的内存,以便使用
    VirtualAllocEx
    保存函数,确保通过
    VAX
    页面执行\u读写标志,使其能够保存可执行代码
  • 通过
    Read/WriteProcessMemory
  • 使用
    CreateRemoteThread
    调用远程进程中的函数(位于
    VirtualAllocEx
    返回的地址)
  • 确保传递给函数的所有数据都存储在结构中和/或驻留在远程进程的地址空间中(使用
    VirtualAllocEx
    /
    WriteProcessMemory
    将其获取到该地址空间)


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

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

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


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

    您可以直接从应用程序使用导出,无需任何操作,只需链接或加载该DLL。这就是DLL的工作原理。它在您的进程地址空间中可能有不同的地址,但它不会他拥有完全相同的页面。这就是为什么DLL也有自己的堆(而不仅仅是使用应用程序的堆)的原因。我只是查看了命名管道,这将满足我的要求。谢谢!如果“这个”进程和另一个进程的位数不同(32/64位),会怎么样?有没有办法从GetProcAddress()中找出答案此进程中的返回值在另一个具有不同比特数的进程中是什么?