从内存加载.NET顺序集(execute-assembly)的应用剖析 | 申博官网
登录
  • 欢迎进入申博官网!
  • 如果您觉得申博官网对你有帮助,那么赶紧使用Ctrl+D 收藏申博官网并分享出去吧
  • 这里是申博官方网!
  • 申博官网是菲律宾sunbet官网品牌平台!
  • 申博开户专业品牌平台!

从内存加载.NET顺序集(execute-assembly)的应用剖析

申博_安全防护 申博 56次浏览 未收录 0个评论

0x00 媒介

Cobalt Strike 3.11中,加入了一个名为”execute-assembly”的敕令,可以从内存中加载.NET顺序集。这个功用不须要向硬盘写入文件,非常隐藏,而且现有的Powershell运用剧本可以很轻易的转换为C#代码,非常轻易。

本文将会对”execute-assembly”的道理举行引见,连系多个开源代码,引见完成要领,剖析运用思绪,末了给出防备发起。

0x01 简介

本文将要引见以下内容:

· 基础知识

· 一般的完成要领

· 开源运用代码剖析

· 运用思绪

· 防备发起

0x02 基础知识

1.CLR

全称Common Language Runtime(大众言语运转库),是一个可由多种编程言语运用的运转环境。

CLR是.NET Framework的重要实行引擎,作用之一是看管顺序的运转:

· 在CLR看管之下运转的顺序属于”托管的”(managed)代码。

· 不在CLR之下、直接在裸机上运转的运用或许组件属于”非托管的”(unmanaged)的代码。

2.Unmanaged API

参考资料:

https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/

用于将.NET 顺序集加载到恣意顺序中的API。

支撑两种接口:

· ICorRuntimeHost Interface

· ICLRRuntimeHost Interface

3.ICorRuntimeHost Interface

参考资料:

https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/icorruntimehost-interface

支撑v1.0.3705, v1.1.4322, v2.0.50727和v4.0.30319。

4.ICLRRuntimeHost Interface

参考资料:

https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/iclrruntimehost-interface

支撑v2.0.50727和v4.0.30319。

在.NET Framework 2.0中,ICLRRuntimeHost用于庖代ICorRuntimeHost。

在现实顺序开辟中,很少会斟酌.NET Framework 1.0,所以两个接口都可以运用。

0x03 一般的完成要领

运用的实例代码:

https://code.msdn.microsoft.com/windowsdesktop/CppHostCLR-e6581ee0#content

这里将参考实例代码并做补充。

通用的完成要领以下:

1.将CLR加载到历程中

(1)挪用CLRCreateInstance函数以猎取ICLRMetaHost或ICLRMetaHostPolicy接口。

(2)挪用ICLRMetaHost::EnumerateInstalledRuntimes, ICLRMetaHost::GetRuntime或许ICLRMetaHostPolicy::GetRequestedRuntime要领以猎取有用的ICLRRuntimeInfo指针。

三个任选一个。

(3)运用ICorRuntimeHost或许ICLRRuntimeHost。

两者都是挪用ICLRRuntimeInfo::GetInterface要领,然则参数差别。

ICorRuntimeHost:

· 支撑v1.0.3705, v1.1.4322, v2.0.50727和v4.0.30319

· 指定CLSID_CorRuntimeHost为rclsid参数

· 指定IID_ICorRuntimeHost为RIID参数

ICLRRuntimeHost:

· 支撑v2.0.50727和v4.0.30319

· 指定CLSID_CLRRuntimeHost为rclsid参数

· 指定IID_ICLRRuntimeHost为RIID参数

2.加载.NET顺序集并挪用静态要领

在代码完成上,运用ICLRRuntimeHost会比运用ICorRuntimeHost简朴的多。

3.清算CLR

开释步骤1中的指针。

下面运用ICLRMetaHost::GetRuntime猎取有用的ICLRRuntimeInfo指针,运用ICLRRuntimeHost从文件加载.NET顺序集并挪用静态要领,完成代码以下:

#include "stdafx.h"
#include <metahost.h>
#include <windows.h>
#pragma comment(lib, "MSCorEE.lib")

