From 0d1c72d606c17bc71438a1099a91e8f790ec8851 Mon Sep 17 00:00:00 2001 From: 0vercl0k <1476421+0vercl0k@users.noreply.github.com> Date: Sat, 26 Sep 2020 16:24:22 -0700 Subject: [PATCH 01/13] dead code found by pvs. --- src/lib/filemap.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/lib/filemap.h b/src/lib/filemap.h index e31cd54..086ab7c 100644 --- a/src/lib/filemap.h +++ b/src/lib/filemap.h @@ -139,15 +139,6 @@ class FileMap { clean: - // - // Unmap the view of the mapping.. - // - - if (ViewBase != nullptr) { - UnmapViewOfFile(ViewBase); - ViewBase = nullptr; - } - // // Close the handle to the file mapping.. // From b6ca824743c3f03b812fdff9e0b29d90fe9d346c Mon Sep 17 00:00:00 2001 From: 0vercl0k <1476421+0vercl0k@users.noreply.github.com> Date: Sat, 26 Sep 2020 16:29:49 -0700 Subject: [PATCH 02/13] few nits --- src/lib/filemap.h | 30 ++++++++++++++++++------------ src/lib/kdmp-parser.cc | 11 ----------- src/lib/kdmp-parser.h | 8 +++----- 3 files changed, 21 insertions(+), 28 deletions(-) diff --git a/src/lib/filemap.h b/src/lib/filemap.h index 086ab7c..ff90e16 100644 --- a/src/lib/filemap.h +++ b/src/lib/filemap.h @@ -3,29 +3,29 @@ #include #if defined(WINDOWS) -class FileMap { +class FileMap_t { // // Handle to the input file. // - HANDLE File_; + HANDLE File_ = nullptr; // // Handle to the file mapping. // - HANDLE FileMap_; + HANDLE FileMap_ = nullptr; // // Base address of the file view. // - PVOID ViewBase_; + PVOID ViewBase_ = nullptr; public: - FileMap() : File_(nullptr), FileMap_(nullptr), ViewBase_(nullptr) {} + explicit FileMap_t() = default; - ~FileMap() { + ~FileMap_t() { // // Unmap the view of the mapping.. // @@ -54,6 +54,9 @@ class FileMap { } } + FileMap_t(const FileMap_t &) = delete; + FileMap_t &operator=(const FileMap_t &) = delete; + void *ViewBase() { return ViewBase_; } bool MapFile(const char *PathFile) { @@ -170,15 +173,15 @@ class FileMap { #include #include -class FileMap { - void *ViewBase_; - off_t ViewSize_; - int Fd_; +class FileMap_t { + void *ViewBase_ = nullptr; + off_t ViewSize_ = 0; + int Fd_ = -1; public: - FileMap() : ViewBase_(nullptr), ViewSize_(0), Fd_(-1) {} + explicit FileMap_t() = default; - ~FileMap() { + ~FileMap_t() { if (ViewBase_) { munmap(ViewBase_, ViewSize_); ViewBase_ = nullptr; @@ -191,6 +194,9 @@ class FileMap { } } + FileMap_t(const FileMap_t &) = delete; + FileMap_t &operator=(const FileMap_t &) = delete; + void *ViewBase() { return ViewBase_; } bool MapFile(const char *PathFile) { diff --git a/src/lib/kdmp-parser.cc b/src/lib/kdmp-parser.cc index cf25add..fd57dd6 100644 --- a/src/lib/kdmp-parser.cc +++ b/src/lib/kdmp-parser.cc @@ -1,17 +1,6 @@ // Axel '0vercl0k' Souchet - February 15 2019 #include "kdmp-parser.h" -KernelDumpParser::KernelDumpParser() : DmpHdr_(nullptr), PathFile_(nullptr) {} - -KernelDumpParser::~KernelDumpParser() { - - // - // Empty out the physmem. - // - - Physmem_.clear(); -} - bool KernelDumpParser::Parse(const char *PathFile) { // diff --git a/src/lib/kdmp-parser.h b/src/lib/kdmp-parser.h index 4acad70..469d826 100644 --- a/src/lib/kdmp-parser.h +++ b/src/lib/kdmp-parser.h @@ -15,8 +15,6 @@ struct BugCheckParameters_t { class KernelDumpParser { public: - KernelDumpParser(); - ~KernelDumpParser(); // // Actually do the parsing of the file. @@ -127,19 +125,19 @@ class KernelDumpParser { // The mapped file. // - FileMap FileMap_; + FileMap_t FileMap_; // // Header of the crash-dump. // - KDMP_PARSER_HEADER64 *DmpHdr_; + KDMP_PARSER_HEADER64 *DmpHdr_ = nullptr; // // File path to the crash-dump. // - const char *PathFile_; + const char *PathFile_ = nullptr; // // Mapping between physical addresses / page data. From 5783cc62889367de8235fd3688e169271efd78e9 Mon Sep 17 00:00:00 2001 From: 0vercl0k <1476421+0vercl0k@users.noreply.github.com> Date: Sat, 26 Sep 2020 16:41:06 -0700 Subject: [PATCH 03/13] nits --- src/lib/kdmp-parser.cc | 8 +++----- src/parser/parser.cc | 25 ++++++++----------------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/lib/kdmp-parser.cc b/src/lib/kdmp-parser.cc index fd57dd6..e115e71 100644 --- a/src/lib/kdmp-parser.cc +++ b/src/lib/kdmp-parser.cc @@ -80,13 +80,11 @@ const BugCheckParameters_t KernelDumpParser::GetBugCheckParameters() { // // Give the user a view of the bugcheck parameters. // + BugCheckParameters_t Parameters = { DmpHdr_->BugCheckCode, - DmpHdr_->BugCheckCodeParameter[0], - DmpHdr_->BugCheckCodeParameter[1], - DmpHdr_->BugCheckCodeParameter[2], - DmpHdr_->BugCheckCodeParameter[3], - }; + {DmpHdr_->BugCheckCodeParameter[0], DmpHdr_->BugCheckCodeParameter[1], + DmpHdr_->BugCheckCodeParameter[2], DmpHdr_->BugCheckCodeParameter[3]}}; return Parameters; } diff --git a/src/parser/parser.cc b/src/parser/parser.cc index 1768d2e..625bb0d 100644 --- a/src/parser/parser.cc +++ b/src/parser/parser.cc @@ -23,58 +23,49 @@ struct Options_t { // This is enabled if -h is used. // - bool ShowHelp; + bool ShowHelp = false; // // This is enabled if -c is used. // - bool ShowContextRecord; + bool ShowContextRecord = false; // // This is enabled if -a is used. // - bool ShowAllStructures; + bool ShowAllStructures = false; // // This is enabled if -e is used. // - bool ShowExceptionRecord; + bool ShowExceptionRecord = false; // // This is enable if -p is used. // - bool ShowPhysicalMem; + bool ShowPhysicalMem = false; // // This is on if the user specified a physical address. // - bool HasPhysicalAddress; + bool HasPhysicalAddress = false; // // If an optional physical address has been passed to -p then this is the // physical address. - uint64_t PhysicalAddress; + uint64_t PhysicalAddress = 0; // // The path to the dump file. // - char *DumpPath; - - // - // Initialize all teh things! - // - - Options_t() - : ShowHelp(false), ShowContextRecord(false), ShowPhysicalMem(false), - ShowAllStructures(false), ShowExceptionRecord(false), - HasPhysicalAddress(0), PhysicalAddress(0), DumpPath(nullptr) {} + char *DumpPath = nullptr; }; // From 9781136af5d81934be9fae647fc2ad26fee1bb12 Mon Sep 17 00:00:00 2001 From: 0vercl0k <1476421+0vercl0k@users.noreply.github.com> Date: Sat, 26 Sep 2020 16:43:39 -0700 Subject: [PATCH 04/13] fix a few /w4 diff --git a/src/python/python-kdmp.cc b/src/python/python-kdmp.cc index 4682b42..6444770 100644 --- a/src/python/python-kdmp.cc +++ b/src/python/python-kdmp.cc @@ -7,10 +7,12 @@ // PyObject *NewDumpParser(PyTypeObject *Type, PyObject *Args, PyObject *Kwds) { + UNREFERENCED_PARAMETER(Kwds); // // Allocate and zero PythonDumpParser. // + PythonDumpParser *Self = reinterpret_cast(Type->tp_alloc(Type, 0)); Self->DumpParser = nullptr; @@ -74,6 +76,7 @@ void DeleteDumpParser(PyObject *Object) { // PyObject *DumpParserGetType(PyObject *Object, PyObject *NotUsed) { + UNREFERENCED_PARAMETER(NotUsed); // // Get the dump type (FullDump, KernelDump or BMPDump). @@ -89,6 +92,7 @@ PyObject *DumpParserGetType(PyObject *Object, PyObject *NotUsed) { // PyObject *DumpParserGetContext(PyObject *Object, PyObject *NotUsed) { + UNREFERENCED_PARAMETER(NotUsed); // // Get the dump context (commons registers). @@ -139,6 +143,7 @@ PyObject *DumpParserGetContext(PyObject *Object, PyObject *NotUsed) { // PyObject *DumpParserGetBugCheckParameters(PyObject *Object, PyObject *NotUsed) { + UNREFERENCED_PARAMETER(NotUsed); // // Retrieve the bugcheck parameters. --- src/python/python-kdmp.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/python/python-kdmp.cc b/src/python/python-kdmp.cc index 4682b42..6444770 100644 --- a/src/python/python-kdmp.cc +++ b/src/python/python-kdmp.cc @@ -7,10 +7,12 @@ // PyObject *NewDumpParser(PyTypeObject *Type, PyObject *Args, PyObject *Kwds) { + UNREFERENCED_PARAMETER(Kwds); // // Allocate and zero PythonDumpParser. // + PythonDumpParser *Self = reinterpret_cast(Type->tp_alloc(Type, 0)); Self->DumpParser = nullptr; @@ -74,6 +76,7 @@ void DeleteDumpParser(PyObject *Object) { // PyObject *DumpParserGetType(PyObject *Object, PyObject *NotUsed) { + UNREFERENCED_PARAMETER(NotUsed); // // Get the dump type (FullDump, KernelDump or BMPDump). @@ -89,6 +92,7 @@ PyObject *DumpParserGetType(PyObject *Object, PyObject *NotUsed) { // PyObject *DumpParserGetContext(PyObject *Object, PyObject *NotUsed) { + UNREFERENCED_PARAMETER(NotUsed); // // Get the dump context (commons registers). @@ -139,6 +143,7 @@ PyObject *DumpParserGetContext(PyObject *Object, PyObject *NotUsed) { // PyObject *DumpParserGetBugCheckParameters(PyObject *Object, PyObject *NotUsed) { + UNREFERENCED_PARAMETER(NotUsed); // // Retrieve the bugcheck parameters. From 232eb22fa99cbc9cd5cc52037873a08844febf85 Mon Sep 17 00:00:00 2001 From: 0vercl0k <1476421+0vercl0k@users.noreply.github.com> Date: Sat, 26 Sep 2020 16:51:01 -0700 Subject: [PATCH 05/13] cosmetic --- src/lib/kdmp-parser-structs.h | 6 +++++ src/lib/kdmp-parser.h | 50 +++++++++++++++++------------------ 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/lib/kdmp-parser-structs.h b/src/lib/kdmp-parser-structs.h index c53d92e..a1d3f8e 100644 --- a/src/lib/kdmp-parser-structs.h +++ b/src/lib/kdmp-parser-structs.h @@ -7,6 +7,12 @@ #include #include +// +// Disable: warning C4201: nonstandard extension used: nameless struct/union +// + +#pragma warning(disable : 4201) + #ifndef WINDOWS #define EXCEPTION_MAXIMUM_PARAMETERS 15 struct EXCEPTION_RECORD64 { diff --git a/src/lib/kdmp-parser.h b/src/lib/kdmp-parser.h index 469d826..e629243 100644 --- a/src/lib/kdmp-parser.h +++ b/src/lib/kdmp-parser.h @@ -14,8 +14,32 @@ struct BugCheckParameters_t { }; class KernelDumpParser { -public: +private: + // + // The mapped file. + // + + FileMap_t FileMap_; + + // + // Header of the crash-dump. + // + + KDMP_PARSER_HEADER64 *DmpHdr_ = nullptr; + + // + // File path to the crash-dump. + // + + const char *PathFile_ = nullptr; + + // + // Mapping between physical addresses / page data. + // + + Physmem_t Physmem_; +public: // // Actually do the parsing of the file. // @@ -120,28 +144,4 @@ class KernelDumpParser { // bool MapFile(); - - // - // The mapped file. - // - - FileMap_t FileMap_; - - // - // Header of the crash-dump. - // - - KDMP_PARSER_HEADER64 *DmpHdr_ = nullptr; - - // - // File path to the crash-dump. - // - - const char *PathFile_ = nullptr; - - // - // Mapping between physical addresses / page data. - // - - Physmem_t Physmem_; }; \ No newline at end of file From ae6435fe9e27d9c99ed6c519e3c2eafa285952f8 Mon Sep 17 00:00:00 2001 From: 0vercl0k <1476421+0vercl0k@users.noreply.github.com> Date: Sat, 26 Sep 2020 16:55:44 -0700 Subject: [PATCH 06/13] UNREFERENCED_PARAMETER is not xplat! diff --git a/src/python/python-kdmp.cc b/src/python/python-kdmp.cc index 6444770..55d0a92 100644 --- a/src/python/python-kdmp.cc +++ b/src/python/python-kdmp.cc @@ -6,8 +6,7 @@ // >>> Dump(filepath) // -PyObject *NewDumpParser(PyTypeObject *Type, PyObject *Args, PyObject *Kwds) { - UNREFERENCED_PARAMETER(Kwds); +PyObject *NewDumpParser(PyTypeObject *Type, PyObject *Args, PyObject *) { // // Allocate and zero PythonDumpParser. @@ -75,8 +74,7 @@ void DeleteDumpParser(PyObject *Object) { // >>> dump_instance.type() # return int // -PyObject *DumpParserGetType(PyObject *Object, PyObject *NotUsed) { - UNREFERENCED_PARAMETER(NotUsed); +PyObject *DumpParserGetType(PyObject *Object, PyObject *) { // // Get the dump type (FullDump, KernelDump or BMPDump). @@ -91,8 +89,7 @@ PyObject *DumpParserGetType(PyObject *Object, PyObject *NotUsed) { // >>> dump_instance.context() # return dict(str -> int) // -PyObject *DumpParserGetContext(PyObject *Object, PyObject *NotUsed) { - UNREFERENCED_PARAMETER(NotUsed); +PyObject *DumpParserGetContext(PyObject *Object, PyObject *) { // // Get the dump context (commons registers). @@ -142,8 +139,7 @@ PyObject *DumpParserGetContext(PyObject *Object, PyObject *NotUsed) { // >>> dump_instance.bugcheck() # return dict // -PyObject *DumpParserGetBugCheckParameters(PyObject *Object, PyObject *NotUsed) { - UNREFERENCED_PARAMETER(NotUsed); +PyObject *DumpParserGetBugCheckParameters(PyObject *Object, PyObject *) { // // Retrieve the bugcheck parameters. --- src/python/python-kdmp.cc | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/python/python-kdmp.cc b/src/python/python-kdmp.cc index 6444770..55d0a92 100644 --- a/src/python/python-kdmp.cc +++ b/src/python/python-kdmp.cc @@ -6,8 +6,7 @@ // >>> Dump(filepath) // -PyObject *NewDumpParser(PyTypeObject *Type, PyObject *Args, PyObject *Kwds) { - UNREFERENCED_PARAMETER(Kwds); +PyObject *NewDumpParser(PyTypeObject *Type, PyObject *Args, PyObject *) { // // Allocate and zero PythonDumpParser. @@ -75,8 +74,7 @@ void DeleteDumpParser(PyObject *Object) { // >>> dump_instance.type() # return int // -PyObject *DumpParserGetType(PyObject *Object, PyObject *NotUsed) { - UNREFERENCED_PARAMETER(NotUsed); +PyObject *DumpParserGetType(PyObject *Object, PyObject *) { // // Get the dump type (FullDump, KernelDump or BMPDump). @@ -91,8 +89,7 @@ PyObject *DumpParserGetType(PyObject *Object, PyObject *NotUsed) { // >>> dump_instance.context() # return dict(str -> int) // -PyObject *DumpParserGetContext(PyObject *Object, PyObject *NotUsed) { - UNREFERENCED_PARAMETER(NotUsed); +PyObject *DumpParserGetContext(PyObject *Object, PyObject *) { // // Get the dump context (commons registers). @@ -142,8 +139,7 @@ PyObject *DumpParserGetContext(PyObject *Object, PyObject *NotUsed) { // >>> dump_instance.bugcheck() # return dict // -PyObject *DumpParserGetBugCheckParameters(PyObject *Object, PyObject *NotUsed) { - UNREFERENCED_PARAMETER(NotUsed); +PyObject *DumpParserGetBugCheckParameters(PyObject *Object, PyObject *) { // // Retrieve the bugcheck parameters. From 36639aa205b8994f6bdd4e59c0e321b4e33e2f54 Mon Sep 17 00:00:00 2001 From: 0vercl0k <1476421+0vercl0k@users.noreply.github.com> Date: Sat, 26 Sep 2020 17:04:12 -0700 Subject: [PATCH 07/13] nits --- src/python/python-kdmp.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/python/python-kdmp.cc b/src/python/python-kdmp.cc index 55d0a92..9683baa 100644 --- a/src/python/python-kdmp.cc +++ b/src/python/python-kdmp.cc @@ -150,12 +150,15 @@ PyObject *DumpParserGetBugCheckParameters(PyObject *Object, PyObject *) { const BugCheckParameters_t Parameters = Self->DumpParser->GetBugCheckParameters(); - PyObject *PythonParamsList = PyList_New(4); + const uint64_t NumberParams = sizeof(Parameters.BugCheckCodeParameter) / + sizeof(Parameters.BugCheckCodeParameter[0]); + PyObject *PythonParamsList = PyList_New(NumberParams); - for (uint64_t idx = 0; idx < 4; idx++) + for (uint64_t Idx = 0; Idx < NumberParams; Idx++) { PyList_SetItem( - PythonParamsList, idx, - PyLong_FromUnsignedLongLong(Parameters.BugCheckCodeParameter[idx])); + PythonParamsList, Idx, + PyLong_FromUnsignedLongLong(Parameters.BugCheckCodeParameter[Idx])); + } // // Create a Python dict object with code and parameters. From 1cbecac9d171a47920081b66be3689deb0d3c643 Mon Sep 17 00:00:00 2001 From: 0vercl0k <1476421+0vercl0k@users.noreply.github.com> Date: Sat, 26 Sep 2020 17:27:53 -0700 Subject: [PATCH 08/13] clean up readme --- README.md | 194 +++++------------------------------------------------- 1 file changed, 18 insertions(+), 176 deletions(-) diff --git a/README.md b/README.md index 9b735fc..8dab540 100644 --- a/README.md +++ b/README.md @@ -2,25 +2,26 @@ ![Build status](https://github.com/0vercl0k/kdmp-parser/workflows/Builds/badge.svg) -This is a small C++ library able to parse Windows kernel full dump (`.dump /f` in WinDbg) as well as BMP dump (`.dump /ka` in WinDbg). The format has been introduced around Windows 8 timeframe according to the [rekall](https://github.com/google/rekall) project. Note that most of the structures used in [kdmp-parser-structs.h](https://github.com/0vercl0k/kdmp-parser/blob/master/src/kdmp-parser/kdmp-parser-structs.h) have been adapted / taken from 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). +This C++ library parses Windows kernel [full](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/complete-memory-dump) dump (`.dump /f` in WinDbg) as well as [BMP](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/active-memory-dump) dump (`.dump /ka` in WinDbg). ![parser](pics/parser.jpg) -The library supports only loading 64-bit dumps (but either x86 or x64 build can do that). It provides read access (no write access) to: +The library supports loading 64-bit dumps and provides read access (not write) to: - The context record, - The exception record, +- The bugcheck parameters, - The physical memory. -Special cheers to [yrp604](https://github.com/yrp604) for being knowledgeable about it. +Compiled binaries are available in the [releases](https://github.com/0vercl0k/kdmp-parser/releases) section. -## Python 3 bindings - -The project includes Python 3 bindings (courtesy of [@masthoon](https://github.com/masthoon)) that allows you to: read the context, read physical memory as well as to do virtual memory translations. +Special thanks to: +- [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). -If you don't want to compile them yourself, you can grab binaries directly from the CI [artifacts](https://github.com/0vercl0k/kdmp-parser/actions). +## Python 3 bindings -Here is an example: +The bindings (contributed by [@masthoon](https://github.com/masthoon)) allow you to: read the context, read physical memory as well as to do virtual memory translations. ```py from kdmp import Dump, FullDump, BMPDump @@ -49,7 +50,7 @@ assert(dmp.get_virtual_page(v) == dmp.get_physical_page(dmp.virt_translate(v))) ## Parser -The `parser.exe` application is a small utility made to dump various information about the dump file: exception record, context record, etc. +The `parser.exe` application is a utility able to dump various information about the dump file: exception record, context record, etc. ```text kdmp-parser\src>x64\Debug\parser.exe -c -e -p 0x1000 full.dmp @@ -121,9 +122,11 @@ Physical memory: ## Building +You can build it yourself using `builder.py` or [CMake](https://cmake.org/) on either [Windows](#Windows) or [Linux](#Linux). More detailed information are described in the below sections. + ### Linux -You can build it via the command line using `builder.py` or invoking `cmake` yourself (also works in WSL): +You can build it via the command line using `builder.py` or by invoking `cmake` yourself: ```text over@oof:/kdmp-parser$ python3 builder.py -h @@ -138,115 +141,30 @@ optional arguments: --arch {x64,x86} over@oof:/kdmp-parser$ python3 builder.py --configuration Debug --- The C compiler identification is GNU 7.4.0 --- The CXX compiler identification is GNU 7.4.0 --- Check for working C compiler: /usr/bin/cc --- Check for working C compiler: /usr/bin/cc -- works --- Detecting C compiler ABI info --- Detecting C compiler ABI info - done --- Detecting C compile features --- Detecting C compile features - done --- Check for working CXX compiler: /usr/bin/c++ --- Check for working CXX compiler: /usr/bin/c++ -- works --- Detecting CXX compiler ABI info --- Detecting CXX compiler ABI info - done --- Detecting CXX compile features --- Detecting CXX compile features - done --- Configuring done --- Generating done --- Build files have been written to: /kdmp-parser/build/linx64-Debug +... [6/6] Linking CXX executable ../../bin/linx64-Debug/testapp --- The C compiler identification is GNU 7.4.0 --- The CXX compiler identification is GNU 7.4.0 --- Check for working C compiler: /usr/bin/cc --- Check for working C compiler: /usr/bin/cc -- works --- Detecting C compiler ABI info --- Detecting C compiler ABI info - done --- Detecting C compile features --- Detecting C compile features - done --- Check for working CXX compiler: /usr/bin/c++ --- Check for working CXX compiler: /usr/bin/c++ -- works --- Detecting CXX compiler ABI info --- Detecting CXX compiler ABI info - done --- Detecting CXX compile features --- Detecting CXX compile features - done --- Configuring done --- Generating done --- Build files have been written to: /kdmp-parser/build/linx86-Debug [6/6] Linking CXX executable ../../bin/linx86-Debug/testapp over@oof:/kdmp-parser/$ cd build/ over@oof:/kdmp-parser/build$ mkdir linx64-RelWithDebInfo/ over@oof:/kdmp-parser/build$ cd linx64-RelWithDebInfo/ -over@oof:/kdmp-parser/build/linx64-RelWithDebInfo$ cmake --DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/kdmp-parser/bin/linx64-RelWithDebInfo -DCMAKE_BUILD_TYPE=RelWithDebInfo ../../ --- The C compiler identification is GNU 7.4.0 --- The CXX compiler identification is GNU 7.4.0 --- Check for working C compiler: /usr/bin/cc --- Check for working C compiler: /usr/bin/cc -- works --- Detecting C compiler ABI info --- Detecting C compiler ABI info - done --- Detecting C compile features --- Detecting C compile features - done --- Check for working CXX compiler: /usr/bin/c++ --- Check for working CXX compiler: /usr/bin/c++ -- works --- Detecting CXX compiler ABI info --- Detecting CXX compiler ABI info - done --- Detecting CXX compile features --- Detecting CXX compile features - done --- Configuring done --- Generating done --- Build files have been written to: /kdmp-parser/build/linx64-RelWithDebInfo - -over@oof:/kdmp-parser/build/linx64-RelWithDebInfo$ cmake --build . +over@oof:/kdmp-parser/build/linx64-RelWithDebInfo$ cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ../../ && cmake --build . ``` ### Windows -You can build it using [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/) by either using the "Open the folder" option or via command line using `builder.py` or `cmake` directly (from a Visual Studio shell): +You can build it using [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/) by either using the *Open the folder* option or via the command line using `builder.py` / `cmake` directly: ```text kdmp-parser>python builder.py --configuration Debug --- The C compiler identification is MSVC 19.25.28614.0 --- The CXX compiler identification is MSVC 19.25.28614.0 --- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe --- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe -- works --- Detecting C compiler ABI info --- Detecting C compiler ABI info - done --- Detecting C compile features --- Detecting C compile features - done --- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe --- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe -- works --- Detecting CXX compiler ABI info --- Detecting CXX compiler ABI info - done --- Detecting CXX compile features --- Detecting CXX compile features - done --- Configuring done --- Generating done --- Build files have been written to: kdmp-parser/build/x64-Debug +... [6/6] Linking CXX executable ..\..\bin\x64-Debug\testapp.exe --- The C compiler identification is MSVC 19.25.28614.0 --- The CXX compiler identification is MSVC 19.25.28614.0 --- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.25.28610/bin/Hostx86/x86/cl.exe --- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.25.28610/bin/Hostx86/x86/cl.exe -- works --- Detecting C compiler ABI info --- Detecting C compiler ABI info - done --- Detecting C compile features --- Detecting C compile features - done --- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.25.28610/bin/Hostx86/x86/cl.exe --- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.25.28610/bin/Hostx86/x86/cl.exe -- works --- Detecting CXX compiler ABI info --- Detecting CXX compiler ABI info - done --- Detecting CXX compile features --- Detecting CXX compile features - done --- Configuring done --- Generating done --- Build files have been written to: kdmp-parser/build/x86-Debug [6/6] Linking CXX executable ..\..\bin\x86-Debug\testapp.exe kdmp-parser>cd build kdmp-parser\build>mkdir x64-RelWithDebInfo kdmp-parser\build>cd x64-RelWithDebInfo -kdmp-parser\build\x64-RelWithDebInfo>cmake -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=c:\kdmp-parser\bin\x64-RelWithDebInfo -DCMAKE_BUILD_TYPE=RelWithDebInfo -GNinja ..\..\ +kdmp-parser\build\x64-RelWithDebInfo>cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -GNinja ..\..\ -- The C compiler identification is MSVC 19.25.28614.0 -- The CXX compiler identification is MSVC 19.25.28614.0 -- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe @@ -267,80 +185,4 @@ kdmp-parser\build\x64-RelWithDebInfo>cmake -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=c:\k kdmp-parser\build\x64-RelWithDebInfo>cmake --build . [6/6] Linking CXX executable ..\..\bin\x64-RelWithDebInfo\parser.exe - -kdmp-parser\build\x64-RelWithDebInfo>..\..\bin\x64-RelWithDebInfo\parser.exe -You didn't provide the path to the dump file. - -parser.exe [-p []] [-c] [-e] [-h] - -Examples: - Show every structures of the dump: - parser.exe -a full.dmp - - Show the context record: - parser.exe -c full.dmp - - Show the exception record: - parser.exe -e full.dmp - - Show all the physical memory (first 16 bytes of every pages): - parser.exe -p full.dmp - - Show the context record as well as the page at physical address 0x1000: - parser.exe -c -p 0x1000 full.dmp -``` - -## Testing - -You can run `builder.py` with the `--run-tests` flag to run basic tests. First, it builds the matrix, then it downloads two kernel dumps (one full dump and one bitmap dump) and runs every flavor of the `testapp` application against the dumps. - -```text -kdmp-parser>python builder.py --configuration RelWithDebInfo --run-tests --- The C compiler identification is MSVC 19.25.28614.0 --- The CXX compiler identification is MSVC 19.25.28614.0 --- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe --- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe -- works --- Detecting C compiler ABI info --- Detecting C compiler ABI info - done --- Detecting C compile features --- Detecting C compile features - done --- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe --- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe -- works --- Detecting CXX compiler ABI info --- Detecting CXX compiler ABI info - done --- Detecting CXX compile features --- Detecting CXX compile features - done --- Configuring done --- Generating done --- Build files have been written to: kdmp-parser/build/x64-RelWithDebInfo -[6/6] Linking CXX executable ..\..\bin\x64-RelWithDebInfo\parser.exe --- The C compiler identification is MSVC 19.25.28614.0 --- The CXX compiler identification is MSVC 19.25.28614.0 --- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.25.28610/bin/Hostx86/x86/cl.exe --- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.25.28610/bin/Hostx86/x86/cl.exe -- works --- Detecting C compiler ABI info --- Detecting C compiler ABI info - done --- Detecting C compile features --- Detecting C compile features - done --- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.25.28610/bin/Hostx86/x86/cl.exe --- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.25.28610/bin/Hostx86/x86/cl.exe -- works --- Detecting CXX compiler ABI info --- Detecting CXX compiler ABI info - done --- Detecting CXX compile features --- Detecting CXX compile features - done --- Configuring done --- Generating done --- Build files have been written to: kdmp-parser/build/x86-RelWithDebInfo -[6/6] Linking CXX executable ..\..\bin\x86-RelWithDebInfo\testapp.exe -Downloading https://github.com/0vercl0k/kdmp-parser/releases/download/v0.1/testdatas.zip.. -Successfully downloaded the test datas in C:\Users\over\AppData\Local\Temp\tmp5o25eqtd, extracting.. -Launching "bin\x64-RelWithDebInfo\testapp C:\Users\over\AppData\Local\Temp\full.dmp".. -GPRs matches the testdatas. -Launching "bin\x86-RelWithDebInfo\testapp C:\Users\over\AppData\Local\Temp\full.dmp".. -GPRs matches the testdatas. -Launching "bin\x64-RelWithDebInfo\testapp C:\Users\over\AppData\Local\Temp\bmp.dmp".. -GPRs matches the testdatas. -Launching "bin\x86-RelWithDebInfo\testapp C:\Users\over\AppData\Local\Temp\bmp.dmp".. -GPRs matches the testdatas. -All good! ``` \ No newline at end of file From 632de5aee49ef673a9545844c6868a8131753d18 Mon Sep 17 00:00:00 2001 From: 0vercl0k <1476421+0vercl0k@users.noreply.github.com> Date: Sat, 26 Sep 2020 17:45:30 -0700 Subject: [PATCH 09/13] nits --- src/lib/kdmp-parser-structs.h | 34 +++++++++++++++++----------------- src/lib/kdmp-parser.cc | 12 ++++++------ src/lib/kdmp-parser.h | 7 ++++--- src/parser/parser.cc | 2 +- src/python/python-kdmp.cc | 9 +++++---- 5 files changed, 33 insertions(+), 31 deletions(-) diff --git a/src/lib/kdmp-parser-structs.h b/src/lib/kdmp-parser-structs.h index a1d3f8e..aa51b06 100644 --- a/src/lib/kdmp-parser-structs.h +++ b/src/lib/kdmp-parser-structs.h @@ -27,15 +27,7 @@ struct EXCEPTION_RECORD64 { #endif // -// Save off the alignement setting and disable -// alignement. -// - -#pragma pack(push) -#pragma pack(1) - -// -// We need a way to represent 128bits integers so here goes. +// We need a way to represent 128-bits integers so here goes. // struct uint128_t { @@ -45,11 +37,19 @@ struct uint128_t { static_assert(sizeof(uint128_t) == 16, "uint128_t's size looks wrong."); -enum DumpType_t : uint32_t { FullDump = 1, KernelDump = 2, BMPDump = 5 }; +enum class DumpType_t : uint32_t { FullDump = 1, KernelDump = 2, BMPDump = 5 }; + +// +// Save off the alignement setting and disable +// alignement. +// + +#pragma pack(push) +#pragma pack(1) // // All the display utilities are in this class because long story short template -// functions were breaking my balls. If you know a cleaner way to do this, hit +// functions were not cooperating. If you know a cleaner way to do this, hit // me up :) // @@ -120,16 +120,16 @@ struct DisplayUtils { const void *This, const DumpType_t *Field) const { DisplayHeader(Prefix, FieldName, This, Field); switch (*Field) { - case KernelDump: { + case DumpType_t::KernelDump: { printf(": Kernel Dump.\n"); break; } - case FullDump: { + case DumpType_t::FullDump: { printf(": Full Dump.\n"); break; } - case BMPDump: { + case DumpType_t::BMPDump: { printf(": BMP Dump.\n"); break; } @@ -689,12 +689,12 @@ struct KDMP_PARSER_HEADER64 : public DisplayUtils { // Make sure it's a dump type we know how to handle. // - if (DumpType == FullDump) { + if (DumpType == DumpType_t::FullDump) { if (!PhysicalMemoryBlockBuffer.LooksGood()) { printf("The PhysicalMemoryBlockBuffer looks wrong.\n"); return false; } - } else if (DumpType == BMPDump) { + } else if (DumpType == DumpType_t::BMPDump) { if (!BmpHeader.LooksGood()) { printf("The BmpHeader looks wrong.\n"); return false; @@ -744,7 +744,7 @@ struct KDMP_PARSER_HEADER64 : public DisplayUtils { DISPLAY_FIELD(SuiteMask); DISPLAY_FIELD(WriterStatus); DISPLAY_FIELD(KdSecondaryVersion); - if (DumpType == BMPDump) { + if (DumpType == DumpType_t::BMPDump) { DISPLAY_FIELD_OFFSET(BmpHeader); BmpHeader.Show(); } diff --git a/src/lib/kdmp-parser.cc b/src/lib/kdmp-parser.cc index e115e71..23e2f8b 100644 --- a/src/lib/kdmp-parser.cc +++ b/src/lib/kdmp-parser.cc @@ -31,12 +31,12 @@ bool KernelDumpParser::Parse(const char *PathFile) { // Retrieve the physical memory according to the type of dump we have. // - if (DmpHdr_->DumpType == FullDump) { + if (DmpHdr_->DumpType == DumpType_t::FullDump) { if (!BuildPhysmemFullDump()) { printf("BuildPhysmemFullDump failed.\n"); return false; } - } else if (DmpHdr_->DumpType == BMPDump) { + } else if (DmpHdr_->DumpType == DumpType_t::BMPDump) { if (!BuildPhysmemBMPDump()) { printf("BuildPhysmemBMPDump failed.\n"); return false; @@ -220,7 +220,7 @@ bool KernelDumpParser::BuildPhysmemFullDump() { return true; } -const uint64_t +uint64_t KernelDumpParser::PhyRead8(const uint64_t PhysicalAddress) const { // @@ -322,7 +322,7 @@ void KernelDumpParser::ShowAllStructures(const uint32_t Prefix = 0) const { DmpHdr_->Show(Prefix); } -const uint64_t KernelDumpParser::GetDirectoryTableBase() const { +uint64_t KernelDumpParser::GetDirectoryTableBase() const { return DmpHdr_->DirectoryTableBase; } @@ -333,7 +333,7 @@ KernelDumpParser::GetPhysicalPage(const uint64_t PhysicalAddress) const { // Attempt to find the physical address. // - Physmem_t::const_iterator Pair = Physmem_.find(PhysicalAddress); + const Physmem_t::const_iterator Pair = Physmem_.find(PhysicalAddress); // // If it doesn't exist then return nullptr. @@ -350,7 +350,7 @@ KernelDumpParser::GetPhysicalPage(const uint64_t PhysicalAddress) const { return Pair->second; } -const uint64_t +uint64_t KernelDumpParser::VirtTranslate(const uint64_t VirtualAddress, const uint64_t DirectoryTableBase) const { diff --git a/src/lib/kdmp-parser.h b/src/lib/kdmp-parser.h index e629243..3291e12 100644 --- a/src/lib/kdmp-parser.h +++ b/src/lib/kdmp-parser.h @@ -98,14 +98,14 @@ class KernelDumpParser { // Get the directory table base. // - const uint64_t GetDirectoryTableBase() const; + uint64_t GetDirectoryTableBase() const; // // Translate a virtual address to physical address using a directory table // base. // - const uint64_t VirtTranslate(const uint64_t VirtualAddress, + uint64_t VirtTranslate(const uint64_t VirtualAddress, const uint64_t DirectoryTableBase = 0) const; // @@ -120,7 +120,8 @@ class KernelDumpParser { // Utility function to read an uint64_t from a physical address. // - const uint64_t PhyRead8(const uint64_t PhysicalAddress) const; + uint64_t PhyRead8(const uint64_t PhysicalAddress) const; + // // Build a map of physical addresses / page data pointers for full dump. // diff --git a/src/parser/parser.cc b/src/parser/parser.cc index 625bb0d..739a1f2 100644 --- a/src/parser/parser.cc +++ b/src/parser/parser.cc @@ -339,7 +339,7 @@ int main(int argc, const char *argv[]) { // Stuff the physical addresses in a vector. // - for (const auto [PhysicalAddress, _] : Dmp.GetPhysmem()) { + for (const auto &[PhysicalAddress, _] : Dmp.GetPhysmem()) { OrderedPhysicalAddresses.emplace_back(PhysicalAddress); } diff --git a/src/python/python-kdmp.cc b/src/python/python-kdmp.cc index 9683baa..ed1711c 100644 --- a/src/python/python-kdmp.cc +++ b/src/python/python-kdmp.cc @@ -81,7 +81,8 @@ PyObject *DumpParserGetType(PyObject *Object, PyObject *) { // PythonDumpParser *Self = reinterpret_cast(Object); - return PyLong_FromUnsignedLong(Self->DumpParser->GetDumpType()); + const DumpType_t DumpType = Self->DumpParser->GetDumpType(); + return PyLong_FromUnsignedLong(static_cast(DumpType)); } // @@ -320,9 +321,9 @@ PyMODINIT_FUNC PyInit_kdmp(void) { // >>> kdmp.FullDump ... // - PyModule_AddIntConstant(Module, "FullDump", DumpType_t::FullDump); - PyModule_AddIntConstant(Module, "KernelDump", DumpType_t::KernelDump); - PyModule_AddIntConstant(Module, "BMPDump", DumpType_t::BMPDump); + PyModule_AddIntConstant(Module, "FullDump", long(DumpType_t::FullDump)); + PyModule_AddIntConstant(Module, "KernelDump", long(DumpType_t::KernelDump)); + PyModule_AddIntConstant(Module, "BMPDump", long(DumpType_t::BMPDump)); return Module; } From d3f7b5219c0c2cf6afedb27cf52c04cca15a18a1 Mon Sep 17 00:00:00 2001 From: 0vercl0k <1476421+0vercl0k@users.noreply.github.com> Date: Sat, 26 Sep 2020 17:48:27 -0700 Subject: [PATCH 10/13] nits --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8dab540..45bca73 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This C++ library parses Windows kernel [full](https://docs.microsoft.com/en-us/w ![parser](pics/parser.jpg) -The library supports loading 64-bit dumps and provides read access (not write) to: +The library supports loading 64-bit dumps and provides read access to things like: - The context record, - The exception record, @@ -21,7 +21,7 @@ Special thanks to: ## Python 3 bindings -The bindings (contributed by [@masthoon](https://github.com/masthoon)) allow you to: read the context, read physical memory as well as to do virtual memory translations. +The bindings (contributed by [@masthoon](https://github.com/masthoon)) allow you to: read the context, read physical memory and to do virtual memory translations: ```py from kdmp import Dump, FullDump, BMPDump @@ -50,7 +50,7 @@ assert(dmp.get_virtual_page(v) == dmp.get_physical_page(dmp.virt_translate(v))) ## Parser -The `parser.exe` application is a utility able to dump various information about the dump file: exception record, context record, etc. +The `parser.exe` application is able to dump various information about the dump file: exception record, context record, etc. ```text kdmp-parser\src>x64\Debug\parser.exe -c -e -p 0x1000 full.dmp From 832e112a99097c9983a533b9ad72f7e1bad151e5 Mon Sep 17 00:00:00 2001 From: 0vercl0k <1476421+0vercl0k@users.noreply.github.com> Date: Sat, 26 Sep 2020 17:52:20 -0700 Subject: [PATCH 11/13] fix --- .github/workflows/kdmp-parser.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/kdmp-parser.yml b/.github/workflows/kdmp-parser.yml index f28e3da..75e163b 100644 --- a/.github/workflows/kdmp-parser.yml +++ b/.github/workflows/kdmp-parser.yml @@ -5,7 +5,7 @@ on: [push, pull_request] jobs: Linux2004Gcc: - name: Ubuntu 20.04 / GCC10 + name: Ubuntu 20.04 runs-on: ubuntu-20.04 steps: - name: Checkout From e9c0ebff23fd778a32056438266435364e440dd3 Mon Sep 17 00:00:00 2001 From: 0vercl0k <1476421+0vercl0k@users.noreply.github.com> Date: Sat, 26 Sep 2020 18:26:13 -0700 Subject: [PATCH 12/13] fix merge --- src/lib/kdmp-parser-structs.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/lib/kdmp-parser-structs.h b/src/lib/kdmp-parser-structs.h index 663c0c6..4d19464 100644 --- a/src/lib/kdmp-parser-structs.h +++ b/src/lib/kdmp-parser-structs.h @@ -15,19 +15,6 @@ namespace kdmpparser { -#ifndef WINDOWS -#define EXCEPTION_MAXIMUM_PARAMETERS 15 -struct EXCEPTION_RECORD64 { - uint32_t ExceptionCode; - uint32_t ExceptionFlags; - uint64_t ExceptionRecord; - uint64_t ExceptionAddress; - uint32_t NumberParameters; - uint32_t __unusedAlignment; - uint64_t ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; -}; -#endif - // // We need a way to represent 128-bits integers so here goes. // From 75141e492f5d8972b8b5400a9fdbff38c5184d71 Mon Sep 17 00:00:00 2001 From: 0vercl0k <1476421+0vercl0k@users.noreply.github.com> Date: Sat, 26 Sep 2020 18:31:28 -0700 Subject: [PATCH 13/13] nits --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 45bca73..884ff95 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ![Build status](https://github.com/0vercl0k/kdmp-parser/workflows/Builds/badge.svg) -This C++ library parses Windows kernel [full](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/complete-memory-dump) dump (`.dump /f` in WinDbg) as well as [BMP](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/active-memory-dump) dump (`.dump /ka` in WinDbg). +This C++ library parses Windows kernel [full](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/complete-memory-dump) dumps (`.dump /f` in WinDbg) as well as [BMP](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/active-memory-dump) dumps (`.dump /ka` in WinDbg). ![parser](pics/parser.jpg)