Last active
May 11, 2023 14:40
-
-
Save susMdT/ef0c7cf73c8815d5d2f7ce503036e847 to your computer and use it in GitHub Desktop.
Based on NaxAlpha's work
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.Diagnostics; | |
using System.Reflection; | |
using System.Runtime.CompilerServices; | |
using System.Runtime.InteropServices; | |
namespace ShittyHook | |
{ | |
internal class Program | |
{ | |
static int hooks = 0; | |
[UnmanagedFunctionPointer(CallingConvention.StdCall)] | |
public delegate uint NtAllocateVirtualMemory( | |
IntPtr ProcessHandle, | |
ref IntPtr BaseAddress, | |
IntPtr ZeroBits, | |
ref IntPtr RegionSize, | |
UInt32 AllocationType, | |
UInt32 Protect | |
); | |
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] | |
static extern IntPtr GetProcAddress(IntPtr hModule, string procName); | |
public static void Main() | |
{ | |
IntPtr ntdll = default; | |
foreach (ProcessModule mod in Process.GetCurrentProcess().Modules) | |
{ | |
if (mod.ModuleName.ToLower() == "ntdll.dll") | |
ntdll = mod.BaseAddress; | |
} | |
IntPtr pOGAlloc = GetProcAddress(ntdll, "NtAllocateVirtualMemory"); | |
// Why do i have to jit the hook now?? | |
MethodInfo method = typeof(Program).GetMethod(nameof(NtAllocateVirtualMemoryHook), BindingFlags.Static | BindingFlags.Public); | |
RuntimeHelpers.PrepareMethod(method.MethodHandle); | |
Console.WriteLine("Our hooked NtAllocateVirtualMemory is at 0x{0:X}", (long)method.MethodHandle.GetFunctionPointer()); | |
using (FxHook hook = new FxHook(pOGAlloc, (NtAllocateVirtualMemory)NtAllocateVirtualMemoryHook)) | |
{ | |
hook.Install(); | |
// Calling the ntallocate from ntdll, which is hooked | |
object[] allocArgs = { (IntPtr)(-1), IntPtr.Zero, IntPtr.Zero, (IntPtr)420420, (UInt32)0x3000, (UInt32)0x420 }; | |
uint ntstatus = (uint)Marshal.GetDelegateForFunctionPointer<NtAllocateVirtualMemory>(pOGAlloc).DynamicInvoke(allocArgs); | |
Console.ReadKey(); | |
Console.WriteLine("Going to do a managed allocation"); | |
IntPtr m = Marshal.AllocHGlobal(12); | |
Console.WriteLine("Managed allocation to 0x{0:X}", (long)m); | |
Console.ReadKey(); | |
} | |
} | |
public static uint NtAllocateVirtualMemoryHook(IntPtr ProcessHandle, ref IntPtr BaseAddress, IntPtr ZeroBits, ref IntPtr RegionSize, UInt32 AllocationType, UInt32 Protect) | |
{ | |
if (hooks != 0) | |
{ | |
Console.WriteLine($"This is hooked call number {hooks+1}"); | |
} | |
if (Protect == 0x420) | |
{ | |
Console.WriteLine("============DETECTED 0x420============="); | |
Console.WriteLine("Why did you pass 0x420 as the protection? Im returned code 0x6969"); | |
Console.WriteLine("======================================="); | |
return (uint)0x6969; | |
} | |
Marshal.Copy(FxHook.src, 0, FxHook.addr, FxHook.nBytes); // temporarily remove hook | |
// Console.WriteLine() apparently will make a stack overflow the first time this hook is called for some reason | |
Console.WriteLine("==========RECEIVED NTALLOCATE=========="); | |
Console.WriteLine("Handle 0x{0:X}", (long)ProcessHandle); | |
Console.WriteLine("BaseAddress 0x{0:X}", (long)BaseAddress); | |
Console.WriteLine("RegionSize 0x{0:X}", (long)RegionSize); | |
Console.WriteLine("AllocationType 0x{0:X}", (long)AllocationType); | |
Console.WriteLine("Protect 0x{0:X}", (long)Protect); | |
Console.WriteLine("======================================="); | |
object[] args = { ProcessHandle, BaseAddress, ZeroBits, RegionSize, AllocationType, Protect }; | |
uint retVal = (uint)Marshal.GetDelegateForFunctionPointer(FxHook.addr, typeof(NtAllocateVirtualMemory)).DynamicInvoke(args); | |
Marshal.Copy(FxHook.dst, 0, FxHook.addr, FxHook.nBytes); // restore hook | |
BaseAddress = (IntPtr)args[1]; | |
RegionSize = (IntPtr)args[3]; | |
hooks += 1; | |
return retVal; | |
} | |
} | |
public class FxHook : IDisposable | |
{ | |
public const int nBytes = 13; | |
// movabs r11, address | |
// jmp r11 | |
public static IntPtr addr; // the function we are hooking | |
Protection old; | |
public static byte[] src = new byte[13]; //source bytes | |
public static byte[] dst = new byte[13]; //trampoline | |
public FxHook(IntPtr source, IntPtr destination) | |
{ | |
Console.WriteLine("Our delegate is at 0x{0:X}", (long)destination); | |
VirtualProtect(source, nBytes, Protection.PAGE_EXECUTE_READWRITE, out old); | |
Marshal.Copy(source, src, 0, nBytes); //copy the original 13 we will patch | |
dst[0] = 0x49; | |
dst[1] = 0XBB; | |
var dx = BitConverter.GetBytes((long)destination); | |
Array.Copy(dx, 0, dst, 2, 8); | |
dst[10] = 0x41; | |
dst[11] = 0xFF; | |
dst[12] = 0xE3; | |
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 | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment