Example #1
0
        /// <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);
        }
Example #2
0
        /// <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);
        }
Example #3
0
        /// <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);
        }
Example #4
0
 /// <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));
 }
Example #5
0
 /// <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));
 }
Example #6
0
 /// <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));
 }
Example #7
0
 /// <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));
 }
Example #8
0
 /// <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));
 }