Skip to content

Instantly share code, notes, and snippets.

@NaxAlpha
Last active December 2, 2023 09:08
  • Star 22 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save NaxAlpha/144d1dd96c7d0ad29fe149e4063a8f25 to your computer and use it in GitHub Desktop.
Windows API Hook with C#
using System;
using System.Runtime.InteropServices;
public class FxHook:IDisposable {
const int nBytes = 5;
IntPtr addr;
Protection old;
byte[] src = new byte[5];
byte[] dst = new byte[5];
public FxHook(IntPtr source, IntPtr destination) {
VirtualProtect(source, nBytes, Protection.PAGE_EXECUTE_READWRITE, out old);
Marshal.Copy(source, src, 0, nBytes);
dst[0] = 0xE9;
var dx = BitConverter.GetBytes((int)destination - (int)source - nBytes);
Array.Copy(dx, 0, dst, 1, nBytes-1);
addr = source;
}
public FxHook(IntPtr source, Delegate destination) :
this(source, Marshal.GetFunctionPointerForDelegate(destination)) {
}
public void Install() {
Marshal.Copy(dst, 0, addr, nBytes);
}
public void Uninstall() {
Marshal.Copy(src, 0, addr, nBytes);
}
public void Dispose() {
Uninstall();
Protection x;
VirtualProtect(addr, nBytes, old, out x);
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize,
Protection flNewProtect, out Protection lpflOldProtect);
public enum Protection {
PAGE_NOACCESS = 0x01,
PAGE_READONLY = 0x02,
PAGE_READWRITE = 0x04,
PAGE_WRITECOPY = 0x08,
PAGE_EXECUTE = 0x10,
PAGE_EXECUTE_READ = 0x20,
PAGE_EXECUTE_READWRITE = 0x40,
PAGE_EXECUTE_WRITECOPY = 0x80,
PAGE_GUARD = 0x100,
PAGE_NOCACHE = 0x200,
PAGE_WRITECOMBINE = 0x400
}
}
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
class Program {
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);
// Function to be hooked
[DllImport("kernel32.dll")]
static extern void Sleep(uint dwMilliseconds);
// Must create delegate type
// Marshal.GetFunctionPointerForDelegate requires non generic delegate tpe
delegate void SleepFx(uint ms);
static FxHook hook;
// Hook function must be of same signature as of original function
static void Sleep2(uint ms) {
MessageBox.Show("Sleeping for: " + ms.ToString());
// Uninstall hook before calling real function otherwise stack overflow
hook.Uninstall();
Sleep(ms);
hook.Install();
}
static void Main(string[] args) {
var k32 = LoadLibrary("kernel32");
var slp = GetProcAddress(k32, "Sleep");
using(hook = new FxHook(slp, (SleepFx)Sleep2)) {
hook.Install();
Sleep(1000);
}
// This will call original sleep
Sleep(1000);
}
}
@Yoticc
Copy link

Yoticc commented Mar 5, 2023

Unfortunately this does not want to work in NativeAOT

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment