private HostConnectionData() { _state = ConnectionState.Invalid; _helperInterface = null; _remoteInfo = null; _unmanagedInfo = null; }
private static GCHandle PrepareInjection( ManagedRemoteInfo InRemoteInfo, ref String InLibraryPath_x86, ref String InLibraryPath_x64, MemoryStream InPassThruStream) { // ensure full path information in case of file names... if ((InLibraryPath_x86 != null) && File.Exists(InLibraryPath_x86)) { InLibraryPath_x86 = Path.GetFullPath(InLibraryPath_x86); } if ((InLibraryPath_x64 != null) && File.Exists(InLibraryPath_x64)) { InLibraryPath_x64 = Path.GetFullPath(InLibraryPath_x64); } /* * validate assembly name... */ Assembly UserAsm; InRemoteInfo.UserLibrary = InLibraryPath_x86; if (NativeAPI.Is64Bit) { InRemoteInfo.UserLibrary = InLibraryPath_x64; } if (File.Exists(InRemoteInfo.UserLibrary)) { // translate to assembly name InRemoteInfo.UserLibrary = AssemblyName.GetAssemblyName(InRemoteInfo.UserLibrary).FullName; } if ((UserAsm = Assembly.ReflectionOnlyLoad(InRemoteInfo.UserLibrary)) == null) { throw new DllNotFoundException("The given assembly could not be found."); } if ((Int32)(UserAsm.GetName().Flags & AssemblyNameFlags.PublicKey) == 0) { throw new ArgumentException("The given assembly has no strong name."); } /* * Convert managed arguments to binary stream... */ BinaryFormatter Format = new BinaryFormatter(); IpcServerChannel Channel = IpcCreateServer <HelperServiceInterface>( ref InRemoteInfo.ChannelName, WellKnownObjectMode.Singleton); Format.Serialize(InPassThruStream, InRemoteInfo); return(GCHandle.Alloc(InPassThruStream.GetBuffer(), GCHandleType.Pinned)); }
/// <summary> /// Creates a new process which is started suspended until you call <see cref="WakeUpProcess"/> /// from within your injected library <c>Run()</c> method. This allows you to hook the target /// BEFORE any of its usual code is executed. In situations where a target has debugging and /// hook preventions, you will get a chance to block those mechanisms for example... /// </summary> /// <remarks> /// <para> /// Please note that this method might fail when injecting into managed processes, especially /// when the target is using the CLR hosting API and takes advantage of AppDomains. For example, /// the Internet Explorer won't be hookable with this method. In such a case your only options /// are either to hook the target with the unmanaged API or to hook it after (non-supended) creation /// with the usual <see cref="Inject"/> method. /// </para> /// <para> /// See <see cref="Inject"/> for more information. The exceptions listed here are additional /// to the ones listed for <see cref="Inject"/>. /// </para> /// </remarks> /// <param name="InEXEPath"> /// A relative or absolute path to the desired executable. /// </param> /// <param name="InCommandLine"> /// Optional command line parameters for process creation. /// </param> /// <param name="InProcessCreationFlags"> /// Internally CREATE_SUSPENDED is already passed to CreateProcess(). With this /// parameter you can add more flags like DETACHED_PROCESS, CREATE_NEW_CONSOLE or /// whatever! /// </param> /// <param name="InLibraryPath_x86"> /// A partially qualified assembly name or a relative/absolute file path of the 32-bit version of your library. /// For example "MyAssembly, PublicKeyToken=248973975895496" or ".\Assemblies\\MyAssembly.dll". /// </param> /// <param name="InLibraryPath_x64"> /// A partially qualified assembly name or a relative/absolute file path of the 64-bit version of your library. /// For example "MyAssembly, PublicKeyToken=248973975895496" or ".\Assemblies\\MyAssembly.dll". /// </param> /// <param name="OutProcessId"> /// The process ID of the newly created process. /// </param> /// <param name="InPassThruArgs"> /// A serializable list of parameters being passed to your library entry points <c>Run()</c> and /// <c>Initialize()</c>. /// </param> /// <exception cref="ArgumentException"> /// The given EXE path could not be found. /// </exception> public static void CreateAndInject( String InEXEPath, String InCommandLine, Int32 InProcessCreationFlags, String InLibraryPath_x86, String InLibraryPath_x64, RhAssemblyInfo[] Assemblies, out Int32 OutProcessId, params Object[] InPassThruArgs) { Int32 RemotePID; Int32 RemoteTID; MemoryStream PassThru = new MemoryStream(); ManagedRemoteInfo RemoteInfo = new ManagedRemoteInfo(); // create suspended process... NativeAPI.RtlCreateSuspendedProcess( InEXEPath, InCommandLine, InProcessCreationFlags, out RemotePID, out RemoteTID); try { InjectEx( NativeAPI.GetCurrentProcessId(), RemotePID, RemoteTID, 0x20000000, InLibraryPath_x86, InLibraryPath_x64, Assemblies, true, false, InPassThruArgs); OutProcessId = RemotePID; } catch (Exception e) { try { Process.GetProcessById(RemotePID).Kill(); } catch (Exception) { } throw e; } }
internal static void InjectEx( Int32 InHostPID, Int32 InTargetPID, Int32 InWakeUpTID, Int32 InNativeOptions, String InLibraryPath_x86, String InLibraryPath_x64, Boolean InCanBypassWOW64, Boolean InCanCreateService, params Object[] InPassThruArgs) { MemoryStream PassThru = new MemoryStream(); ManagedRemoteInfo RemoteInfo = new ManagedRemoteInfo(); BinaryFormatter Format = new BinaryFormatter(); Int32 NtStatus; HelperServiceInterface.BeginInjection(InTargetPID); try { RemoteInfo = new ManagedRemoteInfo(); RemoteInfo.HostPID = InHostPID; RemoteInfo.UserParams = InPassThruArgs; GCHandle hPassThru = PrepareInjection( RemoteInfo, ref InLibraryPath_x86, ref InLibraryPath_x64, PassThru); /* * Inject library... */ try { switch (NtStatus = NativeAPI.RhInjectLibraryEx( InTargetPID, InWakeUpTID, NativeAPI.EASYHOOK_INJECT_MANAGED | InNativeOptions, typeof(Config).Assembly.Location, typeof(Config).Assembly.Location, hPassThru.AddrOfPinnedObject(), (int)PassThru.Length)) { case NativeAPI.STATUS_WOW_ASSERTION: { // Use helper application to bypass WOW64... if (InCanBypassWOW64) { WOW64Bypass.Inject( InHostPID, InTargetPID, InWakeUpTID, InNativeOptions, InLibraryPath_x86, InLibraryPath_x64, InPassThruArgs); } else { throw new AccessViolationException("Unable to inject library into target process."); } } break; case NativeAPI.STATUS_ACCESS_DENIED: { // Use service and try again... if (InCanCreateService) { ServiceMgmt.Inject( InHostPID, InTargetPID, InWakeUpTID, InNativeOptions, InLibraryPath_x86, InLibraryPath_x64, InPassThruArgs); } else { NativeAPI.Force(NtStatus); } } break; case NativeAPI.STATUS_SUCCESS: { // wait for injection completion HelperServiceInterface.WaitForInjection(InTargetPID); } break; default: { NativeAPI.Force(NtStatus); } break; } } finally { hPassThru.Free(); } } finally { HelperServiceInterface.EndInjection(InTargetPID); } }
internal static void InjectEx( Int32 InHostPID, Int32 InTargetPID, Int32 InWakeUpTID, Int32 InNativeOptions, String InLibraryPath_x86, String InLibraryPath_x64, Boolean InCanBypassWOW64, Boolean InCanCreateService, Boolean InRequireStrongName, params Object[] InPassThruArgs) { var PassThru = new MemoryStream(); HelperServiceInterface.BeginInjection(InTargetPID); try { var RemoteInfo = new ManagedRemoteInfo(); RemoteInfo.HostPID = InHostPID; // We first serialise parameters so that they can be deserialised AFTER the UserLibrary is loaded var format = new BinaryFormatter(); var args = new List <object>(); if (InPassThruArgs != null) { foreach (var arg in InPassThruArgs) { using (var ms = new MemoryStream()) { format.Serialize(ms, arg); args.Add(ms.ToArray()); } } } RemoteInfo.UserParams = args.ToArray(); RemoteInfo.RequireStrongName = InRequireStrongName; var hPassThru = PrepareInjection( RemoteInfo, ref InLibraryPath_x86, ref InLibraryPath_x64, PassThru); /* * Inject library... */ try { Int32 NtStatus; switch (NtStatus = NativeAPI.RhInjectLibraryEx( InTargetPID, InWakeUpTID, NativeAPI.EASYHOOK_INJECT_MANAGED | InNativeOptions, typeof(Config).Assembly.Location, typeof(Config).Assembly.Location, hPassThru.AddrOfPinnedObject(), (int)PassThru.Length)) { case NativeAPI.STATUS_WOW_ASSERTION: { // Use helper application to bypass WOW64... if (InCanBypassWOW64) { WOW64Bypass.Inject( InHostPID, InTargetPID, InWakeUpTID, InNativeOptions, InLibraryPath_x86, InLibraryPath_x64, InRequireStrongName, InPassThruArgs); } else { throw new AccessViolationException("Unable to inject library into target process."); } } break; case NativeAPI.STATUS_ACCESS_DENIED: { // Use service and try again... if (InCanCreateService) { ServiceMgmt.Inject( InHostPID, InTargetPID, InWakeUpTID, InNativeOptions, InLibraryPath_x86, InLibraryPath_x64, InRequireStrongName, InPassThruArgs); } else { NativeAPI.Force(NtStatus); } } break; case NativeAPI.STATUS_SUCCESS: { // wait for injection completion HelperServiceInterface.WaitForInjection(InTargetPID); } break; default: { NativeAPI.Force(NtStatus); } break; } } finally { hPassThru.Free(); } } finally { HelperServiceInterface.EndInjection(InTargetPID); } }
private static GCHandle PrepareInjection( ManagedRemoteInfo InRemoteInfo, ref String InLibraryPath_x86, ref String InLibraryPath_x64, MemoryStream InPassThruStream) { if (String.IsNullOrEmpty(InLibraryPath_x86) && String.IsNullOrEmpty(InLibraryPath_x64)) { throw new ArgumentException("At least one library for x86 or x64 must be provided"); } // ensure full path information in case of file names... if ((InLibraryPath_x86 != null) && File.Exists(InLibraryPath_x86)) { InLibraryPath_x86 = Path.GetFullPath(InLibraryPath_x86); } if ((InLibraryPath_x64 != null) && File.Exists(InLibraryPath_x64)) { InLibraryPath_x64 = Path.GetFullPath(InLibraryPath_x64); } /* * validate assembly name... */ Assembly UserAsm; InRemoteInfo.UserLibrary = InLibraryPath_x86; if (NativeAPI.Is64Bit) { InRemoteInfo.UserLibrary = InLibraryPath_x64; } if (File.Exists(InRemoteInfo.UserLibrary)) { // translate to assembly name InRemoteInfo.UserLibraryName = AssemblyName.GetAssemblyName(InRemoteInfo.UserLibrary).FullName; } // Attempt to load the library by its FullName and if that fails, by its original library filename if ((UserAsm = Assembly.ReflectionOnlyLoad(InRemoteInfo.UserLibraryName)) == null && (UserAsm = Assembly.ReflectionOnlyLoadFrom(InRemoteInfo.UserLibrary)) == null) { throw new DllNotFoundException("The given assembly could not be found."); } // Check for a strong name if necessary if (InRemoteInfo.RequireStrongName && (Int32)(UserAsm.GetName().Flags & AssemblyNameFlags.PublicKey) == 0) { throw new ArgumentException("The given assembly has no strong name."); } /* * Convert managed arguments to binary stream... */ var Format = new BinaryFormatter(); var Channel = IpcCreateServer <HelperServiceInterface>( ref InRemoteInfo.ChannelName, WellKnownObjectMode.Singleton); Format.Serialize(InPassThruStream, InRemoteInfo); return(GCHandle.Alloc(InPassThruStream.GetBuffer(), GCHandleType.Pinned)); }