Execute-Assembly(1)

 原理

        在《Cobalt Strike 原理分析》一文中,介绍了内存加载程序集(Assembly)的主要有四步:

1 加载CLR环境 2 获取程序域 3 装载程序集 4 执行程序集

        在odzhan的Shellcode: Loading .NET Assemblies From Memory所描述的那样,.Net Framework随着版本的更新,使用了不同的接口,.Net Framework V1.0 采用的是ICorRuntimeHost接口,支持v1.0.3705, v1.1.4322, v2.0.50727和v4.0.30319。到了.Net Framework v2.0,采用ICLRRuntimeHost接口,支持v2.0.50727和v4.0.30319。然后到了.Net Framework v4.0,则使用了ICLRMetaHost接口,但是可能不再兼容4.0以下的.Net Framework。所以使用ICLRMetaHost接口并不是一个非常合适的接口。

        我们可以使用多个函数进行接口的实例化,最常见的可能属CoCreateInstance或者CLRCreateInstance

剩下的关于获取程序域,装载程序集,以及执行程序集在Execute-Assembly实现都有具体实现。完整代码如下。

#include <stdio.h>
#include <tchar.h>
#include <metahost.h>
//
#import "mscorlib.tlb" raw_interfaces_only   \
     high_property_prefixes("_get","_put","_putref")  \
     rename("ReportEvent", "InteropServices_ReportEvent") \
 rename("or", "InteropServices_or")

using namespace mscorlib;
//
#pragma comment(lib, "MSCorEE.lib")
//
int _tmain(int argc, _TCHAR* argv[])
{
 HANDLE hFile = CreateFileA("CSharp.exe",
  GENERIC_READ | GENERIC_WRITE,
  FILE_SHARE_READ,
  NULL,
  OPEN_EXISTING,
  FILE_ATTRIBUTE_NORMAL,
  NULL);
 if (NULL == hFile)
 {
  return 0;
 }
 DWORD dwFileSize = GetFileSize(hFile, NULL);
 if (dwFileSize == 0)
 {
  return 0;
 }
 PVOID dotnetRaw = malloc(dwFileSize);
 memset(dotnetRaw, 0, dwFileSize);
 DWORD dwReturn = 0;
 if (ReadFile(hFile, dotnetRaw, dwFileSize, &dwReturn, NULL)==FALSE)
 {
  return 0;
 }
//
 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;
//
 //检测点1
 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 = dwFileSize;
 saBound[0].lLbound = 0;
 SAFEARRAY* pSafeArray = SafeArrayCreate(VT_UI1, 1, saBound);
//
 SafeArrayAccessData(pSafeArray, &pData);
 memcpy(pData, dotnetRaw, dwFileSize);
 //free(dotnetRaw);   //释放1
 SafeArrayUnaccessData(pSafeArray);
//
 //检测点2
 pDefaultAppDomain->Load_3(pSafeArray, &pAssembly);
 //free(pSafeArray->pvData);
 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((OLECHAR*)argv[i]));
  }

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

 //检测点3
 HRESULT hr = pMethodInfo->Invoke_3(vObj, args, &vRet);
 pMethodInfo->Release();
 pAssembly->Release();
 pDefaultAppDomain->Release();
 iRuntimeInfo->Release();
 iMetaHost->Release();
 CoUninitialize();
 getchar();
 return 0;
};

这个错误提示表明 Maven 没有找到任何装配描述符。在使用 maven-assembly-plugin 时,必须在项目的 pom.xml 文件中配置相应的描述符,才能生成期望的装配包。如果您没有提供描述符,那么您需要提供一个默认的描述符。 您可以通过在 pom.xml 文件中添加以下配置来提供一个默认的描述符: ```xml <build> <plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <version>2.2-beta-5</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.example.MainClass</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> ``` 在这个示例中,我们指定了 `jar-with-dependencies` 描述符,它将生成一个包含所有依赖项的可执行 JAR 文件。请注意,这里还指定了一个 `mainClass`,用于指定可执行 JAR 的入口类。 如果您想使用自定义的描述符,您需要在 `<configuration>` 标签中指定 `descriptor` 元素,例如: ```xml <configuration> <descriptors> <descriptor>assembly.xml</descriptor> </descriptors> </configuration> ``` 在这个示例中,我们使用 `assembly.xml` 作为描述符文件的名称。请确保该文件位于项目的根目录或相对路径下,并包含正确的装配信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值