/// <summary> /// Installs an unmanaged hook. After this you'll have to activate it by setting a proper <see cref="ThreadACL"/>. /// <see cref="HookRuntimeInfo"/> WON'T be supported! Refer to the native "DetourBarrierXxx" APIs to /// access unmanaged hook runtime information. /// </summary> /// <remarks> /// <para> /// Note that not all entry points are hookable! In general methods like <c>CreateFileW</c> /// won't cause any trouble. But there may be methods that are not hookable because their /// entry point machine code is not eligable to be hooked. You should test all hooks on /// common environments like "Windows XP x86/x64 SP1/SP2/SP3" and "Windows Vista x86/x64 (SP1)". /// This is the only way to ensure that your application will work well on most machines. /// </para><para> /// Unmanaged hooks will require a native DLL which handles the requests. This way /// you will get a high-performance interface, because /// a switch from unmanaged to managed code seems to be rather time consuming without doing anything /// useful (at least nothing visible); so a hook omitting this switch will be handled one or two /// orders of magnitudes faster until finally your handler gains execution. But as a managed hook is still executed /// within at last 1000 nano-seconds, even the "slow" managed implementation will be fast enough in most /// cases. With C++.NET you would be able to provide such native high-speed hooks for frequently /// called API methods, while still using managed ones for usual API methods, within a single assembly! /// A pure unmanaged, empty hook executes in approx. 70 nano-seconds, which is incredible fast /// considering the thread deadlock barrier and thread ACL negotiation that are already included in this benchmark! /// </para> /// </remarks> /// <param name="targetProcess">A target entry point that should be hooked.</param> /// <param name="newProcess">A handler with the same signature as the original entry point /// that will be invoked for every call that has passed the Thread Deadlock Barrier and various integrity checks.</param> /// <param name="callback">An uninterpreted callback that will later be available through <c>DetourBarrierGetCallback()</c>.</param> /// <returns> /// A handle to the newly created hook. /// </returns> /// <exception cref="OutOfMemoryException"> /// Not enough memory available to complete the operation. On 64-Bit this may also indicate /// that no memory can be allocated within a 31-Bit boundary around the given entry point. /// </exception> /// <exception cref="ArgumentException"> /// The given function pointer does not map to executable memory (valid machine code) or /// you passed <c>null</c> as delegate. /// </exception> /// <exception cref="NotSupportedException"> /// The given entry point contains machine code that can not be hooked. /// </exception> /// <exception cref="InsufficientMemoryException"> /// The maximum amount of hooks has been installed. This is currently set to MAX_HOOK_COUNT (1024). /// </exception> public static LocalHook CreateUnmanaged( IntPtr targetProcess, IntPtr newProcess, IntPtr callback) { LocalHook Result = new LocalHook(); Result._callback = callback; Result._handle = Marshal.AllocCoTaskMem(IntPtr.Size); Result._selfHandle = GCHandle.Alloc(Result, GCHandleType.Weak); Marshal.WriteIntPtr(Result._handle, IntPtr.Zero); try { NativeAPI.DetourInstallHook( targetProcess, newProcess, callback, Result._handle); } catch (Exception e) { Marshal.FreeCoTaskMem(Result._handle); Result._handle = IntPtr.Zero; Result._selfHandle.Free(); throw e; } Result._threadACL = new HookAccessControl(Result._handle); return(Result); }
/// <summary> /// Installs an unmanaged hook using the pointer to a hook handler. /// </summary> /// <param name="targetFunction">The target function to install the detour at.</param> /// <param name="detourFunction">The hook handler which intercepts the target function.</param> /// <param name="callback">A context object that will be available for reference inside the detour.</param> /// <returns>The handle to the function hook.</returns> public new static LocalHook <T> CreateUnmanaged(IntPtr targetFunction, IntPtr detourFunction, IntPtr callback) { var hook = new LocalHook <T> { Callback = callback, TargetAddress = targetFunction, Handle = Marshal.AllocCoTaskMem(IntPtr.Size) }; hook.SelfHandle = GCHandle.Alloc(hook, GCHandleType.Weak); Marshal.WriteIntPtr(hook.Handle, IntPtr.Zero); try { NativeApi.DetourInstallHook( targetFunction, detourFunction, callback, hook.Handle); } catch (Exception e) { Marshal.FreeCoTaskMem(hook.Handle); hook.Handle = IntPtr.Zero; hook.SelfHandle.Free(); throw e; } hook.AccessControl = new HookAccessControl(hook.Handle); return(hook); }
/// <summary> /// Installs a managed hook. After this you'll have to activate it by setting a proper <see cref="ThreadACL"/>. /// </summary> /// <remarks> /// <para> /// Note that not all entry points are hookable! In general methods like <c>CreateFileW</c> /// won't cause any trouble. But there might be methods that are not hookable because their /// entry point machine code is not eligable to be hooked. You should test all hooks on /// common environments like "Windows XP x86/x64 SP2/SP3" and "Windows Vista x86/x64 (SP1)". /// This is the only way to ensure that your application will work well on most machines. /// </para><para> /// Your handler delegate has to use the <see cref="UnmanagedFunctionPointerAttribute"/> and /// shall map to the same native method signature, otherwise the application will crash! The best /// way is to use predefined delegates used in related P-Invoke implementations usually found with Google. /// If you know how to write such native delegates you won't need internet resources of course. /// I recommend using C++.NET which allows you to just copy the related windows API to your managed /// class and thread it as delegate without any changes. This will also speed up the whole thing /// because no unnecessary marshalling is required! C++.NET is also better in most cases because you /// may access the whole native windows API from managed code without any effort what significantly eases /// writing of hook handlers. /// </para> /// <para> /// The given delegate is automatically prevented from being garbage collected until the hook itself /// is collected... /// </para> /// </remarks> /// <param name="targetProcess">A target entry point that should be hooked.</param> /// <param name="newProcess">A handler with the same signature as the original entry point /// that will be invoked for every call that has passed the Fiber Deadlock Barrier and various integrity checks.</param> /// <param name="callback">An uninterpreted callback that will later be available through <see cref="HookRuntimeInfo.Callback"/>.</param> /// <returns> /// A handle to the newly created hook. /// </returns> /// <exception cref="OutOfMemoryException"> /// Not enough memory available to complete the operation. On 64-Bit this may also indicate /// that no memory can be allocated within a 31-Bit boundary around the given entry point. /// </exception> /// <exception cref="ArgumentException"> /// The given function pointer does not map to executable memory (valid machine code) or /// you passed <c>null</c> as delegate. /// </exception> /// <exception cref="NotSupportedException"> /// The given entry point contains machine code that can not be hooked. /// </exception> /// <exception cref="InsufficientMemoryException"> /// The maximum amount of hooks has been installed. This is currently set to MAX_HOOK_COUNT (1024). /// </exception> public static LocalHook Create( IntPtr targetProcess, Delegate newProcess, object callback) { LocalHook Result = new LocalHook(); Result._callback = callback; Result._hookProc = newProcess; Result._handle = Marshal.AllocCoTaskMem(IntPtr.Size); Result._selfHandle = GCHandle.Alloc(Result, GCHandleType.Weak); Marshal.WriteIntPtr(Result._handle, IntPtr.Zero); try { NativeAPI.DetourInstallHook( targetProcess, Marshal.GetFunctionPointerForDelegate(Result._hookProc), GCHandle.ToIntPtr(Result._selfHandle), Result._handle); } catch (Exception e) { Marshal.FreeCoTaskMem(Result._handle); Result._handle = IntPtr.Zero; Result._selfHandle.Free(); throw e; } Result._threadACL = new HookAccessControl(Result._handle); return(Result); }
/// <summary> /// Create a managed hook. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="targetFunction"></param> /// <param name="detourFunction"></param> /// <param name="callback"></param> /// <returns></returns> public static IHook <T> CreateHook <T>(IntPtr targetFunction, T detourFunction, object callback = null) where T : class { return(LocalHook <T> .Create(targetFunction, detourFunction as Delegate, callback)); }
/// <summary> /// Create an unmanaged hook /// </summary> /// <typeparam name="T"></typeparam> /// <param name="targetFunction"></param> /// <param name="detourFunction"></param> /// <returns></returns> public static IHook <T> CreateHook <T>(IntPtr targetFunction, IntPtr detourFunction) where T : class { return(LocalHook <T> .CreateUnmanaged(targetFunction, detourFunction, IntPtr.Zero)); }
/// <summary> /// Create an unmanaged hook. /// </summary> /// <param name="targetFunction"></param> /// <param name="detourFunction"></param> /// <returns></returns> public static IHook CreateHook(IntPtr targetFunction, IntPtr detourFunction) { return(LocalHook.CreateUnmanaged(targetFunction, detourFunction, IntPtr.Zero)); }
/// <summary> /// Create a managed hook. /// </summary> /// <param name="targetFunction"></param> /// <param name="detourFunction"></param> /// <param name="callback"></param> /// <returns></returns> public static IHook CreateHook(IntPtr targetFunction, Delegate detourFunction, object callback) { return(LocalHook.Create(targetFunction, detourFunction as Delegate, callback)); }
/// <summary> /// Create an unmanaged hook. /// </summary> /// <typeparam name="TDelegate">The delegate type representing the detoured function signature.</typeparam> /// <param name="targetFunction">The target function address that will be detoured.</param> /// <param name="detourFunction">The detour function that will be called instead of the function at <paramref name="targetFunction"/>.</param> /// <param name="callback">An object that is associated with the hook and can be accessed by the detour function.</param> /// <returns>The handle to the function hook.</returns> public static IHook <TDelegate> CreateHook <TDelegate>(IntPtr targetFunction, IntPtr detourFunction, IntPtr?callback = null) where TDelegate : class { return(LocalHook <TDelegate> .CreateUnmanaged(targetFunction, detourFunction, callback ?? IntPtr.Zero)); }