So I'm trying to access a running program from which I've injected an external DLL at runtime. I have two projects: console app and class library.
Console app:
using System;
using System.Reflection;
namespace SharpConsole
{
public class GameEvent
{
private bool _cancelled;
public bool Cancelled { get => _cancelled; }
public void SetCancelled(bool cancelled)
{
_cancelled = cancelled;
}
public override string ToString()
{
return $"Event (Cancelled={Cancelled})";
}
}
public class API
{
public static void Print(string text)
{
Console.WriteLine($"[API] {text}");
}
}
public class Program
{
public static string TestValue = "some initial test value";
static void Main(string[] args)
{
var evt = new GameEvent();
Console.WriteLine("[Console] " + evt.ToString());
Console.WriteLine("[Console] Loading dll...");
// var asm = Assembly.LoadFile(@"C:\Users\tinytengu\Desktop\SharpTest\SharpExternal\bin\Release\netcoreapp3.1\SharpExternal.dll");
var asm = Assembly.LoadFile(@"C:\Users\tinytengu\SharpExternal\SharpExternal.dll");
var classType = asm.GetType("SharpExternal.Class1");
Console.WriteLine("[Console] Invoking SharpExternal.Class1.Main method...");
var methodInfo = classType.GetMethod("Main", BindingFlags.Static | BindingFlags.Public);
methodInfo.Invoke(null, new object[] { evt });
Console.WriteLine("[Console] After changes: " + evt.ToString());
Console.WriteLine();
methodInfo = classType.GetMethod("ShowTestValue", BindingFlags.Static | BindingFlags.Public);
methodInfo.Invoke(null, null);
Console.ReadLine();
}
}
}
And a class library:
using System;
namespace SharpExternal
{
public class Class1
{
public static void Main(ref SharpConsole.GameEvent evt)
{
Console.WriteLine("[DLL] " + evt.ToString());
Console.WriteLine("[DLL] Cancelling an event");
evt.SetCancelled(true);
}
public static void ShowTestValue()
{
SharpConsole.API.Print(SharpConsole.Program.TestValue);
}
}
}
What is going on:
- The console app creates GameEvent class instance
- It injects the
ExternalSharp.dll
ExternalSharp.Class1.Main
gets called passing previously created GameEvent instance reference to it.- ExternalSharp changes GameEvent's Cancelled state and SharpConsole outputs an instance of a GameEvent that has been successfully modified from ExternalSharp
- ExternalSharp's
ShowTestValue
gets called so it outputs a Console'sTestValue
field value.
The thing is, I can compile SharpExternal (which uses SharpConsole project as a dependency so it can use its classes. I can also compile SharpConsole and use its DLL file as a dependency, the result is the same) once and move its DLL file on the Desktop so it can't access any files, be recompiled and etc., i.e. in a completely empty folder. BUT I can change Console's TestValue at any moment, even from Console.ReadLine
in runtime, then recompile only the Console app and the SharpExternal will output new value when the ShowTestValue method is called. I can add more static properties, methods, etc. before and after TestValue, change the file as I want, but unchanged from the first time SharpExternal.dll file which is still located on the Desktop manages to find TestValue (and other static fields, methods, ...) every time and output the correct value.
I'd like to know how this whole thing works, how ExternalSharp finds the correct TestValue address every time. I suppose it's because of the static modifier, but I haven't found any information beyond the fact that it allows type members to refer to the type itself, and not just to its instance, which I already knew.
Aucun commentaire:
Enregistrer un commentaire