Windows API Hook with C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
Good work! I tried to hook remote process, and changed the code a little bit as following: public FxHook(IntPtr hProcess,IntPtr source, IntPtr destination) { VirtualProtectEx(hProcess,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; } But the memory is write protected and an exception is thrown when Marshal.Copy is called in the Install() function. Any idea?
you cant Marshal.Copy on remote process you need to use WriteProcessMemory API
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
Good work! I tried to hook remote process, and changed the code a little bit as following:
public FxHook(IntPtr hProcess,IntPtr source, IntPtr destination)
{
VirtualProtectEx(hProcess,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;
}
But the memory is write protected and an exception is thrown when Marshal.Copy is called in the Install() function.
Any idea?