【问题标题】:How to call specific function in dll injection?如何在dll注入中调用特定函数?
【发布时间】:2014-08-27 07:31:24
【问题描述】:

以下代码将注入 dll 并调用 DllMain。我如何从 DLL 调用特定函数,而不仅仅是 DllMain?

    DWORD pid;
    HANDLE hd;
    LPVOID gp, rs, proc;

    gp = (LPVOID)GetProcAddress(GetModuleHandle(L"Kernel32.dll"), "LoadLibraryA");
    pid = 6096;

    hd = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);    


    rs = (LPVOID)VirtualAllocEx(hd, 0, sizeof(DLL_NAME), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

    if (!WriteProcessMemory(hd, (LPVOID)rs, DLL_NAME, strlen(DLL_NAME), 0))
    {
        printf("WriteProcessMemory %d", GetLastError());
    }

    if (!CreateRemoteThread(hd, 0, 0, (LPTHREAD_START_ROUTINE)gp, rs, 0, 0))
    {
        printf("CreateRemoteThread %d", GetLastError());
    }

【问题讨论】:

    标签: windows winapi dll code-injection dll-injection


    【解决方案1】:

    当您注入的 DLL 的 DllMain 第一次运行时,调用 CreateThread 来创建一个可以做任何您喜欢的事情的新线程。请注意,您不能按照文档中的说明从 DllMain 调用任意代码。因此从DllMain 调用CreateThread

    【讨论】:

      【解决方案2】:

      嗯,我用的是下面的方法。

      在注入的 DLL 中,我创建了一个共享部分,如下所示:

      #pragma data_seg(".MyShared")
      
      LPTHREAD_START_ROUTINE g_lpMyFunc = NULL;
      
      #pragma data_seg()
      #pragma section(".MyShared", read, write, shared)
      

      共享部分变量 g_lpMyFunc 然后在 DllMain 内部初始化,如下所示:

      BOOL APIENTRY DllMain(HMODULE, DWORD dwReasonForCall, LPVOID)
      {
          if (NULL != GetModuleHandle(_T("MyApp.exe")))
          {
              if (DLL_PROCESS_ATTACH == dwReasonForCall)
              {
                  g_lpMyFunc = (LPTHREAD_START_ROUTINE)&MyFunc;
              }
              else if (DLL_PROCESS_DETACH == dwReasonForCall)
              {
                  g_lpMyFunc = NULL;
              }
          }
          return TRUE;
      }
      

      此代码执行以下操作。函数调用GetModuleHandle 尝试获取 MyApp 的可执行模块句柄。如果成功,则返回非 NULL 值,这意味着从远程进程调用注入的 DLL 的DllMain。如果是这种情况,则将MyFunc 的地址保存到g_lpMyFunc 共享变量中。如果 DLL 与进程分离(例如,当它退出时),我将 g_lpMyFunc 设置为 NULL,以便无法通过不存在的远程地址调用函数。

      然后我创建一个外部函数MyFuncExtern,它在远程进程中调用MyFunc,如下所示:

      extern "C" __declspec(dllexport) bool __cdecl MyFuncExtern(HANDLE hProcess)
      {
          if (NULL == g_lpMyFunc)
          {
              return false;
          }
      
          return NULL != CreateRemoteThread(hProcess, NULL, 0, g_lpMyFunc, NULL, 0, NULL);
      }
      

      这是一个非常简化的版本,但它显示了主要概念:如果 g_lpMyFunc 不为 NULL,它会在 hProcess 中创建一个远程线程(就像在您的代码中一样),该线程在指向的地址调用一个函数g_lpMyFunc.

      这个函数有一些限制,因为CreateRemoteThread 只接受一个远程函数的参数(你可以传递更多,但是它需要一个更复杂的方法),如果你需要一个返回值,您必须等待远程线程完成执行并获取其退出代码,即DWORD

      这种方法擅长编写 Initialize / Uninitialize 函数,此外,它非常适用于托管 C++/CLI DLL。

      当然,您可以使用任何其他跨进程数据存储来保存函数指针。内存映射文件就是一个很好的例子。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多