private static MemoryBasicInformation64 Query64(ASafeMemoryHandle processHandle, IntPtr baseAddress) { var sz = MarshalType <MemoryBasicInformation64> .Size; if (Kernel32.VirtualQueryEx(processHandle, baseAddress, out MemoryBasicInformation64 memoryInfo, (IntPtr)sz) != IntPtr.Zero) { return(memoryInfo); } return(new MemoryBasicInformation64()); }
/// <summary> /// Retrieves information about a range of pages within the virtual address space of a specified process. /// </summary> /// <param name="processHandle">A handle to the process whose memory information is queried.</param> /// <param name="baseAddress">A pointer to the base address of the region of pages to be queried.</param> /// <returns> /// A <see cref="MemoryBasicInformation32" /> structures in which information about the specified page range is /// returned. /// </returns> public static MemoryBasicInformation32 Query32(ASafeMemoryHandle processHandle, IntPtr baseAddress) { // Query the memory region var sz = MarshalType <MemoryBasicInformation32> .Size; if (Kernel32.VirtualQueryEx(processHandle, baseAddress, out MemoryBasicInformation32 memoryInfo, (IntPtr)sz) != IntPtr.Zero) { return(memoryInfo); } return(new MemoryBasicInformation32()); }
/// <summary> /// Sets the context for the specified thread. /// </summary> /// <param name="threadHandle">A handle to the thread whose context is to be set.</param> /// <param name="context"> /// A pointer to a <see cref="ThreadContext" /> structure that contains the context to be set in the /// specified thread. /// </param> public static void SetThreadContext(ASafeMemoryHandle threadHandle, ThreadContext context) { // Check if the handle is valid AHandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); // Set the thread context if (!Kernel32.SetThreadContext(threadHandle, ref context)) { throw new Win32Exception("Couldn't set the thread context."); } }
/// <summary> /// Releases a region of memory within the virtual address space of a specified process. /// </summary> /// <param name="processHandle">A handle to a process.</param> /// <param name="address">A pointer to the starting address of the region of memory to be freed.</param> public static void Free(ASafeMemoryHandle processHandle, IntPtr address) { // Check if the handles are valid AHandleManipulator.ValidateAsArgument(processHandle, "processHandle"); AHandleManipulator.ValidateAsArgument(address, "address"); // Free the memory if (!Kernel32.VirtualFreeEx(processHandle, address, 0, MemoryReleaseFlags.Release)) { // If the memory wasn't correctly freed, throws an exception throw new Win32Exception($"The memory page 0x{address.ToString("X")} cannot be freed."); } }
/// <summary> /// Initializes a new instance of the <see cref="AMemoryProtection" /> class. /// </summary> /// <param name="handle">The reference of the <see cref="ASafeMemoryHandle" /> object.</param> /// <param name="baseAddress">The base address of the memory to change the protection.</param> /// <param name="size">The size of the memory to change.</param> /// <param name="protection">The new protection to apply.</param> /// <param name="mustBeDisposed">The resource will be automatically disposed when the finalizer collects the object.</param> public AMemoryProtection(ASafeMemoryHandle handle, IntPtr baseAddress, int size, MemoryProtectionFlags protection = MemoryProtectionFlags.ExecuteReadWrite, bool mustBeDisposed = true) { // Save the parameters Handle = handle; BaseAddress = baseAddress; NewProtection = protection; Size = size; MustBeDisposed = mustBeDisposed; // Change the memory protection AMemoryHelper.ChangeProtection(Handle, baseAddress, size, protection, out var oldProtection); OldProtection = oldProtection; }
/// <summary> /// Validates an handle to fit correctly as argument. /// </summary> /// <param name="handle">A handle to validate.</param> /// <param name="argumentName">The name of the argument that represents the handle in its original function.</param> public static void ValidateAsArgument(ASafeMemoryHandle handle, string argumentName) { // Check if the handle is not null if (handle == null) { throw new ArgumentNullException(argumentName); } // Check if the handle is valid if (handle.IsClosed || handle.IsInvalid) { throw new ArgumentException("The handle is not valid or closed.", argumentName); } }
/// <summary> /// Terminates a thread. /// </summary> /// <param name="threadHandle">A handle to the thread to be terminated.</param> /// <param name="exitCode">The exit code for the thread.</param> public static void TerminateThread(ASafeMemoryHandle threadHandle, int exitCode) { // Check if the handle is valid AHandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); // Terminate the thread var ret = Kernel32.TerminateThread(threadHandle, exitCode); // If the function failed if (!ret) { throw new Win32Exception("Couldn't terminate the thread."); } }
public static Boolean IsReadable(ASafeMemoryHandle processHandle, IntPtr address) { if (Environment.Is64BitProcess) { var sz = MarshalType <MemoryBasicInformation64> .Size; var memoryInfo = Query64(processHandle, address, out var v); return((v == (IntPtr)sz) && memoryInfo.State == MemoryStateFlags.Commit); } else { var sz = MarshalType <MemoryBasicInformation32> .Size; var memoryInfo = Query32(processHandle, address, out var v); return((v == (IntPtr)sz) && memoryInfo.State == MemoryStateFlags.Commit); } }
/// <summary> /// Converts an handle into a <see cref="ProcessThread" /> object assuming this is a thread handle. /// </summary> /// <param name="threadHandle">A valid handle to an opened thread.</param> /// <returns>A <see cref="ProcessThread" /> object from the specified handle.</returns> public static ProcessThread HandleToThread(ASafeMemoryHandle threadHandle) { // Search the thread by iterating the processes list foreach (var process in System.Diagnostics.Process.GetProcesses()) { var ret = process.Threads.Cast <ProcessThread>().FirstOrDefault(t => t.Id == HandleToThreadId(threadHandle)); if (ret != null) { return(ret); } } // If no thread was found, throws a exception like the First() function with no element throw new InvalidOperationException("Sequence contains no matching element"); }
/// <summary> /// Suspends the specified thread. /// </summary> /// <param name="threadHandle">A handle to the thread that is to be suspended.</param> /// <returns>The thread's previous suspend count.</returns> public static int SuspendThread(ASafeMemoryHandle threadHandle) { // Check if the handle is valid AHandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); // Suspend the thread var ret = Kernel32.SuspendThread(threadHandle); // If the function failed if (ret == int.MaxValue) { throw new Win32Exception("Couldn't suspend the thread."); } return(ret); }
public static Boolean ChangeProtection(ASafeMemoryHandle processHandle, IntPtr address, int size, MemoryProtectionFlags protection, out MemoryProtectionFlags oldProtection) { // Check if the handles are valid AHandleManipulator.ValidateAsArgument(processHandle, "processHandle"); AHandleManipulator.ValidateAsArgument(address, "address"); // Change the protection in the target process if (Kernel32.VirtualProtectEx(processHandle, address, size, protection, out oldProtection)) { // Return the old protection return(true); } // Else the protection couldn't be changed return(false); }
/// <summary> /// Retrieves a descriptor table entry for the specified selector and thread. /// </summary> /// <param name="threadHandle">A handle to the thread containing the specified selector.</param> /// <param name="selector">The global or local selector value to look up in the thread's descriptor tables.</param> /// <returns>A pointer to an <see cref="LdtEntry" /> structure that receives a copy of the descriptor table entry.</returns> public static LdtEntry GetThreadSelectorEntry(ASafeMemoryHandle threadHandle, int selector) { // Check if the handle is valid AHandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); // Get the selector entry LdtEntry entry; if (Kernel32.GetThreadSelectorEntry(threadHandle, selector, out entry)) { return(entry); } // Else couldn't get the selector entry, throws an exception throw new Win32Exception($"Couldn't get the selector entry for this selector: {selector}."); }
/// <summary> /// Waits an infinite amount of time for the specified object to become signaled. /// </summary> /// <param name="handle">A handle to the object.</param> /// <returns>If the function succeeds, the return value indicates the event that caused the function to return.</returns> public static WaitValues WaitForSingleObject(ASafeMemoryHandle handle) { // Check if the handle is valid AHandleManipulator.ValidateAsArgument(handle, "handle"); // Wait for single object var ret = Kernel32.WaitForSingleObject(handle, 0xFFFFFFFF); // If the function failed if (ret == WaitValues.Failed) { throw new Win32Exception("The WaitForSingleObject function call failed."); } return(ret); }
/// <summary> /// Converts an handle into a thread id assuming this is a thread handle. /// </summary> /// <param name="threadHandle">A valid handle to an opened thread.</param> /// <returns>A thread id from the specified handle.</returns> public static int HandleToThreadId(ASafeMemoryHandle threadHandle) { // Check if the handle is valid ValidateAsArgument(threadHandle, "threadHandle"); // Find the thread id var ret = Kernel32.GetThreadId(threadHandle); // If the thread id is valid if (ret != 0) { return(ret); } //Else the function failed, throws an exception throw new Win32Exception("Couldn't find the thread id of the specified handle."); }
/// <summary> /// Waits until the specified object is in the signaled state or the time-out interval elapses. /// </summary> /// <param name="handle">A handle to the object.</param> /// <param name="timeout"> /// The time-out interval. If this parameter is NULL, the function does not enter a wait state if the /// object is not signaled; it always returns immediately. /// </param> /// <returns>Indicates the <see cref="WaitValues" /> event that caused the function to return.</returns> public static WaitValues WaitForSingleObject(ASafeMemoryHandle handle, TimeSpan?timeout) { // Check if the handle is valid AHandleManipulator.ValidateAsArgument(handle, "handle"); // Wait for single object var ret = Kernel32.WaitForSingleObject(handle, timeout.HasValue ? Convert.ToUInt32(timeout.Value.TotalMilliseconds) : 0); // If the function failed if (ret == WaitValues.Failed) { throw new Win32Exception("The WaitForSingleObject function call failed."); } return(ret); }
/// <summary> /// Reads an array of bytes in the memory form the target process. /// </summary> /// <param name="processHandle">A handle to the process with memory that is being read.</param> /// <param name="address">A pointer to the base address in the specified process from which to read.</param> /// <param name="size">The number of bytes to be read from the specified process.</param> /// <returns>The collection of read bytes.</returns> public static byte[] ReadBytes(ASafeMemoryHandle processHandle, IntPtr address, int size) { // Check if the handles are valid AHandleManipulator.ValidateAsArgument(processHandle, "processHandle"); AHandleManipulator.ValidateAsArgument(address, "address"); // Allocate the buffer var buffer = new byte[size]; int nbBytesRead; // Read the data from the target process if (Kernel32.ReadProcessMemory(processHandle, address, buffer, size, out nbBytesRead) && size == nbBytesRead) { return(buffer); } // Else the data couldn't be read, throws an exception throw new Win32Exception($"Couldn't read {size} byte(s) from 0x{address.ToString("X")}."); }
public static IntPtr Allocate(ASafeMemoryHandle processHandle, IntPtr address, int size, MemoryProtectionFlags protectionFlags = MemoryProtectionFlags.ExecuteReadWrite, MemoryAllocationFlags allocationFlags = MemoryAllocationFlags.Commit) { // Check if the handle is valid AHandleManipulator.ValidateAsArgument(processHandle, "processHandle"); // Allocate a memory page var ret = Kernel32.VirtualAllocEx(processHandle, address, size, allocationFlags, protectionFlags); // Check whether the memory page is valid if (ret != IntPtr.Zero) { return(ret); } // If the pointer isn't valid, throws an exception throw new Win32Exception($"Couldn't allocate memory of {size} byte(s)."); }
/// <summary> /// etrieves information about the specified process. /// </summary> /// <param name="processHandle">A handle to the process to query.</param> /// <returns>A <see cref="ProcessBasicInformation" /> structure containg process information.</returns> public static ProcessBasicInformation NtQueryInformationProcess(ASafeMemoryHandle processHandle) { // Check if the handle is valid AHandleManipulator.ValidateAsArgument(processHandle, "processHandle"); // Create a structure to store process info var info = new ProcessBasicInformation(); // Get the process info var ret = Nt.NtQueryInformationProcess(processHandle, ProcessInformationClass.ProcessBasicInformation, ref info, info.Size, IntPtr.Zero); // If the function succeeded if (ret == 0) { return(info); } // Else, couldn't get the process info, throws an exception throw new ApplicationException($"Couldn't get the information from the process, error code '{ret}'."); }
/// <summary> /// Creates a thread that runs in the virtual address space of another process. /// </summary> /// <param name="processHandle">A handle to the process in which the thread is to be created.</param> /// <param name="startAddress"> /// A pointer to the application-defined function to be executed by the thread and represents /// the starting address of the thread in the remote process. /// </param> /// <param name="parameter">A pointer to a variable to be passed to the thread function.</param> /// <param name="creationFlags">The flags that control the creation of the thread.</param> /// <returns>A handle to the new thread.</returns> public static ASafeMemoryHandle CreateRemoteThread(ASafeMemoryHandle processHandle, IntPtr startAddress, IntPtr parameter, ThreadCreationFlags creationFlags = ThreadCreationFlags.Run) { // Check if the handles are valid AHandleManipulator.ValidateAsArgument(processHandle, "processHandle"); AHandleManipulator.ValidateAsArgument(startAddress, "startAddress"); // Create the remote thread int threadId; var ret = Kernel32.CreateRemoteThread(processHandle, IntPtr.Zero, 0, startAddress, parameter, creationFlags, out threadId); // If the thread is created if (!ret.IsClosed && !ret.IsInvalid) { return(ret); } // Else couldn't create thread, throws an exception throw new Win32Exception($"Couldn't create the thread at 0x{startAddress.ToString("X")}."); }
/// <summary> /// Retrieves information about the specified thread. /// </summary> /// <param name="threadHandle">A handle to the thread to query.</param> /// <returns>A <see cref="ThreadBasicInformation" /> structure containg thread information.</returns> public static ThreadBasicInformation NtQueryInformationThread(ASafeMemoryHandle threadHandle) { // Check if the handle is valid AHandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); // Create a structure to store thread info var info = new ThreadBasicInformation(); // Get the thread info var ret = Nt.NtQueryInformationThread(threadHandle, 0, ref info, MarshalType <ThreadBasicInformation> .Size, IntPtr.Zero); // If the function succeeded if (ret == 0) { return(info); } // Else, couldn't get the thread info, throws an exception throw new ApplicationException($"Couldn't get the information from the thread, error code '{ret}'."); }
/// <summary> /// Retrieves information about a range of pages within the virtual address space of a specified process. /// </summary> /// <param name="processHandle">A handle to the process whose memory information is queried.</param> /// <param name="baseAddress">A pointer to the base address of the region of pages to be queried.</param> /// <param name="query">The original return value from the native API</param> /// <returns> /// A <see cref="MemoryBasicInformation64" /> structures in which information about the specified page range is /// returned. /// </returns> public static MemoryBasicInformation Query(ASafeMemoryHandle processHandle, IntPtr baseAddress, out IntPtr query) { var ret = new MemoryBasicInformation(); if (Environment.Is64BitProcess) { var sz = MarshalType <MemoryBasicInformation64> .Size; query = Kernel32.VirtualQueryEx(processHandle, baseAddress, out MemoryBasicInformation64 memoryInfo, (IntPtr)sz); if (query == IntPtr.Zero) { return(ret); } ret.BaseAddress = memoryInfo.BaseAddress; ret.AllocationBase = memoryInfo.AllocationBase; ret.AllocationProtect = memoryInfo.AllocationProtect; ret.Protect = memoryInfo.Protect; ret.RegionSize = (Int64)memoryInfo.RegionSize; ret.State = memoryInfo.State; ret.Type = memoryInfo.Type; } else { var sz = MarshalType <MemoryBasicInformation32> .Size; query = Kernel32.VirtualQueryEx(processHandle, baseAddress, out MemoryBasicInformation32 memoryInfo, (IntPtr)sz); if (query == IntPtr.Zero) { return(ret); } ret.BaseAddress = memoryInfo.BaseAddress; ret.AllocationBase = memoryInfo.AllocationBase; ret.AllocationProtect = memoryInfo.AllocationProtect; ret.Protect = memoryInfo.Protect; ret.RegionSize = memoryInfo.RegionSize; ret.State = memoryInfo.State; ret.Type = memoryInfo.Type; } return(ret); }
/// <summary> /// Retrieves the context of the specified thread. /// </summary> /// <param name="threadHandle">A handle to the thread whose context is to be retrieved.</param> /// <param name="contextFlags">Determines which registers are returned or set.</param> /// <returns>A <see cref="ThreadContext" /> structure that receives the appropriate context of the specified thread.</returns> public static ThreadContext GetThreadContext(ASafeMemoryHandle threadHandle, ThreadContextFlags contextFlags = ThreadContextFlags.Full) { // Check if the handle is valid AHandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); // Allocate a thread context structure var context = new ThreadContext { ContextFlags = contextFlags }; // Set the context flag // Get the thread context if (Kernel32.GetThreadContext(threadHandle, ref context)) { return(context); } // Else couldn't get the thread context, throws an exception throw new Win32Exception("Couldn't get the thread context."); }
public static IntPtr LastChanceAllocPreferred(ASafeMemoryHandle processHandle, IntPtr preferred, int size, MemoryProtectionFlags protection) { var startTime = UDateTime.Ticks(); var address = UIntPtr.Zero; var distance = 0UL; var count = 0; if (preferred.ToInt64() % 65536 > 0) { preferred = (IntPtr)(preferred.ToInt64() - (preferred.ToInt64() % 65536)); } while (address == UIntPtr.Zero && (count < 10 || (UDateTime.Ticks() < startTime + 10000)) && (distance < 0x80000000UL)) { address = Allocate(processHandle, (IntPtr)(preferred.ToUIntPtr().ToUInt64() + distance), size, protection, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.Commit).ToUIntPtr(); if (address == UIntPtr.Zero) { distance += 65536; } count += 1; } return(address.ToIntPtr()); }
/// <summary> /// Writes data to an area of memory in a specified process. /// </summary> /// <param name="processHandle">A handle to the process memory to be modified.</param> /// <param name="address">A pointer to the base address in the specified process to which data is written.</param> /// <param name="byteArray">A buffer that contains data to be written in the address space of the specified process.</param> /// <returns>The number of bytes written.</returns> public static int WriteBytes(ASafeMemoryHandle processHandle, IntPtr address, byte[] byteArray) { // Check if the handles are valid AHandleManipulator.ValidateAsArgument(processHandle, "processHandle"); AHandleManipulator.ValidateAsArgument(address, "address"); // Create the variable storing the number of bytes written int nbBytesWritten; // Write the data to the target process if (Kernel32.WriteProcessMemory(processHandle, address, byteArray, byteArray.Length, out nbBytesWritten)) { // Check whether the length of the data written is equal to the inital array if (nbBytesWritten == byteArray.Length) { return(nbBytesWritten); } } // Else the data couldn't be written, throws an exception throw new Win32Exception($"Couldn't write {byteArray.Length} bytes to 0x{address.ToString("X")}"); }
/// <summary> /// Retrieves information about a range of pages within the virtual address space of a specified process. /// </summary> /// <param name="processHandle">A handle to the process whose memory information is queried.</param> /// <param name="addressFrom">A pointer to the starting address of the region of pages to be queried.</param> /// <param name="addressTo">A pointer to the ending address of the region of pages to be queried.</param> /// <returns>A collection of <see cref="MemoryBasicInformation32" /> structures.</returns> public static IEnumerable <MemoryBasicInformation32> Query32(ASafeMemoryHandle processHandle, IntPtr addressFrom, IntPtr addressTo) { // Check if the handle is valid AHandleManipulator.ValidateAsArgument(processHandle, "processHandle"); // Convert the addresses to Int64 var numberFrom = addressFrom.ToInt64(); var numberTo = addressTo.ToInt64(); // The first address must be lower than the second if (numberFrom >= numberTo) { throw new ArgumentException("The starting address must be lower than the ending address.", "addressFrom"); } // Create the variable storing the result of the call of VirtualQueryEx IntPtr ret; // Enumerate the memory pages do { // Allocate the structure to store information of memory MemoryBasicInformation32 memoryInfo; // Get the next memory page var sz = MarshalType <MemoryBasicInformation32> .Size; ret = Kernel32.VirtualQueryEx(processHandle, new IntPtr(numberFrom), out memoryInfo, (IntPtr)sz); // Increment the starting address with the size of the page numberFrom += memoryInfo.RegionSize; // Return the memory page if (memoryInfo.State != MemoryStateFlags.Free) { yield return(memoryInfo); } } while (numberFrom < numberTo && ret != IntPtr.Zero); }
/// <summary> /// Retrieves the termination status of the specified thread. /// </summary> /// <param name="threadHandle">A handle to the thread.</param> /// <returns> /// Nullable type: the return value is A pointer to a variable to receive the thread termination status or /// <code>null</code> if it is running. /// </returns> public static IntPtr?GetExitCodeThread(ASafeMemoryHandle threadHandle) { // Check if the handle is valid AHandleManipulator.ValidateAsArgument(threadHandle, "threadHandle"); // Create the variable storing the output exit code IntPtr exitCode; // Get the exit code of the thread if (!Kernel32.GetExitCodeThread(threadHandle, out exitCode)) { throw new Win32Exception("Couldn't get the exit code of the thread."); } // If the thread is still active if (exitCode == new IntPtr(259)) { return(null); } return(exitCode); }
public static extern bool SetThreadContext(ASafeMemoryHandle hThread, [MarshalAs(UnmanagedType.Struct)] ref ThreadContext lpContext);
public static IntPtr FindFreeBlockForRegion(ASafeMemoryHandle processHandle, IntPtr baseAddress, int size) { return(IntPtr.Zero); //MemoryBasicInformation32 mbi = new MemoryBasicInformation32(); //UIntPtr x, b, offset; //UIntPtr minAddress, maxAddress; //if (!process.is64Bit) // return UIntPtr.Zero; //don't bother ////64-bit //if (baseAddress == 0) // return UIntPtr.Zero; //minAddress = baseAddress - 0x70000000; //let's add in some extra overhead to skip the last fffffff //maxAddress = baseAddress + 0x70000000; //if ((minAddress > PtrToUInt(systeminfo.lpMaximumApplicationAddress)) || (minAddress < PtrToUInt(systeminfo.lpMinimumApplicationAddress))) // minAddress = PtrToUInt(systeminfo.lpMinimumApplicationAddress); //if ((maxAddress < PtrToUInt(systeminfo.lpMinimumApplicationAddress)) || (maxAddress > PtrToUInt(systeminfo.lpMaximumApplicationAddress))) // maxAddress = PtrToUInt(systeminfo.lpMaximumApplicationAddress); //b = minAddress; //ZeroMemory(&mbi, sizeof(mbi)); //while (VirtualQueryEx(process.Handle, UIntToPtr(b), mbi, sizeof(mbi)) == sizeof(mbi)) //{ // if (mbi.BaseAddress > UIntToPtr(maxAddress)) return FindFreeBlockForRegion_result; //no memory found, just return 0 and let windows decide // // if ((mbi.State == MEM_FREE) && ((mbi.RegionSize) > size)) // { // if ((PtrToUInt(mbi.baseaddress) % systeminfo.dwAllocationGranularity) > 0) // { // //the whole size can not be used // x = PtrToUInt(mbi.baseaddress); // offset = systeminfo.dwAllocationGranularity - (x % systeminfo.dwAllocationGranularity); // // //check if there's enough left // if ((mbi.regionsize - offset) > size) // { // //yes // x = x + offset; // // if (x < base) // { // x = x + (mbi.regionsize - offset) - size; // if (x > base) x = base; // // //now decrease x till it's alligned properly // x = x - (x % systeminfo.dwAllocationGranularity); // } // // //if the difference is closer then use that // if (abs(PtrInt(x - base)) < abs(PtrInt(PtrToUInt(result) - base))) // result = UIntToPtr(x); // } // //nope // // } // else // { // x = PtrToUInt(mbi.BaseAddress); // if (x < base) //try to get it the closest possible (so to the end of the region-size and aligned by dwAllocationGranularity) // { // x = (x + mbi.RegionSize) - size; // if (x > base) x = base; // // //now decrease x till it's alligned properly // x = x - (x % systeminfo.dwAllocationGranularity); // } // // if (abs(ptrInt(x - base)) < abs(ptrInt(PtrToUInt(result) - base))) // result = UIntToPtr(x); // } // // } // b = PtrToUInt(mbi.BaseAddress) + mbi.RegionSize; //} //return FindFreeBlockForRegion_result; }
public static Boolean IsAddress(ASafeMemoryHandle processHandle, IntPtr address) { var memoryInfo = Query(processHandle, address, out var v); return(v != IntPtr.Zero && memoryInfo.State == MemoryStateFlags.Commit); }
public static Boolean FullAccess(ASafeMemoryHandle processHandle, IntPtr address, int size, out MemoryProtectionFlags oldProtection) { return(ChangeProtection(processHandle, address, size, MemoryProtectionFlags.ExecuteReadWrite, out oldProtection)); }