We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ReadMemoryIgnoreErrors can be speeded up by scanning valid memory regions via VirtualQueryEx and reading them as whole, instead of by pages. Example:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; namespace ConsoleApp1 { class Program { [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)] static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName); [Flags] enum LoadLibraryFlags : uint { None = 0, DONT_RESOLVE_DLL_REFERENCES = 0x00000001, LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010, LOAD_LIBRARY_AS_DATAFILE = 0x00000002, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040, LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020, LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100, LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800, LOAD_LIBRARY_SEARCH_USER_DIRS = 0x00000400, LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008 } [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags); [StructLayout(LayoutKind.Sequential)] public struct MODULEINFO { public IntPtr lpBaseOfDll; public uint SizeOfImage; public IntPtr EntryPoint; } [DllImport("psapi.dll", SetLastError = true)] static extern bool GetModuleInformation(IntPtr hProcess, IntPtr hModule, out MODULEINFO lpmodinfo, uint cb); [DllImport("kernel32.dll", SetLastError = true)] static extern bool ReadProcessMemory( IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead); [DllImport("kernel32.dll", SetLastError = true, EntryPoint = "ReadProcessMemory")] static extern bool ReadProcessMemory_Byte( IntPtr hProcess, IntPtr lpBaseAddress, out byte lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead ); [StructLayout(LayoutKind.Sequential)] public struct MEMORY_BASIC_INFORMATION { public IntPtr BaseAddress; public IntPtr AllocationBase; public uint AllocationProtect; public IntPtr RegionSize; public uint State; public uint Protect; public uint Type; } public enum AllocationProtect : uint { PAGE_EXECUTE = 0x00000010, PAGE_EXECUTE_READ = 0x00000020, PAGE_EXECUTE_READWRITE = 0x00000040, PAGE_EXECUTE_WRITECOPY = 0x00000080, PAGE_NOACCESS = 0x00000001, PAGE_READONLY = 0x00000002, PAGE_READWRITE = 0x00000004, PAGE_WRITECOPY = 0x00000008, PAGE_GUARD = 0x00000100, PAGE_NOCACHE = 0x00000200, PAGE_WRITECOMBINE = 0x00000400 } const uint MEM_COMMIT = 0x1000; const uint MEM_FREE = 0x10000; const uint MEM_RESERVE = 0x2000; [DllImport("kernel32.dll")] static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength); public struct MemoryRegion { public long Address { get; set; } public long Size { get; set; } public bool IsReadable { get; set; } } static bool IsReadAccess(uint protectionFlags) { AllocationProtect ap = (AllocationProtect)protectionFlags; return ap == AllocationProtect.PAGE_EXECUTE_READ || ap == AllocationProtect.PAGE_EXECUTE_READWRITE || ap == AllocationProtect.PAGE_EXECUTE_WRITECOPY || ap == AllocationProtect.PAGE_READONLY || ap == AllocationProtect.PAGE_READWRITE || ap == AllocationProtect.PAGE_WRITECOPY; } public static MemoryRegion[] GetMemoryRegions(IntPtr hProcess, IntPtr address, int size) { List<MemoryRegion> ret = new List<MemoryRegion>(50); long MaxAddress = (long)address + size; while(true) { MEMORY_BASIC_INFORMATION m=new MEMORY_BASIC_INFORMATION(); int result = VirtualQueryEx( hProcess, address, out m, (uint)Marshal.SizeOf(m) ); if (result==0||m.RegionSize == IntPtr.Zero) break; MemoryRegion reg = new MemoryRegion(); reg.Address = (long)m.BaseAddress; reg.Size = (long)m.RegionSize; if (m.State == MEM_COMMIT && IsReadAccess(m.AllocationProtect)) { reg.IsReadable = true; } ret.Add(reg); address = (IntPtr)((long)m.BaseAddress + (long)m.RegionSize); if ((long)address > MaxAddress) break; } return ret.ToArray(); } static void EnumMemoryRegions(IntPtr hProcess,IntPtr address, int size) { MemoryRegion[] regions = GetMemoryRegions(hProcess, address, size); for (int i = 0; i < regions.Length; i++) { Console.WriteLine("0x{0} : {1} bytes, Readable: {2}", regions[i].Address.ToString("X"), regions[i].Size, regions[i].IsReadable ); } } static void Main(string[] args) { string path = "C:\\Test\\Lib.dll"; //string path = typeof(object).Assembly.Location; IntPtr hModule = LoadLibraryEx(path, IntPtr.Zero, LoadLibraryFlags.None); if (hModule == IntPtr.Zero) throw new Win32Exception(Marshal.GetLastWin32Error()); IntPtr hProcess = Process.GetCurrentProcess().Handle; MODULEINFO mi = new MODULEINFO(); bool res = GetModuleInformation(hProcess, hModule, out mi, (uint)Marshal.SizeOf(mi)); if (res == false) throw new Win32Exception(Marshal.GetLastWin32Error()); EnumMemoryRegions(hProcess, mi.lpBaseOfDll, (int)mi.SizeOfImage); Console.ReadKey(); } } }
The text was updated successfully, but these errors were encountered:
No branches or pull requests
ReadMemoryIgnoreErrors can be speeded up by scanning valid memory regions via VirtualQueryEx and reading them as whole, instead of by pages. Example:
The text was updated successfully, but these errors were encountered: