/// <summary> /// Allocates memory that satisfies a set size constraint and proximity to a set address. /// </summary> /// <param name="size">The minimum size of the memory to be allocated.</param> /// <param name="minimumAddress">The minimum absolute address to allocate in.</param> /// <param name="maximumAddress">The maximum absolute address to allocate in.</param> /// <param name="retryCount">In the case the memory allocation fails; the amount of times memory allocation is to be retried.</param> /// <exception cref="System.Exception">Memory allocation failure due to possible race condition with other process/process itself/Windows scheduling.</exception> /// <remarks> /// This function is virtually the same to running <see cref="FindBufferLocation"/> and then running Windows' /// VirtualAlloc yourself. Except for the extra added safety of mutual exclusion (Mutex). /// The memory is allocated with the PAGE_EXECUTE_READWRITE permissions. /// </remarks> public BufferAllocationProperties Allocate(int size, int minimumAddress = 0x10000, int maximumAddress = 0x7FFFFFFF, int retryCount = 3) { if (minimumAddress <= 0) { throw new ArgumentException("Please do not set the minimum address to 0 or negative. It collides with the return values of Windows API functions" + "where e.g. 0 is returned on failure but you can also allocate successfully on 0."); } // Keep retrying memory allocation. _allocateMemoryMutex.WaitOne(); try { return(Run(retryCount, () => { var memoryLocation = FindBufferLocation(size, minimumAddress, maximumAddress, true); var virtualAllocFunction = VirtualAllocUtility.GetVirtualAllocFunction(Process); var result = virtualAllocFunction(Process.Handle, memoryLocation.MemoryAddress, (ulong)memoryLocation.Size); if (result == IntPtr.Zero) { throw new Exception("Failed to allocate memory using VirtualAlloc/VirtualAllocEx"); } _allocateMemoryMutex.ReleaseMutex(); return memoryLocation; })); } catch (Exception) { _allocateMemoryMutex.ReleaseMutex(); throw; } }
/// <summary> /// Allocates memory to store a <see cref="MemoryBuffer"/>s inside the target process/ /// </summary> internal static void AllocateBuffer(Process process, nuint bufferAddress, int bufferSize) { // Get the function, commit the pages and check. var virtualAllocFunction = VirtualAllocUtility.GetVirtualAllocFunction(process); var address = virtualAllocFunction(process.Handle, bufferAddress, (uint)bufferSize); if (address == UIntPtr.Zero) { throw new Exception($"Failed to allocate MemoryBuffer of size {bufferSize} at address {bufferAddress}. Last Win32 Error: {Marshal.GetLastWin32Error()}"); } }