HRESULT RuntimeHost_GetRuntime_ICLRRuntimeInfo(PCWSTR pszVersion, PCWSTR pszAssemblyName, PCWSTR pszClassName, PCWSTR pszMethodName, PCWSTR pszArgName)
{
	// Call the ICLRMetaHost::GetRuntime to get a valid ICLRRuntimeInfo.
	// Call the ICLRRuntimeInfo:GetInterface method.
	HRESULT hr;
	ICLRMetaHost *pMetaHost = NULL;
	ICLRRuntimeInfo *pRuntimeInfo = NULL;
	ICLRRuntimeHost *pClrRuntimeHost = NULL;
	DWORD dwLengthRet;
	// 
	// Load and start the .NET runtime.
	// 
	wprintf(L"Load and start the .NET runtime %s \n", pszVersion);
	hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
	if (FAILED(hr))
	{
		wprintf(L"[!]CLRCreateInstance failed w/hr 0x%08lx\n", hr);
		goto Cleanup;
	}
	// Get the ICLRRuntimeInfo corresponding to a particular CLR version. It 
	// supersedes CorBindToRuntimeEx with STARTUP_LOADER_SAFEMODE.
	hr = pMetaHost->GetRuntime(pszVersion, IID_PPV_ARGS(&pRuntimeInfo));
	if (FAILED(hr))
	{
		wprintf(L"[!]ICLRMetaHost::GetRuntime failed w/hr 0x%08lx\n", hr);
		goto Cleanup;
	}
	// Check if the specified runtime can be loaded into the process. This 
	// method will take into account other runtimes that may already be 
	// loaded into the process and set pbLoadable to TRUE if this runtime can 
	// be loaded in an in-process side-by-side fashion. 
	BOOL fLoadable;
	hr = pRuntimeInfo->IsLoadable(&fLoadable);
	if (FAILED(hr))
	{
		wprintf(L"[!]ICLRRuntimeInfo::IsLoadable failed w/hr 0x%08lx\n", hr);
		goto Cleanup;
	}
	if (!fLoadable)
	{
		wprintf(L"[!].NET runtime %s cannot be loaded\n", pszVersion);
		goto Cleanup;
	}
	// Load the CLR into the current process and return a runtime interface 
	// pointer. ICorRuntimeHost and ICLRRuntimeHost are the two CLR hosting  
	// interfaces supported by CLR 4.0. Here we demo the ICLRRuntimeHost 
	// interface that was provided in .NET v2.0 to support CLR 2.0 new 
	// features. ICLRRuntimeHost does not support loading the .NET v1.x 
	// runtimes.
	hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS(&pClrRuntimeHost));
	if (FAILED(hr))
	{
		wprintf(L"[!]ICLRRuntimeInfo::GetInterface failed w/hr 0x%08lx\n", hr);
		goto Cleanup;
	}
	// Start the CLR.
	hr = pClrRuntimeHost->Start();
	if (FAILED(hr))
	{
		wprintf(L"[!]CLR failed to start w/hr 0x%08lx\n", hr);
		goto Cleanup;
	}
	// 
	// Load the NET assembly and call the static method.
	// 
	wprintf(L"[+]Load the assembly %s\n", pszAssemblyName);
	// The invoked method of ExecuteInDefaultAppDomain must have the 
	// following signature: static int pwzMethodName (String pwzArgument)
	// where pwzMethodName represents the name of the invoked method, and 
	// pwzArgument represents the string value passed as a parameter to that 
	// method. If the HRESULT return value of ExecuteInDefaultAppDomain is 
	// set to S_OK, pReturnValue is set to the integer value returned by the 
	// invoked method. Otherwise, pReturnValue is not set.
	hr = pClrRuntimeHost->ExecuteInDefaultAppDomain(pszAssemblyName, pszClassName, pszMethodName, pszArgName, &dwLengthRet);
	if (FAILED(hr))
	{
		wprintf(L"[!]Failed to call %s w/hr 0x%08lx\n", pszMethodName, hr);
		goto Cleanup;
	}
	// Print the call result of the static method.
	wprintf(L"[+]Call %s.%s(\"%s\") => %d\n", pszClassName, pszMethodName, pszArgName, dwLengthRet);

