/// <summary> /// Remove protection from address and write value. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="address">Address to unprotect and write.</param> /// <param name="value">Value to write.</param> public static void UnprotectWrite <T>(IntPtr address, T value) where T : unmanaged { int size = Unsafe.SizeOf <T>(); if (OSHelper.IsWindows) { Kernel32.MemoryProtection oldFlags = Kernel32.VirtualProtect(address, size, Kernel32.MemoryProtection.READ_WRITE); Write(address, value); Kernel32.VirtualProtect(address, size, oldFlags); } else if (OSHelper.IsLinux) { byte[] byteValue; unsafe { void *ptr = Unsafe.AsPointer(ref value); byteValue = new Span <byte>(ptr, size).ToArray(); } lock (LockSelfMemLinux) { //Prevent segmentation fault. using FileStream fs = File.Open($"/proc/self/mem", FileMode.Open, FileAccess.ReadWrite); fs.Seek(address.ToInt64(), SeekOrigin.Begin); fs.Write(byteValue, 0, byteValue.Length); } } else { Mman.mprotect(address, (ulong)size, MmapProts.PROT_WRITE); Write(address, value); } }
/// <summary> /// Free memory trampoline. /// </summary> /// <param name="address"></param> public static void FreeTrampoline(IntPtr address) { if (OSHelper.IsPosix) { Mman.munmap(address, TrampolineInstruction.Length); } else { Kernel32.VirtualFree(address, TrampolineInstruction.Length); } }
/// <summary> /// Free memory trampoline. /// </summary> /// <param name="address"></param> public static void FreeTrampoline(IntPtr address) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Kernel32.VirtualFree(address, TrampolineInstruction.Length); } else { Mman.munmap(address, TrampolineInstruction.Length); } }
public static IntPtr AllocateTrampoline(IntPtr address) { byte[] trampoline = GetTrampoline(address); IntPtr jmpNative; if (OSHelper.IsPosix) { jmpNative = Mman.mmap(trampoline.Length, MmapProts.PROT_EXEC | MmapProts.PROT_WRITE, MmapFlags.MAP_ANON | MmapFlags.MAP_SHARED); } else { jmpNative = Kernel32.VirtualAlloc(trampoline.Length, Kernel32.AllocationType.Commit, Kernel32.MemoryProtection.EXECUTE_READ_WRITE); } Marshal.Copy(trampoline, 0, jmpNative, trampoline.Length); return(jmpNative); }
/// <summary> /// Create a trampoline 64 bits. /// </summary> /// <param name="address"></param> /// <returns></returns> public static IntPtr AllocateTrampoline(IntPtr address) { IntPtr jmpNative; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { jmpNative = Kernel32.VirtualAlloc(TrampolineInstruction.Length, Kernel32.AllocationType.Commit, Kernel32.MemoryProtection.EXECUTE_READ_WRITE); } else { jmpNative = Mman.mmap(TrampolineInstruction.Length, MmapProts.PROT_EXEC | MmapProts.PROT_WRITE, MmapFlags.MAP_ANON | MmapFlags.MAP_SHARED); } Marshal.Copy(TrampolineInstruction, 0, jmpNative, TrampolineInstruction.Length); Marshal.WriteIntPtr(jmpNative, 2, address); return(jmpNative); }
/// <summary> /// Write pointer on address. /// </summary> /// <param name="address">Address to write pointer.</param> /// <param name="pointer">Pointer to write.</param> private static void WritePointer(IntPtr address, IntPtr pointer) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Kernel32.MemoryProtection oldFlags = Kernel32.VirtualProtect(address, IntPtr.Size, Kernel32.MemoryProtection.READ_WRITE); Marshal.WriteIntPtr(address, pointer); Kernel32.VirtualProtect(address, IntPtr.Size, oldFlags); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { byte[] newAddress = BitConverter.GetBytes(pointer.ToInt64()); //Prevent segmentation fault. using FileStream fs = File.Open($"/proc/{ProcessInfo.PID}/mem", FileMode.Open, FileAccess.ReadWrite); fs.Seek(address.ToInt64(), SeekOrigin.Begin); fs.Write(newAddress, 0, newAddress.Length); } else { Mman.mprotect(address, (ulong)IntPtr.Size, MmapProts.PROT_WRITE); Marshal.WriteIntPtr(address, pointer); } }