idiotc4t's blog
  • 关于这个博客
  • 武器设计
    • 我也不知道能不能写
    • C2手稿
      • Heap加密
      • 数据打包DataPacker
      • 真·手稿
      • 实现UML图
    • 先占个位置
  • 武器化
    • COM组件相关的武器化开发技术
    • 攻击demo的bof改造
    • Go项目反射改造
    • VulnBins的利用 (vuln driver)
  • 红队研究
    • NtQueryInformationProcess逆向
    • NetUserAdd逆向
  • 应急响应
    • WannaMine4.0专杀的一些技巧
  • 防御逃避
    • ReflectiveDLLInjection变形应用
    • Execute-Assembly实现
    • ShadowMove复现与思考
    • 载入第二个Ntdll绕Hook
    • 编译时混淆字符串&函数调用
    • 基于线程结束的EventLog绕过
    • 动态获取系统调用(syscall)号
    • 基于内存补丁的AMSI绕过
    • 基于API Hook和DLL注入的AMSI绕过
    • 基于内存补丁ETW的绕过
    • 基于断链的DLL隐藏
    • 基于HEX字符串执行的AV绕过
    • CobaltStrike Argue命令实现
    • 简单的分离免杀
    • 伪装PPID规避检测
    • 伪装命令行规避检测
    • 通过重写ring3 API函数实现免杀
    • 动态调用无导入表编译
    • 基于Registry的虚拟机检测
    • 利用杀毒软件删除任意文件
    • 反转字符串绕杀软
    • 重新加载.text节拖钩
    • x64转换层&跨位数进程注入
  • 代码与进程注入
    • Divide and Conquer
    • Clipboard Data Deliver
    • .NET Reflective Injection
    • APC Thread Hijack
    • CreateRemoteThread
    • APC Injection
    • Mapping Injection
    • Bypass Session 0 Injection
    • WhiteFile Offset Table Generate Shellcode
    • Early Bird
    • Early Bird & CreateRemoteThread
    • TLS Code Execute
    • SEH Code Execute
    • APC & NtTestAlert Code Execute
    • NtCreateSection & NtMapViewOfSection Code Execute
    • Process Hollowing
    • SetContext Hijack Thread
    • DLL Hollowing
  • 权限提升
    • 基于注册表劫持BypassUAC
    • 基于dll劫持BypassUac
    • 通过com组件BypassUAC
    • 通过复制Token提权到SYSTEM
    • 通过code&dll注入提权到SYSTEM
    • 通过伪装PPID提权到SYSTEM
    • 通过系统服务提权到SYSTEM
  • 权限维持
    • 主机特征绑定木马
    • 寻找有价值的文件
    • 获取机器安装的软件
    • 通过API添加Windows用户
    • Detours InLine Hook
    • DLL劫持
    • RID劫持
    • 自启动服务
    • 编写简单远控
    • 注册表自启动项
由 GitBook 提供支持
在本页
  • 简介
  • 流程A(硬盘加载)
  • 实现
  • 流程B(内存加载)
  • 完整代码
  • LINKS

这有帮助吗?

  1. 防御逃避

Execute-Assembly实现

简介

cs实现了在非托管程序中加载.net程序集的功能,该功能使我们的恶意.net程序集不落地在内存中执行,这个实质是当前进程通过com接口初始化(公共语言运行时)CLR环境,本文尝试对该功能进行复现。

ICLRMetaHost 接口

提供一些方法,这些方法基于公共语言运行时的版本号返回特定版本的公共语言运行时 () ,列出所有已安装的 Clr,列出在指定进程中加载的所有运行时,发现编译程序集所用的 CLR 版本,退出使用干净运行时关闭的进程,以及查询旧的 API 绑定。

GetRuntime 方法 获取与特定 CLR 版本相对应的 ICLRRuntimeInfo 接口。 此方法取代了与STARTUP_LOADER_SAFEMODE标志一起使用的CorBindToRuntimeEx函数。

ICLRRuntimeInfo 接口

接口 提供一些方法,这些方法可返回有关特定公共语言运行时 (CLR) 的信息,包括版本、目录和加载状态。 此接口还提供了特定于运行时的功能,而无需初始化运行时。 它包括运行时相对 LoadLibrary 方法、运行时模块特定的 GetProcAddress 方法和通过 GetInterface 方法提供的运行时提供的接口。

