/// <summary> /// Loads <see cref="HostConnectionData" /> from the <see cref="IntPtr" /> specified. /// </summary> /// <param name="unmanagedInfoPointer"></param> public static HostConnectionData LoadData(IntPtr unmanagedInfoPointer) { var data = new HostConnectionData { _state = ConnectionState.Valid, _unmanagedInfo = new REMOTE_ENTRY_INFO() }; try { // Get the unmanaged data Marshal.PtrToStructure(unmanagedInfoPointer, data._unmanagedInfo); using (Stream passThruStream = new MemoryStream()) { var passThruBytes = new byte[data._unmanagedInfo.UserDataSize]; var format = new BinaryFormatter(); // Workaround for deserialization when not using GAC registration format.Binder = new AllowAllAssemblyVersionsDeserializationBinder(); Marshal.Copy(data._unmanagedInfo.UserData, passThruBytes, 0, data._unmanagedInfo.UserDataSize); passThruStream.Write(passThruBytes, 0, passThruBytes.Length); passThruStream.Position = 0; data._remoteInfo = (ManagedRemoteInfo)format.Deserialize(passThruStream); } // Connect the HelperServiceInterface data._helperInterface = RemoteHooking.IpcConnectClient <HelperServiceInterface>(data._remoteInfo.ChannelName); // Ensure that the connection is working... data._helperInterface.Ping(); if (!_connectedChannels.Contains(data._remoteInfo.ChannelName)) { _connectedChannels.Add(data._remoteInfo.ChannelName); return(new HostConnectionData { _state = ConnectionState.NoChannel }); } } catch (Exception ExtInfo) { Config.PrintError(ExtInfo.ToString()); return(new HostConnectionData { _state = ConnectionState.Invalid }); } return(data); }
private static void Install() { lock (ThreadSafe) { if (m_Interface == null) { var ChannelName = RemoteHooking.GenerateName(); var SvcExecutablePath = (Config.DependencyPath.Length > 0 ? Config.DependencyPath : Config.GetProcessPath()) + Config.GetWOW64BypassExecutableName(); var Proc = new Process(); var StartInfo = new ProcessStartInfo( SvcExecutablePath, "\"" + ChannelName + "\""); // create sync objects var 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."); } var Interface = RemoteHooking.IpcConnectClient <HelperServiceInterface>(ChannelName); Interface.Ping(); m_Interface = Interface; } } }
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; } } }
public void InjectEx( Int32 InHostPID, Int32 InTargetPID, Int32 InWakeUpTID, Int32 InNativeOptions, String InLibraryPath_x86, String InLibraryPath_x64, Boolean InCanBypassWOW64, Boolean InCanCreateService, params Object[] InPassThruArgs) { RemoteHooking.InjectEx( InHostPID, InTargetPID, InWakeUpTID, InNativeOptions, InLibraryPath_x86, InLibraryPath_x64, InCanBypassWOW64, InCanCreateService, InPassThruArgs); }
private static void Install() { lock (ThreadSafe) { 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; } } } }
public static int Main(String InParam) { HelperServiceInterface Interface; String[] Params; String HostChannel; Assembly UserAssembly = null; Type EntryPoint = null; if (InParam == null) { return(-1); } /* * We will now connect to our hooking host. This is to provide extensive * error information. */ try { Params = InParam.Split('|'); if (Params.Length != 4) { return(-1); } HostChannel = Params[0]; Interface = RemoteHooking.IpcConnectClient <HelperServiceInterface>(HostChannel); // ensure connection... Interface.Ping(); if (!ConnectedChannels.Contains(HostChannel)) { ConnectedChannels.Add(HostChannel); return(0); } } catch (Exception ExtInfo) { Config.PrintError(ExtInfo.ToString()); return(-2); } try { /* * After this we are ready to load the user supplied library. */ String UserLibrary = Params[1]; String InfoPtr = Params[3]; List <Object> UserParams = new List <object>(); Object Instance = null; RemoteHooking.SetWakeUpThreadID(Int32.Parse(Params[2])); try { UserAssembly = Assembly.LoadWithPartialName(UserLibrary); // search for user library entry point... Type[] ExportedTypes = UserAssembly.GetExportedTypes(); for (int iType = 0; iType < ExportedTypes.Length; iType++) { EntryPoint = ExportedTypes[iType]; if (EntryPoint.GetInterface("EasyHook.IEntryPoint") != null) { break; } EntryPoint = null; } if (EntryPoint == null) { throw new EntryPointNotFoundException("The given user library does not export a proper type implementing the 'IEasyHookInjection' interface."); } // parse injection information (should work always as there is nothing tricky about it)... RemoteHooking.IContext Context = RemoteHooking.QueryContext(InfoPtr); // assemble user parameters and initialize library... BinaryFormatter Format = new BinaryFormatter(); UserParams.Add(Context); try { UserParams.AddRange((Object[])Format.Deserialize(new MemoryStream(Context.UserData))); } catch (Exception ExtInfo) { throw new ArgumentException("Unable to deserialize user supplied argument list.", ExtInfo); } Instance = EntryPoint.InvokeMember(null, BindingFlags.Public | BindingFlags.Instance | BindingFlags.CreateInstance, null, null, UserParams.ToArray()); // notify the host about successful injection... Interface.InjectionCompleted(RemoteHooking.GetCurrentProcessId()); } catch (Exception ExtInfo) { // we will now get extensive error information on host side... try { Interface.InjectionException(RemoteHooking.GetCurrentProcessId(), ExtInfo); } finally { Instance = null; Release(EntryPoint); } return(-1); } try { /* * After this it is safe to enter the main method, which will block until assembly unloading... * From now on the user library has to take care about error reporting! */ EntryPoint.InvokeMember("Run", BindingFlags.Public | BindingFlags.Instance | BindingFlags.ExactBinding | BindingFlags.InvokeMethod, null, Instance, UserParams.ToArray()); } finally { Instance = null; Release(EntryPoint); } } catch (Exception ExtInfo) { Config.PrintWarning(ExtInfo.ToString()); return(-1); } finally { if (ConnectedChannels.Contains(HostChannel)) { ConnectedChannels.Remove(HostChannel); } } return(0); }
/// <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); }
#pragma warning disable 0028 public static int Main(String InParam) { HelperServiceInterface Interface; Assembly UserAssembly = null; Type EntryPoint = null; ManagedRemoteInfo RemoteInfo; REMOTE_ENTRY_INFO UnmanagedInfo = new REMOTE_ENTRY_INFO(); if (InParam == null) { return(0); } /* * We will now connect to our hooking host. This is to provide extensive * error information. */ try { Marshal.PtrToStructure( (IntPtr)Int64.Parse(InParam, System.Globalization.NumberStyles.HexNumber), UnmanagedInfo); Byte[] PassThruBytes = new Byte[UnmanagedInfo.UserDataSize]; MemoryStream PassThruStream = new MemoryStream(); BinaryFormatter Format = new BinaryFormatter(); // Workaround for deserialization when not using GAC registration Format.Binder = new AllowAllAssemblyVersionsDeserializationBinder(); Marshal.Copy(UnmanagedInfo.UserData, PassThruBytes, 0, UnmanagedInfo.UserDataSize); PassThruStream.Write(PassThruBytes, 0, PassThruBytes.Length); PassThruStream.Position = 0; RemoteInfo = (ManagedRemoteInfo)Format.Deserialize(PassThruStream); Interface = RemoteHooking.IpcConnectClient <HelperServiceInterface>(RemoteInfo.ChannelName); // ensure connection... Interface.Ping(); if (!ConnectedChannels.Contains(RemoteInfo.ChannelName)) { ConnectedChannels.Add(RemoteInfo.ChannelName); return(1); } } catch (Exception ExtInfo) { Config.PrintError(ExtInfo.ToString()); return(0); } try { // adjust host PID in case of WOW64 bypass and service help... UnmanagedInfo.m_HostPID = RemoteInfo.HostPID; // prepare parameter array Object[] ParamArray = new Object[1 + RemoteInfo.UserParams.Length]; ParamArray[0] = (RemoteHooking.IContext)UnmanagedInfo; for (int i = 0; i < RemoteInfo.UserParams.Length; i++) { ParamArray[i + 1] = RemoteInfo.UserParams[i]; } /* * After this we are ready to load the user supplied library. */ Object Instance = null; try { // First attempt to load the library using its full name (e.g. strong name) if (!String.IsNullOrEmpty(RemoteInfo.UserLibraryName)) { try { UserAssembly = Assembly.Load(RemoteInfo.UserLibraryName); Config.PrintComment("SUCCESS: Assembly.Load({0})", RemoteInfo.UserLibraryName); } catch (Exception e) { Config.PrintWarning("FAIL: Assembly.Load({0}) - {1}", RemoteInfo.UserLibraryName, e.ToString()); } } // If loading by strong name failed, attempt to load the assembly from its file location if (UserAssembly == null) { try { UserAssembly = Assembly.LoadFrom(RemoteInfo.UserLibrary); Config.PrintComment("SUCCESS: Assembly.LoadFrom({0})", RemoteInfo.UserLibrary); } catch (Exception e) { Config.PrintWarning("FAIL: Assembly.LoadFrom({0}) - {1}", RemoteInfo.UserLibrary, e.ToString()); } } if (UserAssembly == null) { Config.PrintError("Could not load assembly {0}, {1}", RemoteInfo.UserLibrary, RemoteInfo.UserLibraryName); return(0); } // Only attempt to deserialise parameters after we have loaded the UserAssembly // this allows types from the UserAssembly to be passed as parameters BinaryFormatter format = new BinaryFormatter(); format.Binder = new AllowAllAssemblyVersionsDeserializationBinder(UserAssembly); for (int i = 1; i < ParamArray.Length; i++) { using (MemoryStream ms = new MemoryStream((byte[])ParamArray[i])) { ParamArray[i] = format.Deserialize(ms); } } // search for user library entry point... Type[] ExportedTypes = UserAssembly.GetExportedTypes(); for (int iType = 0; iType < ExportedTypes.Length; iType++) { EntryPoint = ExportedTypes[iType]; if (EntryPoint.GetInterface("EasyHook.IEntryPoint") != null) { break; } EntryPoint = null; } if (EntryPoint == null) { throw new EntryPointNotFoundException("The given user library does not export a proper type implementing the 'EasyHook.IEntryPoint' interface."); } // test for strictly typed Run() method MethodInfo Run = EntryPoint.GetMethod("Run", BindingFlags.Public | BindingFlags.Instance); if (Run != null) { if (ParamArray.Length != Run.GetParameters().Length) { throw new MissingMethodException("The given user library does export a Run() method in the 'EasyHook.IEntryPoint' interface, but the parameter count does not match!"); } for (int i = 0; i < ParamArray.Length; i++) { var param = Run.GetParameters()[i]; if (param.ParameterType.IsByRef && ParamArray[i] == null) // allow null parameter values { continue; } if (!param.ParameterType.IsInstanceOfType(ParamArray[i])) { Config.PrintError("Run() parameter {0} type {1}, does not match input parameter type {2}", i, param.ParameterType.AssemblyQualifiedName, ParamArray[i].GetType().AssemblyQualifiedName); throw new MissingMethodException( "The given user library does export a Run() method in the 'EasyHook.IEntryPoint' interface, but the parameter types do not match!"); } } } else { throw new MissingMethodException("The given user library does not export a proper Run() method in the 'EasyHook.IEntryPoint' interface."); } // assemble user parameters and initialize library... Instance = EntryPoint.InvokeMember(null, BindingFlags.Public | BindingFlags.Instance | BindingFlags.CreateInstance, null, null, ParamArray); // notify the host about successful injection... Interface.InjectionCompleted(RemoteHooking.GetCurrentProcessId()); } catch (Exception ExtInfo) { // we will now get extensive error information on host side... try { Interface.InjectionException(RemoteHooking.GetCurrentProcessId(), ExtInfo); } finally { Instance = null; Release(EntryPoint); } return(-1); } try { /* * After this it is safe to enter the main method, which will block until assembly unloading... * From now on the user library has to take care about error reporting! */ EntryPoint.InvokeMember("Run", BindingFlags.Public | BindingFlags.Instance | BindingFlags.ExactBinding | BindingFlags.InvokeMethod, null, Instance, ParamArray); } finally { Instance = null; Release(EntryPoint); } } catch (Exception ExtInfo) { Config.PrintWarning(ExtInfo.ToString()); return(-1); } finally { if (ConnectedChannels.Contains(RemoteInfo.ChannelName)) { ConnectedChannels.Remove(RemoteInfo.ChannelName); } } return(0); }
#pragma warning disable 0028 public static int Main(String InParam) { HelperServiceInterface Interface; Assembly UserAssembly = null; Type EntryPoint = null; ManagedRemoteInfo RemoteInfo; REMOTE_ENTRY_INFO UnmanagedInfo = new REMOTE_ENTRY_INFO(); if (InParam == null) { return(0); } /* * We will now connect to our hooking host. This is to provide extensive * error information. */ try { Marshal.PtrToStructure( (IntPtr)Int64.Parse(InParam, System.Globalization.NumberStyles.HexNumber), UnmanagedInfo); Byte[] PassThruBytes = new Byte[UnmanagedInfo.UserDataSize]; MemoryStream PassThruStream = new MemoryStream(); BinaryFormatter Format = new BinaryFormatter(); Marshal.Copy(UnmanagedInfo.UserData, PassThruBytes, 0, UnmanagedInfo.UserDataSize); PassThruStream.Write(PassThruBytes, 0, PassThruBytes.Length); PassThruStream.Position = 0; RemoteInfo = (ManagedRemoteInfo)Format.Deserialize(PassThruStream); Interface = RemoteHooking.IpcConnectClient <HelperServiceInterface>(RemoteInfo.ChannelName); // ensure connection... Interface.Ping(); if (!ConnectedChannels.Contains(RemoteInfo.ChannelName)) { ConnectedChannels.Add(RemoteInfo.ChannelName); return(1); } } catch (Exception ExtInfo) { Config.PrintError(ExtInfo.ToString()); return(0); } try { // adjust host PID in case of WOW64 bypass and service help... UnmanagedInfo.m_HostPID = RemoteInfo.HostPID; // prepare parameter array Object[] ParamArray = new Object[1 + RemoteInfo.UserParams.Length]; ParamArray[0] = (RemoteHooking.IContext)UnmanagedInfo; for (int i = 0; i < RemoteInfo.UserParams.Length; i++) { ParamArray[i + 1] = RemoteInfo.UserParams[i]; } /* * After this we are ready to load the user supplied library. */ Object Instance = null; try { UserAssembly = Assembly.LoadWithPartialName(RemoteInfo.UserLibrary); // search for user library entry point... Type[] ExportedTypes = UserAssembly.GetExportedTypes(); for (int iType = 0; iType < ExportedTypes.Length; iType++) { EntryPoint = ExportedTypes[iType]; if (EntryPoint.GetInterface("EasyHook.IEntryPoint") != null) { break; } EntryPoint = null; } if (EntryPoint == null) { throw new EntryPointNotFoundException("The given user library does not export a proper type implementing the 'EasyHook.IEntryPoint' interface."); } // test for strictly typed Run() method MethodInfo Run = EntryPoint.GetMethod("Run", BindingFlags.Public | BindingFlags.Instance); if (Run != null) { if (ParamArray.Length != Run.GetParameters().Length) { throw new MissingMethodException("The given user library does export a Run() method in the 'EasyHook.IEntryPoint' interface, but the parameter count does not match!"); } for (int i = 0; i < ParamArray.Length; i++) { if (!Run.GetParameters()[i].ParameterType.IsInstanceOfType(ParamArray[i])) { throw new MissingMethodException("The given user library does export a Run() method in the 'EasyHook.IEntryPoint' interface, but the parameter types do not match!"); } } } else { throw new MissingMethodException("The given user library does not export a proper Run() method in the 'EasyHook.IEntryPoint' interface."); } // assemble user parameters and initialize library... Instance = EntryPoint.InvokeMember(null, BindingFlags.Public | BindingFlags.Instance | BindingFlags.CreateInstance, null, null, ParamArray); // notify the host about successful injection... Interface.InjectionCompleted(RemoteHooking.GetCurrentProcessId()); } catch (Exception ExtInfo) { // we will now get extensive error information on host side... try { Interface.InjectionException(RemoteHooking.GetCurrentProcessId(), ExtInfo); } finally { Instance = null; Release(EntryPoint); } return(-1); } try { /* * After this it is safe to enter the main method, which will block until assembly unloading... * From now on the user library has to take care about error reporting! */ EntryPoint.InvokeMember("Run", BindingFlags.Public | BindingFlags.Instance | BindingFlags.ExactBinding | BindingFlags.InvokeMethod, null, Instance, ParamArray); } finally { Instance = null; Release(EntryPoint); } } catch (Exception ExtInfo) { Config.PrintWarning(ExtInfo.ToString()); return(-1); } finally { if (ConnectedChannels.Contains(RemoteInfo.ChannelName)) { ConnectedChannels.Remove(RemoteInfo.ChannelName); } } return(0); }
/// <summary> /// Dont use this method, refer to <see cref="RemoteHooking.Impersonate(ImpersonationHandler)"/> /// for a supported public method! /// </summary> /// <param name="InClientTID"> /// The ID of the thread whose privileges should be upgraded to LOCAL-SYSTEM. /// </param> public void Impersonate(Int32 InClientTID) { RemoteHooking.Impersonate(InClientTID); }