private HostConnectionData() { _state = ConnectionState.Invalid; _helperInterface = null; _remoteInfo = null; _unmanagedInfo = null; }
private static void Install() { lock (ThreadSafe) { // Ensure we create a new one if the existing // channel cannot be pinged try { if (m_Interface != null) { m_Interface.Ping(); } } catch { m_Interface = null; } if (m_Interface == null) { String ChannelName = RemoteHooking.GenerateName(); String SvcExecutablePath = (Config.DependencyPath.Length > 0 ? Config.DependencyPath : Config.GetProcessPath()) + Config.GetWOW64BypassExecutableName(); Process Proc = new Process(); ProcessStartInfo StartInfo = new ProcessStartInfo( SvcExecutablePath, "\"" + ChannelName + "\""); // create sync objects EventWaitHandle Listening = new EventWaitHandle( false, EventResetMode.ManualReset, "Global\\Event_" + ChannelName); m_TermMutex = new Mutex(true, "Global\\Mutex_" + ChannelName); // start and connect program StartInfo.CreateNoWindow = true; StartInfo.WindowStyle = ProcessWindowStyle.Hidden; Proc.StartInfo = StartInfo; Proc.Start(); if (!Listening.WaitOne(5000, true)) { throw new ApplicationException("Unable to wait for service application due to timeout."); } HelperServiceInterface Interface = RemoteHooking.IpcConnectClient <HelperServiceInterface>(ChannelName); Interface.Ping(); m_Interface = Interface; } } }
private static void Install() { lock (ThreadSafe) { // Ensure we create a new one if the existing // channel cannot be pinged try { if (m_Interface != null) { m_Interface.Ping(); } } catch { m_Interface = null; } if (m_Interface == null) { // create sync objects String ChannelName = RemoteHooking.GenerateName(); EventWaitHandle Listening = new EventWaitHandle( false, EventResetMode.ManualReset, "Global\\Event_" + ChannelName); Mutex TermMutex = new Mutex(true, "Global\\Mutex_" + ChannelName); using (TermMutex) { // install and start service NativeAPI.RtlInstallService( "EasyHook" + (NativeAPI.Is64Bit?"64":"32") + "Svc", Path.GetFullPath(Config.GetDependantSvcExecutableName()), ChannelName); if (!Listening.WaitOne(5000, true)) { throw new ApplicationException("Unable to wait for service startup."); } HelperServiceInterface Interface = RemoteHooking.IpcConnectClient <HelperServiceInterface>(ChannelName); Interface.Ping(); // now we can be sure that all things are fine... m_Interface = Interface; m_TermMutex = TermMutex; } } } }
/// <summary> /// Loads the user library, /// creates an instance for the <see cref="IEntryPoint"/> specified in the library /// and invokes the Run() method specified in that instance. /// </summary> /// <param name="userLibrary">The assembly provided by the user, located in the application directory or in the global assembly cache.</param> /// <param name="paramArray">Array of parameters to use with the constructor and with the Run() method.</param> /// <param name="helperServiceInterface"><see cref="HelperServiceInterface"/> to use for reporting to the host side.</param> /// <returns>The exit code to be returned by the main() method.</returns> private static int LoadUserLibrary(string userLibrary, object[] paramArray, HelperServiceInterface helperServiceInterface) { Type entryPoint = null; MethodInfo runMethod; object instance; try { entryPoint = FindEntryPoint(userLibrary); /// Determine if a Run() method is defined, before initializing an instance for the type. runMethod = FindMatchingMethod(entryPoint, "Run", paramArray); if (runMethod == null) { throw new MissingMethodException(ConstructMissingMethodExceptionMessage("Run", paramArray)); } /// Initialize an object for the entrypoint. instance = InitializeInstance(entryPoint, paramArray); if (instance == null) { throw new MissingMethodException(ConstructMissingMethodExceptionMessage(entryPoint.Name, paramArray)); } /// Notify the host about successful injection. helperServiceInterface.InjectionCompleted(RemoteHooking.GetCurrentProcessId()); } catch (Exception e) { /// Provide error information on host side. try { helperServiceInterface.InjectionException(RemoteHooking.GetCurrentProcessId(), e); } finally { Release(entryPoint); } return(-1); } try { /// After this it is safe to enter the Run() method, which will block until assembly unloading... /// From now on the user library has to take care about error reporting! runMethod.Invoke(instance, BindingFlags.Public | BindingFlags.Instance | BindingFlags.ExactBinding | BindingFlags.InvokeMethod, null, paramArray, null); } finally { Release(entryPoint); } return(0); }
internal static void Install() { lock (ThreadSafe) { if (m_Interface == null) { String ChannelName = RemoteHooking.GenerateName(); String EasyHookDir = Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName); Process Proc = new Process(); ProcessStartInfo StartInfo = new ProcessStartInfo( EasyHookDir + (NativeAPI.Is64Bit ? "\\EasyHook32Svc.exe" : "\\EasyHook64Svc.exe"), "\"" + ChannelName + "\""); // create sync objects EventWaitHandle Listening = new EventWaitHandle( false, EventResetMode.ManualReset, "Global\\Event_" + ChannelName); m_TermMutex = new Mutex(true, "Global\\Mutex_" + ChannelName); // start and connect program StartInfo.CreateNoWindow = true; StartInfo.WindowStyle = ProcessWindowStyle.Hidden; Proc.StartInfo = StartInfo; Proc.Start(); if (!Listening.WaitOne(5000, true)) { throw new ApplicationException("Unable to wait for service application due to timeout."); } HelperServiceInterface Interface = RemoteHooking.IpcConnectClient <HelperServiceInterface>(ChannelName); Interface.Ping(); m_Interface = Interface; } } }
/// <summary> /// Loads the user library (trying the strong name first, then the file name), /// creates an instance for the <see cref="IEntryPoint" /> specified in the library /// and invokes the Run() method specified in that instance. /// </summary> /// <param name="userLibraryStrongName"> /// The assembly strong name provided by the user, located in the global assembly /// cache. /// </param> /// <param name="userLibraryFileName">The assembly file name provided by the user to be loaded.</param> /// <param name="paramArray"> /// Array of parameters to use with the constructor and with the Run() method. Note that all but /// the first parameter should be binary encoded. /// </param> /// <param name="helperServiceInterface"><see cref="HelperServiceInterface" /> to use for reporting to the host side.</param> /// <returns>The exit code to be returned by the main() method.</returns> private static int LoadUserLibrary(string userLibraryStrongName, string userLibraryFileName, object[] paramArray, HelperServiceInterface helperServiceInterface) { Type entryPoint = null; MethodInfo runMethod; object instance; // 1. Load the assembly and find the EasyHook.IEntryPoint and matching Run() method try { // Load the given assembly and find the first EasyHook.IEntryPoint entryPoint = FindEntryPoint(userLibraryStrongName, userLibraryFileName); // Only attempt to deserialise parameters after we have loaded the userAssembly // this allows types from the userAssembly to be passed as parameters var format = new BinaryFormatter(); format.Binder = new AllowAllAssemblyVersionsDeserializationBinder(entryPoint.Assembly); for (var i = 1; i < paramArray.Length; i++) { using (var ms = new MemoryStream((byte[])paramArray[i])) { paramArray[i] = format.Deserialize(ms); } } // Determine if a Run() method is defined with matching parameters, before initializing an instance for the type. runMethod = FindMatchingMethod(entryPoint, "Run", paramArray); if (runMethod == null) { throw new MissingMethodException(ConstructMissingMethodExceptionMessage("Run", paramArray)); } // Initialize an object for the entrypoint. instance = InitializeInstance(entryPoint, paramArray); if (instance == null) { throw new MissingMethodException(ConstructMissingMethodExceptionMessage(entryPoint.Name, paramArray)); } // Notify the host about successful injection. helperServiceInterface.InjectionCompleted(RemoteHooking.GetCurrentProcessId()); } catch (Exception e) { // Provide error information on host side. try { helperServiceInterface.InjectionException(RemoteHooking.GetCurrentProcessId(), e); } finally { Release(entryPoint); } return(-1); } // 2. Invoke the Run() method try { // After this it is safe to enter the Run() method, which will block until assembly unloading... // From now on the user library has to take care about error reporting! runMethod.Invoke(instance, BindingFlags.Public | BindingFlags.Instance | BindingFlags.ExactBinding | BindingFlags.InvokeMethod, null, paramArray, null); } finally { Release(entryPoint); } return(0); }
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); } }