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 int VirtualQueryEx(SafeMemoryHandle hProcess, IntPtr lpAddress, out MemoryBasicInformation32 lpBuffer, int dwLength);
public static extern Int32 VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MemoryBasicInformation32 lpBuffer, Int32 dwLength);
public static extern int VirtualQueryEx32(IntPtr hProcess, UIntPtr lpAddress, out MemoryBasicInformation32 lpBuffer, uint dwLength);