Cleanup:
	if (pMetaHost)
	{
		pMetaHost->Release();
		pMetaHost = NULL;
	}
	if (pRuntimeInfo)
	{
		pRuntimeInfo->Release();
		pRuntimeInfo = NULL;
	}
	if (pClrRuntimeHost)
	{
		// Please note that after a call to Stop, the CLR cannot be 
		// reinitialized into the same process. This step is usually not 
		// necessary. You can leave the .NET runtime loaded in your process.
		//wprintf(L"Stop the .NET runtime\n");
		//pClrRuntimeHost->Stop();
		pClrRuntimeHost->Release();
		pClrRuntimeHost = NULL;
	}
	return hr;
}

int main()
{
	RuntimeHost_GetRuntime_ICLRRuntimeInfo(L"v4.0.30319", L"ClassLibrary1.dll", L"ClassLibrary1.Class1", L"TestMethod", L"argstring");
	return 0;
}

代码将会加载同级目录下.Net4.0开辟的ClassLibrary1.dll,类名为Class1,要领为TestMethod,传入的参数为argstring。

ClassLibrary1.dll的代码以下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ClassLibrary1
{
    public class Class1
    {
        public static int TestMethod(string str)
        {
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo.FileName = "c:\\windows\\system32\\calc.exe";
            p.Start();
            return 0;
        }
    }
}

0x04 开源运用代码剖析

1、Unmanaged CLR Hosting Assembly loader

从攻击设备到攻击人脑,医疗安全岌岌可危

医疗安全重于泰山 《时间简史》里有这样一段话: 如果有10%的利润,黑客就保证不会消停;如果有20%的利润,黑客就会异常活跃;如果有50%的利润,黑客就会铤而走险;为了100%的利润,黑客就敢践踏一切人间法律” 这句话即便放在救死扶伤的医疗数据领域一样适用。 试想两个场景: 医生开具药房不以药品疗效为先,哪个药商给的提成高开哪个。 一家医院的信息系统遭到入侵崩溃,急诊瘫痪、手术延期,感冒发烧开不出药。 在利益驱使下,医疗早就成为了黑客虎视眈眈的一块肥肉。 医疗系统的价值其实不难理解。 首先,普通人在医疗方面的投入是不计成本的,甚至是砸锅卖铁。 而一旦医药公司掌握了患者信息,就能将其应用于定向推广,尤其针对患有疑难杂症的患者。 打个比方。 病人在医院就诊后病情不见好转,正在各路求医时,收到短信: **医院专治**病症,治愈率高达80% 去还是不去?面对重获健康的机会,结

https://github.com/caseysmithrc/AssemblyLoader

运用CLR从代码中定义好的数组读取shellcode,加载到内存并实行。

完成要领以下:

1.将CLR加载到历程中

(1)挪用CLRCreateInstance函数以猎取ICLRMetaHost或ICLRMetaHostPolicy接口。

(2)挪用ICLRMetaHost::GetRuntime要领以猎取有用的ICLRRuntimeInfo指针。

(3)运用ICorRuntimeHost。

注:

在运用ICorRuntimeHost时,须要添加对mscorlib.tlb的援用,c++代码以下:

// Import mscorlib.tlb (Microsoft Common Language Runtime Class Library).
#import "mscorlib.tlb" raw_interfaces_only				\
    high_property_prefixes("_get","_put","_putref")		\
    rename("ReportEvent", "InteropServices_ReportEvent")
using namespace mscorlib;
#pragma endregion

在ICorRuntimeHost中,从文件读取并加载.NET顺序集的要领定义以下:

  virtual HRESULT __stdcall Load_2 (
    /*[in]*/ BSTR assemblyString,
    /*[out,retval]*/ struct _Assembly * * pRetVal ) = 0;

从内存中读取并加载.NET顺序集的要领定义以下:

  virtual HRESULT __stdcall Load_3 (
    /*[in]*/ SAFEARRAY * rawAssembly,
    /*[out,retval]*/ struct _Assembly * * pRetVal ) = 0;

