C++ 加载CLR后无法在托管dll中调用方法。为什么?

C++ 加载CLR后无法在托管dll中调用方法。为什么?,c++,.net,dll,clr,inject,C++,.net,Dll,Clr,Inject,我在尝试将dll注入进程时遇到了一些问题。我在这个话题上很新,但是我对C语言很熟悉,所以阅读和理解C++的语法并不陌生,我大部分理解。p> 我所尝试的只是为了学习,我正在使用一些简单的应用程序,比如notepad.exe和calc.exe 项目设置: WPF应用程序-选择我想要修补的进程并注入非托管dll CppDLL.dll-用于加载CLR、托管dll和托管dll上的调用方法的非托管dll SharpDLL.dll-托管dll (wpf)c#感兴趣的 dllToInject = fileD

我在尝试将dll注入进程时遇到了一些问题。我在这个话题上很新,但是我对C语言很熟悉,所以阅读和理解C++的语法并不陌生,我大部分理解。p> 我所尝试的只是为了学习,我正在使用一些简单的应用程序,比如notepad.exe和calc.exe

项目设置:

  • WPF应用程序-选择我想要修补的进程并注入非托管dll
  • CppDLL.dll-用于加载CLR、托管dll和托管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.dlldllmain.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;
}
在CppDLL.dll中,如果取消对函数的注释并对messagebox进行注释,则会失败。SharpDLL.dll不会被注入。当我试图关闭记事本时,进程仍然显示在process Explorer中

我在前面已经看过了这个过程,默认情况下不会加载clr.dll,但是在函数运行时会加载它。也许是.NET版本?我正在运行Windows10x64

更新

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

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();
}

第一个消息框显示。

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

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

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

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;
}
在这种特殊情况下,读取CreateThread应该是安全的

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;
}