Injecting a managed dll into a native process

2019-07-11 02:23发布

问题:

I'm trying to inject a managed c# dll into a native executable. I'm injecting the following code into the executable in order to load the CLR.

I know the injection works, because when I inject the code into cmd.exe it outputs correctly. I know that CLRCreateInstance, pMetaHost->GetRuntime, pRuntimeInfo->GetInterface all return S_OK, but pClrRuntimeHost->Start() returns E_FAIL.

This only happens when I inject the dll into a remote process. If I load the dll on my own process and call Main from there, all calls return S_OK and the managed code runs fine.

Update: I've tried injecting the code into other processes like notepad.exe and explorer.exe. It runs fine in those. I'm still curious as to why it doesn't run in cmd.exe, but I only used it for testing purposes so it isn't a problem anymore.

GetLastError returns "An attempt was made to reference a token that does not exist"

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

using namespace std;

//Forward declarations
void StartTheDotNetRuntime();

DllExport HRESULT Main(_In_ LPCTSTR lpCommand)
{
    cout << "Starting .NET runtime" << endl;
    StartTheDotNetRuntime();
    return 0;
}

void StartTheDotNetRuntime()
{
    wprintf(L"Press enter to load the .net runtime...");

    HRESULT hr;
    ICLRMetaHost *pMetaHost = NULL;
    ICLRRuntimeInfo *pRuntimeInfo = NULL;
    ICLRRuntimeHost *pClrRuntimeHost = NULL;

    // build runtime
    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
    hr = pClrRuntimeHost->Start();
    cout << "RESULT: " << hr << endl;

    wprintf(L".Net runtime is loaded.");

    // Okay, the CLR is up and running in this (previously native) process.
    // Now call a method on our managed C# class library.
    DWORD dwReturn = 0;
    hr = pClrRuntimeHost->ExecuteInDefaultAppDomain(
        L"F:\\Client.dll",
        L"Client.Main", L"Start", L"MyParameter", &dwReturn);
    cout << dwReturn << endl;
}

回答1:

I've found the answer to the problem, atleast for me, the process that the bootstrap is injected into needs to have admin permissions. It took me ages to realise as all programs have admin permissions by default for me, and once I started the process I was injecting into as Administrator it worked!