GetInterface 方法 将 CLR 加载到当前进程并返回运行时接口指针,如 ICLRRuntimeHost、 ICLRStrongName 和 IMetaDataDispenser。 此方法将取代所有 CorBindTo* 函数。

ICLRRuntimeHost 接口

提供与 .NET Framework 版本1中提供的 ICorRuntimeHost 接口类似的功能,其中包含以下更改: 用于设置宿主控件接口的 SetHostControl 方法的添加。 省略提供的某些方法 ICorRuntimeHost 。

Start 方法 将 CLR 初始化为一个进程。

ExecuteInDefaultAppDomain 方法 在指定的程序集中调用指定类型的指定方法。

流程A(硬盘加载)

  1. 初始化ICLRMetaHost接口。

  2. 通过ICLRMetaHost获取ICLRRuntimeInfo接口。

  3. 通过ICLRRuntimeInfo将 CLR 加载到当前进程并返回运行时接口ICLRRuntimeHost指针。

  4. 通过ICLRRuntimeHost.Start()初始化CLR。

  5. 通过ICLRRuntimeHost.EecuteInDefaultAppDomain执行指定程序集(硬盘上)。

实现

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

int main()
{
    ICLRMetaHost* iMetaHost = NULL;
    ICLRRuntimeInfo* iRuntimeInfo = NULL;
    ICLRRuntimeHost* iRuntimeHost = NULL;

    //初始化环境
    CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&iMetaHost);
    iMetaHost->GetRuntime(L"v4.0.30319", IID_ICLRRuntimeInfo, (LPVOID*)&iRuntimeInfo);
    iRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&iRuntimeHost);
    iRuntimeHost->Start();

    //执行
    iRuntimeHost->ExecuteInDefaultAppDomain(L"C:\\Users\\Black Sheep\\source\\repos\\HostingCLR\\TEST\\bin\\Debug\\TEST.exe", L"TEST.Program", L"print", L"test", NULL);

    //释放
    iRuntimeInfo->Release();
    iMetaHost->Release();
    iRuntimeHost->Release();

    return 0;
};
using System;

namespace TEST
{
    class Program
    {
        static int Main(String[] args)
        {

            return 1;
        }
        static int print(String strings)
        {
            Console.WriteLine(strings);
            return 1;
        }
    }
}

流程B(内存加载)

1.初始化CLR环境(同上)

	CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (VOID**)&iMetaHost);
	iMetaHost->GetRuntime(L"v4.0.30319", IID_ICLRRuntimeInfo, (VOID**)&iRuntimeInfo);
	iRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, (VOID**)&iRuntimeHost);
	iRuntimeHost->Start();

2.通过ICLRRuntimeHost获取AppDomain接口指针,然后通过AppDomain接口的QueryInterface方法来查询默认应用程序域的实例指针。

	iRuntimeHost->GetDefaultDomain(&pAppDomain);
	pAppDomain->QueryInterface(__uuidof(_AppDomain), (VOID**)&pDefaultAppDomain);

3.通过默认应用程序域实例的Load_3方法加载安全.net程序集数组,并返回Assembly的实例对象指针,通过Assembly实例对象的get_EntryPoint方法获取描述入口点的MethodInfo实例对象。

	saBound[0].cElements = ASSEMBLY_LENGTH;
	saBound[0].lLbound = 0;
	SAFEARRAY* pSafeArray = SafeArrayCreate(VT_UI1, 1, saBound);

	SafeArrayAccessData(pSafeArray, &pData);
	memcpy(pData, dotnetRaw, ASSEMBLY_LENGTH);
	SafeArrayUnaccessData(pSafeArray);

	pDefaultAppDomain->Load_3(pSafeArray, &pAssembly);
	pAssembly->get_EntryPoint(&pMethodInfo);

4.创建参数安全数组

ZeroMemory(&vRet, sizeof(VARIANT));
	ZeroMemory(&vObj, sizeof(VARIANT));
	vObj.vt = VT_NULL;

	vPsa.vt = (VT_ARRAY | VT_BSTR);
	args = SafeArrayCreateVector(VT_VARIANT, 0, 1);

	if (argc > 1)
	{
		vPsa.parray = SafeArrayCreateVector(VT_BSTR, 0, argc);
		for (long i = 0; i < argc; i++)
		{
			SafeArrayPutElement(vPsa.parray, &i, SysAllocString(argv[i]));
		}

		long idx[1] = { 0 };
		SafeArrayPutElement(args, idx, &vPsa);
	}

