Skip to content

Instantly share code, notes, and snippets.

@susMdT
Last active May 11, 2023 14:40
Show Gist options
  • Save susMdT/ef0c7cf73c8815d5d2f7ce503036e847 to your computer and use it in GitHub Desktop.
Save susMdT/ef0c7cf73c8815d5d2f7ce503036e847 to your computer and use it in GitHub Desktop.
Based on NaxAlpha's work
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