-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNaHook.cs
151 lines (138 loc) · 5.39 KB
/
NaHook.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// :::: ::: ::: ::::::::::: ::::::::: ::::::::::: ::: ::: ::: :::
// :+:+: :+: :+: :+: :+: :+: :+: :+: :+: :+: :+:+: :+:+:
// :+:+:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+:+ +:+
// +#+ +:+ +#+ +#++:++#++: +#+ +#++:++#: +#+ +#+ +:+ +#+ +:+ +#+
// +#+ +#+#+# +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+
// #+# #+#+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+#
// ### #### ### ### ### ### ### ########### ######## ### ###
// NaHook
// Native hooking lib
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Natrium
{
/// <summary>
/// Class for managing hooks
/// </summary>
public static class NaHook
{
[DllImport("kernel32.dll")]
internal static extern bool VirtualProtect(nint lpAddress, nuint dwSize, uint flNewProtect, out uint lpflOldProtect);
/// <summary>
/// List of hooks.
/// </summary>
public static Dictionary<string, IHook> Hooks = new();
/// <summary>
/// Hook into a native function, replacing it with the hook. Returns Hook, which is used to unhook and contains crucial information like the original method.
/// </summary>
/// <param name="NativeFunction">Function pointer for function to hook</param>
/// <param name="hook">Delegate of the hook</param>
/// <param name="Identifier">Key for the entry in Hooks dictionary</param>
/// <returns>Object representing hook</returns>
public static Hook<T> Hook<T>(IntPtr NativeFunction, T hook, string Identifier, bool AddToDict = true)
{
IntPtr HookPointer = Marshal.GetFunctionPointerForDelegate(hook);
return new(HookPointer, hook, GetBytes(NativeFunction,5), Identifier);
}
public static unsafe byte[] GetBytes(IntPtr NativeFunction, int x)
{
List<byte> LOriginalBytes = new();
byte[] OriginalBytes;
byte* p = (byte*)NativeFunction.ToPointer();
for (int i = 0; i < 5; i++)
{
LOriginalBytes.Add(p[x]);
}
return LOriginalBytes.ToArray();
}
}
/// <summary>
/// Interface of Hook<T> when you need to use the Hook object and dont know the type beforehand
/// </summary>
public interface IHook
{
void Rehook();
void Unhook();
void UnhookPerma();
}
/// <summary>
/// Instance of a hook.
/// </summary>
/// <typeparam name="T">Delegate type.</typeparam>
public class Hook<T> : IHook
{
public IntPtr JmpLocation;
public T HookFnc;
public byte[] OriginalFnc;
public string Identifier;
public bool Hooked;
public Hook(IntPtr jl, T hf, byte[] of, string identifier)
{
(JmpLocation, HookFnc, OriginalFnc, Identifier) = (jl, hf, of, identifier);
Rehook();
if (NaHook.Hooks.ContainsKey(Identifier))
NaHook.Hooks[Identifier].UnhookPerma();
NaHook.Hooks.Add(Identifier, this);
}
/// <summary>
/// Readd the previously removed hook
/// </summary>
/// <exception cref="System.ComponentModel.Win32Exception">Unknown windows error</exception>
public unsafe void Rehook()
{
if (Hooked)
throw new Exception("Already hooked");
uint OldProtect;
IntPtr HookPointer = Marshal.GetFunctionPointerForDelegate(HookFnc);
if (NaHook.VirtualProtect(JmpLocation, (UIntPtr)5, 0x40, out OldProtect))
{
byte* p = (byte*)JmpLocation.ToPointer();
OriginalFnc = NaHook.GetBytes(JmpLocation, 5);
*p = 0xE9; // JMP
*(int*)(p + 1) = (int)(HookPointer.ToInt64() - JmpLocation.ToInt64() - 5);
NaHook.VirtualProtect(JmpLocation, (UIntPtr)5, OldProtect, out _);
Hooked = true;
}
else
{
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
}
}
/// <summary>
/// Remove the hook and restore the bytes
/// </summary>
/// <exception cref="System.ComponentModel.Win32Exception">Unknown windows error</exception>
public unsafe void Unhook()
{
if (!Hooked)
throw new Exception("Already unhooked");
uint oldProtect;
if (NaHook.VirtualProtect(JmpLocation, (UIntPtr)5, 0x40, out oldProtect))
{
byte* p = (byte*)JmpLocation.ToPointer();
for (int i = 0; i < 5; i++)
{
p[i] = OriginalFnc[i];
}
NaHook.VirtualProtect(JmpLocation, (UIntPtr)5, oldProtect, out _);
Hooked = false;
}
else
{
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
}
}
/// <summary>
/// Unhooks and removes from the Hooks dict.
/// </summary>
public unsafe void UnhookPerma()
{
Unhook();
NaHook.Hooks.Remove(Identifier);
}
}
}