Hello.
After some trial and error, I figured out how to inject assemblies into Mono embedded processes and I'm going to share the method here.
I am using the Process.NET library written by lolp1 to invoke functions in the target process, and Fasm.NET written by ZenLulz as the assembler that Process.NET requires.
The target process does not have to be restarted in order to inject an updated version of the assembly. Instead, you need to properly eject the assembly which this tool simplifies, and then inject again.
Compiled binaries + source code is included in the attached archive.
Below is a much simplified version of the source code for those that want a quick look.
Code:
using System;
using System****;
using Process.NET;
using Process.NE*****mory;
using Process.NET.Assembly;
using Process.NET.Native.Types;
using Binarysharp.Assemblers.Fasm;
using Process.NET.Assembly.Assemblers;
namespace Injector
{
class Assembler : IAssembler
{
public static bool Attach = false;
public static IntPtr MonoThreadAttach;
public static IntPtr MonoRootDomain;
public byte[] Assemble(string asm)
{
return Assemble(asm, IntPtr.Zero);
}
public byte[] Assemble(string asm, IntPtr baseAddress)
{
if (!Attach)
asm = $"use32\norg {baseAddress}\n" + asm;
else
// Ensure mono_thread_attach is called first
asm = $"use32\norg {baseAddress}\npush {MonoRootDomain}\ncall {MonoThreadAttach}\nadd esp, 4\n" + asm;
return FasmNet.Assemble(asm);
}
}
class Program
{
static ProcessSharp target;
static AssemblyFactory factory;
static void Main(string[] args)
{
System.Diagnostics.Process p =
System.Diagnostics.Process.GetProcessesByName("target")[0];
target = new ProcessSharp(p, MemoryType.Remote);
factory = new AssemblyFactory(target, new Assembler());
byte[] data = File.ReadAllBytes("ExampleAssembly.dll");
string nameSpace = "ExampleAssembly",
klass = "Loader",
method = "Load";
IntPtr rawImage = OpenImageFromData(data);
/* From this point on, the threads created by AssemblyFactory.Execute
will have to be registered with the Mono runtime since we
are accessing Mono objects. Otherwise the target process crashes. */
Assembler.MonoThreadAttach = target.ModuleFactory["mono.dll"]["mono_thread_attach"].BaseAddress;
Assembler.MonoRootDomain = GetRootDomain();
Assembler.Attach = true;
RuntimeInvoke(
GetMethodFromName(
GetClassFromName(
GetImageFromAssembly(
OpenAssemblyFromImage(
rawImage)),
nameSpace, klass),
method));
factory.Dispose();
target.Dispose();
}
static IntPtr GetRootDomain()
{
IntPtr addr = target.ModuleFactory["mono.dll"]["mono_get_root_domain"].BaseAddress;
return factory.Execute<IntPtr>(addr, CallingConventions.Cdecl);
}
static IntPtr OpenImageFromData(byte[] assembly)
{
IntPtr addr = target.ModuleFactory["mono.dll"]["mono_image_open_from_data"].BaseAddress;
IAllocatedMemory alloc = targe*****moryFactory.Allocate("assembly", assembly.Length);
alloc.Write(0, assembly);
IntPtr image = factory.Execute<IntPtr>(addr, CallingConventions.Cdecl, alloc.BaseAddress, assembly.Length, 1, IntPtr.Zero);
targe*****moryFactory.Deallocate(alloc);
return image;
}
static IntPtr OpenAssemblyFromImage(IntPtr image)
{
IntPtr addr = target.ModuleFactory["mono.dll"]["mono_assembly_load_from_full"].BaseAddress;
return factory.Execute<IntPtr>(addr, CallingConventions.Cdecl, image, "UNUSED", IntPtr.Zero, 0);
}
static IntPtr GetImageFromAssembly(IntPtr assembly)
{
IntPtr addr = target.ModuleFactory["mono.dll"]["mono_assembly_get_image"].BaseAddress;
return factory.Execute<IntPtr>(addr, CallingConventions.Cdecl, assembly);
}
static IntPtr GetClassFromName(IntPtr image, string name_space, string klass)
{
IntPtr addr = target.ModuleFactory["mono.dll"]["mono_class_from_name"].BaseAddress;
return factory.Execute<IntPtr>(addr, CallingConventions.Cdecl, image, name_space, klass);
}
static IntPtr GetMethodFromName(IntPtr klass, string method)
{
IntPtr addr = target.ModuleFactory["mono.dll"]["mono_class_get_method_from_name"].BaseAddress;
return factory.Execute<IntPtr>(addr, CallingConventions.Cdecl, klass, method, 0);
}
static int RuntimeInvoke(IntPtr method)
{
IntPtr addr = target.ModuleFactory["mono.dll"]["mono_runtime_invoke"].BaseAddress;
return factory.Execute<int>(addr, CallingConventions.Cdecl, method, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
}
}
}
https://virusscan.jotti.org/en-US/fi...job/lqr49ac4aa
https://www.virustotal.com/#/file/0b...3c06/detection