/// <summary> /// Create the config class that is passed to the CLR bootstrap library to be loaded. /// The <paramref name="remoteInfo"/> holds information such as what hooking module to load. /// </summary> /// <param name="remoteInfo">The configuration that is serialized and passed to CoreLoad.</param> /// <param name="userDataFormatter">Serializes the <paramref name="remoteInfo"/> data.</param> /// <param name="pluginPath">The plugin to be loaded and executed in the target process.</param> /// <param name="argumentsStream">The stream that holds the the serialized <paramref name="remoteInfo"/> class.</param> /// <param name="injectionPipeName">The pipe name used for notifying the host process that the hook plugin has been loaded in the target process.</param> private static void CreatePluginArguments( ManagedRemoteInfo remoteInfo, IUserDataFormatter userDataFormatter, string pluginPath, Stream argumentsStream, string injectionPipeName) { if (string.IsNullOrWhiteSpace(pluginPath)) { throw new ArgumentException("The injection library was not valid"); } if (File.Exists(pluginPath)) { pluginPath = Path.GetFullPath(pluginPath); } remoteInfo.UserLibrary = pluginPath; if (File.Exists(remoteInfo.UserLibrary)) { remoteInfo.UserLibraryName = AssemblyName.GetAssemblyName(remoteInfo.UserLibrary).FullName; } else { throw new FileNotFoundException($"The given assembly could not be found: '{remoteInfo.UserLibrary}'", remoteInfo.UserLibrary); } remoteInfo.ChannelName = injectionPipeName; userDataFormatter.Serialize(argumentsStream, remoteInfo); }
/// <summary> /// Create the config class that is passed to the CLR bootstrap library to be loaded. /// The <paramref name="remoteInfo"/> holds information such as what hooking module to load. /// </summary> /// <param name="remoteInfo">The configuration that is serialized and passed to CoreLoad.</param> /// <param name="serializer">Serializes the <paramref name="remoteInfo"/> data.</param> /// <param name="library">The managed hooking library to be loaded and executed in the target process.</param> /// <param name="argumentsStream">The stream that holds the the serialized <paramref name="remoteInfo"/> class.</param> /// <param name="injectionPipeName">The pipe name used for notifying the host process that the hook plugin has been loaded in the target process.</param> private static void PrepareInjection( ManagedRemoteInfo remoteInfo, IUserDataFormatter serializer, ref string library, MemoryStream argumentsStream, string injectionPipeName) { if (string.IsNullOrWhiteSpace(library)) { throw new ArgumentException("The injection library was not valid"); } if ((library != null) && File.Exists(library)) { library = Path.GetFullPath(library); } remoteInfo.UserLibrary = library; if (File.Exists(remoteInfo.UserLibrary)) { remoteInfo.UserLibraryName = AssemblyName.GetAssemblyName(remoteInfo.UserLibrary).FullName; } else { throw new FileNotFoundException($"The given assembly could not be found: '{remoteInfo.UserLibrary}'", remoteInfo.UserLibrary); } remoteInfo.ChannelName = injectionPipeName; serializer.Serialize(argumentsStream, remoteInfo); }
void ShouldThrowErrorWhenSerializingNullManagedRemoteInfoClass() { ManagedRemoteInfo remoteInfo = null; Assert.Throws <ArgumentNullException>( () => CreateDefaultFormatter().Serialize(new MemoryStream(), remoteInfo)); }
private HostConnectionData() { _state = ConnectionState.Invalid; _helperInterface = null; _remoteInfo = null; _unmanagedInfo = null; }
void ShouldThrowErrorWhenSerializingNullStreamClass() { MemoryStream memoryStream = null; ManagedRemoteInfo remoteInfo = new ManagedRemoteInfo(); Assert.Throws <ArgumentNullException>( () => new BinaryFormatter().Serialize(memoryStream, remoteInfo)); }
void ShouldSerializeAndDeserializeManagedRemoteInfoObject() { var memoryStream = new MemoryStream(); var remoteInfo = new ManagedRemoteInfo(); var binaryFormatter = CreateDefaultFormatter(); binaryFormatter.Serialize(memoryStream, remoteInfo); memoryStream.Position = 0; Assert.NotNull(binaryFormatter.Deserialize <ManagedRemoteInfo>(memoryStream)); }
void ShouldSerializeAndDeserializeManagedRemoteInfoObject() { var memoryStream = new MemoryStream(); var remoteInfo = new ManagedRemoteInfo(); var binaryFormatter = new BinaryFormatter(); binaryFormatter.Serialize(memoryStream, remoteInfo); memoryStream.Position = 0; object deserializedRemoteInfo = binaryFormatter.Deserialize(memoryStream); Assert.NotNull(deserializedRemoteInfo); }
void ShouldSerializeAndDeserializeManagedRemoteInfoClass() { var memoryStream = new MemoryStream(); var remoteInfo = new ManagedRemoteInfo(); var binaryFormatter = CreateDefaultFormatter(); binaryFormatter.Serialize(memoryStream, remoteInfo); memoryStream.Position = 0; var deserializedRemoteInfo = binaryFormatter.Deserialize <ManagedRemoteInfo>(memoryStream); Assert.NotNull(deserializedRemoteInfo); Assert.IsType(typeof(ManagedRemoteInfo), deserializedRemoteInfo); }
void ShouldSerializeAndDeserializeManagedRemoteInfoChannelName() { const string channelName = "ChannelName"; var memoryStream = new MemoryStream(); var remoteInfo = new ManagedRemoteInfo { ChannelName = channelName }; var binaryFormatter = CreateDefaultFormatter(); binaryFormatter.Serialize(memoryStream, remoteInfo); memoryStream.Position = 0; var deserializedRemoteInfo = binaryFormatter.Deserialize <ManagedRemoteInfo>(memoryStream); Assert.NotNull(deserializedRemoteInfo); Assert.IsType(typeof(ManagedRemoteInfo), deserializedRemoteInfo); Assert.Equal(channelName, deserializedRemoteInfo.ChannelName); }
/// <summary> /// /// </summary> /// <param name="processId">The process ID of the local process that is injecting into another remote process.</param> /// <param name="formatter">Serializer for the user arguments passed to the plugin.</param> /// <param name="passThruArguments">The arguments passed to the plugin during initialization.</param> /// <returns></returns> private static ManagedRemoteInfo CreateRemoteInfo(int processId, IUserDataFormatter formatter, params object[] passThruArguments) { var remoteInfo = new ManagedRemoteInfo { RemoteProcessId = processId }; var arguments = new List <object>(); if (passThruArguments != null) { foreach (var arg in passThruArguments) { using (var ms = new MemoryStream()) { formatter.Serialize(ms, arg); arguments.Add(ms.ToArray()); } } } remoteInfo.UserParams = arguments.ToArray(); return(remoteInfo); }
/// <summary> /// Start CoreCLR and execute a .NET assembly in a target process. /// </summary> /// <param name="hostPID">Process ID of the process communicating with the target process.</param> /// <param name="targetPID">The process ID of the process to inject the .NET assembly into.</param> /// <param name="remoteHookConfig">Configuration settings for starting CoreCLR and executing .NET assemblies.</param> /// <param name="pipePlatform">Class for creating pipes for communication with the target process.</param> /// <param name="passThruArguments">Arguments passed to the .NET hooking library in the target process.</param> public static void InjectEx( int hostPID, int targetPID, RemoteHookingConfig remoteHookConfig, IPipePlatform pipePlatform, params object[] passThruArguments) { string injectionPipeName = remoteHookConfig.InjectionPipeName; if (string.IsNullOrWhiteSpace(injectionPipeName)) { throw new ArgumentException("Invalid injection pipe name"); } InjectionHelper.BeginInjection(targetPID); using (InjectionHelper.CreateServer(injectionPipeName, pipePlatform)) { try { var remoteInfo = new ManagedRemoteInfo { HostPID = hostPID }; var format = new BinaryFormatter(); var arguments = new List <object>(); if (passThruArguments != null) { foreach (var arg in passThruArguments) { using (var ms = new MemoryStream()) { format.Serialize(ms, arg); arguments.Add(ms.ToArray()); } } } remoteInfo.UserParams = arguments.ToArray(); using (var passThruStream = new MemoryStream()) { var libraryPath = remoteHookConfig.PayloadLibrary; PrepareInjection( remoteInfo, new UserDataBinaryFormatter(), libraryPath, passThruStream, injectionPipeName); // Inject the corerundll into the process, start the CoreCLR // and use the CoreLoad dll to resolve the dependencies of the hooking library // and then call the IEntryPoint.Run method located in the hooking library try { var process = GetProcessById(targetPID); var length = (int)passThruStream.Length; using (var binaryLoader = GetBinaryLoader(process)) { binaryLoader.Load(process, remoteHookConfig.HostLibrary, new[] { remoteHookConfig.DetourLibrary }); binaryLoader.ExecuteRemoteFunction(process, new RemoteFunctionCall { Arguments = new BinaryLoaderSerializer(GetBinaryLoaderConfig()) { Arguments = new BinaryLoaderArguments { Verbose = remoteHookConfig.VerboseLog, PayloadFileName = remoteHookConfig.CLRBootstrapLibrary, CoreRootPath = remoteHookConfig.CoreCLRPath, CoreLibrariesPath = remoteHookConfig.CoreCLRLibrariesPath } }, FunctionName = new FunctionName { Module = remoteHookConfig.HostLibrary, Function = GetCoreCLRStartFunctionName() }, }); binaryLoader.ExecuteRemoteManagedFunction(process, new RemoteManagedFunctionCall { ManagedFunction = CoreHookLoaderDel, FunctionName = new FunctionName { Module = remoteHookConfig.HostLibrary, Function = GetCoreCLRExecuteManagedFunctionName() }, Arguments = new RemoteFunctionArguments { Is64BitProcess = process.Is64Bit(), UserData = binaryLoader.CopyMemoryTo(process, passThruStream.GetBuffer(), length), UserDataSize = length } } ); InjectionHelper.WaitForInjection(targetPID); } } catch (Exception ex) { Debug.WriteLine(ex.ToString()); } } } finally { InjectionHelper.EndInjection(targetPID); } } }