Skip to content

Commit f61d0bd

Browse files
authored
v0.2.0 (#4)
The main change is exposing the list of kernel drivers / the list of user modules loaded when the dump was generated.
1 parent 2fa8a36 commit f61d0bd

File tree

12 files changed

+3354
-144
lines changed

12 files changed

+3354
-144
lines changed

Cargo.toml

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,26 @@
11
[package]
22
name = "kdmp-parser"
3-
version = "0.1.1"
3+
version = "0.2.0"
44
edition = "2021"
55
authors = ["Axel '0vercl0k' Souchet"]
66
categories = ["parser-implementations"]
77
description = "A KISS Rust crate to parse Windows kernel crash-dumps created by Windows & its debugger."
8-
include = [
9-
"/Cargo.toml",
10-
"/LICENSE",
11-
"/src/**",
12-
"/examples/**",
13-
"README.md",
14-
]
8+
include = ["/Cargo.toml", "/LICENSE", "/src/**", "/examples/**", "README.md"]
159
keywords = ["windows", "kernel", "crashdump"]
1610
license = "MIT"
1711
repository = "https://github.com/0vercl0k/kdmp-parser-rs"
1812
rust-version = "1.70"
1913

2014
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
2115
[dependencies]
22-
bitflags = "2.4.2"
23-
thiserror = "1.0.58"
16+
bitflags = "2.5.0"
17+
thiserror = "1.0"
2418

2519
[dev-dependencies]
2620
anyhow = "1.0.80"
2721
clap = { version = "4.5.1", features = ["derive"] }
22+
serde = { version = "1.0", features = ["derive"] }
23+
serde_json = "1.0"
2824

2925
[[example]]
3026
name = "parser"

README.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<div align='center'>
2-
<h1><code>kdmp-parser-rs</code></h1>
2+
<h1><code>kdmp-parser</code></h1>
33
<p>
44
<strong>A <a href="https://en.wikipedia.org/wiki/KISS_principle">KISS</a> Rust crate to parse Windows kernel crash-dumps created by Windows & its debugger.</strong>
55
</p>
@@ -22,7 +22,7 @@ The [parser](src/examples/parser.rs) application is a small utility to show-case
2222

2323
Here are the options supported:
2424
```text
25-
A Rust crate for parsing Windows kernel crashdumps
25+
A KISS Rust crate to parse Windows kernel crash-dumps created by Windows & its debugger.
2626
2727
Usage: parser.exe [OPTIONS] <DUMP_PATH>
2828
@@ -31,11 +31,14 @@ Arguments:
3131
The dump path
3232
3333
Options:
34+
--dump-headers
35+
Dump the dump headers
36+
3437
-c, --context-record
35-
Show the context record
38+
Dump the context record
3639
3740
-e, --exception-record
38-
Show the exception record
41+
Dump the exception record
3942
4043
-m, --mem[=<MEM>]
4144
Dump the first `len` bytes of every physical pages, unless an address is specified
@@ -44,15 +47,22 @@ Options:
4447
The address specified is interpreted as a virtual address, not a physical address
4548
4649
--len <LEN>
50+
The number of bytes to dump out
51+
4752
[default: 16]
4853
4954
-r, --reader <READER>
55+
Reader mode
56+
5057
[default: mmap]
5158
5259
Possible values:
5360
- mmap: The crash-dump is memory-mapped
5461
- file: The crash-dump is read as a file on disk
5562
63+
--modules
64+
Dump the list of kernel & user modules
65+
5666
-h, --help
5767
Print help (see a summary with '-h')
5868

examples/parser.rs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use core::default::Default;
33
use std::fs::File;
44
use std::path::PathBuf;
55

6-
use anyhow::{anyhow, Context, Result};
6+
use anyhow::{Context, Result};
77
use clap::{Parser, ValueEnum};
88
use kdmp_parser::{Gpa, Gva, Gxa, KernelDumpParser, MappedFileReader};
99

@@ -21,10 +21,13 @@ enum ReaderMode {
2121
struct Args {
2222
/// The dump path.
2323
dump_path: PathBuf,
24-
/// Show the context record.
24+
/// Dump the dump headers.
25+
#[arg(long, default_value_t = false)]
26+
dump_headers: bool,
27+
/// Dump the context record.
2528
#[arg(short, long)]
2629
context_record: bool,
27-
/// Show the exception record.
30+
/// Dump the exception record.
2831
#[arg(short, long)]
2932
exception_record: bool,
3033
/// Dump the first `len` bytes of every physical pages, unless an address is
@@ -41,6 +44,9 @@ struct Args {
4144
/// Reader mode.
4245
#[arg(short, long, value_enum, default_value_t = ReaderMode::Mmap)]
4346
reader: ReaderMode,
47+
/// Dump the list of kernel & user modules.
48+
#[arg(long, default_value_t = false)]
49+
modules: bool,
4450
}
4551

4652
/// Print a hexdump of data that started at `address`.
@@ -90,6 +96,10 @@ fn main() -> Result<()> {
9096
}
9197
.context("failed to parse the kernel dump")?;
9298

99+
if args.dump_headers {
100+
println!("{:?}", parser.headers());
101+
}
102+
93103
if args.context_record {
94104
println!("{:#x?}", parser.context_record());
95105
}
@@ -98,14 +108,18 @@ fn main() -> Result<()> {
98108
println!("{:#x?}", parser.exception_record());
99109
}
100110

111+
if args.modules {
112+
for (at, module) in parser.user_modules().chain(parser.kernel_modules()) {
113+
println!("{:#x}-{:#x}: {module}", at.start.u64(), at.end.u64());
114+
}
115+
}
116+
101117
if let Some(addr) = args.mem {
102118
let mut buffer = vec![0; args.len];
103119
let addr = to_hex(&addr)?;
104120
if addr == u64::MAX {
105121
for (gpa, _) in parser.physmem() {
106-
parser
107-
.phys_read_exact(gpa, &mut buffer)
108-
.ok_or_else(|| anyhow!("failed to read {gpa}"))?;
122+
parser.phys_read_exact(gpa, &mut buffer)?;
109123
hexdump(gpa.u64(), &buffer)
110124
}
111125
} else {
@@ -115,7 +129,7 @@ fn main() -> Result<()> {
115129
parser.phys_read(Gpa::new(addr), &mut buffer)
116130
};
117131

118-
if let Some(amount) = amount {
132+
if let Ok(amount) = amount {
119133
hexdump(addr, &buffer[..amount]);
120134
} else {
121135
println!(

src/error.rs

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,47 @@
11
// Axel '0vercl0k' Souchet - March 19 2024
22
//! This is the error type used across the codebase.
3-
use std::io;
3+
use std::fmt::Display;
4+
use std::{io, string};
45

56
use thiserror::Error;
67

7-
use crate::structs::{HEADER64_EXPECTED_SIGNATURE, HEADER64_EXPECTED_VALID_DUMP};
8-
use crate::Gpa;
8+
use crate::structs::{DUMP_HEADER64_EXPECTED_SIGNATURE, DUMP_HEADER64_EXPECTED_VALID_DUMP};
9+
use crate::{Gpa, Gva};
910
pub type Result<R> = std::result::Result<R, KdmpParserError>;
1011

12+
#[derive(Debug)]
13+
pub enum PxeNotPresent {
14+
Pml4e,
15+
Pdpte,
16+
Pde,
17+
Pte,
18+
}
19+
20+
#[derive(Debug, Error)]
21+
pub enum AddrTranslationError {
22+
Virt(Gva, PxeNotPresent),
23+
Phys(Gpa),
24+
}
25+
26+
impl Display for AddrTranslationError {
27+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28+
match self {
29+
AddrTranslationError::Virt(gva, not_pres) => f.write_fmt(format_args!(
30+
"virt to phys translation of {gva}: {not_pres:?}"
31+
)),
32+
AddrTranslationError::Phys(gpa) => {
33+
f.write_fmt(format_args!("phys to offset translation of {gpa}"))
34+
}
35+
}
36+
}
37+
}
38+
1139
#[derive(Error, Debug)]
1240
pub enum KdmpParserError {
41+
#[error("invalid UNICODE_STRING")]
42+
InvalidUnicodeString,
43+
#[error("utf16: {0}")]
44+
Utf16(#[from] string::FromUtf16Error),
1345
#[error("overflow: {0}")]
1446
Overflow(&'static str),
1547
#[error("io: {0}")]
@@ -20,14 +52,20 @@ pub enum KdmpParserError {
2052
UnknownDumpType(u32),
2153
#[error("duplicate gpa found in physmem map for {0}")]
2254
DuplicateGpa(Gpa),
23-
#[error("header's signature looks wrong: {0:#x} vs {HEADER64_EXPECTED_SIGNATURE:#x}")]
55+
#[error("header's signature looks wrong: {0:#x} vs {DUMP_HEADER64_EXPECTED_SIGNATURE:#x}")]
2456
InvalidSignature(u32),
25-
#[error("header's valid dump looks wrong: {0:#x} vs {HEADER64_EXPECTED_VALID_DUMP:#x}")]
57+
#[error("header's valid dump looks wrong: {0:#x} vs {DUMP_HEADER64_EXPECTED_VALID_DUMP:#x}")]
2658
InvalidValidDump(u32),
2759
#[error("overflow for phys addr w/ run {0} page {1}")]
2860
PhysAddrOverflow(u32, u64),
2961
#[error("overflow for page offset w/ run {0} page {1}")]
3062
PageOffsetOverflow(u32, u64),
3163
#[error("overflow for page offset w/ bitmap_idx {0} bit_idx {1}")]
3264
BitmapPageOffsetOverflow(u64, usize),
65+
#[error("partial physical memory read")]
66+
PartialPhysRead,
67+
#[error("partial virtual memory read")]
68+
PartialVirtRead,
69+
#[error("memory translation: {0}")]
70+
AddrTranslation(#[from] AddrTranslationError),
3371
}

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ mod pxe;
99
mod structs;
1010

1111
pub use bits::Bits;
12-
pub use error::KdmpParserError;
12+
pub use error::{AddrTranslationError, KdmpParserError, PxeNotPresent, Result};
1313
pub use gxa::{Gpa, Gva, Gxa};
1414
pub use map::{MappedFileReader, Reader};
1515
pub use parse::KernelDumpParser;

0 commit comments

Comments
 (0)