/// <summary> /// Given a process, this function generates a basic memory map of the entire process. All the extra details are skipped. /// </summary> /// <param name="process"></param> /// <returns></returns> public static List<HEAP_INFO> GenerateMemoryMapFast(Process process) { try { // Initialize the return structure List<HEAP_INFO> result = new List<HEAP_INFO>(200); // Walk the process heaps uint address = 0; uint addressLast = uint.MaxValue; MEMORY_BASIC_INFORMATION mbi = new MEMORY_BASIC_INFORMATION(); while (address != addressLast && address < 0x7fffffff) { // Load this heap information uint blockSize = (uint)VirtualQueryEx(process.Handle, address, ref mbi, Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION))); addressLast = address; address = (uint)mbi.BaseAddress + (uint)mbi.RegionSize + 1; // Add this heap information result.Add(new HEAP_INFO((ulong)mbi.BaseAddress, (ulong)mbi.RegionSize, mbi.Protect.ToString(), "", null)); } return result; } catch (Exception ex) { oConsole.printException(ex); return new List<HEAP_INFO>(); } }
static extern Int32 VirtualQueryEx(IntPtr hProcess, uint lpAddress, ref MEMORY_BASIC_INFORMATION buffer, Int32 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>(100); // Create a list of module base addresses List<IntInt> moduleBases = new List<IntInt>(process.Modules.Count); for( int i = 0; i < process.Modules.Count; i++ ) { moduleBases.Add( new IntInt((int) process.Modules[i].BaseAddress, i) ); } IntInt.IntIntComparer comparer = new IntInt.IntIntComparer(); moduleBases.Sort(comparer); // Walk the process heaps uint address = 0; uint addressLast = uint.MaxValue; MEMORY_BASIC_INFORMATION mbi = new MEMORY_BASIC_INFORMATION(); List<ulong> peHeaderBases = new List<ulong>(20); List<IntInt> addressToHeapinfoIndex = new List<IntInt>(100); while (address != addressLast && address < 0x7fffffff) { // Load this heap information uint blockSize = (uint)VirtualQueryEx(process.Handle, address, ref mbi, Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION))); addressLast = address; address = (uint)mbi.BaseAddress + (uint)mbi.RegionSize + 1; // If this is a PE header, lets mark it for processing later bool isPeHeader = HeaderReader.isPeHeader(process, (ulong) mbi.BaseAddress, mbi.Protect); ProcessModule associatedModule = null; if( isPeHeader ) { // Add this PE header base for later processing peHeaderBases.Add((ulong)mbi.BaseAddress); // Try to associate a module with this peHeader int index = moduleBases.BinarySearch(new IntInt((int)mbi.BaseAddress, 0), comparer); if (index < 0) index = ~index - 1; if (index >= 0 && index < moduleBases.Count) associatedModule = process.Modules[moduleBases[index].int2]; } // Add this heap information HEAP_INFO heapInfo = new HEAP_INFO((ulong) mbi.BaseAddress, (ulong) mbi.RegionSize, mbi.Protect.ToString(), (isPeHeader ? "PE HEADER" : ""), associatedModule); result.Add(heapInfo); addressToHeapinfoIndex.Add(new IntInt((int)mbi.BaseAddress, result.Count - 1)); } // Now add all the header information from the PE headers to the regions for (int i = 0; i < peHeaderBases.Count; i++) { // Get this header HeaderReader headerReader = new HeaderReader(process, peHeaderBases[i]); // Find the associated module for this pe header int moduleIndex = moduleBases.BinarySearch(new IntInt((int)peHeaderBases[i], 0), comparer); ProcessModule associatedModule = null; if (moduleIndex < 0) moduleIndex = ~moduleIndex - 1; if (moduleIndex >= 0 && moduleIndex < moduleBases.Count) associatedModule = process.Modules[moduleBases[moduleIndex].int2]; // Record the highest address, because we know the section from the start of the PE until // the highest section is all part of this module int highestAddress = (int) peHeaderBases[i]; // Mark the execution entry point heap int entry = (int) headerReader.optHeader.AddressOfEntryPoint; // Associate this with a heap int index = addressToHeapinfoIndex.BinarySearch(new IntInt(entry + (int)peHeaderBases[i], 0), comparer); if (index < 0) index = ~index - 1; if (index >= 0 && index < addressToHeapinfoIndex.Count) { // We found the heap this section resides in, lets add this section and associate the module. HEAP_INFO newInfo = result[index]; newInfo.associatedModule = associatedModule; // Add the section information newInfo.extra = (newInfo.extra + " entry_point").Trim(); // Change the heap info result[index] = newInfo; if ( (int) newInfo.heapAddress > highestAddress) highestAddress = (int) newInfo.heapAddress; } // Add the section information to the heaps foreach(section section in headerReader.sections ) { // Associate this section with a heap index = addressToHeapinfoIndex.BinarySearch(new IntInt((int)section.SectionHeader.VirtualAddress + (int)peHeaderBases[i], 0), comparer); if (index < 0) index = ~index - 1; if (index >= 0 && index < addressToHeapinfoIndex.Count) { // We found the heap this section resides in, lets add this section and associate the module. HEAP_INFO newInfo = result[index]; newInfo.associatedModule = associatedModule; // Add the section information newInfo.extra = section.Name + " " + newInfo.extra; // Change the heap info result[index] = newInfo; if ((int)newInfo.heapAddress > highestAddress) highestAddress = (int)newInfo.heapAddress; } } // Now associate all heaps up until highestAddress with this module int indexStart = addressToHeapinfoIndex.BinarySearch(new IntInt(entry + (int)peHeaderBases[i], 0), comparer); if (indexStart < 0) indexStart = ~indexStart - 1; int indexEnd = addressToHeapinfoIndex.BinarySearch(new IntInt(highestAddress,0), comparer); if (indexEnd < 0) indexEnd = ~indexEnd - 1; for( int n = indexStart; n <= indexEnd; n++ ) { // Associate this heap HEAP_INFO newInfo = result[n]; newInfo.associatedModule = associatedModule; result[n] = newInfo; } } return result; } catch (Exception ex) { oConsole.printException(ex); return new List<HEAP_INFO>(); } }
public static bool validExecuteAddress(uint address) { bool result = false; // First make sure this address makes sense if (address > 0x0000000000 && address < 0xffffffff) { // Make sure the destination has access writes execute MEMORY_BASIC_INFORMATION mbi = new MEMORY_BASIC_INFORMATION(); try { int size = VirtualQueryEx(oProcess.activeProcess.Handle, (IntPtr)address, ref mbi, Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION))); if (mbi.Protect == MEMORY_PROTECT.PAGE_EXECUTE || mbi.Protect == MEMORY_PROTECT.PAGE_EXECUTE_READ || mbi.Protect == MEMORY_PROTECT.PAGE_EXECUTE_READWRITE || mbi.Protect == MEMORY_PROTECT.PAGE_EXECUTE_WRITECOPY) { // This function call is to a execute page. result = true; } } catch { } } return result; }