public Vtero(string MemoryDump) : this() { MemFile = MemoryDump.ToLower(); if (MemFile.EndsWith(".dmp")) { var dump = new CrashDump(MemFile); if (dump.IsSupportedFormat()) { DetectedDesc = dump.PhysMemDesc; } } else if (MemFile.EndsWith(".vmss") || MemFile.EndsWith(".vmsn") || MemFile.EndsWith(".vmem")) { var dump = new VMWare(MemFile); if (dump.IsSupportedFormat()) { DetectedDesc = dump.PhysMemDesc; MemFile = dump.MemFile; } } scan = new Scanner(MemFile); FileSize = new FileInfo(MemFile).Length; }
public Mem(String mFile) { GapScanSize = 0x10000000; StartOfMemory = 0; MapViewBase = 0; MapViewSize = MapWindowSize = (0x1000 * 0x1000 * 64); // 1G if (File.Exists(mFile)) { MemoryDump = mFile; FileSize = new FileInfo(MemoryDump).Length; MD = new MemoryDescriptor(FileSize); MapViewSize = FileSize < MapWindowSize ? FileSize : MapWindowSize; var lmindex = Interlocked.Increment(ref mindex); var mapName = Path.GetFileNameWithoutExtension(MemoryDump) + lmindex.ToString(); mapStream = new FileStream(MemoryDump, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); mappedFile = MemoryMappedFile.CreateFromFile(mapStream, mapName, 0, MemoryMappedFileAccess.Read, null, HandleInheritability.Inheritable, false); mappedAccess = mappedFile.CreateViewAccessor( MapViewBase, MapViewSize, MemoryMappedFileAccess.Read); DiscoveredGaps = new Dictionary<long, long>(); } }
public Vtero Scanit(ScanOptions op) { bool SkipVMCS = false; #if TESTING foreach (var sx in op.DisabledScans) { var spec = sx.ToLower(); if (spec.Contains("vmcs")) SkipVMCS = true; if (spec.Contains("obsd")) Version = Version & ~PTType.OpenBSD; if (spec.Contains("nbsd")) Version = Version & ~PTType.NetBSD; if (spec.Contains("fbsd")) Version = Version & ~PTType.FreeBSD; if (spec.Contains("lin")) Version = Version & ~PTType.LinuxS; if (spec.Contains("hv")) Version = Version & ~PTType.HyperV; if (spec.Contains("gen")) Version = Version & ~PTType.GENERIC; if (spec.Contains("win")) Version = Version & ~PTType.Windows; } if((Version & PTType.VALUE) == PTType.VALUE) { bool Parsed = false; do { if(args.Length < 2) { WriteLine($"Specify value"); return; } Parsed = uint.TryParse(args[2],NumberStyles.HexNumber, CultureInfo.CurrentCulture, out valuI); if (!Parsed) { Parsed = ulong.TryParse(args[2], NumberStyles.HexNumber, CultureInfo.CurrentCulture, out valuL); if (Parsed) Is64Scan = true; else { WriteLine($"Unable to parse input {args[2]}"); return; } } else valuL = (ulong)valuI; } while (!Parsed); } #endif string Filename = null; Vtero vtero = null; PTType Version = PTType.Windows; // this instance is temporally used for loading state // i.e. don't set properties or fields here var saveStateFile = $"{Filename}.inVtero.net"; if (File.Exists(saveStateFile)) { if (todo.Key != ConsoleKey.D ) { vtero = vtero.CheckpointRestoreState(saveStateFile); vtero.OverRidePhase = true; } else File.Delete(saveStateFile); } if (vtero.Phase < 2) vtero = new Vtero(Filename); //Mem.InitMem(parsed.FileName, null, vtero.DetectedDesc); ProgressBarz.Bar.Message = "First pass, looking for processes"; ForegroundColor = ConsoleColor.Cyan; #if TESTING Timer = Stopwatch.StartNew(); if ((Version & PTType.VALUE) == PTType.VALUE) { var off = vtero.ScanValue(Is64Scan, valuL, 0); WriteLine(FormatRate(vtero.FileSize, Timer.Elapsed)); using (var dstream = File.OpenRead(vtero.MemFile)) { using (var dbin = new BinaryReader(dstream)) { foreach (var xoff in off) { WriteLine($"Checking Memory Descriptor @{(xoff + 28):X}"); if (xoff > vtero.FileSize) { WriteLine($"offset {xoff:X} > FileSize {vtero.FileSize:X}"); continue; } dstream.Position = xoff + 28; var MemRunDescriptor = new MemoryDescriptor(); MemRunDescriptor.NumberOfRuns = dbin.ReadInt64(); MemRunDescriptor.NumberOfPages = dbin.ReadInt64(); Console.WriteLine($"Runs: {MemRunDescriptor.NumberOfRuns}, Pages: {MemRunDescriptor.NumberOfPages} "); if (MemRunDescriptor.NumberOfRuns < 0 || MemRunDescriptor.NumberOfRuns > 32) { continue; } for (int i = 0; i < MemRunDescriptor.NumberOfRuns; i++) { var basePage = dbin.ReadInt64(); var pageCount = dbin.ReadInt64(); MemRunDescriptor.Run.Add(new MemoryRun() { BasePage = basePage, PageCount = pageCount }); } WriteLine($"MemoryDescriptor {MemRunDescriptor}"); } } } WriteLine("Finished VALUE scan."); return; } if ((Version & PTType.VALUE) == PTType.VALUE) return; #endif // basic perf checking QuickOptions.Timer = Stopwatch.StartNew(); var procCount = vtero.ProcDetectScan(Version); WriteColor(ConsoleColor.Blue, ConsoleColor.Yellow, $"{procCount} candidate process page tables. Time so far: {QuickOptions.Timer.Elapsed}, second pass starting. {QuickOptions.FormatRate(vtero.FileSize, QuickOptions.Timer.Elapsed)}"); //BackgroundColor = ConsoleColor.Black; //ForegroundColor = ConsoleColor.Cyan; if (procCount < 3) { WriteColor(ConsoleColor.Red,"Seems like a fail. Try generic scanning or implement a state scan like LinuxS"); return null; } // second pass // with the page tables we acquired, locate candidate VMCS pages in the format // [31-bit revision id][abort indicator] // the page must also have at least 1 64bit value which is all set (-1) // Root-HOST CR3 will have uniform diff // unless an extent based dump image is input, some .DMP variations // TODO: Add support for extent based inputs // Guest VMCS will contain host CR3 & guest CR3 (hCR3 & gCR3) // sometimes CR3 will be found in multiple page tables, e.g. system process or SMP // if I have more than 1 CR3 from different file_offset, just trim them out for now // future may have a reason to isolate based on original locationAG if (SkipVMCS) return vtero; ProgressBarz.Bar.Message = "Second pass, correlating for VMCS pages"; var VMCSCount = vtero.VMCSScan(); //Timer.Stop(); WriteColor(ConsoleColor.Blue, ConsoleColor.Yellow, $"{VMCSCount} candidate VMCS pages. Time to process: {QuickOptions.Timer.Elapsed}, Data scanned: {vtero.FileSize:N}"); // second time WriteColor(ConsoleColor.Blue, ConsoleColor.Yellow, $"Second pass done. {QuickOptions.FormatRate(vtero.FileSize * 2, QuickOptions.Timer.Elapsed)}"); // each of these depends on a VMCS scan/pass having been done at the moment WriteColor(ConsoleColor.Cyan, ConsoleColor.Black, "grouping and joining all memory"); // After this point were fairly functional vtero.GroupAS(); // sync-save state so restarting is faster if (!File.Exists(saveStateFile)) { Write($"Saving checkpoint... "); saveStateFile = vtero.CheckpointSaveState(); WriteColor(ConsoleColor.White, saveStateFile); } return vtero; }
public Vtero(string MemoryDump, MemoryDescriptor MD) : this(MemoryDump) { DetectedDesc = MD; }
public Vtero(string MemoryDump) :this() { MemFile = MemoryDump.ToLower(); if (MemFile.EndsWith(".dmp")) { var dump = new CrashDump(MemFile); if (dump.IsSupportedFormat()) DetectedDesc = dump.PhysMemDesc; } else if(MemFile.EndsWith(".vmss") || MemFile.EndsWith(".vmsn") || MemFile.EndsWith(".vmem")) { var dump = new VMWare(MemFile); if (dump.IsSupportedFormat()) { DetectedDesc = dump.PhysMemDesc; MemFile = dump.MemFile; } } scan = new Scanner(MemFile); FileSize = new FileInfo(MemFile).Length; }
public Vtero Scanit(ScanOptions op) { bool SkipVMCS = false; #if TESTING foreach (var sx in op.DisabledScans) { var spec = sx.ToLower(); if (spec.Contains("vmcs")) { SkipVMCS = true; } if (spec.Contains("obsd")) { Version = Version & ~PTType.OpenBSD; } if (spec.Contains("nbsd")) { Version = Version & ~PTType.NetBSD; } if (spec.Contains("fbsd")) { Version = Version & ~PTType.FreeBSD; } if (spec.Contains("lin")) { Version = Version & ~PTType.LinuxS; } if (spec.Contains("hv")) { Version = Version & ~PTType.HyperV; } if (spec.Contains("gen")) { Version = Version & ~PTType.GENERIC; } if (spec.Contains("win")) { Version = Version & ~PTType.Windows; } } if ((Version & PTType.VALUE) == PTType.VALUE) { bool Parsed = false; do { if (args.Length < 2) { WriteLine($"Specify value"); return; } Parsed = uint.TryParse(args[2], NumberStyles.HexNumber, CultureInfo.CurrentCulture, out valuI); if (!Parsed) { Parsed = ulong.TryParse(args[2], NumberStyles.HexNumber, CultureInfo.CurrentCulture, out valuL); if (Parsed) { Is64Scan = true; } else { WriteLine($"Unable to parse input {args[2]}"); return; } } else { valuL = (ulong)valuI; } } while (!Parsed); } #endif string Filename = null; Vtero vtero = null; PTType Version = PTType.Windows; // this instance is temporally used for loading state // i.e. don't set properties or fields here var saveStateFile = $"{Filename}.inVtero.net"; if (File.Exists(saveStateFile)) { if (todo.Key != ConsoleKey.D) { vtero = vtero.CheckpointRestoreState(saveStateFile); vtero.OverRidePhase = true; } else { File.Delete(saveStateFile); } } if (vtero.Phase < 2) { vtero = new Vtero(Filename); } //Mem.InitMem(parsed.FileName, null, vtero.DetectedDesc); ProgressBarz.Bar.Message = "First pass, looking for processes"; ForegroundColor = ConsoleColor.Cyan; #if TESTING Timer = Stopwatch.StartNew(); if ((Version & PTType.VALUE) == PTType.VALUE) { var off = vtero.ScanValue(Is64Scan, valuL, 0); WriteLine(FormatRate(vtero.FileSize, Timer.Elapsed)); using (var dstream = File.OpenRead(vtero.MemFile)) { using (var dbin = new BinaryReader(dstream)) { foreach (var xoff in off) { WriteLine($"Checking Memory Descriptor @{(xoff + 28):X}"); if (xoff > vtero.FileSize) { WriteLine($"offset {xoff:X} > FileSize {vtero.FileSize:X}"); continue; } dstream.Position = xoff + 28; var MemRunDescriptor = new MemoryDescriptor(); MemRunDescriptor.NumberOfRuns = dbin.ReadInt64(); MemRunDescriptor.NumberOfPages = dbin.ReadInt64(); Console.WriteLine($"Runs: {MemRunDescriptor.NumberOfRuns}, Pages: {MemRunDescriptor.NumberOfPages} "); if (MemRunDescriptor.NumberOfRuns < 0 || MemRunDescriptor.NumberOfRuns > 32) { continue; } for (int i = 0; i < MemRunDescriptor.NumberOfRuns; i++) { var basePage = dbin.ReadInt64(); var pageCount = dbin.ReadInt64(); MemRunDescriptor.Run.Add(new MemoryRun() { BasePage = basePage, PageCount = pageCount }); } WriteLine($"MemoryDescriptor {MemRunDescriptor}"); } } } WriteLine("Finished VALUE scan."); return; } if ((Version & PTType.VALUE) == PTType.VALUE) { return; } #endif // basic perf checking QuickOptions.Timer = Stopwatch.StartNew(); var procCount = vtero.ProcDetectScan(Version); WriteColor(ConsoleColor.Blue, ConsoleColor.Yellow, $"{procCount} candidate process page tables. Time so far: {QuickOptions.Timer.Elapsed}, second pass starting. {QuickOptions.FormatRate(vtero.FileSize, QuickOptions.Timer.Elapsed)}"); //BackgroundColor = ConsoleColor.Black; //ForegroundColor = ConsoleColor.Cyan; if (procCount < 3) { WriteColor(ConsoleColor.Red, "Seems like a fail. Try generic scanning or implement a state scan like LinuxS"); return(null); } // second pass // with the page tables we acquired, locate candidate VMCS pages in the format // [31-bit revision id][abort indicator] // the page must also have at least 1 64bit value which is all set (-1) // Root-HOST CR3 will have uniform diff // unless an extent based dump image is input, some .DMP variations // TODO: Add support for extent based inputs // Guest VMCS will contain host CR3 & guest CR3 (hCR3 & gCR3) // sometimes CR3 will be found in multiple page tables, e.g. system process or SMP // if I have more than 1 CR3 from different file_offset, just trim them out for now // future may have a reason to isolate based on original locationAG if (SkipVMCS) { return(vtero); } ProgressBarz.Bar.Message = "Second pass, correlating for VMCS pages"; var VMCSCount = vtero.VMCSScan(); //Timer.Stop(); WriteColor(ConsoleColor.Blue, ConsoleColor.Yellow, $"{VMCSCount} candidate VMCS pages. Time to process: {QuickOptions.Timer.Elapsed}, Data scanned: {vtero.FileSize:N}"); // second time WriteColor(ConsoleColor.Blue, ConsoleColor.Yellow, $"Second pass done. {QuickOptions.FormatRate(vtero.FileSize * 2, QuickOptions.Timer.Elapsed)}"); // each of these depends on a VMCS scan/pass having been done at the moment WriteColor(ConsoleColor.Cyan, ConsoleColor.Black, "grouping and joining all memory"); // After this point were fairly functional vtero.GroupAS(); // sync-save state so restarting is faster if (!File.Exists(saveStateFile)) { Write($"Saving checkpoint... "); saveStateFile = vtero.CheckpointSaveState(); WriteColor(ConsoleColor.White, saveStateFile); } return(vtero); }
public static Vtero Scanit(ConfigOptions co) { bool SkipVMCS = (co.VersionsToEnable & PTType.VMCS) != PTType.VMCS; var Filename = co.FileName; co.VersionsToEnable = co.VersionsToEnable & ~PTType.VMCS; // allocate now so that we can un-serialize or keep an instance Vtero vtero = new Vtero(); // this instance is temporally used for loading state // i.e. don't set properties or fields here var saveStateFile = $"{Filename}.inVtero.net"; if (File.Exists(saveStateFile)) { if (!co.IgnoreSaveData) { vtero = vtero.CheckpointRestoreState(saveStateFile); if(vtero == null) { WriteColor(ConsoleColor.Red, "ERROR IN SERIALIZER"); return null; } vtero.OverRidePhase = true; } else File.Delete(saveStateFile); } if (vtero.Phase < 2) vtero = new Vtero(Filename); if (!vtero.OverRidePhase) { Mem.InitMem(co.FileName, vtero.MRD); ProgressBarz.BaseMessage = new ConsoleString("First pass, looking for processes"); ForegroundColor = ConsoleColor.Cyan; #if TESTING Timer = Stopwatch.StartNew(); if ((Version & PTType.VALUE) == PTType.VALUE) { var off = vtero.ScanValue(Is64Scan, valuL, 0); WriteLine(FormatRate(vtero.FileSize, Timer.Elapsed)); using (var dstream = File.OpenRead(vtero.MemFile)) { using (var dbin = new BinaryReader(dstream)) { foreach (var xoff in off) { WriteLine($"Checking Memory Descriptor @{(xoff + 28):X}"); if (xoff > vtero.FileSize) { WriteLine($"offset {xoff:X} > FileSize {vtero.FileSize:X}"); continue; } dstream.Position = xoff + 28; var MemRunDescriptor = new MemoryDescriptor(); MemRunDescriptor.NumberOfRuns = dbin.ReadInt64(); MemRunDescriptor.NumberOfPages = dbin.ReadInt64(); Console.WriteLine($"Runs: {MemRunDescriptor.NumberOfRuns}, Pages: {MemRunDescriptor.NumberOfPages} "); if (MemRunDescriptor.NumberOfRuns < 0 || MemRunDescriptor.NumberOfRuns > 32) { continue; } for (int i = 0; i < MemRunDescriptor.NumberOfRuns; i++) { var basePage = dbin.ReadInt64(); var pageCount = dbin.ReadInt64(); MemRunDescriptor.Run.Add(new MemoryRun() { BasePage = basePage, PageCount = pageCount }); } WriteLine($"MemoryDescriptor {MemRunDescriptor}"); } } } WriteLine("Finished VALUE scan."); return; } if ((Version & PTType.VALUE) == PTType.VALUE) return; #endif } // basic perf checking QuickOptions.Timer = Stopwatch.StartNew(); var procCount = vtero.ProcDetectScan(co.VersionsToEnable); if (!vtero.OverRidePhase) { WriteColor(ConsoleColor.Blue, ConsoleColor.Yellow, $"{procCount} candidate process page tables. Time so far: {QuickOptions.Timer.Elapsed}, second pass starting. {QuickOptions.FormatRate(vtero.FileSize, QuickOptions.Timer.Elapsed)}"); if (procCount < 3) { WriteColor(ConsoleColor.Red, "Seems like a fail. Try generic scanning or implement a state scan like LinuxS"); return null; } } // second pass // with the page tables we acquired, locate candidate VMCS pages in the format // [31-bit revision id][abort indicator] // the page must also have at least 1 64bit value which is all set (-1) // Root-HOST CR3 will have uniform diff // unless an extent based dump image is input, some .DMP variations // TODO: Add support for extent based inputs // Guest VMCS will contain host CR3 & guest CR3 (hCR3 & gCR3) // sometimes CR3 will be found in multiple page tables, e.g. system process or SMP // if I have more than 1 CR3 from different file_offset, just trim them out for now // future may have a reason to isolate based on original locationAG if (SkipVMCS) { if (!vtero.OverRidePhase) vtero.GroupAS(); if (co.VerboseLevel > 1) WriteColor(ConsoleColor.Yellow, "Skipping VMCS scan (as requested)."); } else { ProgressBarz.BaseMessage = new ConsoleString("Second pass, correlating for VMCS pages"); var VMCSCount = vtero.VMCSScan(); //Timer.Stop(); if (!vtero.OverRidePhase) { WriteColor(ConsoleColor.Blue, ConsoleColor.Yellow, $"{VMCSCount} candidate VMCS pages. Time to process: {QuickOptions.Timer.Elapsed}, Data scanned: {vtero.FileSize:N}"); // second time WriteColor(ConsoleColor.Blue, ConsoleColor.Yellow, $"Second pass done. {QuickOptions.FormatRate(vtero.FileSize * 2, QuickOptions.Timer.Elapsed)}"); // each of these depends on a VMCS scan/pass having been done at the moment WriteColor(ConsoleColor.Cyan, ConsoleColor.Black, "grouping and joining all memory"); } // After this point were fairly functional vtero.GroupAS(); } // sync-save state so restarting is faster if (!File.Exists(saveStateFile)) { Write($"Saving checkpoint... "); saveStateFile = vtero.CheckpointSaveState(); WriteColor(ConsoleColor.White, saveStateFile); } Console.CursorVisible = true; return vtero; }
public Mem(String mFile, uint[] BitmapArray = null, MemoryDescriptor Override = null) { GapScanSize = 0x10000000; StartOfMemory = Override != null ? Override.StartOfMemmory : 0; MapViewBase = 0; MapViewSize = MapWindowSize = (0x1000 * 0x1000 * 4); // Due to the physical page allocation algorithm a modest window is probably fine // so not even 1/2 the size of the window which was only getting < 50% hit ratio at best // PageCache may be better off than a huge window... if (PageCache == null) { PageCache = new ConcurrentDictionary <long, long[]>(8, PageCacheMax); } if (BitmapArray != null) { pfnTableIdx = new WAHBitArray(WAHBitArray.TYPE.Bitarray, BitmapArray); } else { pfnTableIdx = new WAHBitArray(); } // 32bit's of pages should be plenty? pfnTableIdx.Length = (int)(MapViewSize / 0x1000); if (File.Exists(mFile)) { MemoryDump = mFile; FileSize = new FileInfo(MemoryDump).Length; if (Override != null) { MD = Override; } else { MD = new MemoryDescriptor(FileSize); if (DetectedDescriptor != null) { MD = DetectedDescriptor; } } MapViewSize = FileSize < MapWindowSize ? FileSize : MapWindowSize; var lmindex = Interlocked.Increment(ref mindex); var mapName = Path.GetFileNameWithoutExtension(MemoryDump) + lmindex.ToString(); mapStream = new FileStream(MemoryDump, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); mappedFile = MemoryMappedFile.CreateFromFile(mapStream, mapName, 0, MemoryMappedFileAccess.Read, null, HandleInheritability.Inheritable, false); mappedAccess = mappedFile.CreateViewAccessor( MapViewBase, MapViewSize, MemoryMappedFileAccess.Read); DiscoveredGaps = new Dictionary <long, long>(); } }
public Mem(String mFile, uint[] BitmapArray = null, MemoryDescriptor Override = null) { GapScanSize = 0x10000000; StartOfMemory = Override != null ? Override.StartOfMemmory : 0; MapViewBase = 0; MapViewSize = MapWindowSize = (0x1000 * 0x1000 * 4); // Due to the physical page allocation algorithm a modest window is probably fine // so not even 1/2 the size of the window which was only getting < 50% hit ratio at best // PageCache may be better off than a huge window... if (PageCache == null) PageCache = new ConcurrentDictionary<long, long[]>(8, PageCacheMax); if (BitmapArray != null) pfnTableIdx = new WAHBitArray(WAHBitArray.TYPE.Bitarray, BitmapArray); else pfnTableIdx = new WAHBitArray(); // 32bit's of pages should be plenty? pfnTableIdx.Length = (int) (MapViewSize / 0x1000); if (File.Exists(mFile)) { MemoryDump = mFile; FileSize = new FileInfo(MemoryDump).Length; if (Override != null) MD = Override; else { MD = new MemoryDescriptor(FileSize); if (DetectedDescriptor != null) MD = DetectedDescriptor; } MapViewSize = FileSize < MapWindowSize ? FileSize : MapWindowSize; var lmindex = Interlocked.Increment(ref mindex); var mapName = Path.GetFileNameWithoutExtension(MemoryDump) + lmindex.ToString(); mapStream = new FileStream(MemoryDump, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); mappedFile = MemoryMappedFile.CreateFromFile(mapStream, mapName, 0, MemoryMappedFileAccess.Read, null, HandleInheritability.Inheritable, false); mappedAccess = mappedFile.CreateViewAccessor( MapViewBase, MapViewSize, MemoryMappedFileAccess.Read); DiscoveredGaps = new Dictionary<long, long>(); } }
public override bool IsSupportedFormat(Vtero vtero) { bool rv = false; if (!File.Exists(DumpFile)) return rv; // use abstract implementation & scan for internal LogicalPhysMemDesc = ExtractMemDesc(vtero); using (var dstream = File.OpenRead(DumpFile)) { MemSize = dstream.Length; using (var dbin = new BinaryReader(dstream)) { // start with a easy to handle format of DMP if (ASCIIEncoding.ASCII.GetString(dbin.ReadBytes(8)) != "PAGEDU64") return rv; dbin.BaseStream.Position = 0x2020; StartOfMem = dbin.ReadUInt32(); // Find the RUN info dbin.BaseStream.Position = 0x88; var MemRunDescriptor = new MemoryDescriptor(); MemRunDescriptor.StartOfMemmory = StartOfMem; MemRunDescriptor.NumberOfRuns = dbin.ReadInt64(); MemRunDescriptor.NumberOfPages = dbin.ReadInt64(); // this struct has to fit in the header which is only 0x2000 in total size if (MemRunDescriptor.NumberOfRuns > 32 || MemRunDescriptor.NumberOfRuns < 0) { // TODO: in this case we have to de-patchguard the KDDEBUGGER_DATA block // before resulting to that... implemented a memory scanning mode to extract the runs out via struct detection PhysMemDesc = LogicalPhysMemDesc; PhysMemDesc.StartOfMemmory = StartOfMem; // physmem is preferred place to load from so if we have only 1 run move it to phys. LogicalPhysMemDesc = null; } else { // in this case StartOfMem is 0x2000 MemRunDescriptor.StartOfMemmory = 0x2000; // we have an embedded RUN in the DMP file that appears to conform to the rules we know for (int i = 0; i < MemRunDescriptor.NumberOfRuns; i++) { var basePage = dbin.ReadInt64(); var pageCount = dbin.ReadInt64(); MemRunDescriptor.Run.Add(new MemoryRun() { BasePage = basePage, PageCount = pageCount }); } PhysMemDesc = MemRunDescriptor; } rv = true; } } #if OLD_CODE long aSkipCount = 0; for (int i = 0; i < PhysMemDesc.NumberOfRuns; i++) { var RunSkip = PhysMemDesc.Run[i].BasePage - aSkipCount; PhysMemDesc.Run[i].SkipCount = RunSkip; aSkipCount = PhysMemDesc.Run[i].BasePage + PhysMemDesc.Run[i].PageCount; } #endif return rv; }