/// <summary> /// Writes your own memory bytes into process' memory and gives you the address /// for the memory location of the written bytes. /// </summary> /// <param name="bytesToWrite">Individual bytes to be written onto the buffer.</param> /// <returns>Pointer to the passed in bytes written to memory. Null pointer, if it cannot fit into the buffer.</returns> public IntPtr Add(byte[] bytesToWrite) { // Read the buffer contents back from memory. BufferHeader = Bindings.TargetProcess.ReadMemoryExternal <MemoryBufferHeader>(BaseBufferAddress); // Do not add beyond buffer size. if (!CheckItemSize(bytesToWrite.Length)) { return(IntPtr.Zero); } // If the buffer is invalid, do not add either. if (BaseBufferAddress == IntPtr.Zero) { return(IntPtr.Zero); } // Do the append operation. IntPtr appendAddress = (IntPtr)((ulong)BaseBufferAddress + BufferHeader.BufferOffset); Bindings.TargetProcess.WriteMemoryExternal(appendAddress, ref bytesToWrite); // Set current offset. BufferHeader.BufferOffset += (uint)bytesToWrite.Length; // Write the new buffer contents back to memory. Bindings.TargetProcess.WriteMemoryExternal(BaseBufferAddress, ref BufferHeader); return(appendAddress); }
/// <summary> /// Creates a new buffer in a specified location in memory with a specified size. /// This constructor is not intended to be used directly, consider using <see cref="MemoryBufferManager"/> instead. /// While you can use this constructor if you're sure the memory pages to be allocated are free, it is not recommended. /// MemoryBuffer creates a buffer if it doesn't exist, if the supplied address is already allocated and is not a buffer, sets the Base Address to 0. /// </summary> /// <param name="bufferAddress">Specifies the base address of the new buffer to be created.</param> /// <param name="bufferSize">The size of the buffer to be created. Note that the buffer size includes the buffer header!</param> public unsafe MemoryBuffer(IntPtr bufferAddress, uint bufferSize) { // Set the base address for the buffer. this.BaseBufferAddress = bufferAddress; // Get our info on desired page from VirtualQueryEx. MEMORY_BASIC_INFORMATION memoryInformation = new MEMORY_BASIC_INFORMATION(); VirtualQueryEx(Bindings.TargetProcess.ProcessHandle, bufferAddress, out memoryInformation, (uint)sizeof(MEMORY_BASIC_INFORMATION)); // If the page is already occupied, check and assign the buffer header. if (memoryInformation.State != PageState.Free) { // Check if buffer already exists by reading an existing or nonexisting header. MemoryBufferHeader bufferHeader = Bindings.TargetProcess.ReadMemoryExternal <MemoryBufferHeader>(BaseBufferAddress); // If buffer already exists, set buffer's header. if (bufferHeader.ReloadedMagic == MemoryBufferHeader.RELOADED_MAGIC) { BufferHeader = bufferHeader; } else { BaseBufferAddress = IntPtr.Zero; } } // Else if the pages are free. else { // Commit the pages. IntPtr virtualAllocAddress = VirtualAllocEx ( Bindings.TargetProcess.ProcessHandle, BaseBufferAddress, bufferSize, AllocationTypes.Reserve | AllocationTypes.Commit, MemoryProtections.ExecuteReadWrite ); // MemoryBuffer. if (virtualAllocAddress == IntPtr.Zero) { Bindings.PrintError("[FATAL] Failed to allocate MemoryBuffer."); throw new Exception("Failed to allocate MemoryBuffer."); } // Write a new Buffer BufferHeader = new MemoryBufferHeader() { BufferOffset = (uint)sizeof(MemoryBufferHeader), BufferSize = bufferSize, ReloadedMagic = MemoryBufferHeader.RELOADED_MAGIC }; Bindings.TargetProcess.WriteMemoryExternal(BaseBufferAddress, ref BufferHeader); } }
/// <summary> /// Returns true if the supplied memory address is the start of a Reloaded Buffer. /// Else false. /// </summary> /// <param name="address">Address to check if it contains the start of a buffer, a start of a region of pages obtained from GetPages().</param> private static bool IsBuffer(IntPtr address) { try { // Check if buffer already exists by reading an existing or nonexisting header. MemoryBufferHeader bufferHeader = Bindings.TargetProcess.ReadMemoryExternal <MemoryBufferHeader>(address); if (bufferHeader.ReloadedMagic == MemoryBufferHeader.RELOADED_MAGIC) { return(true); } else { return(false); } } catch (Exception) { return(false); } }