0x00 前言
在之前的文章《从内存加载.NET程序集(execute-assembly)的利用分析》介绍了"execute-assembly"的实现方法和利用思路,能够从内存中加载.NET程序集。这个功能不需要向硬盘写入文件,十分隐蔽。
与此相似的方法还有一个是Assembly.Load,同样能够从内存中加载.NET程序集。
本文将会结合三个开源工程,介绍Assembly.Load的实现方法,分析利用思路。
0x01 简介
本文将要介绍以下内容:
· 基础知识
· SharpCradle的利用分析
· SharpShell的利用分析
· SharpCompile的利用分析
0x02 基础知识
参考资料:
https://docs.microsoft.com/en-us/dotnet/api/system.reflection.assembly.load?view=netframework-4.5
1.Assembly.Load()、Assembly.LoadFrom()和Assembly.LoadFile()的区别
Assembly.Load()是从String或AssemblyName类型加载程序集,可以读取字符串形式的程序集,也就是说,文件不需要写入硬盘。
Assembly.LoadFrom()从指定文件中加载程序集,同时会加载目标程序集所引用和依赖的其他程序集。
例如:
Assembly.LoadFrom("a.dll"),如果a.dll中引用了b.dll,那么会同时加载a.dll和b.dll。
Assembly.LoadFile()也是从指定文件中加载程序集,但不会加载目标程序集所引用和依赖的其他程序集。
例如:
Assembly.LoadFile("a.dll"),如果a.dll中引用了b.dll,那么不会加载b.dll。
2.Assembly.Load()的实现示例
(1)编写测试程序
测试程序的代码如下:
using System;
namespace TestApplication
{
public class Program
{
public static void Main()
{
Console.WriteLine("Main");
}
}
public class aaa
{
public static void bbb()
{
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "c:\\windows\\system32\\calc.exe";
p.Start();
}
}
}
使用csc.exe进行编译:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /out:testcalc.exe test.cs
生成testcalc.exe。
(2)读取testcalc.exe的内容,并作base64加密
代码如下:
using System;
using System.Reflection;
namespace TestApplication
{
public class Program
{
public static void Main()
{
byte[] buffer = System.IO.File.ReadAllBytes("testcalc.exe");
string base64str = Convert.ToBase64String(buffer);
Console.WriteLine(base64str);
}
}
}
(3)解密字符串变量,还原testcalc.exe的内容,使用Assembly.Load()加载程序集并调用方法bbb
代码如下:
using System;
using System.Reflection;
namespace TestApplication
{
public class Program
{
public static void Main()
{
string base64str = "TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9