5.通过描述入口点的MethodInfo实例对象的Invoke方法执行入口点。

HRESULT hr = pMethodInfo->Invoke_3(vObj, args, &vRet);

完整代码

#include <stdio.h>
#include <tchar.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")	\
	rename("or", "InteropServices_or")

using namespace mscorlib;
#define ASSEMBLY_LENGTH  8192


unsigned char dotnetRaw[8192] =
"\x4d\x5a\x90\x00\x03\x00\x00\x00\x04\x00\x00\x00\xff\xff\x00...";//.net程序集字节数组



int _tmain(int argc, _TCHAR* argv[])
{

	ICLRMetaHost* iMetaHost = NULL;
	ICLRRuntimeInfo* iRuntimeInfo = NULL;
	ICorRuntimeHost* iRuntimeHost = NULL;
	IUnknownPtr pAppDomain = NULL;
	_AppDomainPtr pDefaultAppDomain = NULL;
	_AssemblyPtr pAssembly = NULL;
	_MethodInfoPtr pMethodInfo = NULL;
	SAFEARRAYBOUND saBound[1];
	void* pData = NULL;
	VARIANT vRet;
	VARIANT vObj;
	VARIANT vPsa;
	SAFEARRAY* args = NULL;

	CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (VOID**)&iMetaHost);
	iMetaHost->GetRuntime(L"v4.0.30319", IID_ICLRRuntimeInfo, (VOID**)&iRuntimeInfo);
	iRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, (VOID**)&iRuntimeHost);
	iRuntimeHost->Start();


	iRuntimeHost->GetDefaultDomain(&pAppDomain);
	pAppDomain->QueryInterface(__uuidof(_AppDomain), (VOID**)&pDefaultAppDomain);

	saBound[0].cElements = ASSEMBLY_LENGTH;
	saBound[0].lLbound = 0;
	SAFEARRAY* pSafeArray = SafeArrayCreate(VT_UI1, 1, saBound);

	SafeArrayAccessData(pSafeArray, &pData);
	memcpy(pData, dotnetRaw, ASSEMBLY_LENGTH);
	SafeArrayUnaccessData(pSafeArray);

	pDefaultAppDomain->Load_3(pSafeArray, &pAssembly);
	pAssembly->get_EntryPoint(&pMethodInfo);

	ZeroMemory(&vRet, sizeof(VARIANT));
	ZeroMemory(&vObj, sizeof(VARIANT));
	vObj.vt = VT_NULL;



	vPsa.vt = (VT_ARRAY | VT_BSTR);
	args = SafeArrayCreateVector(VT_VARIANT, 0, 1);

	if (argc > 1)
	{
		vPsa.parray = SafeArrayCreateVector(VT_BSTR, 0, argc);
		for (long i = 0; i < argc; i++)
		{
			SafeArrayPutElement(vPsa.parray, &i, SysAllocString(argv[i]));
		}

		long idx[1] = { 0 };
		SafeArrayPutElement(args, idx, &vPsa);
	}

	HRESULT hr = pMethodInfo->Invoke_3(vObj, args, &vRet);
	pMethodInfo->Release();
	pAssembly->Release();
	pDefaultAppDomain->Release();
	iRuntimeInfo->Release();
	iMetaHost->Release();
	CoUninitialize();

	return 0;
};
using System;

namespace TEST
{
    class Program
    {
        static int Main(String[] args)
        {
            Console.WriteLine("hello world!");
            foreach (var s in args)
            {
                Console.WriteLine(s);
            }
            return 1;
        }
    }
}

LINKS

上一页ReflectiveDLLInjection变形应用下一页ShadowMove复现与思考

最后更新于4年前

这有帮助吗?

In Process Execute Assembly and Mail SlotsTeam Hydra
Logo
Developer tools, technical documentation and coding examplesdocsmsft
Logo
Execute assembly via Meterpreter sessionB4rtik
Execute assembly via Meterpreter session - Part 2B4rtik