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

时间:2016-05-06 23:26:17

标签: c++ .net dll clr inject

尝试将dll注入进程时遇到了一些问题。我对这个主题很新,但我熟悉C#,所以阅读和理解C ++的语法并不是那些不熟悉的,我在很大程度上理解它。

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

项目设置:

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

(wpf)c#of interest

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,如下所示。

Screenshot showing successful injection of unmanaged dll to notepad process

但是当我尝试加载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中。

我事先查看了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();
}

第一个消息框显示。

1 个答案:

答案 0 :(得分:0)

我发现问题是DllMain中的代码不能访问CLR。

  

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

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

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

NSInteger weekday = [[NSCalendar currentCalendar] component:NSCalendarUnitWeekday fromDate:[NSDate date]];

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