From 87f9668b7afab0a532d9d2785e19fed0c027f9cb Mon Sep 17 00:00:00 2001 From: crazy hugsy Date: Mon, 4 Mar 2024 18:17:27 -0800 Subject: [PATCH] Make dumps of type `CompleteMemoryDump` trust `TotalNumberOfPages` header field instead of just `MetadataSize` (#28) --------- Co-authored-by: 0vercl0k <1476421+0vercl0k@users.noreply.github.com> --- README.md | 2 ++ src/lib/kdmp-parser.h | 25 ++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 292812f..caa2d54 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ The library supports loading 64-bit dumps and provides read access to things lik Compiled binaries are available in the [releases](https://github.com/0vercl0k/kdmp-parser/releases) section. Special thanks to: +- [hugsy](https://github.com/hugsy) for numerous contributions: the new Python bindings, CI improvements, new dump types, etc., +- [masthoon](https://github.com/masthoon) for the initial version of the Python bindings, - [yrp604](https://github.com/yrp604) for being knowledgeable about the format, - the [rekall](https://github.com/google/rekall) project and their [Python implementation](https://github.com/google/rekall/blob/master/rekall-core/rekall/plugins/overlays/windows/crashdump.py) (most of the structures in [kdmp-parser-structs.h](https://github.com/0vercl0k/kdmp-parser/blob/master/src/kdmp-parser/kdmp-parser-structs.h) have been adapted from it). diff --git a/src/lib/kdmp-parser.h b/src/lib/kdmp-parser.h index 7bb21cd..c9a2be1 100644 --- a/src/lib/kdmp-parser.h +++ b/src/lib/kdmp-parser.h @@ -585,6 +585,8 @@ class KernelDumpParser { uint8_t *Page = nullptr; uint64_t MetadataSize = 0; uint8_t *Bitmap = nullptr; + uint64_t TotalNumberOfPages = 0; + uint64_t CurrentPageCount = 0; switch (Type) { case DumpType_t::KernelMemoryDump: @@ -597,10 +599,11 @@ class KernelDumpParser { } case DumpType_t::CompleteMemoryDump: { - FirstPageOffset = DmpHdr_->u3.RdmpHeader.Hdr.FirstPageOffset; + FirstPageOffset = DmpHdr_->u3.FullRdmpHeader.Hdr.FirstPageOffset; Page = (uint8_t *)DmpHdr_ + FirstPageOffset; MetadataSize = DmpHdr_->u3.FullRdmpHeader.Hdr.MetadataSize; Bitmap = DmpHdr_->u3.FullRdmpHeader.Bitmap.data(); + TotalNumberOfPages = DmpHdr_->u3.FullRdmpHeader.TotalNumberOfPages; break; } @@ -626,13 +629,33 @@ class KernelDumpParser { uint64_t NumberOfPages; }; + // Sanity check + if (MetadataSize % sizeof(PfnRange)) { + return false; + } + for (uint64_t Offset = 0; Offset < MetadataSize; Offset += sizeof(PfnRange)) { + + if (Type == DumpType_t::CompleteMemoryDump) { + // `CompleteMemoryDump` type seems to be bound by the + // `TotalNumberOfPages` field, *not* by `MetadataSize`. + if (CurrentPageCount == TotalNumberOfPages) { + break; + } + + if (CurrentPageCount > TotalNumberOfPages) { + return false; + } + } + const PfnRange &Entry = (PfnRange &)Bitmap[Offset]; if (!FileMap_.InBounds(&Entry, sizeof(Entry))) { return false; } + CurrentPageCount += Entry.NumberOfPages; + const uint64_t Pfn = Entry.PageFileNumber; if (!Pfn) { break;