【问题标题】:Unable to call method in managed dll after loading CLR. Why?加载 CLR 后无法调用托管 dll 中的方法。为什么?
【发布时间】:2016-05-06 23:26:17
【问题描述】:

我在尝试将 dll 注入进程时遇到了一些问题。我对这个话题很陌生,但对 C# 很熟悉,所以阅读和理解 C++ 的语法并不是那么陌生,而且我大部分都理解它。

我正在尝试的只是为了学习,我正在尝试使用 notepad.exe 和 calc.exe 等简单的应用程序。

项目设置:

  • WPF 应用程序 - 选择我想要修改的进程并注入非托管 dll。
  • CppDLL.dll - 非托管 dll 加载 CLR、托管 dll 并调用托管 dll 上的方法。
  • SharpDLL.dll - 托管 dll。

(wpf) 感兴趣的 c#

dllToInject = fileDialog.FileName;
Process targetProcess = Process.GetProcessById(processToInject.ID);
var dllInjector = DllInjector.GetInstance;
DllInjectionResult injectResult;
if ((injectResult = dllInjector.Inject(processToInject.Name,dllToInject)) == DllInjectionResult.Success)
{
    MessageBox.Show("Success");
} else
{
    MessageBox.Show("Error: " + injectResult.ToString());
}

未尝试加载clr和托管dll时,非托管dll注入成功,如下图。

但是当我尝试加载 CLR 和托管 dll 时它失败了。

CppDLL.dll dllmain.cpp:

#include "stdafx.h"
#include <Windows.h>
#include <metahost.h>
#pragma comment(lib, "mscoree.lib")

#import "mscorlib.tlb" raw_interfaces_only \
    high_property_prefixes("_get","_put","_putref") \
    rename("ReportEvent", "InteropServices_ReportEvent")

void LoadDotNet()
{
  HRESULT hr;
  ICLRMetaHost *pMetaHost = NULL;
  ICLRRuntimeInfo *pRuntimeInfo = NULL;
  ICLRRuntimeHost *pClrRuntimeHost = NULL;

  hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
  hr = pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo));
  hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost,
    IID_PPV_ARGS(&pClrRuntimeHost));
  hr = pClrRuntimeHost->Start();

  DWORD pReturnValue;
  hr = pClrRuntimeHost->ExecuteInDefaultAppDomain(
    L"C:\\Users\\DanHovedPC\\Desktop\\inject\\SharpDLL.dll",
    L"SharpDLL.Injected",
    L"Start",
    L"Hello from .NET",
    &pReturnValue);

  pMetaHost->Release();
  pRuntimeInfo->Release();
  pClrRuntimeHost->Release();
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
           )
{
  switch (ul_reason_for_call)
  {
  case DLL_PROCESS_ATTACH:
    MessageBox(NULL, L"Hi!", L"From cpp DLL", NULL);
    //LoadDotNet();
  case DLL_THREAD_ATTACH:
  case DLL_THREAD_DETACH:
  case DLL_PROCESS_DETACH:
    break;
  }
  return TRUE;
}

SharpDLL.dll Injected.cs

using System.Windows;
namespace SharpDLL
{
    class Injected
    {
        public static int Start(string arg)
        {
            MessageBox.Show(arg);
            return 0;
        }
    }
}

在 CppDLL.dll 中,如果我取消注释函数并注释消息框,它会失败。 SharpDLL.dll 不会被注入。当我尝试关闭记事本时,进程仍然显示在进程资源管理器中。

我事先查看了Process Explorer 中的进程,默认情况下不加载 clr.dll,但在函数运行时会加载它。也许它可能是 .NET 版本?我正在运行 Windows 10 x64。

更新

代码一直运行,直到我尝试实际启动运行时

void LoadDotNet()
{
  HRESULT hr;
  ICLRMetaHost *pMetaHost = NULL;
  ICLRRuntimeInfo *pRuntimeInfo = NULL;
  ICLRRuntimeHost *pClrRuntimeHost = NULL;

  hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
  hr = pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo));
  hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost,
    IID_PPV_ARGS(&pClrRuntimeHost));

  // start runtime
  MessageBox(NULL, L"Runs up to here...", L"DEBUG", NULL);
  hr = pClrRuntimeHost->Start();
  MessageBox(NULL,(LPCWSTR)GetLastError(),L"DEBUG",NULL);
  pMetaHost->Release();
  pRuntimeInfo->Release();
  pClrRuntimeHost->Release();
}

显示第一个消息框。

【问题讨论】:

    标签: c++ .net dll clr inject


    【解决方案1】:

    我发现问题在于 DllMain 中的代码不能访问 CLR。​​

    DllMain 中的代码不得访问 CLR。这意味着 DllMain 不应直接或间接调用托管函数;不应在 DllMain 中声明或实现托管代码;并且不应在 DllMain 中进行垃圾收集或自动库加载。

    https://msdn.microsoft.com/en-us/library/ms173266.aspx

    创建新线程时代码运行成功

    BOOL APIENTRY DllMain(HMODULE hModule,
      DWORD  ul_reason_for_call,
      LPVOID lpReserved
      )
    {
      switch (ul_reason_for_call)
      {
      case DLL_PROCESS_ATTACH:
        //printf("DLL Loaded!");
        CreateThread(NULL, 0,
          (LPTHREAD_START_ROUTINE)LoadDotNet, NULL, 0, NULL);
      }
      return TRUE;
    }
    

    通过阅读comment on another question here on SO CreateThread 在这种特殊情况下应该是安全的。

    【讨论】:

      猜你喜欢
      • 2011-08-27
      • 1970-01-01
      • 2018-10-22
      • 2019-08-15
      • 2018-02-14
      • 2011-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多