PolyHook2.NET.Attributes
1.0.0
dotnet add package PolyHook2.NET.Attributes --version 1.0.0
NuGet\Install-Package PolyHook2.NET.Attributes -Version 1.0.0
<PackageReference Include="PolyHook2.NET.Attributes" Version="1.0.0" />
<PackageVersion Include="PolyHook2.NET.Attributes" Version="1.0.0" />
<PackageReference Include="PolyHook2.NET.Attributes" />
paket add PolyHook2.NET.Attributes --version 1.0.0
#r "nuget: PolyHook2.NET.Attributes, 1.0.0"
#:package PolyHook2.NET.Attributes@1.0.0
#addin nuget:?package=PolyHook2.NET.Attributes&version=1.0.0
#tool nuget:?package=PolyHook2.NET.Attributes&version=1.0.0
<div align="center">
<img src="logo.png" alt="Logo (original by Darksuger)" width="128" height="128"/>
PolyHook2.NET.Attributes
PolyHook2.NET.Attributes is a companion library for PolyHook2.NET that enables high-performance, attribute-based hooking utilizing C# Source Generators. <br/>
| CI/CD | Release | NuGet | Tech Stack | Platform | License |
|---|---|---|---|---|---|
</div>
This project provides a declarative way to create function detours using PolyHook2.NET. Instead of manually managing detour objects, trampoline delegates, and function pointers, you can simply decorate a C# method with an attribute. A source generator automatically writes the high-performance boilerplate code for you at compile time.
Features
- Declarative Hooking: Define detours with a simple
[X64ManagedFunctionDetourAOB]attribute. - Zero-Overhead Trampoline: The original function is provided to your hook via a strongly-typed
Func<>delegate, which compiles down to a direct, high-performance call. No runtime reflection or dictionary lookups. - AOB Scanning: Automatically find function addresses at runtime using Array of Bytes (AOB) patterns, making your hooks more resilient to module updates.
- Supports Calling Conventions: Easily specify calling conventions like
Stdcallusing moderntypeof(CallConvStdcall)syntax. - Automatic Management: The source generator creates
ApplyHooks()andRemoveHooks()methods for you to easily activate and clean up all detours.
Building the Project
The project is configured for a straightforward build process using standard .NET tooling. No special dependencies outside of the .NET SDK are required.
Prerequisites
- .NET 8 SDK (or later): The SDK is required to build, test, and pack the project. The .NET 8 SDK includes the necessary compilers and targeting packs for
.NET Standard 2.0. Download .NET SDK.
Building with Visual Studio / Rider
Clone the repository:
git clone https://gitlab.com/Rawra/polyhook2.net.attributes.gitNavigate to the directory:
cd PolyHook2.NETOpen the Solution: Open the
PolyHook2.NET.Attributes.slnfile in your IDE.Build the Solution:
- Set the solution configuration to Release.
- Build the solution using the build command (e.g.,
Ctrl+Shift+Bin Visual Studio or from theBuildmenu).
Building with the Command Line (.NET CLI)
Clone the repository:
git clone https://gitlab.com/Rawra/polyhook2.net.attributes.gitNavigate to the directory:
cd PolyHook2.NET.AttributesRestore NuGet Packages: Run the
restorecommand to download all required dependencies.dotnet restoreBuild the Project: Execute the
buildcommand. Using theReleaseconfiguration is recommended for an optimized build.dotnet build --configuration Release
Build Output
After a successful build, the compiled artifacts will be located in the bin/ folder at the root of the solution directory. The structure will be as follows:
/bin
└───/Release
├───/netstandard2.0
├─── PolyHook2.NET.Attributes.dll
└─── PolyHook2.NET.Detour.Generator.dll
Installation
Install the NuGet package into your project:
dotnet add package PolyHook2.NET.Attributes
Example Usage
This example demonstrates how to intercept the WinAPI Beep function, modify its arguments, and then call the original function.
1. Define Your Hooks in a partial static Class
Create a partial static class to contain your hook methods. Decorate your hook with the [X64ManagedFunctionDetourAOB] attribute. The last parameter of your hook method must be a Func<> or Action<> delegate whose signature matches the original function you are hooking. This parameter will be automatically populated with the trampoline to the original function.
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using PolyHook2.Attributes;
public static partial class MyHooks
{
// Hook the WinAPI Beep function from kernelbase.dll, specifying its Stdcall convention.
// The AOB pattern is for a specific version of Windows and may need to be updated.
// x64 win11: 48 8B C4 48 89 58 08 48 89 70 10 57 48 83 EC ?? 8B FA 8B // from kernelbase.dll
// x86 win11: 6A ?? 68 ?? ?? ?? ?? E8 ?? ?? ?? ?? 33 F6 89 75 E0 // from kernelbase.dll
[X64ManagedFunctionDetourAOB("48 8B C4 48 89 58 08 48 89 70 10 57 48 83 EC ?? 8B FA 8B", "kernelbase.dll", typeof(CallConvStdcall))]
[return: MarshalAs(UnmanagedType.Bool)]
private static bool HookedBeep(uint dwFreq, uint dwDuration, Func<uint, uint, bool> original)
{
// This is your hook logic.
Console.WriteLine($"Beep hooked! Original Frequency: {dwFreq}. Overriding duration to 5000ms.");
// Call the original Beep function via the injected 'original' delegate,
// but with modified arguments.
bool originalResult = original(dwFreq, 5000);
// You can also modify the return value.
return originalResult;
}
}
2. Apply the Hooks in Your Application
In your application's entry point, simply call the ApplyHooks() method that the source generator created for you on your partial class.
using System.Runtime.InteropServices;
namespace TestRunner;
public static class Program
{
public static void Main()
{
// This single call finds and applies all hooks defined in the MyHooks class.
MyHooks.ApplyHooks();
Console.WriteLine("\nCalling the original Beep function (now hooked)...");
Beep(500, 200); // The hook will change the duration to 5000ms.
Console.WriteLine("\nPress Enter to remove hooks and exit.");
Console.ReadLine();
MyHooks.RemoveHooks();
}
// P/Invoke for the original function so we can call it.
[DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool Beep(uint dwFreq, uint dwDuration);
}
How It Works
When you build your project, the PolyHook2.NET.Attributes source generator scans your code for the [X64ManagedFunctionDetourAOB] attribute. For each one it finds, it generates the other partial half of your class, containing:
- A non-generic delegate type required for native interop.
- A private static field to store the trampoline delegate.
- A wrapper method that is the actual target of the detour. This wrapper calls your hook method, "injecting" the trampoline delegate as the final parameter.
- The
ApplyHooks()andRemoveHooks()methods, which contain all the logic for AOB scanning, creating theX64ManagedFunctionDetourobject, and managing its lifetime.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- PolyHook2.NET (>= 1.0.6)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 232 | 9/22/2025 |