Repository navigation
Interaction With Remote Objects
RemoteNET's goal is to allow the developer of the manipulating app to
access remote objects as if they were local objects.
This includes reading fields & properties, setting properties, invoking functions and subscribing to/usubscribing from events.
To allow a smooth coding expereince, RemoteNET is utilizing a special dynamic object which any RemoteObject can turn into.
This object can be used to access field/properties just if they were field/properties of a local object:
// Reading the 'Capacity' property of a newly created StringBuilder
RemoteObject remoteStringBuilder = remoteApp.Activator.CreateInstance(typeof(StringBuilder));
dynamic dynamicStringBuilder = remoteStringBuilder.Dynamify();
Console.WriteLine("Remote StringBuilder's Capacity: " + dynamicStringBuilder.Capacity);A more interesting example would be retrieving the ConnectionStrings of every SqlConnection instance:
var sqlConCandidates = remoteApp.QueryInstances(typeof(SqlConnection));
foreach (CandidateObject candidate in sqlConCandidates)
{
RemoteObject remoteSqlConnection = remoteApp.GetRemoteObject(candidate);
dynamic dynamicSqlConnection = remoteSqlConnection.Dynamify();
Console.WriteLine("ConnectionString: " + dynamicSqlConnection.ConnectionString);
}Setting fields/properties are done just as you'd expect:
Console.WriteLine("Remote StringBuilder's Old Capacity: " + dynamicStringBuilder.Capacity)
dynamicStringBuilder.Capacity = 1337;
Console.WriteLine("Remote StringBuilder's New Capacity: " + dynamicStringBuilder.Capacity)Just like accessing fields & properties, invoking methods can be done on the dynamic objects directly.
This fun example dumps all private RSA keys (which are stored in RSACryptoServiceProviders) found in the target's memory:
(Note the invocation of RSACryptoServiceProvider.ExportParameters())
Func<byte[], string> ToHex = ba => BitConverter.ToString(ba).Replace("-", "");
// Finding every RSACryptoServiceProvider instance
var rsaProviderCandidates = remoteApp.QueryInstances(typeof(RSACryptoServiceProvider));
foreach (CandidateObject candidateRsa in rsaProviderCandidates)
{
RemoteObject rsaProv = remoteApp.GetRemoteObject(candidateRsa);
dynamic dynamicRsaProv = rsaProv.Dynamify();
// Calling remote `ExportParameters`.
// First parameter (true) indicates we want the private key.
Console.WriteLine(" * Key found:");
dynamic parameters = dynamicRsaProv.ExportParameters(true);
Console.WriteLine("Modulus: " + ToHex(parameters.Modulus));
Console.WriteLine("Exponent: " + ToHex(parameters.Exponent));
Console.WriteLine("D: " + ToHex(parameters.D));
Console.WriteLine("P: " + ToHex(parameters.P));
Console.WriteLine("Q: " + ToHex(parameters.Q));
Console.WriteLine("DP: " + ToHex(parameters.DP));
Console.WriteLine("DQ: " + ToHex(parameters.DQ));
Console.WriteLine("InverseQ: " + ToHex(parameters.InverseQ));
}You can also subscribe to/unsubscribe from remote events.
Note that the syntax is similar to "normal" C# events altough not exact:
CandidateObject cand = remoteApp.QueryInstances("System.IO.FileSystemWatcher").Single();
RemoteObject remoteFileSysWatcher = remoteApp.GetRemoteObject(cand);
dynamic dynFileSysWatcher = remoteFileSysWatcher.Dynamify();
Action<dynamic, dynamic> callback = (dynamic o, dynamic e) => Console.WriteLine("Event Invoked!");
dynFileSysWatcher.Changed += callback;
/* ... Somewhere further ... */
dynFileSysWatcher.Changed -= callback;The limitations:
- The parameters for the callback must be
dynamics - The callback must define the exact number of parameters for that event
- Lambda expression are not allowed. The callback must be casted to an
Action<...>.