/// <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 MemoryBasicInformation64 Query(SafeMemoryHandle processHandle, IntPtr baseAddress) { var memoryInfo64 = new MemoryBasicInformation64(); if (!Environment.Is64BitProcess) { // Query the memory region if (Kernel32.VirtualQueryEx(processHandle, baseAddress, out MemoryBasicInformation32 memoryInfo32, MarshalType <MemoryBasicInformation32> .Size) == 0) { return(memoryInfo64); } // Copy from the 32 bit struct to the 64 bit struct memoryInfo64.AllocationBase = memoryInfo32.AllocationBase; memoryInfo64.AllocationProtect = memoryInfo32.AllocationProtect; memoryInfo64.BaseAddress = memoryInfo32.BaseAddress; memoryInfo64.Protect = memoryInfo32.Protect; memoryInfo64.RegionSize = memoryInfo32.RegionSize; memoryInfo64.State = memoryInfo32.State; memoryInfo64.Type = memoryInfo32.Type; return(memoryInfo64); } return(memoryInfo64); }
public static UIntPtr VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MemoryBasicInformation lpBuffer) { UIntPtr retVal; if (Is64Bit()) { var tmp64 = new MemoryBasicInformation64(); retVal = Native_VirtualQueryEx(hProcess, lpAddress, out tmp64, new UIntPtr((uint)Marshal.SizeOf(tmp64))); lpBuffer.BaseAddress = tmp64.BaseAddress; lpBuffer.AllocationBase = tmp64.AllocationBase; lpBuffer.AllocationProtect = tmp64.AllocationProtect; lpBuffer.RegionSize = (long)tmp64.RegionSize; lpBuffer.State = tmp64.State; lpBuffer.Protect = tmp64.Protect; lpBuffer.Type = tmp64.Type; return(retVal); } var tmp32 = new MemoryBasicInformation32(); retVal = Native_VirtualQueryEx(hProcess, lpAddress, out tmp32, new UIntPtr((uint)Marshal.SizeOf(tmp32))); lpBuffer.BaseAddress = tmp32.BaseAddress; lpBuffer.AllocationBase = tmp32.AllocationBase; lpBuffer.AllocationProtect = tmp32.AllocationProtect; lpBuffer.RegionSize = tmp32.RegionSize; lpBuffer.State = tmp32.State; lpBuffer.Protect = tmp32.Protect; lpBuffer.Type = tmp32.Type; return(retVal); }
/// <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="startAddress">A pointer to the starting address of the region of pages to be queried.</param> /// <param name="endAddress">A pointer to the ending address of the region of pages to be queried.</param> /// <param name="requiredProtection">Protection flags required to be present.</param> /// <param name="excludedProtection">Protection flags that must not be present.</param> /// <param name="allowedTypes">Memory types that can be present.</param> /// <returns> /// A collection of <see cref="MemoryBasicInformation64"/> structures containing info about all virtual pages in the target process. /// </returns> public static IEnumerable <MemoryBasicInformation64> VirtualPages( IntPtr processHandle, IntPtr startAddress, IntPtr endAddress, MemoryProtectionFlags requiredProtection, MemoryProtectionFlags excludedProtection, MemoryTypeEnum allowedTypes) { if (startAddress.ToUInt64() >= endAddress.ToUInt64()) { yield return(new MemoryBasicInformation64()); } Boolean wrappedAround = false; Int32 queryResult; // Enumerate the memory pages do { // Allocate the structure to store information of memory MemoryBasicInformation64 memoryInfo = new MemoryBasicInformation64(); if (!Environment.Is64BitProcess) { // 32 Bit struct is not the same MemoryBasicInformation32 memoryInfo32 = new MemoryBasicInformation32(); // Query the memory region (32 bit native method) queryResult = NativeMethods.VirtualQueryEx(processHandle, startAddress, out memoryInfo32, Marshal.SizeOf(memoryInfo32)); // Copy from the 32 bit struct to the 64 bit struct memoryInfo.AllocationBase = memoryInfo32.AllocationBase; memoryInfo.AllocationProtect = memoryInfo32.AllocationProtect; memoryInfo.BaseAddress = memoryInfo32.BaseAddress; memoryInfo.Protect = memoryInfo32.Protect; memoryInfo.RegionSize = memoryInfo32.RegionSize; memoryInfo.State = memoryInfo32.State; memoryInfo.Type = memoryInfo32.Type; } else { // Query the memory region (64 bit native method) queryResult = NativeMethods.VirtualQueryEx(processHandle, startAddress, out memoryInfo, Marshal.SizeOf(memoryInfo)); } // Increment the starting address with the size of the page IntPtr previousFrom = startAddress; startAddress = startAddress.Add(memoryInfo.RegionSize); if (previousFrom.ToUInt64() > startAddress.ToUInt64()) { wrappedAround = true; } // Ignore free memory. These are unallocated memory regions. if ((memoryInfo.State & MemoryStateFlags.Free) != 0) { continue; } // At least one readable memory flag is required if ((memoryInfo.Protect & MemoryProtectionFlags.ReadOnly) == 0 && (memoryInfo.Protect & MemoryProtectionFlags.ExecuteRead) == 0 && (memoryInfo.Protect & MemoryProtectionFlags.ExecuteReadWrite) == 0 && (memoryInfo.Protect & MemoryProtectionFlags.ReadWrite) == 0) { continue; } // Do not bother with this shit, this memory is not worth scanning if ((memoryInfo.Protect & MemoryProtectionFlags.ZeroAccess) != 0 || (memoryInfo.Protect & MemoryProtectionFlags.NoAccess) != 0 || (memoryInfo.Protect & MemoryProtectionFlags.Guard) != 0) { continue; } // Enforce allowed types switch (memoryInfo.Type) { case MemoryTypeFlags.None: if ((allowedTypes & MemoryTypeEnum.None) == 0) { continue; } break; case MemoryTypeFlags.Private: if ((allowedTypes & MemoryTypeEnum.Private) == 0) { continue; } break; case MemoryTypeFlags.Image: if ((allowedTypes & MemoryTypeEnum.Image) == 0) { continue; } break; case MemoryTypeFlags.Mapped: if ((allowedTypes & MemoryTypeEnum.Mapped) == 0) { continue; } break; } // Ensure at least one required protection flag is set if (requiredProtection != 0 && (memoryInfo.Protect & requiredProtection) == 0) { continue; } // Ensure no ignored protection flags are set if (excludedProtection != 0 && (memoryInfo.Protect & excludedProtection) != 0) { continue; } // Return the memory page yield return(memoryInfo); }while (startAddress.ToUInt64() < endAddress.ToUInt64() && queryResult != 0 && !wrappedAround); }
/// <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="startAddress">A pointer to the starting address of the region of pages to be queried.</param> /// <param name="endAddress">A pointer to the ending address of the region of pages to be queried.</param> /// <returns> /// A collection of <see cref="MemoryBasicInformation64"/> structures containing info about all virtual pages in the target process. /// </returns> public static IEnumerable <MemoryBasicInformation64> QueryUnallocatedMemory( IntPtr processHandle, IntPtr startAddress, IntPtr endAddress) { if (startAddress.ToUInt64() >= endAddress.ToUInt64()) { yield return(new MemoryBasicInformation64()); } Boolean wrappedAround = false; Int32 queryResult; // Enumerate the memory pages do { // Allocate the structure to store information of memory MemoryBasicInformation64 memoryInfo = new MemoryBasicInformation64(); if (!Environment.Is64BitProcess) { // 32 Bit struct is not the same MemoryBasicInformation32 memoryInfo32 = new MemoryBasicInformation32(); // Query the memory region (32 bit native method) queryResult = NativeMethods.VirtualQueryEx(processHandle, startAddress, out memoryInfo32, Marshal.SizeOf(memoryInfo32)); // Copy from the 32 bit struct to the 64 bit struct memoryInfo.AllocationBase = memoryInfo32.AllocationBase; memoryInfo.AllocationProtect = memoryInfo32.AllocationProtect; memoryInfo.BaseAddress = memoryInfo32.BaseAddress; memoryInfo.Protect = memoryInfo32.Protect; memoryInfo.RegionSize = memoryInfo32.RegionSize; memoryInfo.State = memoryInfo32.State; memoryInfo.Type = memoryInfo32.Type; } else { // Query the memory region (64 bit native method) queryResult = NativeMethods.VirtualQueryEx(processHandle, startAddress, out memoryInfo, Marshal.SizeOf(memoryInfo)); } // Increment the starting address with the size of the page IntPtr previousFrom = startAddress; startAddress = startAddress.Add(memoryInfo.RegionSize); if (previousFrom.ToUInt64() > startAddress.ToUInt64()) { wrappedAround = true; } if ((memoryInfo.State & MemoryStateFlags.Free) != 0) { // Return the unallocated memory page yield return(memoryInfo); } else { // Ignore actual memory continue; } }while (startAddress.ToUInt64() < endAddress.ToUInt64() && queryResult != 0 && !wrappedAround); }
public static extern bool VirtualQueryEx( [In] IntPtr Process, [In][Optional] IntPtr Address, [Out] /*[MarshalAs(UnmanagedType.Struct)]*/ out MemoryBasicInformation64 Buffer, [In] int Size );
/// <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 <MemoryBasicInformation64> Query(SafeMemoryHandle processHandle, IntPtr addressFrom, IntPtr addressTo) { // Check if the handle is valid HandleManipulator.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 int ret; // Enumerate the memory pages do { // Allocate the structure to store information of memory var memoryInfo = new MemoryBasicInformation64(); if (!Environment.Is64BitProcess) { // Get the next memory page ret = Kernel32.VirtualQueryEx(processHandle, new IntPtr(numberFrom), out memoryInfo, MarshalType <MemoryBasicInformation64> .Size); } else { // Allocate the structure to store information of memory MemoryBasicInformation32 memoryInfo32; // Get the next memory page ret = Kernel32.VirtualQueryEx(processHandle, new IntPtr(numberFrom), out memoryInfo32, MarshalType <MemoryBasicInformation32> .Size); // Copy from the 32 bit struct to the 64 bit struct memoryInfo.AllocationBase = memoryInfo32.AllocationBase; memoryInfo.AllocationProtect = memoryInfo32.AllocationProtect; memoryInfo.BaseAddress = memoryInfo32.BaseAddress; memoryInfo.Protect = memoryInfo32.Protect; memoryInfo.RegionSize = memoryInfo32.RegionSize; memoryInfo.State = memoryInfo32.State; memoryInfo.Type = memoryInfo32.Type; } // 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 != 0); }
public static extern int VirtualQueryEx(SafeMemoryHandle hProcess, IntPtr lpAddress, out MemoryBasicInformation64 lpBuffer, int dwLength);
public static extern Int32 VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MemoryBasicInformation64 lpBuffer, Int32 dwLength);
public static extern int VirtualQueryEx64(IntPtr hProcess, UIntPtr lpAddress, out MemoryBasicInformation64 lpBuffer, uint dwLength);