注:

要领定义来自mscorlib.tlh。

这里运用了Load_3(…),先从数组中读取shellcode,再加载.NET顺序集。

2.加载.NET顺序集并挪用静态要领

3.清算CLR

2、Executing a .NET Assembly from C++ in Memory (CLR Hosting)

https://github.com/etormadiv/HostingCLR

同caseysmith的要领基础雷同,都是挪用ICLRMetaHost::GetRuntime要领以猎取有用的ICLRRuntimeInfo指针,运用ICorRuntimeHost接口,运用Load_3(…)从内存中读取并加载.NET顺序集。

3、CLR via native code

https://gist.githubusercontent.com/xpn/e95a62c6afcf06ede52568fcd8187cc2/raw/f3498245c8309d44af38502a2cc7090c318e8adf/clr_via_native.c

值得注意的是这里挪用ICLRMetaHost::EnumerateInstalledRuntimes猎取有用的ICLRRuntimeInfo指针。

接着运用ICLRRuntimeHost从文件加载.NET顺序集并挪用静态要领。

4、metasploit-execute-assembly

https://github.com/b4rtik/metasploit-execute-assembly

起首建立历程notepad.exe,然后向notepad.exe注入HostingCLRx64.dll,HostingCLRx64.dll完成内存加载.Net顺序集。

这里我们只关注内存加载.Net顺序集的细节,代码位置:

https://github.com/b4rtik/metasploit-execute-assembly/blob/master/HostingCLR_inject/HostingCLR/HostingCLR.cpp

细节以下:

· 运用.Net v4.0.30319

· 挪用ICLRMetaHost::GetRuntime要领以猎取有用的ICLRRuntimeInfo指针

· 运用ICorRuntimeHost接口

· 运用Load_3(…)从内存中读取并加载.NET顺序集

同1和2基础雷同。

0x05 运用思绪

综合0x04中的开源代码,execute-assembly一般有以下两种运用思绪:

1.从内存中读取shellcode并加载.NET顺序集

· 挪用ICLRMetaHost::EnumerateInstalledRuntimes, ICLRMetaHost::GetRuntime或许ICLRMetaHostPolicy::GetRequestedRuntime要领以猎取有用的ICLRRuntimeInfo指针。

· 运用ICorRuntimeHost接口。

· 运用Load_3(…)从内存中读取并加载.NET顺序集。

· 挪用静态要领。

2.从硬盘读取并加载.NET顺序集

· 挪用ICLRMetaHost::EnumerateInstalledRuntimes, ICLRMetaHost::GetRuntime或许ICLRMetaHostPolicy::GetRequestedRuntime要领以猎取有用的ICLRRuntimeInfo指针。

· 运用ICorRuntimeHost(运用Load_2(…))或许ICLRRuntimeHost接口。

· 加载.NET顺序集并挪用静态要领。

第一种运用思绪要优于第二种,完全的运用历程以下:

· 建立一个一般的历程。

· 经由过程Dll反射向历程注入dll。

· dll完成从内存中读取shellcode并加载终究的.NET顺序集。

长处以下:

· 全部历程在内存实行,不写入文件体系。

· Payload以dll情势存在,不会发生可疑的历程。

· 终究的Payload为C#顺序,现有的Powershell运用剧本转换为C#代码很轻易。

0x06 防备发起

全部运用历程必需要用到dll注入,可以对罕见的dll注入要领(尤其是Dll反射)举行阻拦。

而关于dll自身,在运用CLR时,会加载体系的dll,比方:

· mscoree.dll

· mscoreei.dll

· mscorlib.dll

可对此举行监控。

0x07 小结

本文连系多个开源代码,总结了”execute-assembly”的完成要领和运用思绪,剖析长处,末了给出防备发起。

原文地点: https://www.4hou.com/technology/19125.html


申博|网络安全巴士站声明:该文看法仅代表作者自己,与本平台无关。版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明从内存加载.NET顺序集(execute-assembly)的应用剖析
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址