Skip to content

Instantly share code, notes, and snippets.

@loldot
Created September 10, 2023 18:14
Show Gist options
  • Save loldot/8820220cb361f48855ccf381c3502e76 to your computer and use it in GitHub Desktop.
Save loldot/8820220cb361f48855ccf381c3502e76 to your computer and use it in GitHub Desktop.
// See https://aka.ms/new-console-template for more information
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Loader;
using System.Security.Cryptography;
internal class Program
{
private static async Task Main(string[] args)
{
EncryptFile();
do
{
ExecuteInline(out var asmWRef);
int gcCount = 0;
while(asmWRef.IsAlive && (++gcCount < 10))
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
Console.WriteLine($"assembly unloaded [{gcCount}]");
await Task.Delay(60_000);
} while(true);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void ExecuteInline(out WeakReference asmWRef)
{
var ctx = new EncryptedLoadContext();
var asm = ctx.LoadFromAssemblyName(new AssemblyName
{
Name = "impl"
});
var type = asm.DefinedTypes.First(x => x.Name.Contains("MyClass"));
Console.WriteLine(type);
var method = type.GetMethod("Execute", BindingFlags.Static | BindingFlags.Public);
Console.WriteLine(method);
method!.Invoke(null, Array.Empty<object>());
asmWRef = new WeakReference(ctx, trackResurrection: true);
ctx.Unload();
}
private static void EncryptFile()
{
using var aes = Aes.Create();
// TODO: use real key and IV
aes.KeySize = 256;
aes.IV = Convert.FromHexString("392822A5BCFC47ABED338F8745C9F5DD");
aes.Key = Convert.FromHexString("2B3E5DDB832115976DC416D09A371E95B6698D5E7AEE906C7946C6AD16939140");
using var fs = File.OpenRead(@"C:\dev\sleep\impl\bin\Debug\net7.0\impl.dll");
using var outFs = File.Open(@"C:\temp\dll.bin", FileMode.Truncate, FileAccess.ReadWrite);
using var cs = new CryptoStream(outFs, aes.CreateEncryptor(), CryptoStreamMode.Write);
fs.CopyTo(cs);
cs.Flush();
}
}
public class EncryptedLoadContext : AssemblyLoadContext
{
public EncryptedLoadContext() : base(isCollectible: true)
{
}
protected override Assembly? Load(AssemblyName name)
{
if (!name.Name.Contains("impl")) return base.Load(name);
using var aes = Aes.Create();
aes.KeySize = 256;
aes.IV = Convert.FromHexString("392822A5BCFC47ABED338F8745C9F5DD");
aes.Key = Convert.FromHexString("2B3E5DDB832115976DC416D09A371E95B6698D5E7AEE906C7946C6AD16939140");
using var fs = File.OpenRead(@"C:\temp\dll.bin");
using var cs = new CryptoStream(fs, aes.CreateDecryptor(), CryptoStreamMode.Read);
using var ms = new MemoryStream();
cs.CopyTo(ms);
ms.Seek(0, SeekOrigin.Begin);
return LoadFromStream(ms);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment