public static List<addressRegion> GetValidReadHeaps(Process process) { List<addressRegion> result = new List<addressRegion>(200); // Search the process for heaps long address = 0; long addressLast = long.MaxValue; MEMORY_BASIC_INFORMATION mbi = new MEMORY_BASIC_INFORMATION(); while (address != addressLast) { // Load this heap information long blockSize = (long)VirtualQueryEx(process.Handle, (IntPtr)address, ref mbi, (IntPtr)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION))); addressLast = address; address = (long)mbi.BaseAddress + (long)mbi.RegionSize + 1; // Check if this has READ privilege and does not have a GUARD if ((mbi.Protect & (MEMORY_PROTECT.PAGE_GUARD | MEMORY_PROTECT.PAGE_NOACCESS | MEMORY_PROTECT.PAGE_EXECUTE)) == 0 && mbi.State == StateEnum.MEM_COMMIT) { // This is a valid read heap result.Add(new addressRegion((IntPtr)mbi.BaseAddress, (int)mbi.RegionSize)); } } return result; }
static extern Int32 VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, ref MEMORY_BASIC_INFORMATION buffer, IntPtr dwLength);
/// <summary> /// Given a process, this function generates a memory map of the entire process. /// </summary> /// <param name="process"></param> /// <returns></returns> public static List<HEAP_INFO> GenerateMemoryMap(Process process) { try { // Initialize the return structure List<HEAP_INFO> result = new List<HEAP_INFO>(); // Search the process for heaps long address = 0; long addressLast = long.MaxValue; MEMORY_BASIC_INFORMATION mbi = new MEMORY_BASIC_INFORMATION(); while (address != addressLast) { // Load this heap information long blockSize = (long)VirtualQueryEx(process.Handle, (IntPtr)address, ref mbi, (IntPtr)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION))); if (blockSize == 0) { int error = GetLastError(); error++; } // Try to associate a module with this memory block ProcessModule associatedModule = null; foreach (ProcessModule module in process.Modules) { if (((ulong)module.BaseAddress >= (ulong)mbi.BaseAddress) && ((ulong)module.BaseAddress < (ulong)mbi.BaseAddress + (ulong)mbi.RegionSize)) { associatedModule = module; break; } else if (associatedModule == null && (ulong)module.BaseAddress < (ulong)mbi.BaseAddress) { associatedModule = module; } else if (associatedModule == null) { } else if (((ulong)module.BaseAddress <= (ulong)mbi.BaseAddress) && ((ulong)module.BaseAddress > (ulong)associatedModule.BaseAddress)) { associatedModule = module; } } addressLast = address; address = (long)mbi.BaseAddress + (long)mbi.RegionSize + 1; // Decide if this heap is a PE header or not string peHeader = ""; if (((mbi.Protect & MEMORY_PROTECT.PAGE_GUARD) == 0) && (mbi.State == StateEnum.MEM_COMMIT)) { peHeader = (HeaderReader.isPeHeader(process, (ulong)mbi.BaseAddress, mbi.Protect) ? "PE HEADER" : ""); } // Add this heap information result.Add(new HEAP_INFO((ulong)mbi.BaseAddress, (ulong)mbi.RegionSize, mbi.Protect.ToString(), peHeader, associatedModule, mbi.State, mbi.Protect)); } return result; } catch (Exception ex) { Console.WriteLine(ex.ToString()); return new List<HEAP_INFO>(); } }
public static UInt32 ReadMemoryDword(Process process, IntPtr address) { // Copy the bytes from this heap byte[] buffer = new byte[4]; int numRead = 0; bool result = ReadProcessMemory(process.Handle, (IntPtr)address, buffer, 4, out numRead); // Check that all the data was read correctly if ((UInt32)numRead != 4 || !result) { // Retry once incase we caused a page guard stack growth MEMORY_BASIC_INFORMATION mbi = new MEMORY_BASIC_INFORMATION(); long blockSize = (long)VirtualQueryEx(process.Handle, (IntPtr)address, ref mbi, (IntPtr)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION))); throw new Exception("Failed to read DWORD from address " + address.ToString("X") + ". Read " + numRead.ToString() + " of 4. GetLastError() = " + GetLastError().ToString() + "\n" + mbi.Protect.ToString() + "\n" + mbi.State.ToString()); } return (UInt32)RawDataToObject(ref buffer, typeof(UInt32)); }